SMSSynthesis.cxx

Go to the documentation of this file.
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 

Generated on Tue Aug 12 22:33:45 2008 for CLAM by  doxygen 1.5.5