/**
* Copyright 2000-2009 DFKI GmbH.
* All Rights Reserved. Use is subject to license terms.
*
* This file is part of MARY TTS.
*
* MARY TTS is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, version 3 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package marytts.signalproc.process;
import java.util.Arrays;
import marytts.signalproc.analysis.PitchMarks;
import marytts.util.data.DoubleDataSource;
import marytts.util.signal.SignalProcUtils;
public class PsolaFrameProvider {
protected double[] buffer;
protected DoubleDataSource input;
protected int index; // Pitch mark index for pitch synchronous processing, and frame index for fixed window size & rate
// processing
protected int numPeriods;
protected PitchMarks pitchMarker;
protected int frmSize;
protected int prevFrmSize;
protected int remain;
protected int fromBuffer;
private boolean isFixedRate;
private int wsFixedLen;
private int ssFixedLen;
private int totalFixedFrames;
private double currentTimeInSeconds;
private int samplingRate;
// Pitch synchronous frame provider
public PsolaFrameProvider(DoubleDataSource inputSource, PitchMarks pm, int fs, int psPeriods) {
this.input = inputSource;
this.numPeriods = psPeriods;
this.pitchMarker = pm;
samplingRate = fs;
int maxFrmSize = (int) (numPeriods * fs / 40.0);
if ((maxFrmSize % 2) != 0)
maxFrmSize++;
this.buffer = new double[maxFrmSize];
Arrays.fill(buffer, 0.0);
index = -1;
isFixedRate = false;
totalFixedFrames = 0;
currentTimeInSeconds = -1.0;
}
// Fixed rate frame provider
public PsolaFrameProvider(DoubleDataSource inputSource, double fixedWindowSizeInSeconds, double fixedSkipSizeInSeconds,
int fs, int totalFrames) {
this.input = inputSource;
this.numPeriods = -1;
this.pitchMarker = null;
samplingRate = fs;
wsFixedLen = (int) Math.floor(fixedWindowSizeInSeconds * fs + 0.5);
if ((wsFixedLen % 2) != 0)
wsFixedLen++;
if (wsFixedLen < 4)
wsFixedLen = 4;
frmSize = wsFixedLen;
ssFixedLen = (int) Math.floor(fixedSkipSizeInSeconds * fs + 0.5);
int maxFrmSize = wsFixedLen;
this.buffer = new double[maxFrmSize];
Arrays.fill(buffer, 0.0);
index = -1;
isFixedRate = true;
totalFixedFrames = totalFrames;
currentTimeInSeconds = -1.0;
}
public double[] getNextFrame() {
double[] y = null;
if (!isFixedRate) // Return next pitch synchronous speech frame
{
index++;
if (index + numPeriods < pitchMarker.pitchMarks.length) {
frmSize = pitchMarker.pitchMarks[index + numPeriods] - pitchMarker.pitchMarks[index] + 1;
currentTimeInSeconds = SignalProcUtils.sample2time((int) (0.5 * (pitchMarker.pitchMarks[index + numPeriods]
+ pitchMarker.pitchMarks[index] + 1)), samplingRate);
if ((frmSize % 2) != 0)
frmSize++;
if (frmSize < 4)
frmSize = 4;
y = new double[frmSize];
if (index == 0) // Read all from the source
input.getData(y, 0, frmSize);
else // Read numPeriods-1 pitch synchronous frames from the buffer and one period from the source
{
fromBuffer = prevFrmSize - (pitchMarker.pitchMarks[index] - pitchMarker.pitchMarks[index - 1]);
System.arraycopy(buffer, pitchMarker.pitchMarks[index] - pitchMarker.pitchMarks[index - 1], y, 0, fromBuffer);
remain = frmSize - fromBuffer;
input.getData(y, fromBuffer, remain);
}
System.arraycopy(y, 0, buffer, 0, frmSize);
prevFrmSize = frmSize;
}
} else // Return next fixed window size and rate speech frame
{
index++;
if (index < totalFixedFrames) {
y = new double[frmSize];
if (index == 0) // Read all from the source
input.getData(y, 0, frmSize);
else // Read numPeriods-1 pitch synchronous frames from the buffer and one period from the source
{
System.arraycopy(buffer, prevFrmSize - ssFixedLen, y, 0, ssFixedLen);
remain = frmSize - ssFixedLen;
input.getData(y, ssFixedLen, remain);
}
currentTimeInSeconds = SignalProcUtils.sample2time((int) (index * ssFixedLen + 0.5 * frmSize), samplingRate);
System.arraycopy(y, 0, buffer, 0, frmSize);
prevFrmSize = frmSize;
}
}
return y;
}
public double getCurrentTime() {
return currentTimeInSeconds;
}
}