/** * 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.util.math.MathUtils; import marytts.util.signal.SignalProcUtils; /** * Generates test signals that consist of artificially generated noise * * @author Oytun Türk */ public class NoiseTester extends BaseTester { public static final float DEFAULT_TRANSITION_BANDWIDTH_IN_HZ = 50.0f; public static final double FIXED_F0_NOISE = 100.0; public NoiseTester() { this(0.0f, 0.5f * DEFAULT_FS); } public NoiseTester(float freqStartInHz, float freqEndInHz) { this(freqStartInHz, freqEndInHz, DEFAULT_AMP); } public NoiseTester(float freqStartInHz, float freqEndInHz, float amp) { this(freqStartInHz, freqEndInHz, amp, DEFAULT_DUR); } public NoiseTester(float freqStartInHz, float freqEndInHz, float amp, float durationInSeconds) { this(freqStartInHz, freqEndInHz, amp, durationInSeconds, DEFAULT_FS); } public NoiseTester(float freqStartInHz, float freqEndInHz, float amp, float durationInSeconds, int samplingRateInHz) { float[][] freqs = new float[1][]; float[] amps = new float[1]; freqs[0] = new float[2]; freqs[0][0] = freqStartInHz; freqs[0][1] = freqEndInHz; amps[0] = amp; fs = samplingRateInHz; checkFreqs(freqs); init(freqs, amps, durationInSeconds, samplingRateInHz); } public NoiseTester(float[][] freqs) { init(freqs); } public NoiseTester(float[][] freqs, float durationInSeconds) { init(freqs, durationInSeconds); } public NoiseTester(float[][] freqs, float[] amps) { init(freqs, amps); } public NoiseTester(float[][] freqs, float[] amps, float durationInSeconds) { init(freqs, amps, durationInSeconds); } public NoiseTester(float[][] freqs, float[] amps, float startTimeInSeconds, float endTimeInSeconds) { this(freqs, amps, startTimeInSeconds, endTimeInSeconds, DEFAULT_FS); } public NoiseTester(float[][] freqs, float[] amps, float durationInSeconds, int samplingRateInHz) { init(freqs, amps, durationInSeconds, samplingRateInHz); } public NoiseTester(float[][] freqs, float[] amps, float startTimeInSeconds, float endTimeInSeconds, int samplingRateInHz) { float[] startTimesInSeconds = new float[freqs.length]; float[] endTimesInSeconds = new float[freqs.length]; Arrays.fill(startTimesInSeconds, startTimeInSeconds); Arrays.fill(endTimesInSeconds, endTimeInSeconds); init(freqs, amps, startTimesInSeconds, endTimesInSeconds, samplingRateInHz); } public NoiseTester(float[][] freqs, float[] amps, float[] startTimesInSeconds, float[] endTimesInSeconds, int samplingRateInHz) { init(freqs, amps, startTimesInSeconds, endTimesInSeconds, samplingRateInHz); } // Check if any of the freqs are greater than half sampling rate // or any left freq is greater than the right freq (these are simply swapped) // Note that only the first two entries for each frequency pair are considered public void checkFreqs(float[][] freqs) { if (freqs != null) { float maxFreq = 0.5f * fs; for (int i = 0; i < freqs.length; i++) { for (int j = 0; j < 2; j++) { if (freqs[i][j] < 0.0f) freqs[i][j] = 0.0f; if (freqs[i][j] > maxFreq) freqs[i][j] = maxFreq; } if (freqs[i][0] > freqs[i][1]) { float tmp = freqs[i][0]; freqs[i][0] = freqs[i][1]; freqs[i][1] = tmp; } } } } public void init(float[][] freqs) { float[] amps = new float[freqs.length]; for (int i = 0; i < amps.length; i++) amps[i] = DEFAULT_AMP; init(freqs, amps); } public void init(float[][] freqs, float durationInSeconds) { float[] amps = new float[freqs.length]; for (int i = 0; i < amps.length; i++) amps[i] = DEFAULT_AMP; init(freqs, amps, durationInSeconds); } public void init(float[][] freqs, float[] amps) { init(freqs, amps, DEFAULT_DUR); } public void init(float[][] freqs, float[] amps, float durationInSeconds) { init(freqs, amps, durationInSeconds, DEFAULT_FS); } public void init(float[][] freqs, float[] amps, float durationInSeconds, int samplingRateInHz) { if (freqs != null && freqs.length > 0) { float[] startTimesInSeconds = new float[freqs.length]; float[] endTimesInSeconds = new float[freqs.length]; for (int i = 0; i < freqs.length; i++) { startTimesInSeconds[i] = 0.0f; endTimesInSeconds[i] = durationInSeconds; } init(freqs, amps, startTimesInSeconds, endTimesInSeconds, samplingRateInHz); } } public void init(float[][] freqs, float[] amps, float[] startTimesInSeconds, float[] endTimesInSeconds, int samplingRateInHz) { fs = samplingRateInHz; signal = null; pitchMarks = null; int i, j; if (freqs != null && freqs.length > 0) { assert amps.length == freqs.length; assert startTimesInSeconds.length == freqs.length; assert startTimesInSeconds.length == endTimesInSeconds.length; for (i = 0; i < freqs.length; i++) assert freqs[i].length >= 2; int[] startSampleIndices = new int[freqs.length]; int[] endSampleIndices = new int[freqs.length]; for (i = 0; i < startTimesInSeconds.length; i++) { if (startTimesInSeconds[i] < 0.0f) startTimesInSeconds[i] = 0.0f; if (endTimesInSeconds[i] < 0.0f) endTimesInSeconds[i] = 0.0f; if (startTimesInSeconds[i] > endTimesInSeconds[i]) startTimesInSeconds[i] = endTimesInSeconds[i]; startSampleIndices[i] = (int) (Math.floor(startTimesInSeconds[i] * fs + 0.5)); endSampleIndices[i] = (int) (Math.floor(endTimesInSeconds[i] * fs + 0.5)) - 1; } // int minStartSampleIndex = MathUtils.getMin(startSampleIndices); int minStartSampleIndex = 0; // To ensure pitch marks being generated starting from 0th sample int maxEndSampleIndex = MathUtils.getMax(endSampleIndices); // Create pitch marks by finding the longest period int maxT0 = SignalProcUtils.time2sample(1.0 / FIXED_F0_NOISE, fs); int numPitchMarks = (int) (Math.floor(((double) (maxEndSampleIndex - minStartSampleIndex + 1)) / maxT0 + 0.5)) + 1; pitchMarks = new int[numPitchMarks]; for (i = 0; i < numPitchMarks; i++) pitchMarks[i] = Math.min(i * maxT0 + minStartSampleIndex, maxEndSampleIndex); // 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, FIXED_F0_NOISE); if (maxEndSampleIndex > 0) { signal = new double[maxEndSampleIndex + 1]; Arrays.fill(signal, 0.0); // Synthesize noise for (i = 0; i < freqs.length; i++) { double[] noise = SignalProcUtils.getNoise(freqs[i][0], freqs[i][1], DEFAULT_TRANSITION_BANDWIDTH_IN_HZ, fs, endSampleIndices[i] - startSampleIndices[i] + 1); for (j = startSampleIndices[i]; j < endSampleIndices[i]; j++) signal[j] += 2.0f * amps[i] * noise[j - startSampleIndices[i]]; } } } } public static void main(String[] args) throws IOException { int i, numTracks; float[] tStarts, tEnds; NoiseTester t = null; numTracks = 1; float[][] freqs = new float[numTracks][]; for (i = 0; i < numTracks; i++) freqs[i] = new float[2]; freqs[0][0] = 2000; freqs[0][1] = 4000; float durationInSeconds = 1.0f; t = new NoiseTester(freqs, durationInSeconds); if (args.length > 1) t.write(args[0], args[1]); else t.write(args[0]); } }