/** * 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.math.MathUtils; import marytts.util.signal.SignalProcUtils; /** * This class can be used to generate various sinusoid signals and writing them to wav and ptc files to be used in testing the * analysis/synthesis algorithms * * @author Oytun Türk */ public class SinusoidsTester extends BaseTester { public static float DEFAULT_PHASE = 0.0f; public static int DEFAULT_FRAME_INDEX = 0; public SinusoidsTester() { } public SinusoidsTester(float freqInHz) { this(freqInHz, DEFAULT_AMP); } public SinusoidsTester(float freqInHz, float amp) { this(freqInHz, amp, DEFAULT_PHASE); } public SinusoidsTester(float freqInHz, float amp, float phaseInDegrees) { this(freqInHz, amp, phaseInDegrees, DEFAULT_FRAME_INDEX); } public SinusoidsTester(float freqInHz, float amp, float phaseInDegrees, int frameIndex) { this(freqInHz, amp, phaseInDegrees, frameIndex, DEFAULT_DUR); } public SinusoidsTester(float freqInHz, float amp, float phaseInDegrees, int frameIndex, float durationInSeconds) { this(freqInHz, amp, phaseInDegrees, frameIndex, durationInSeconds, DEFAULT_FS); } public SinusoidsTester(Sinusoid sin) { this(sin, DEFAULT_DUR); } public SinusoidsTester(Sinusoid sin, float durationInSeconds) { this(sin, durationInSeconds, DEFAULT_FS); } public SinusoidsTester(float freqInHz, float amp, float phaseInDegrees, int frameIndex, float durationInSeconds, int samplingRateInHz) { super(); Sinusoid[] tmpSins = new Sinusoid[1]; tmpSins[0] = new Sinusoid(amp, freqInHz, phaseInDegrees, frameIndex); init(tmpSins, durationInSeconds, samplingRateInHz); } public SinusoidsTester(Sinusoid sin, float durationInSeconds, int samplingRateInHz) { super(); Sinusoid[] tmpSins = new Sinusoid[1]; tmpSins[0] = new Sinusoid(sin); init(tmpSins, durationInSeconds, samplingRateInHz); } public SinusoidsTester(Sinusoid[] sinsIn) { this(sinsIn, DEFAULT_DUR); } public SinusoidsTester(Sinusoid[] sinsIn, float durationInSeconds) { this(sinsIn, durationInSeconds, DEFAULT_FS); } public SinusoidsTester(Sinusoid[] sinsIn, float durationInSeconds, int samplingRateInHz) { super(); init(sinsIn, durationInSeconds, samplingRateInHz); } // These constructors can be used to create tracks starting and terminating at desired time instants public SinusoidsTester(Sinusoid[] sinsIn, float[] startTimesInSeconds, float[] endTimesInSeconds) { this(sinsIn, startTimesInSeconds, endTimesInSeconds, DEFAULT_FS); } public SinusoidsTester(Sinusoid[] sinsIn, float[] startTimesInSeconds, float[] endTimesInSeconds, int samplingRateInHz) { super(); init(sinsIn, startTimesInSeconds, endTimesInSeconds, samplingRateInHz); } // public void init(Sinusoid[] sinsIn, float durationInSeconds, int samplingRateInHz) { if (sinsIn.length > 0) { float[] startTimesInSeconds = new float[sinsIn.length]; float[] endTimesInSeconds = new float[sinsIn.length]; for (int i = 0; i < sinsIn.length; i++) { startTimesInSeconds[i] = 0.0f; endTimesInSeconds[i] = durationInSeconds; } init(sinsIn, startTimesInSeconds, endTimesInSeconds, samplingRateInHz); } } public void init(Sinusoid[] sinsIn, float startTimeInSeconds, float endTimeInSeconds, int samplingRateInHz) { float[] startTimesInSeconds = new float[sinsIn.length]; float[] endTimesInSeconds = new float[sinsIn.length]; Arrays.fill(startTimesInSeconds, startTimeInSeconds); Arrays.fill(endTimesInSeconds, endTimeInSeconds); init(sinsIn, startTimesInSeconds, endTimesInSeconds, samplingRateInHz); } public void init(Sinusoid[] sinsIn, float[] startTimesInSeconds, float[] endTimesInSeconds, int samplingRateInHz) { fs = samplingRateInHz; signal = null; pitchMarks = null; int i, j; if (sinsIn != null) { assert startTimesInSeconds.length == endTimesInSeconds.length; assert sinsIn.length == endTimesInSeconds.length; float minFreq = 2 * fs; int minFreqInd = -1; for (i = 0; i < sinsIn.length; i++) { if (sinsIn[i].freq > 0.0f && sinsIn[i].freq < minFreq) { minFreq = sinsIn[i].freq; minFreqInd = i; } } int[] startSampleIndices = new int[sinsIn.length]; int[] endSampleIndices = new int[sinsIn.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; if (minFreqInd >= 0) maxT0 = (int) (Math.floor(fs / minFreq + 0.5)); else // No non-zero Hz sinusoids found, therefore set maxT0 to a fixed number maxT0 = (int) Math.floor(0.010f * fs + 0.5); 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, minFreq); if (maxEndSampleIndex > 0) { signal = new double[maxEndSampleIndex + 1]; Arrays.fill(signal, 0.0); // Synthesize sinusoids for (i = 0; i < sinsIn.length; i++) { for (j = startSampleIndices[i]; j < endSampleIndices[i]; j++) signal[j] += sinsIn[i].amp * Math.sin(MathUtils.TWOPI * ((j - startSampleIndices[i]) * (sinsIn[i].freq / fs) + sinsIn[i].phase / 360.0)); } } } } public static void main(String[] args) throws IOException { int i, numSins; float[] tStarts, tEnds; SinusoidsTester s = null; // Single sinusoid, time-invariant s = new SinusoidsTester(200.0f); // // Several sinusoids, time-invariant numSins = 1; Sinusoid[] sins = new Sinusoid[numSins]; tStarts = new float[numSins]; tEnds = new float[numSins]; sins[0] = new Sinusoid(100.0f, 400.0f, 0.0f); tStarts[0] = 0.0f; tEnds[0] = 1.5f; // sins[1] = new Sinusoid(25.0f, 211.0f, 0.0f); tStarts[1] = 0.0f; tEnds[1] = 1.5f; // sins[2] = new Sinusoid(125.0f, 555.0f, 0.0f); tStarts[2] = 0.0f; tEnds[2] = 1.5f; // sins[3] = new Sinusoid(110.0f, 917.0f, 0.0f); tStarts[3] = 0.0f; tEnds[3] = 1.5f; // sins[4] = new Sinusoid(100.0f, 175.0f, 0.0f); tStarts[4] = 1.3f; tEnds[4] = 2.5f; // sins[5] = new Sinusoid(25.0f, 346.0f, 0.0f); tStarts[5] = 1.3f; tEnds[5] = 2.5f; // sins[6] = new Sinusoid(125.0f, 981.0f, 0.0f); tStarts[6] = 2.0f; tEnds[6] = 3.0f; // sins[7] = new Sinusoid(70.0f, 1317.0f, 0.0f); tStarts[7] = 2.0f; tEnds[7] = 3.5f; s = new SinusoidsTester(sins, tStarts, tEnds); // /* * //Sinus part numSins = 10; float [] sinFreqs = new float[numSins]; sinFreqs[0] = 180.0f; sinFreqs[1] = 380.0f; * sinFreqs[2] = 580.0f; sinFreqs[3] = 780.0f; * * Sinusoid [] sins = new Sinusoid[numSins]; for (i=0; i<numSins; i++) sins[i] = new Sinusoid(100.0f, i*300+100, 0.0f); * * s = new SinusoidsTester(sins); // */ /* * //Fixed sinusoidal track with a gap numSins = 4; Sinusoid [] sins = new Sinusoid[numSins]; tStarts = new * float[numSins]; tEnds = new float[numSins]; * * sins[0] = new Sinusoid(0.0f, 0.0f, 0.0f); tStarts[0] = 0.0f; tEnds[0] = 0.1f; sins[1] = new Sinusoid(100.0f, 200.0f, * 0.0f); tStarts[1] = 0.1f; tEnds[1] = 0.2f; sins[2] = new Sinusoid(100.0f, 300.0f, 0.0f); tStarts[2] = 0.3f; tEnds[2] = * 0.4f; sins[3] = new Sinusoid(0.0f, 0.0f, 0.0f); tStarts[3] = 0.4f; tEnds[3] = 0.5f; s = new SinusoidsTester(sins, * tStarts, tEnds); // */ if (args.length > 1) s.write(args[0], args[1]); else s.write(args[0]); } }