|
CLAM-Development
1.3
|
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(const SMSSynthesisConfig& cfg) 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(cfg); 00069 AttachChildren(); 00070 } 00071 00072 SMSSynthesis::~SMSSynthesis() 00073 { 00074 00075 } 00076 00077 bool SMSSynthesis::ConfigureChildren() 00078 { 00079 // mConfig.SetSpectrumSize( mAudioFrame.GetSize()/2+1 ); 00080 00081 //configure global spectral synthesis 00082 if(!mSpectralSynthesis.Configure(mConfig.GetSpectralSynth())) 00083 return false; 00084 00085 //configure residual spectral synthesis 00086 mConfig.GetSpectralSynth().SetResidual(true); 00087 if(!mResSpectralSynthesis.Configure(mConfig.GetSpectralSynth())) 00088 return false; 00089 00090 //configure sinusoidal spectral synthesis 00091 mConfig.GetSpectralSynth().SetResidual(false); 00092 if(!mSinSpectralSynthesis.Configure(mConfig.GetSpectralSynth())) 00093 return false; 00094 00095 //SynthSineSpectrum 00096 if(!mSynthSineSpectrum.Configure(mConfig.GetSynthSineSpectrum())) 00097 return false; 00098 00099 //Phase Management 00100 if(!mPhaseMan.Configure(mConfig.GetPhaseMan())) 00101 return false; 00102 00103 mPhaseMan.Init(); 00104 00105 //Spectrum Adder 00106 if(!mSpectrumAdder.Configure(SpecAdder2Config())) 00107 return false; 00108 00109 //Overlap and add PO 00110 if(!mOverlapAddSin.Configure(mConfig.GetOverlapAddSin())) 00111 return false; 00112 if(!mOverlapAddRes.Configure(mConfig.GetOverlapAddRes())) 00113 return false; 00114 if(!mOverlapAddGlobal.Configure(mConfig.GetOverlapAddGlobal())) 00115 return false; 00116 00117 return true; 00118 } 00119 00120 void SMSSynthesis::ConfigureData() 00121 { 00122 mAudioFrame.SetSize(mConfig.GetHopSize()*2);//audio used as input of the overlap and add 00123 mOutputAudio.SetSize( mAudioFrame.GetSize()/2 ); 00124 mOutputSinAudio.SetSize( mAudioFrame.GetSize()/2 ); 00125 mOutputResAudio.SetSize( mAudioFrame.GetSize()/2 ); 00126 00127 mOutputAudio.SetHop( mConfig.GetHopSize() ); 00128 mOutputSinAudio.SetHop( mConfig.GetHopSize() ); 00129 mOutputResAudio.SetHop( mConfig.GetHopSize() ); 00130 00131 mOutputSpectrum.GetData().SetSize( mAudioFrame.GetSize()/2+1); 00132 mOutputSinSpectrum.GetData().SetSize( mAudioFrame.GetSize()/2+1); 00133 } 00134 00135 00136 bool SMSSynthesis::ConcreteConfigure(const ProcessingConfig& c) 00137 { 00138 CopyAsConcreteConfig(mConfig, c); 00139 ConfigureChildren(); 00140 ConfigureData(); 00141 mCurrentTimeControl.DoControl(-1.0); 00142 return true; 00143 } 00144 00145 bool SMSSynthesis::SinusoidalSynthesis(const SpectralPeakArray& in,Audio& out) 00146 { 00147 SpectrumConfig tmpcfg; 00148 tmpcfg.SetScale(EScale::eLinear); 00149 Spectrum tmpSpec(tmpcfg); 00150 return SinusoidalSynthesis(in,tmpSpec,out); 00151 00152 } 00153 00155 bool SMSSynthesis::SinusoidalSynthesis(const SpectralPeakArray& in,Spectrum& outSpec,Audio& outAudio) 00156 { 00157 // outSpec.SetSize(mConfig.GetSpectrumSize()); 00158 mSynthSineSpectrum.Do(in,outSpec); 00159 00160 mSinSpectralSynthesis.Do(outSpec,mAudioFrame); 00161 //Finally the overlap and add is accomplished 00162 00163 return mOverlapAddSin.Do(mAudioFrame, outAudio); 00164 00165 } 00166 00167 00168 bool SMSSynthesis::Do(void) 00169 { 00170 bool result; 00171 if (mOutputSinAudio.HasConnections() || mOutputResAudio.HasConnections()) 00172 { 00173 result = Do(mInputSinSpectralPeaks.GetData(),mInputResSpectrum.GetData(), 00174 mOutputSinSpectrum.GetData(),mOutputSpectrum.GetData(), 00175 mOutputAudio.GetAudio(),mOutputSinAudio.GetAudio(),mOutputResAudio.GetAudio()); 00176 } 00177 else 00178 { 00179 result = Do(mInputSinSpectralPeaks.GetData(),mInputResSpectrum.GetData(), 00180 mOutputSinSpectrum.GetData(),mOutputSpectrum.GetData(), 00181 mOutputAudio.GetAudio()); 00182 } 00183 00184 mInputSinSpectralPeaks.Consume(); 00185 mInputResSpectrum.Consume(); 00186 00187 mOutputSinSpectrum.Produce(); 00188 mOutputSpectrum.Produce(); 00189 mOutputAudio.Produce(); 00190 mOutputSinAudio.Produce(); 00191 mOutputResAudio.Produce(); 00192 00193 return result; 00194 } 00195 00196 00197 bool SMSSynthesis::Do( 00198 SpectralPeakArray& inputSinusoidalPeaks, 00199 Spectrum& inputResidualSpectrum, 00200 Audio& outputAudio, 00201 Audio& outputSinusoidalAudio, 00202 Audio& outputResidualAudio) 00203 { 00204 Spectrum tmpOutputSinSpec; 00205 Spectrum tmpOutputSpec; 00206 // init its size since we'll operate with these spectrums 00207 tmpOutputSinSpec.SetSize( inputResidualSpectrum.GetSize() ); 00208 tmpOutputSinSpec.SetSize( inputResidualSpectrum.GetSize() ); 00209 00210 return Do(inputSinusoidalPeaks,inputResidualSpectrum,tmpOutputSinSpec,tmpOutputSpec, 00211 outputAudio,outputSinusoidalAudio,outputResidualAudio); 00212 00213 } 00214 00215 bool SMSSynthesis::Do( 00216 SpectralPeakArray& inputSinusoidalPeaks, 00217 Spectrum& inputResidualSpectrum, 00218 Spectrum& outputSinusoidalSpectrum, // 00219 Spectrum& outputSpectrum, // 00220 Audio& outputAudio, 00221 Audio& outputSinusoidalAudio, 00222 Audio& outputResidualAudio) 00223 { 00224 //First we do the phase managing. Note that if the Do(frame) overload is not used, 00225 //the time and pitch controls in this processing should be set by hand before this 00226 //method is used 00227 00228 00229 // mPhaseMan.mCurrentTime.DoControl(mCurrentTimeControl.GetLastValue()); //TODO used in SMSBase (Synth from segment) 00230 TData currentTime = 0; 00231 if (mCurrentTimeControl.GetLastValue() < -0.9) 00232 { 00233 int framesize = outputAudio.GetSize(); 00234 TData samplerate = inputResidualSpectrum.GetSpectralRange()*2; 00235 currentTime = TData( mCurrentFrame*framesize ) / samplerate; 00236 } 00237 else 00238 { 00239 currentTime = mCurrentTimeControl.GetLastValue(); 00240 } 00241 mPhaseMan.mCurrentTime.DoControl( currentTime ); 00242 mCurrentFrame ++; 00243 00244 mPhaseMan.mCurrentPitch.DoControl(mCurrentPitch.GetLastValue()); 00245 mPhaseMan.Do(inputSinusoidalPeaks); 00246 00247 //We synthesize the sinusoidal component 00248 SinusoidalSynthesis(inputSinusoidalPeaks,outputSinusoidalSpectrum,outputSinusoidalAudio); 00249 00250 outputSpectrum.SetSize( inputResidualSpectrum.GetSize() ); 00251 00252 00253 //We add Residual spectrum in the input frame plus the synthesized sinusoidal spectrum 00254 mSpectrumAdder.Do(outputSinusoidalSpectrum, inputResidualSpectrum, outputSpectrum); 00255 00256 //We synthesize to audio the resulting summed spectrum 00257 mSpectralSynthesis.Do(outputSpectrum,mAudioFrame); 00258 00259 00260 //We do the overlap and add 00261 mOverlapAddGlobal.Do(mAudioFrame, outputAudio); 00262 00263 //Now we synthesize only the residual spectrum 00264 mResSpectralSynthesis.Do(inputResidualSpectrum,mAudioFrame); 00265 //And we do the overlap and add process for the residual 00266 00267 mOverlapAddRes.Do(mAudioFrame, outputResidualAudio); 00268 00269 /* Note: although sinusoidal spectrum is already available from the analysis phase, we 00270 need to store it again in the frame because the original peak array may have been 00271 transformed 00272 */ 00273 return true; 00274 } 00275 00276 bool SMSSynthesis::Do( 00277 SpectralPeakArray& inputSinusoidalPeaks, 00278 Spectrum& inputResidualSpectrum, 00279 Spectrum& outputSinusoidalSpectrum, // 00280 Spectrum& outputSpectrum, // 00281 Audio& outputAudio) 00282 { 00283 //First we do the phase managing. Note that if the Do(frame) overload is not used, 00284 //the time and pitch controls in this processing should be set by hand before this 00285 //method is used 00286 00287 // mPhaseMan.mCurrentTime.DoControl(mCurrentTimeControl.GetLastValue()); //TODO used in SMSBase (Synth from segment) 00288 TData currentTime = 0; 00289 if (mCurrentTimeControl.GetLastValue() < -0.9) 00290 { 00291 int framesize = outputAudio.GetSize(); 00292 TData samplerate = inputResidualSpectrum.GetSpectralRange()*2; 00293 currentTime = TData( mCurrentFrame*framesize ) / samplerate; 00294 } 00295 else 00296 { 00297 currentTime = mCurrentTimeControl.GetLastValue(); 00298 } 00299 mPhaseMan.mCurrentTime.DoControl( currentTime ); 00300 mCurrentFrame ++; 00301 00302 mPhaseMan.mCurrentPitch.DoControl(mCurrentPitch.GetLastValue()); 00303 mPhaseMan.Do(inputSinusoidalPeaks); 00304 00305 // We create a spectrum from the sinusoidal peaks 00306 outputSinusoidalSpectrum.SetSize(mConfig.GetSpectrumSize()); 00307 mSynthSineSpectrum.Do(inputSinusoidalPeaks,outputSinusoidalSpectrum); 00308 00309 outputSpectrum.SetSize( inputResidualSpectrum.GetSize() ); 00310 00311 //We add Residual spectrum in the input frame plus the synthesized sinusoidal spectrum 00312 mSpectrumAdder.Do(outputSinusoidalSpectrum, inputResidualSpectrum, outputSpectrum); 00313 00314 //We synthesize to audio the resulting summed spectrum 00315 mSpectralSynthesis.Do(outputSpectrum,mAudioFrame); 00316 00317 00318 //We do the overlap and add 00319 mOverlapAddGlobal.Do(mAudioFrame, outputAudio); 00320 00321 /* Note: although sinusoidal spectrum is already available from the analysis phase, we 00322 need to store it again in the frame because the original peak array may have been 00323 transformed 00324 */ 00325 return true; 00326 } 00327 00328 bool SMSSynthesis::Do(Frame& in) 00329 { 00330 bool isSynthesizeSinusoidsAndResidual = true; 00331 return Do(in, isSynthesizeSinusoidsAndResidual); 00332 } 00333 00334 bool SMSSynthesis::Do(Frame& in, bool isSynthesizeSinusoidsAndResidual) 00335 { 00336 if(in.GetCenterTime()<0) return false;//such frames should not be synthesized 00337 00338 //We initialize input frame, adding necessary attributes 00339 InitFrame(in); 00340 //First we set the controls sa mCurrentTimeControl.DoControl(in.GetCenterTime()); 00341 mCurrentPitch.DoControl(in.GetFundamental().GetFreq(0)); 00342 00343 00344 //We make sure that spectrums in input frame has the appropiate size and spectral range. 00345 //Note that the only spectrum we can be sure has the correct spectral range is the residual 00346 //because it its the only one that has been stored in the analysis process. 00347 in.GetOutSpec().SetSize(mConfig.GetSpectrumSize()); 00348 in.GetOutSpec().SetSpectralRange(in.GetResidualSpec().GetSpectralRange()); 00349 in.GetSinusoidalSpec().SetSpectralRange(in.GetResidualSpec().GetSpectralRange()); 00350 00351 if ( isSynthesizeSinusoidsAndResidual ) 00352 { 00353 return Do(in.GetSpectralPeakArray(),in.GetResidualSpec(),in.GetSinusoidalSpec(),in.GetOutSpec(), 00354 in.GetSynthAudioFrame(),in.GetSinusoidalAudioFrame(),in.GetResidualAudioFrame()); 00355 } 00356 else 00357 { 00358 return Do(in.GetSpectralPeakArray(),in.GetResidualSpec(),in.GetSinusoidalSpec(),in.GetOutSpec(), 00359 in.GetSynthAudioFrame()); 00360 } 00361 } 00362 00363 bool SMSSynthesis::Do(Segment& in) 00364 { 00365 return Do(in.GetFrame(in.mCurrentFrameIndex++)); 00366 } 00367 00368 00369 void SMSSynthesis::InitFrame(Frame& in) 00370 { 00371 in.AddOutSpec(); 00372 in.AddSinusoidalSpec(); 00373 in.AddSinusoidalAudioFrame(); 00374 in.AddResidualAudioFrame(); 00375 in.AddSynthAudioFrame(); 00376 in.UpdateData(); 00377 00378 in.GetSinusoidalAudioFrame().SetSize(mConfig.GetFrameSize()); 00379 in.GetResidualAudioFrame().SetSize(mConfig.GetFrameSize()); 00380 in.GetSynthAudioFrame().SetSize(mConfig.GetFrameSize()); 00381 00382 } 00383 00384 } // namespace CLAM 00385
1.7.6.1