/**
* Copyright 2007 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.sinusoidal.test;
import java.io.IOException;
import java.util.Arrays;
import marytts.signalproc.sinusoidal.Sinusoid;
import marytts.util.io.FileUtils;
import marytts.util.math.ArrayUtils;
import marytts.util.math.MathUtils;
import marytts.util.signal.SignalProcUtils;
/**
* This class combines SinusoidsTester and NoiseTester classes You can simply give a SinusoidsTester object and NoiseTester object
* and generate the superposition of the outputs of the two objects, i.e. multiple sinusoids located at desired instants of time
* plus white or pink noise with desired bandwidth at desired time instants Using this class one can generate fairly complicated
* yet parametric test signals
*
* @author Oytun Türk
**/
public class SinusoidsNoiseTester extends BaseTester {
public SinusoidsNoiseTester(SinusoidsTester s, NoiseTester n) {
assert s.fs == n.fs;
fs = s.fs;
int i;
int maxLen = 0;
if (s.signal != null)
maxLen = s.signal.length;
if (n.signal != null && n.signal.length > maxLen)
maxLen = n.signal.length;
signal = new double[maxLen];
pitchMarks = null;
Arrays.fill(signal, 0.0);
if (s.signal != null) {
System.arraycopy(s.signal, 0, signal, 0, s.signal.length);
// System.out.println("1: " + String.valueOf(MathUtils.getAbsMax(signal)));
if (n.signal != null) {
for (i = 0; i < n.signal.length; i++)
signal[i] += n.signal[i];
}
// System.out.println("2: " + String.valueOf(MathUtils.getAbsMax(signal)));
for (i = 0; i < signal.length; i++)
signal[i] *= 0.5;
// System.out.println("3: " + String.valueOf(MathUtils.getAbsMax(signal)));
if (s.pitchMarks != null) {
if (s.pitchMarks[s.pitchMarks.length - 1] >= maxLen - 1) // Everything is covered by sinusoids so no need to worry
// about noise part
{
pitchMarks = ArrayUtils.copy(s.pitchMarks);
f0s = ArrayUtils.copy(s.f0s);
} else // We need some extra fixed rate marks to cover all signal
{
int maxT0 = SignalProcUtils.time2sample(1.0 / NoiseTester.FIXED_F0_NOISE, fs);
int pitchMarksLen = s.pitchMarks.length;
int currInd;
if (n.pitchMarks != null) {
int noiseInd = n.pitchMarks.length - 1;
// Compute how much extra we will need:
while (n.pitchMarks[noiseInd] - s.pitchMarks[s.pitchMarks.length - 1] > maxT0) {
noiseInd--;
if (noiseInd < 0) {
noiseInd = 0;
break;
}
}
pitchMarksLen += n.pitchMarks.length - noiseInd;
// Check if there is still a gap between the sinusoid end and noise start:
if (noiseInd == 0) {
currInd = n.pitchMarks[0];
while (currInd - s.pitchMarks[s.pitchMarks.length - 1] > maxT0) {
pitchMarksLen++;
currInd -= maxT0;
}
}
pitchMarks = new int[pitchMarksLen];
System.arraycopy(s.pitchMarks, 0, pitchMarks, 0, s.pitchMarks.length);
for (i = s.pitchMarks.length; i < s.pitchMarks.length + n.pitchMarks.length - noiseInd; i++)
pitchMarks[i] = n.pitchMarks[i - s.pitchMarks.length + noiseInd];
for (i = s.pitchMarks.length + n.pitchMarks.length - noiseInd; i < pitchMarksLen; i++)
pitchMarks[i] = Math.min(pitchMarks[i - 1] + maxT0, maxLen - 1);
} else // Noise pitch marks do not exist so just generate extra marks at the end to cover all signal
{
currInd = s.pitchMarks[s.pitchMarks.length - 1];
while (maxLen - currInd > maxT0) {
pitchMarksLen++;
currInd += maxT0;
}
pitchMarks = new int[pitchMarksLen];
System.arraycopy(s.pitchMarks, 0, pitchMarks, 0, s.pitchMarks.length);
for (i = s.pitchMarks.length; i < pitchMarksLen; i++)
pitchMarks[i] = Math.min(pitchMarks[i - 1] + maxT0, maxLen - 1);
float lastTime = SignalProcUtils.sample2time(pitchMarks[pitchMarks.length - 1], fs);
int numfrm = (int) Math.floor((lastTime - 0.5 * ws) / ss + 0.5);
f0s = new double[numfrm];
System.arraycopy(s.f0s, 0, f0s, 0, s.f0s.length);
for (i = s.f0s.length; i < numfrm; i++)
f0s[i] = NoiseTester.FIXED_F0_NOISE;
}
}
} else // Generate fixed pitch marks all along the signal
{
int maxT0 = SignalProcUtils.time2sample(1.0 / NoiseTester.FIXED_F0_NOISE, fs);
int numPitchMarks = (int) (Math.floor(((double) maxLen) / maxT0 + 0.5)) + 1;
pitchMarks = new int[numPitchMarks];
for (i = 0; i < numPitchMarks; i++)
pitchMarks[i] = Math.min(i * maxT0, maxLen - 1);
float lastTime = SignalProcUtils.sample2time(pitchMarks[pitchMarks.length - 1], fs);
int numfrm = (int) Math.floor((lastTime - 0.5 * ws) / ss + 0.5);
f0s = new double[numfrm];
Arrays.fill(f0s, NoiseTester.FIXED_F0_NOISE);
}
} else {
System.arraycopy(n.signal, 0, signal, 0, n.signal.length);
if (n.pitchMarks != null) {
pitchMarks = ArrayUtils.copy(n.pitchMarks);
f0s = ArrayUtils.copy(n.f0s);
}
}
}
public static void main(String[] args) throws IOException {
int i, numSins, numNoises;
SinusoidsTester s = null;
NoiseTester n = null;
SinusoidsNoiseTester h = null;
// Sinus part
numSins = 5;
float[] sinFreqs = new float[numSins];
sinFreqs[0] = 120.0f;
sinFreqs[1] = 230.0f;
sinFreqs[2] = 500.0f;
sinFreqs[3] = 1100.0f;
sinFreqs[4] = 1500.0f;
Sinusoid[] sins = new Sinusoid[numSins];
for (i = 0; i < numSins; i++)
sins[i] = new Sinusoid(100.0f, sinFreqs[i], 0.0f);
s = new SinusoidsTester(sins);
//
// Noise part
numNoises = 1;
float[][] freqs = new float[numNoises][];
float[] amps = new float[numNoises];
for (i = 0; i < numNoises; i++)
freqs[i] = new float[2];
freqs[0][0] = 2000;
freqs[0][1] = 4000;
amps[0] = 100.0f;
n = new NoiseTester(freqs, amps);
//
h = new SinusoidsNoiseTester(s, n);
if (args.length > 1)
h.write(args[0], args[1]);
else
h.write(args[0]);
System.out.println(String.valueOf(MathUtils.getAbsMax(h.signal)) + " " + MathUtils.getAbsMax(s.signal) + " "
+ MathUtils.getAbsMax(n.signal));
int[] pitchMarks = FileUtils.readFromBinaryFile(args[1]);
for (i = 0; i < pitchMarks.length; i++)
System.out.println(String.valueOf(pitchMarks[i]) + " ");
}
}