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(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 
Generated by  doxygen 1.6.3