/** * 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; import java.io.File; import java.io.IOException; import javax.sound.sampled.AudioFileFormat; import javax.sound.sampled.AudioInputStream; import javax.sound.sampled.AudioSystem; import javax.sound.sampled.UnsupportedAudioFileException; import marytts.signalproc.analysis.PitchMarks; import marytts.signalproc.analysis.PitchReaderWriter; import marytts.signalproc.filter.FIRWaveletFilterBankAnalyser; import marytts.signalproc.filter.FIRWaveletFilterBankSynthesiser; import marytts.signalproc.filter.FilterBankAnalyserBase; import marytts.signalproc.filter.Subband; import marytts.signalproc.window.Window; import marytts.util.data.BufferedDoubleDataSource; import marytts.util.data.audio.AudioDoubleDataSource; import marytts.util.data.audio.DDSAudioInputStream; import marytts.util.math.MathUtils; import marytts.util.signal.SignalProcUtils; /** * A basic multi-resolution version of the sinusoidal synthesizer. This class has not been tested sufficiently and the subband * reconstruction procedure does not seem to be appropriate for this kind of synthesis. * * @author Oytun Türk * */ public class MultiresolutionSinusoidalSynthesizer { public MultiresolutionSinusoidalAnalyzer analyser; public MultiresolutionSinusoidalSynthesizer(MultiresolutionSinusoidalAnalyzer analyserIn) { analyser = analyserIn; } public double[] synthesize(SinusoidalTracks[] subbandTracks, boolean isSilentSynthesis) { double[] y = null; double[] tmpy = null; if (subbandTracks != null) { int i, j; // Sinusoidal resynthesis if (analyser.multiresolutionFilterbankType == FilterBankAnalyserBase.FIR_WAVELET_FILTERBANK) { Subband[] subbands = new Subband[subbandTracks.length]; for (i = 0; i < subbandTracks.length; i++) { PeakMatchedSinusoidalSynthesizer ss = new PeakMatchedSinusoidalSynthesizer(subbandTracks[i].fs); tmpy = ss.synthesize(subbandTracks[i], isSilentSynthesis); subbands[i] = new Subband(tmpy, subbandTracks[i].fs); } FIRWaveletFilterBankSynthesiser filterbankSynthesiser = new FIRWaveletFilterBankSynthesiser(); y = filterbankSynthesiser.apply((FIRWaveletFilterBankAnalyser) (analyser.filterbankAnalyser), subbands, false); } else { for (i = 0; i < subbandTracks.length; i++) { PeakMatchedSinusoidalSynthesizer ss = new PeakMatchedSinusoidalSynthesizer(subbandTracks[i].fs); tmpy = ss.synthesize(subbandTracks[i], isSilentSynthesis); if (i == 0) { y = new double[tmpy.length]; System.arraycopy(tmpy, 0, y, 0, tmpy.length); } else { for (j = 0; j < Math.min(y.length, tmpy.length); j++) y[j] += tmpy[j]; } } } } return y; } public static void main(String[] args) throws UnsupportedAudioFileException, IOException { AudioInputStream inputAudio = AudioSystem.getAudioInputStream(new File(args[0])); int samplingRate = (int) inputAudio.getFormat().getSampleRate(); AudioDoubleDataSource signal = new AudioDoubleDataSource(inputAudio); double[] x = signal.getAllData(); int multiresolutionFilterbankType; // multiresolutionFilterbankType = FilterBankAnalyserBase.FIR_BANDPASS_FILTERBANK; multiresolutionFilterbankType = FilterBankAnalyserBase.FIR_WAVELET_FILTERBANK; // multiresolutionFilterbankType = FilterBankAnalyserBase.COMPLEMENTARY_FILTERBANK; int numBands = 2; double lowestBandWindowSizeInSeconds = 0.020; double startFreqInHz = 0.0; double endFreqInHz = 0.5 * samplingRate; int windowType = Window.HANNING; boolean bRefinePeakEstimatesParabola = false; boolean bRefinePeakEstimatesBias = false; boolean bSpectralReassignment = false; boolean bAdjustNeighFreqDependent = false; boolean isSilentSynthesis = false; boolean bFreqLimitedAnalysis = false; // Only used for FIR_BANDPASS_FILTERBANK boolean bPitchSynchronous = false; float numPeriods = 2.5f; SinusoidalAnalysisParams params = new SinusoidalAnalysisParams(samplingRate, startFreqInHz, endFreqInHz, windowType, bRefinePeakEstimatesParabola, bRefinePeakEstimatesBias, bSpectralReassignment, bAdjustNeighFreqDependent); MultiresolutionSinusoidalAnalyzer msa = new MultiresolutionSinusoidalAnalyzer(multiresolutionFilterbankType, numBands, samplingRate); SinusoidalTracks[] subbandTracks = null; if (!bPitchSynchronous) subbandTracks = msa.analyze(x, lowestBandWindowSizeInSeconds, windowType, bRefinePeakEstimatesParabola, bRefinePeakEstimatesBias, bSpectralReassignment, bAdjustNeighFreqDependent, bFreqLimitedAnalysis); else { String strPitchFile = args[0].substring(0, args[0].length() - 4) + ".ptc"; PitchReaderWriter f0 = new PitchReaderWriter(strPitchFile); int pitchMarkOffset = 0; PitchMarks pm = SignalProcUtils.pitchContour2pitchMarks(f0.contour, samplingRate, x.length, f0.header.windowSizeInSeconds, f0.header.skipSizeInSeconds, true, pitchMarkOffset); PitchSynchronousSinusoidalAnalyzer sa = new PitchSynchronousSinusoidalAnalyzer(params); subbandTracks = msa.analyze(x, lowestBandWindowSizeInSeconds, windowType, bRefinePeakEstimatesParabola, bRefinePeakEstimatesBias, bSpectralReassignment, bAdjustNeighFreqDependent, bFreqLimitedAnalysis, true, pm, numPeriods); } // Resynthesis MultiresolutionSinusoidalSynthesizer mss = new MultiresolutionSinusoidalSynthesizer(msa); x = mss.synthesize(subbandTracks, isSilentSynthesis); // // This scaling is only for comparison among different parameter sets, different synthesizer outputs etc double maxx = MathUtils.getAbsMax(x); for (int i = 0; i < x.length; i++) x[i] = x[i] / maxx * 0.9; // // File output DDSAudioInputStream outputAudio = new DDSAudioInputStream(new BufferedDoubleDataSource(x), inputAudio.getFormat()); String outFileName = args[0].substring(0, args[0].length() - 4) + "_multiResWaveletFixedRate.wav"; AudioSystem.write(outputAudio, AudioFileFormat.Type.WAVE, new File(outFileName)); // } }