CLAM-Development  1.4.0
SMSSynthesis.cxx
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2001-2004 MUSIC TECHNOLOGY GROUP (MTG)
3  * UNIVERSITAT POMPEU FABRA
4  *
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19  *
20  */
21 
22 #include "SpectrumConfig.hxx"
23 #include "SMSSynthesis.hxx"
24 #include "ProcessingFactory.hxx"
25 
26 
27 
28 namespace CLAM
29 {
30 
31 namespace Hidden
32 {
33  static const char * metadata[] = {
34  "key", "SMSSynthesis",
35  "category", "Synthesis",
36  "description", "SMSSynthesis",
37  0
38  };
39  static FactoryRegistrator<ProcessingFactory, SMSSynthesis> reg = metadata;
40 }
41 
42 
43 void SMSSynthesis::AttachChildren()
44 {
45  mSpectralSynthesis.SetParent(this);
46  mResSpectralSynthesis.SetParent(this);
47  mSinSpectralSynthesis.SetParent(this);
48  mSynthSineSpectrum.SetParent(this);
49  mPhaseMan.SetParent(this);
50  mSpectrumAdder.SetParent(this);
51  mOverlapAddSin.SetParent(this);
52  mOverlapAddRes.SetParent(this);
53  mOverlapAddGlobal.SetParent(this);
54 }
55 
57  : mInputSinSpectralPeaks("InputSinPeaks",this)
58  , mInputResSpectrum("InputResSpectrum",this)
59  , mOutputSinSpectrum("OutputSinSpectrum",this)
60  , mOutputSpectrum("OutputSpectrum",this)
61  , mOutputAudio("OutputAudio",this)
62  , mOutputResAudio("OutputResAudio",this)
63  , mOutputSinAudio("OutputSinAudio",this)
64  , mCurrentTimeControl("CurrentTime",this)
65  , mCurrentPitch("CurrentPitch",this)
66 {
67  mCurrentFrame = 0;
68  Configure(cfg);
69  AttachChildren();
70 }
71 
73 {
74 
75 }
76 
77 bool SMSSynthesis::ConfigureChildren()
78 {
79 // mConfig.SetSpectrumSize( mAudioFrame.GetSize()/2+1 );
80 
81  //configure global spectral synthesis
82  if(!mSpectralSynthesis.Configure(mConfig.GetSpectralSynth()))
83  return false;
84 
85  //configure residual spectral synthesis
86  mConfig.GetSpectralSynth().SetResidual(true);
87  if(!mResSpectralSynthesis.Configure(mConfig.GetSpectralSynth()))
88  return false;
89 
90  //configure sinusoidal spectral synthesis
91  mConfig.GetSpectralSynth().SetResidual(false);
92  if(!mSinSpectralSynthesis.Configure(mConfig.GetSpectralSynth()))
93  return false;
94 
95  //SynthSineSpectrum
96  if(!mSynthSineSpectrum.Configure(mConfig.GetSynthSineSpectrum()))
97  return false;
98 
99  //Phase Management
100  if(!mPhaseMan.Configure(mConfig.GetPhaseMan()))
101  return false;
102 
103  mPhaseMan.Init();
104 
105  //Spectrum Adder
106  if(!mSpectrumAdder.Configure(SpecAdder2Config()))
107  return false;
108 
109  //Overlap and add PO
110  if(!mOverlapAddSin.Configure(mConfig.GetOverlapAddSin()))
111  return false;
112  if(!mOverlapAddRes.Configure(mConfig.GetOverlapAddRes()))
113  return false;
114  if(!mOverlapAddGlobal.Configure(mConfig.GetOverlapAddGlobal()))
115  return false;
116 
117  return true;
118 }
119 
120 void SMSSynthesis::ConfigureData()
121 {
122  mAudioFrame.SetSize(mConfig.GetHopSize()*2);//audio used as input of the overlap and add
123  mOutputAudio.SetSize( mAudioFrame.GetSize()/2 );
124  mOutputSinAudio.SetSize( mAudioFrame.GetSize()/2 );
125  mOutputResAudio.SetSize( mAudioFrame.GetSize()/2 );
126 
127  mOutputAudio.SetHop( mConfig.GetHopSize() );
128  mOutputSinAudio.SetHop( mConfig.GetHopSize() );
129  mOutputResAudio.SetHop( mConfig.GetHopSize() );
130 
131  mOutputSpectrum.GetData().SetSize( mAudioFrame.GetSize()/2+1);
132  mOutputSinSpectrum.GetData().SetSize( mAudioFrame.GetSize()/2+1);
133 }
134 
135 
136 bool SMSSynthesis::ConcreteConfigure(const ProcessingConfig& c)
137 {
138  CopyAsConcreteConfig(mConfig, c);
139  ConfigureChildren();
140  ConfigureData();
142  return true;
143 }
144 
146 {
147  SpectrumConfig tmpcfg;
148  tmpcfg.SetScale(EScale::eLinear);
149  Spectrum tmpSpec(tmpcfg);
150  return SinusoidalSynthesis(in,tmpSpec,out);
151 
152 }
153 
156 {
157 // outSpec.SetSize(mConfig.GetSpectrumSize());
158  mSynthSineSpectrum.Do(in,outSpec);
159 
160  mSinSpectralSynthesis.Do(outSpec,mAudioFrame);
161  //Finally the overlap and add is accomplished
162 
163  return mOverlapAddSin.Do(mAudioFrame, outAudio);
164 
165 }
166 
167 
169 {
170  bool result;
172  {
176  }
177  else
178  {
182  }
183 
186 
192 
193  return result;
194 }
195 
196 
198  SpectralPeakArray& inputSinusoidalPeaks,
199  Spectrum& inputResidualSpectrum,
200  Audio& outputAudio,
201  Audio& outputSinusoidalAudio,
202  Audio& outputResidualAudio)
203 {
204  Spectrum tmpOutputSinSpec;
205  Spectrum tmpOutputSpec;
206  // init its size since we'll operate with these spectrums
207  tmpOutputSinSpec.SetSize( inputResidualSpectrum.GetSize() );
208  tmpOutputSinSpec.SetSize( inputResidualSpectrum.GetSize() );
209 
210  return Do(inputSinusoidalPeaks,inputResidualSpectrum,tmpOutputSinSpec,tmpOutputSpec,
211  outputAudio,outputSinusoidalAudio,outputResidualAudio);
212 
213 }
214 
216  SpectralPeakArray& inputSinusoidalPeaks,
217  Spectrum& inputResidualSpectrum,
218  Spectrum& outputSinusoidalSpectrum, //
219  Spectrum& outputSpectrum, //
220  Audio& outputAudio,
221  Audio& outputSinusoidalAudio,
222  Audio& outputResidualAudio)
223 {
224  //First we do the phase managing. Note that if the Do(frame) overload is not used,
225  //the time and pitch controls in this processing should be set by hand before this
226  //method is used
227 
228 
229 // mPhaseMan.mCurrentTime.DoControl(mCurrentTimeControl.GetLastValue()); //TODO used in SMSBase (Synth from segment)
230  TData currentTime = 0;
231  if (mCurrentTimeControl.GetLastValue() < -0.9)
232  {
233  int framesize = outputAudio.GetSize();
234  TData samplerate = inputResidualSpectrum.GetSpectralRange()*2;
235  currentTime = TData( mCurrentFrame*framesize ) / samplerate;
236  }
237  else
238  {
239  currentTime = mCurrentTimeControl.GetLastValue();
240  }
241  mPhaseMan.mCurrentTime.DoControl( currentTime );
242  mCurrentFrame ++;
243 
245  mPhaseMan.Do(inputSinusoidalPeaks);
246 
247  //We synthesize the sinusoidal component
248  SinusoidalSynthesis(inputSinusoidalPeaks,outputSinusoidalSpectrum,outputSinusoidalAudio);
249 
250  outputSpectrum.SetSize( inputResidualSpectrum.GetSize() );
251 
252 
253  //We add Residual spectrum in the input frame plus the synthesized sinusoidal spectrum
254  mSpectrumAdder.Do(outputSinusoidalSpectrum, inputResidualSpectrum, outputSpectrum);
255 
256  //We synthesize to audio the resulting summed spectrum
257  mSpectralSynthesis.Do(outputSpectrum,mAudioFrame);
258 
259 
260  //We do the overlap and add
261  mOverlapAddGlobal.Do(mAudioFrame, outputAudio);
262 
263  //Now we synthesize only the residual spectrum
264  mResSpectralSynthesis.Do(inputResidualSpectrum,mAudioFrame);
265  //And we do the overlap and add process for the residual
266 
267  mOverlapAddRes.Do(mAudioFrame, outputResidualAudio);
268 
269  /* Note: although sinusoidal spectrum is already available from the analysis phase, we
270  need to store it again in the frame because the original peak array may have been
271  transformed
272  */
273  return true;
274 }
275 
277  SpectralPeakArray& inputSinusoidalPeaks,
278  Spectrum& inputResidualSpectrum,
279  Spectrum& outputSinusoidalSpectrum, //
280  Spectrum& outputSpectrum, //
281  Audio& outputAudio)
282 {
283  //First we do the phase managing. Note that if the Do(frame) overload is not used,
284  //the time and pitch controls in this processing should be set by hand before this
285  //method is used
286 
287 // mPhaseMan.mCurrentTime.DoControl(mCurrentTimeControl.GetLastValue()); //TODO used in SMSBase (Synth from segment)
288  TData currentTime = 0;
289  if (mCurrentTimeControl.GetLastValue() < -0.9)
290  {
291  int framesize = outputAudio.GetSize();
292  TData samplerate = inputResidualSpectrum.GetSpectralRange()*2;
293  currentTime = TData( mCurrentFrame*framesize ) / samplerate;
294  }
295  else
296  {
297  currentTime = mCurrentTimeControl.GetLastValue();
298  }
299  mPhaseMan.mCurrentTime.DoControl( currentTime );
300  mCurrentFrame ++;
301 
303  mPhaseMan.Do(inputSinusoidalPeaks);
304 
305  // We create a spectrum from the sinusoidal peaks
306  outputSinusoidalSpectrum.SetSize(mConfig.GetSpectrumSize());
307  mSynthSineSpectrum.Do(inputSinusoidalPeaks,outputSinusoidalSpectrum);
308 
309  outputSpectrum.SetSize( inputResidualSpectrum.GetSize() );
310 
311  //We add Residual spectrum in the input frame plus the synthesized sinusoidal spectrum
312  mSpectrumAdder.Do(outputSinusoidalSpectrum, inputResidualSpectrum, outputSpectrum);
313 
314  //We synthesize to audio the resulting summed spectrum
315  mSpectralSynthesis.Do(outputSpectrum,mAudioFrame);
316 
317 
318  //We do the overlap and add
319  mOverlapAddGlobal.Do(mAudioFrame, outputAudio);
320 
321  /* Note: although sinusoidal spectrum is already available from the analysis phase, we
322  need to store it again in the frame because the original peak array may have been
323  transformed
324  */
325  return true;
326 }
327 
329 {
330  bool isSynthesizeSinusoidsAndResidual = true;
331  return Do(in, isSynthesizeSinusoidsAndResidual);
332 }
333 
334 bool SMSSynthesis::Do(Frame& in, bool isSynthesizeSinusoidsAndResidual)
335 {
336  if(in.GetCenterTime()<0) return false;//such frames should not be synthesized
337 
338 //We initialize input frame, adding necessary attributes
339  InitFrame(in);
340 //First we set the controls sa mCurrentTimeControl.DoControl(in.GetCenterTime());
341  mCurrentPitch.DoControl(in.GetFundamental().GetFreq(0));
342 
343 
344 //We make sure that spectrums in input frame has the appropiate size and spectral range.
345 //Note that the only spectrum we can be sure has the correct spectral range is the residual
346 //because it its the only one that has been stored in the analysis process.
347  in.GetOutSpec().SetSize(mConfig.GetSpectrumSize());
348  in.GetOutSpec().SetSpectralRange(in.GetResidualSpec().GetSpectralRange());
349  in.GetSinusoidalSpec().SetSpectralRange(in.GetResidualSpec().GetSpectralRange());
350 
351  if ( isSynthesizeSinusoidsAndResidual )
352  {
353  return Do(in.GetSpectralPeakArray(),in.GetResidualSpec(),in.GetSinusoidalSpec(),in.GetOutSpec(),
354  in.GetSynthAudioFrame(),in.GetSinusoidalAudioFrame(),in.GetResidualAudioFrame());
355  }
356  else
357  {
358  return Do(in.GetSpectralPeakArray(),in.GetResidualSpec(),in.GetSinusoidalSpec(),in.GetOutSpec(),
359  in.GetSynthAudioFrame());
360  }
361 }
362 
364 {
365  return Do(in.GetFrame(in.mCurrentFrameIndex++));
366 }
367 
368 
370 {
371  in.AddOutSpec();
372  in.AddSinusoidalSpec();
373  in.AddSinusoidalAudioFrame();
374  in.AddResidualAudioFrame();
375  in.AddSynthAudioFrame();
376  in.UpdateData();
377 
378  in.GetSinusoidalAudioFrame().SetSize(mConfig.GetFrameSize());
379  in.GetResidualAudioFrame().SetSize(mConfig.GetFrameSize());
380  in.GetSynthAudioFrame().SetSize(mConfig.GetFrameSize());
381 
382 }
383 
384 } // namespace CLAM
385