CLAM-Development
1.1
|
00001 /* 00002 * Copyright (c) 2001-2004 MUSIC TECHNOLOGY GROUP (MTG) 00003 * UNIVERSITAT POMPEU FABRA 00004 * 00005 * 00006 * This program is free software; you can redistribute it and/or modify 00007 * it under the terms of the GNU General Public License as published by 00008 * the Free Software Foundation; either version 2 of the License, or 00009 * (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this program; if not, write to the Free Software 00018 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00019 * 00020 */ 00021 00022 #include "SpectrumConfig.hxx" 00023 #include "SMSSynthesis.hxx" 00024 #include "ProcessingFactory.hxx" 00025 00026 00027 00028 namespace CLAM 00029 { 00030 00031 namespace Hidden 00032 { 00033 static const char * metadata[] = { 00034 "key", "SMSSynthesis", 00035 "category", "Synthesis", 00036 "description", "SMSSynthesis", 00037 0 00038 }; 00039 static FactoryRegistrator<ProcessingFactory, SMSSynthesis> reg = metadata; 00040 } 00041 00042 00043 void SMSSynthesis::AttachChildren() 00044 { 00045 mSpectralSynthesis.SetParent(this); 00046 mResSpectralSynthesis.SetParent(this); 00047 mSinSpectralSynthesis.SetParent(this); 00048 mSynthSineSpectrum.SetParent(this); 00049 mPhaseMan.SetParent(this); 00050 mSpectrumAdder.SetParent(this); 00051 mOverlapAddSin.SetParent(this); 00052 mOverlapAddRes.SetParent(this); 00053 mOverlapAddGlobal.SetParent(this); 00054 } 00055 00056 SMSSynthesis::SMSSynthesis(): 00057 mInputSinSpectralPeaks("InputSinPeaks",this), 00058 mInputResSpectrum("InputResSpectrum",this), 00059 mOutputSinSpectrum("OutputSinSpectrum",this), 00060 mOutputSpectrum("OutputSpectrum",this), 00061 mOutputAudio("OutputAudio",this), 00062 mOutputResAudio("OutputResAudio",this), 00063 mOutputSinAudio("OutputSinAudio",this), 00064 mCurrentTimeControl("CurrentTime",this), 00065 mCurrentPitch("CurrentPitch",this) 00066 { 00067 mCurrentFrame = 0; 00068 Configure(SMSSynthesisConfig()); 00069 AttachChildren(); 00070 } 00071 00072 SMSSynthesis::SMSSynthesis(const SMSSynthesisConfig& cfg): 00073 mInputSinSpectralPeaks("InputSinPeaks",this), 00074 mInputResSpectrum("InputResSpectrum",this), 00075 mOutputSinSpectrum("OutputSinSpectrum",this), 00076 mOutputSpectrum("OutputSpectrum",this), 00077 mOutputAudio("OutputAudio",this), 00078 mOutputResAudio("OutputResAudio",this), 00079 mOutputSinAudio("OutputSinAudio",this), 00080 mCurrentTimeControl("CurrentTime",this), 00081 mCurrentPitch("CurrentPitch",this) 00082 { 00083 mCurrentFrame = 0; 00084 Configure(cfg); 00085 AttachChildren(); 00086 } 00087 00088 SMSSynthesis::~SMSSynthesis() 00089 { 00090 00091 } 00092 00093 bool SMSSynthesis::ConfigureChildren() 00094 { 00095 // mConfig.SetSpectrumSize( mAudioFrame.GetSize()/2+1 ); 00096 00097 //configure global spectral synthesis 00098 if(!mSpectralSynthesis.Configure(mConfig.GetSpectralSynth())) 00099 return false; 00100 00101 //configure residual spectral synthesis 00102 mConfig.GetSpectralSynth().SetResidual(true); 00103 if(!mResSpectralSynthesis.Configure(mConfig.GetSpectralSynth())) 00104 return false; 00105 00106 //configure sinusoidal spectral synthesis 00107 mConfig.GetSpectralSynth().SetResidual(false); 00108 if(!mSinSpectralSynthesis.Configure(mConfig.GetSpectralSynth())) 00109 return false; 00110 00111 //SynthSineSpectrum 00112 if(!mSynthSineSpectrum.Configure(mConfig.GetSynthSineSpectrum())) 00113 return false; 00114 00115 //Phase Management 00116 if(!mPhaseMan.Configure(mConfig.GetPhaseMan())) 00117 return false; 00118 00119 mPhaseMan.Init(); 00120 00121 //Spectrum Adder 00122 if(!mSpectrumAdder.Configure(SpecAdder2Config())) 00123 return false; 00124 00125 //Overlap and add PO 00126 if(!mOverlapAddSin.Configure(mConfig.GetOverlapAddSin())) 00127 return false; 00128 if(!mOverlapAddRes.Configure(mConfig.GetOverlapAddRes())) 00129 return false; 00130 if(!mOverlapAddGlobal.Configure(mConfig.GetOverlapAddGlobal())) 00131 return false; 00132 00133 return true; 00134 } 00135 00136 void SMSSynthesis::ConfigureData() 00137 { 00138 mAudioFrame.SetSize(mConfig.GetHopSize()*2);//audio used as input of the overlap and add 00139 mOutputAudio.SetSize( mAudioFrame.GetSize()/2 ); 00140 mOutputSinAudio.SetSize( mAudioFrame.GetSize()/2 ); 00141 mOutputResAudio.SetSize( mAudioFrame.GetSize()/2 ); 00142 00143 mOutputAudio.SetHop( mConfig.GetHopSize() ); 00144 mOutputSinAudio.SetHop( mConfig.GetHopSize() ); 00145 mOutputResAudio.SetHop( mConfig.GetHopSize() ); 00146 00147 mOutputSpectrum.GetData().SetSize( mAudioFrame.GetSize()/2+1); 00148 mOutputSinSpectrum.GetData().SetSize( mAudioFrame.GetSize()/2+1); 00149 } 00150 00151 00152 bool SMSSynthesis::ConcreteConfigure(const ProcessingConfig& c) 00153 { 00154 CopyAsConcreteConfig(mConfig, c); 00155 ConfigureChildren(); 00156 ConfigureData(); 00157 mCurrentTimeControl.DoControl(-1.0); 00158 return true; 00159 } 00160 00161 bool SMSSynthesis::SinusoidalSynthesis(const SpectralPeakArray& in,Audio& out) 00162 { 00163 SpectrumConfig tmpcfg; 00164 tmpcfg.SetScale(EScale::eLinear); 00165 Spectrum tmpSpec(tmpcfg); 00166 return SinusoidalSynthesis(in,tmpSpec,out); 00167 00168 } 00169 00171 bool SMSSynthesis::SinusoidalSynthesis(const SpectralPeakArray& in,Spectrum& outSpec,Audio& outAudio) 00172 { 00173 // outSpec.SetSize(mConfig.GetSpectrumSize()); 00174 mSynthSineSpectrum.Do(in,outSpec); 00175 00176 mSinSpectralSynthesis.Do(outSpec,mAudioFrame); 00177 //Finally the overlap and add is accomplished 00178 00179 return mOverlapAddSin.Do(mAudioFrame, outAudio); 00180 00181 } 00182 00183 00184 bool SMSSynthesis::Do(void) 00185 { 00186 bool result; 00187 if (mOutputSinAudio.HasConnections() || mOutputResAudio.HasConnections()) 00188 { 00189 result = Do(mInputSinSpectralPeaks.GetData(),mInputResSpectrum.GetData(), 00190 mOutputSinSpectrum.GetData(),mOutputSpectrum.GetData(), 00191 mOutputAudio.GetAudio(),mOutputSinAudio.GetAudio(),mOutputResAudio.GetAudio()); 00192 } 00193 else 00194 { 00195 result = Do(mInputSinSpectralPeaks.GetData(),mInputResSpectrum.GetData(), 00196 mOutputSinSpectrum.GetData(),mOutputSpectrum.GetData(), 00197 mOutputAudio.GetAudio()); 00198 } 00199 00200 mInputSinSpectralPeaks.Consume(); 00201 mInputResSpectrum.Consume(); 00202 00203 mOutputSinSpectrum.Produce(); 00204 mOutputSpectrum.Produce(); 00205 mOutputAudio.Produce(); 00206 mOutputSinAudio.Produce(); 00207 mOutputResAudio.Produce(); 00208 00209 return result; 00210 } 00211 00212 00213 bool SMSSynthesis::Do( 00214 SpectralPeakArray& inputSinusoidalPeaks, 00215 Spectrum& inputResidualSpectrum, 00216 Audio& outputAudio, 00217 Audio& outputSinusoidalAudio, 00218 Audio& outputResidualAudio) 00219 { 00220 Spectrum tmpOutputSinSpec; 00221 Spectrum tmpOutputSpec; 00222 // init its size since we'll operate with these spectrums 00223 tmpOutputSinSpec.SetSize( inputResidualSpectrum.GetSize() ); 00224 tmpOutputSinSpec.SetSize( inputResidualSpectrum.GetSize() ); 00225 00226 return Do(inputSinusoidalPeaks,inputResidualSpectrum,tmpOutputSinSpec,tmpOutputSpec, 00227 outputAudio,outputSinusoidalAudio,outputResidualAudio); 00228 00229 } 00230 00231 bool SMSSynthesis::Do( 00232 SpectralPeakArray& inputSinusoidalPeaks, 00233 Spectrum& inputResidualSpectrum, 00234 Spectrum& outputSinusoidalSpectrum, // 00235 Spectrum& outputSpectrum, // 00236 Audio& outputAudio, 00237 Audio& outputSinusoidalAudio, 00238 Audio& outputResidualAudio) 00239 { 00240 //First we do the phase managing. Note that if the Do(frame) overload is not used, 00241 //the time and pitch controls in this processing should be set by hand before this 00242 //method is used 00243 00244 00245 // mPhaseMan.mCurrentTime.DoControl(mCurrentTimeControl.GetLastValue()); //TODO used in SMSBase (Synth from segment) 00246 TData currentTime = 0; 00247 if (mCurrentTimeControl.GetLastValue() < -0.9) 00248 { 00249 int framesize = outputAudio.GetSize(); 00250 TData samplerate = inputResidualSpectrum.GetSpectralRange()*2; 00251 currentTime = TData( mCurrentFrame*framesize ) / samplerate; 00252 } 00253 else 00254 { 00255 currentTime = mCurrentTimeControl.GetLastValue(); 00256 } 00257 mPhaseMan.mCurrentTime.DoControl( currentTime ); 00258 mCurrentFrame ++; 00259 00260 mPhaseMan.mCurrentPitch.DoControl(mCurrentPitch.GetLastValue()); 00261 mPhaseMan.Do(inputSinusoidalPeaks); 00262 00263 //We synthesize the sinusoidal component 00264 SinusoidalSynthesis(inputSinusoidalPeaks,outputSinusoidalSpectrum,outputSinusoidalAudio); 00265 00266 outputSpectrum.SetSize( inputResidualSpectrum.GetSize() ); 00267 00268 00269 //We add Residual spectrum in the input frame plus the synthesized sinusoidal spectrum 00270 mSpectrumAdder.Do(outputSinusoidalSpectrum, inputResidualSpectrum, outputSpectrum); 00271 00272 //We synthesize to audio the resulting summed spectrum 00273 mSpectralSynthesis.Do(outputSpectrum,mAudioFrame); 00274 00275 00276 //We do the overlap and add 00277 mOverlapAddGlobal.Do(mAudioFrame, outputAudio); 00278 00279 //Now we synthesize only the residual spectrum 00280 mResSpectralSynthesis.Do(inputResidualSpectrum,mAudioFrame); 00281 //And we do the overlap and add process for the residual 00282 00283 mOverlapAddRes.Do(mAudioFrame, outputResidualAudio); 00284 00285 /* Note: although sinusoidal spectrum is already available from the analysis phase, we 00286 need to store it again in the frame because the original peak array may have been 00287 transformed 00288 */ 00289 return true; 00290 } 00291 00292 bool SMSSynthesis::Do( 00293 SpectralPeakArray& inputSinusoidalPeaks, 00294 Spectrum& inputResidualSpectrum, 00295 Spectrum& outputSinusoidalSpectrum, // 00296 Spectrum& outputSpectrum, // 00297 Audio& outputAudio) 00298 { 00299 //First we do the phase managing. Note that if the Do(frame) overload is not used, 00300 //the time and pitch controls in this processing should be set by hand before this 00301 //method is used 00302 00303 // mPhaseMan.mCurrentTime.DoControl(mCurrentTimeControl.GetLastValue()); //TODO used in SMSBase (Synth from segment) 00304 TData currentTime = 0; 00305 if (mCurrentTimeControl.GetLastValue() < -0.9) 00306 { 00307 int framesize = outputAudio.GetSize(); 00308 TData samplerate = inputResidualSpectrum.GetSpectralRange()*2; 00309 currentTime = TData( mCurrentFrame*framesize ) / samplerate; 00310 } 00311 else 00312 { 00313 currentTime = mCurrentTimeControl.GetLastValue(); 00314 } 00315 mPhaseMan.mCurrentTime.DoControl( currentTime ); 00316 mCurrentFrame ++; 00317 00318 mPhaseMan.mCurrentPitch.DoControl(mCurrentPitch.GetLastValue()); 00319 mPhaseMan.Do(inputSinusoidalPeaks); 00320 00321 // We create a spectrum from the sinusoidal peaks 00322 outputSinusoidalSpectrum.SetSize(mConfig.GetSpectrumSize()); 00323 mSynthSineSpectrum.Do(inputSinusoidalPeaks,outputSinusoidalSpectrum); 00324 00325 outputSpectrum.SetSize( inputResidualSpectrum.GetSize() ); 00326 00327 //We add Residual spectrum in the input frame plus the synthesized sinusoidal spectrum 00328 mSpectrumAdder.Do(outputSinusoidalSpectrum, inputResidualSpectrum, outputSpectrum); 00329 00330 //We synthesize to audio the resulting summed spectrum 00331 mSpectralSynthesis.Do(outputSpectrum,mAudioFrame); 00332 00333 00334 //We do the overlap and add 00335 mOverlapAddGlobal.Do(mAudioFrame, outputAudio); 00336 00337 /* Note: although sinusoidal spectrum is already available from the analysis phase, we 00338 need to store it again in the frame because the original peak array may have been 00339 transformed 00340 */ 00341 return true; 00342 } 00343 00344 bool SMSSynthesis::Do(Frame& in) 00345 { 00346 bool isSynthesizeSinusoidsAndResidual = true; 00347 return Do(in, isSynthesizeSinusoidsAndResidual); 00348 } 00349 00350 bool SMSSynthesis::Do(Frame& in, bool isSynthesizeSinusoidsAndResidual) 00351 { 00352 if(in.GetCenterTime()<0) return false;//such frames should not be synthesized 00353 00354 //We initialize input frame, adding necessary attributes 00355 InitFrame(in); 00356 //First we set the controls sa mCurrentTimeControl.DoControl(in.GetCenterTime()); 00357 mCurrentPitch.DoControl(in.GetFundamental().GetFreq(0)); 00358 00359 00360 //We make sure that spectrums in input frame has the appropiate size and spectral range. 00361 //Note that the only spectrum we can be sure has the correct spectral range is the residual 00362 //because it its the only one that has been stored in the analysis process. 00363 in.GetOutSpec().SetSize(mConfig.GetSpectrumSize()); 00364 in.GetOutSpec().SetSpectralRange(in.GetResidualSpec().GetSpectralRange()); 00365 in.GetSinusoidalSpec().SetSpectralRange(in.GetResidualSpec().GetSpectralRange()); 00366 00367 if ( isSynthesizeSinusoidsAndResidual ) 00368 { 00369 return Do(in.GetSpectralPeakArray(),in.GetResidualSpec(),in.GetSinusoidalSpec(),in.GetOutSpec(), 00370 in.GetSynthAudioFrame(),in.GetSinusoidalAudioFrame(),in.GetResidualAudioFrame()); 00371 } 00372 else 00373 { 00374 return Do(in.GetSpectralPeakArray(),in.GetResidualSpec(),in.GetSinusoidalSpec(),in.GetOutSpec(), 00375 in.GetSynthAudioFrame()); 00376 } 00377 } 00378 00379 bool SMSSynthesis::Do(Segment& in) 00380 { 00381 return Do(in.GetFrame(in.mCurrentFrameIndex++)); 00382 } 00383 00384 00385 void SMSSynthesis::InitFrame(Frame& in) 00386 { 00387 in.AddOutSpec(); 00388 in.AddSinusoidalSpec(); 00389 in.AddSinusoidalAudioFrame(); 00390 in.AddResidualAudioFrame(); 00391 in.AddSynthAudioFrame(); 00392 in.UpdateData(); 00393 00394 in.GetSinusoidalAudioFrame().SetSize(mConfig.GetFrameSize()); 00395 in.GetResidualAudioFrame().SetSize(mConfig.GetFrameSize()); 00396 in.GetSynthAudioFrame().SetSize(mConfig.GetFrameSize()); 00397 00398 } 00399 00400 } // namespace CLAM 00401