CLAM-Development  1.4.0
IFFT_fftw3.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 "IFFT_fftw3.hxx"
23 #include "SpecTypeFlags.hxx"
24 
25 #include "Audio.hxx"
26 #include "Spectrum.hxx"
27 #include "ProcessingFactory.hxx"
28 
29 #include <fftw3.h>
30 
31 
32 namespace CLAM {
33 
34 namespace Hidden
35 {
36  static const char * metadata[] = {
37  "key", "IFFT_fftw3",
38  "category", "Synthesis",
39  "description", "IFFT_fftw3",
40  0
41  };
42  static FactoryRegistrator<ProcessingFactory, IFFT_fftw3> reg = metadata;
43 }
44 
45 struct IFFT_fftw3::Implementation
46 {
47  Implementation(unsigned size)
48  {
49  // Special malloc which aligns to SIMD segment boundaries
50  _complexInput = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * size);
51  _realOutput = (double*) fftw_malloc(sizeof(double) * size);
52  fftw_import_system_wisdom();
53  _plan = fftw_plan_dft_c2r_1d(size, _complexInput, _realOutput, FFTW_ESTIMATE);
54  }
55  ~Implementation()
56  {
57  fftw_destroy_plan(_plan);
58  fftw_free(_realOutput);
59  fftw_free(_complexInput);
60  }
61  fftw_plan _plan;
62  fftw_complex * _complexInput;
63  double * _realOutput;
64 };
65 
67  : _fftw3(0)
68 {
69  Configure(c);
70 };
71 
72 bool IFFT_fftw3::ConcreteConfigure(const ProcessingConfig& c)
73 {
76  if (mConfig.HasAudioSize()) {
77  CLAM_ASSERT (mConfig.GetAudioSize()>=0,"Wrong (negative) Size in IFFT Configuration.");
78  mSize = mConfig.GetAudioSize();
79  }
80  mOutput.SetSize( mSize );
81  mOutput.SetHop( mSize );
82 
83  mState=sOther;
84  SetupMemory();
85  return true;
86 }
87 
89 {
90  ReleaseMemory();
91 }
92 
93 void IFFT_fftw3::ReleaseMemory()
94 {
95  if (_fftw3) delete _fftw3;
96 }
97 void IFFT_fftw3::SetupMemory()
98 {
99  ReleaseMemory();
100  _fftw3 = new Implementation(mSize);
101 }
102 
103 void IFFT_fftw3::CheckTypes(const Spectrum& in, const Audio &out) const
104 {
105  CLAM_ASSERT(out.HasBuffer(),"IFFT Do: Float attribute required for Audio object.");
107  // Input object checking
108  if (out.GetSize()!=mSize) {
109  std::stringstream ss;
110  ss << "IFFT_fftw3::Do: Wrong size in IFFT Audio output\n"
111  << " Expected: " << mSize*2+1 << ", used " << out.GetSize();
112  CLAM_ASSERT(0,ss.str().c_str());
113  }
114  if (in.GetSize() < mSize/2+1 ) { // ALGORITHM DEPENDENT CHECKING
115  std::stringstream ss;
116  ss << "IFFT_fftw3::Do: not enough memory in input Spectrum.\n"
117  << " Expected: " << mSize/2+1 << ", used " << in.GetSize();
118  CLAM_ASSERT(0,ss.str().c_str());
119 
120  }
122 }
123 /*
124 void IFFT_fftw3::Attach(Spectrum &in, Audio& out)
125 {
126  mInput.Attach(in);
127  mOutput.Attach(out);
128 }
129 */
130 
132 {
133  bool toReturn = Do(mInput.GetData(),mOutput.GetAudio());
134  mInput.Consume();
135  mOutput.Produce();
136  return toReturn;
137 };
138 
139 
140 bool IFFT_fftw3::SetPrototypes(const Spectrum& in, const Audio &out)
141 {
142  CheckTypes(in,out);
143 
144  SpecTypeFlags flags;
145  in.GetType(flags);
146 
147  if (flags.bComplex)
148  mState=sComplex;
149  else
150  {
151  CLAM_ASSERT(flags.bPolar || flags.bMagPhase || flags.bMagPhaseBPF,"IFFT_fftw3: SetPrototypes(): No Spectrum Attributes!");
152  mState=sOther;
153  }
154  // TODO: Maybe should update the prototype in the port?
155 
156  return true;
157 }
158 
160 {
161  mState=sOther;
162  return true;
163 }
164 
165 
166 bool IFFT_fftw3::Do( const Spectrum& in, Audio &out) const
167 {
168  CLAM_ASSERT(IsRunning() ,"IFFT_fftw3: Do(): Not in execution mode");
169  CLAM_ASSERT(out.GetSize() == mSize,
170  "Not proper IFFT output size");
171 
172  if (mState==sComplex)
173  ComplexToRIFFTW(in);
174  else
175  {
176  CheckTypes(in,out);
177  OtherToRIFFTW(in);
178  }
179  fftw_execute(_fftw3->_plan);
180  TData * outbuffer = out.GetBuffer().GetPtr();
181  for (int i=0; i<mSize; i++)
182  outbuffer[i] = _fftw3->_realOutput[i];
183 
184  out.SetSampleRate(TData(in.GetSpectralRange()*2));
185  return true;
186 }
187 
189 {
190  // @todo Check port prototypes, and set the state (or de
191  // backup state if disabled) acordingly.
192  CLAM_ASSERT(false,"IFFT_fftw3::SetPrototypes: Not implemented.");
193  return false;
194 }
195 
196 inline void IFFT_fftw3::ComplexToRIFFTW(const Spectrum &in) const
197 {
198  CLAM_ASSERT(in.HasComplexArray(), "Input spectrum has no complex array");
199  const Array<Complex> & inbuffer = in.GetComplexArray();
200  CLAM_ASSERT(inbuffer.Size() == mSize/2+1, "IFFT_fftw3::ComplexToRIFFTW: sizes doesn't match.");
201  for (int i=0; i< inbuffer.Size(); i++)
202  {
203  _fftw3->_complexInput[i][0] = inbuffer[i].Real()/mSize;
204  _fftw3->_complexInput[i][1] = inbuffer[i].Imag()/mSize;
205  }
206 /*
207  // TODO: Use this code for the r2r format
208  ifftbuffer[0]=(*inbuffer)[0].Real()/mSize; // Real Values
209  ifftbuffer[mSize/2]=(*inbuffer)[mSize/2].Real()/mSize;
210  for (int i=1; i< mSize/2; i++) {
211  ifftbuffer[i] = (*inbuffer)[i].Real()/mSize;
212  ifftbuffer[mSize-i] = (*inbuffer)[i].Imag()/mSize;
213  }
214  if (mSize&1)
215  ifftbuffer[mSize/2+1] = (*inbuffer)[mSize/2].Imag()/mSize;
216 */
217 }
218 
219 
220 inline void IFFT_fftw3::OtherToRIFFTW(const Spectrum &in) const
221 {
222  if (in.HasComplexArray())
223  {
224  ComplexToRIFFTW(in);
225  return;
226  }
227  SpecTypeFlags flags;
228  Spectrum spec = in;
229  spec.GetType(flags);
230  flags.bComplex=1;
231  spec.SetTypeSynchronize(flags);
232  ComplexToRIFFTW(spec);
233 }
234 }
235