CLAM-Development  1.4.0
IFFT_ooura.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 
23 #include "IFFT_ooura.hxx"
24 #include "FFT_ooura.hxx"
25 
26 #include "Assert.hxx"
27 #include "Audio.hxx"
28 #include "Spectrum.hxx"
29 #include "SpectrumConfig.hxx"
30 #include "CLAM_Math.hxx"
31 #include "ProcessingFactory.hxx"
32 
33 namespace CLAM {
34 
35 namespace Hidden
36 {
37  static const char * metadata[] = {
38  "key", "IFFT_ooura",
39  "category", "Synthesis",
40  "description", "IFFT_ooura",
41  0
42  };
43  static FactoryRegistrator<ProcessingFactory, IFFT_ooura> reg = metadata;
44 }
45 
46 
47  bool IFFT_ooura::ConcreteConfigure(const ProcessingConfig& c) {
48  int oldSize=mSize;
50  if (mConfig.HasAudioSize()) {
51  CLAM_ASSERT (mConfig.GetAudioSize()>=0,"Wrong (negative) Size in IFFT Configuration.");
52  mSize = mConfig.GetAudioSize();
53  if(mSize>0)
54  {
55  mOutput.SetSize( mSize );
56  mOutput.SetHop( mSize );
57  }
58  }
59  else
60  mSize = CLAM_DEFAULT_IFFT_SIZE;
61 
62  mState=sOther;
63  mComplexflags.bComplex=1;
64  mComplexflags.bMagPhase=0;
65  if (mSize>0) {
66  delete [] ifftbuffer;
67  ifftbuffer = new TData[mSize];
68  }
69  else ifftbuffer = 0;
70 
71  if ( !isPowerOfTwo( mSize ) )
72  {
73  AddConfigErrorMessage("Configure failed: IFFT Ooura algorithm only works for input buffers that are a power of two!");
74  return false;
75  }
76  if (mSize>0) {
77  if (mSize != oldSize) {
78  ReleaseMemory();
79  SetupMemory();
80  }
81  return true;
82  }
83  ReleaseMemory();
84  return false;
85  }
86 
87  void IFFT_ooura::ReleaseMemory() {
88  if (ip) { delete[] ip; ip = 0; }
89  if (w) { delete[] w; w = 0; }
90  }
91 
92  void IFFT_ooura::SetupMemory() {
93  int ipSize = (int)(2+(1<<(int)(log(mSize/2+0.5)/log(2.0))/2));
94  ip = new int[ipSize];
95  for (int i=0; i<ipSize; i++) ip[i] = 0;
96 
97  int wSize = (int)(mSize*5/8-1);
98  w = new TData[wSize];
99  for (int i=0; i<wSize; i++) w[i] = 0;
100  }
101 
103  : ip(0), w(0)
104  {
106  }
107 
109  : ip(0), w(0)
110  {
111  Configure(c);
112  };
113 
115  {
116  ReleaseMemory();
117  }
118 
120  {
121  bool toReturn = Do(mInput.GetData(),mOutput.GetAudio());
122  mInput.Consume();
123  mOutput.Produce();
124  return toReturn;
125  }
126 
127  bool IFFT_ooura::Do(const Spectrum& in, Audio &out) const{
128  TData* outbuffer = out.GetBuffer().GetPtr();
129  int i;
130 
132  "IFFT_ooura: Do(): Not in execution mode");
133 
135  "IFFT_ooura: Do(): Not a power of two");
136 
137  out.SetSampleRate(in.GetSpectralRange()*2);
138 
139  TData twoOverSize = 2.0/mSize;
140 
141  switch(mState) {
142  case sComplex:
143  ComplexToIFFTOoura(in);
144  FFT_ooura::rdft(mSize, -1, ifftbuffer, ip, w);
145  // Buffer dump. This is a kludge; the right way to do this
146  // is using a non-inplace version of rdft (which would
147  // not reduce performance).
148  for (i=0; i<mSize; i++)
149  outbuffer[i]=ifftbuffer[i]*twoOverSize;
150  break;
151  case sOther:
152  OtherToIFFTOoura(in);
153  FFT_ooura::rdft(mSize, -1, ifftbuffer, ip, w);
154  // Buffer dump. This is a kludge; the right way to do this
155  // is using a non-inplace version of rdft (which would
156  // not reduce performance).
157  for (i=0; i<mSize; i++)
158  outbuffer[i]=ifftbuffer[i]*twoOverSize;
159 
160  break;
161  default:
162  CLAM_ASSERT(false, "IFFT_ooura: Do(): Inconsistent state");
163  }
164 
165  return true;
166  }
167 
168  void IFFT_ooura::ComplexToIFFTOoura(const Spectrum &in) const {
169  int i;
170  Array<Complex> inbuffer = in.GetComplexArray();
171 
172  ifftbuffer[0] = inbuffer[0].Real();
173  ifftbuffer[1] = inbuffer[mSize/2].Real();
174 
175  for (i=1; i<mSize/2; i++) {
176  ifftbuffer[2*i] = inbuffer[i].Real();
177  ifftbuffer[2*i+1] = -inbuffer[i].Imag();
178  }
179  }
180 
181  inline void IFFT_ooura::OtherToIFFTOoura(const Spectrum &in) const
182  {
183  SpecTypeFlags flags;
184  in.GetType(flags);
185  /* if(flags.bMagPhase)
186  {
187  DataArray& inMag = in.GetMagBuffer();
188  DataArray& inPhase = in.GetPhaseBuffer();
189  ifftbuffer[0] = inMag[0]*CLAM_cos(inPhase[0]);//inbuffer[0].Real();
190  ifftbuffer[1] = inMag[mSize/2]*CLAM_cos(inPhase[mSize/2]);//inbuffer[mSize/2].Real();
191  int i;
192  TData* ifftbuffer_iter1 = &(ifftbuffer[2]);
193  TData* ifftbuffer_iter2 = &(ifftbuffer[3]);
194  TData* inMag_iter = &(inMag[1]);
195  TData* inPhase_iter = &(inPhase[1]);
196  for (i=1; i<mSize/2; ifftbuffer_iter1+=2,ifftbuffer_iter2+=2, inMag_iter++, inPhase_iter++, i++) {
197  *ifftbuffer_iter1 = (*inMag_iter)*CLAM_cos((*inPhase_iter));
198  *ifftbuffer_iter2 = (*inMag_iter)*CLAM_sin(*inPhase_iter);
199  }
200 
201  }
202  else
203  {
204  */ Spectrum tmpSpec = in;
205  if (!in.HasComplexArray()) {
206  flags.bComplex=1;
207  tmpSpec.SetTypeSynchronize(flags);
208  }
209  ComplexToIFFTOoura(tmpSpec);
210  // }
211 
212  }
213 
214  bool IFFT_ooura::SetPrototypes(const Spectrum& in, const Audio &out)
215  {
216  CheckTypes(in,out);
217 
218  SpecTypeFlags flags;
219  in.GetType(flags);
220 
221  if (flags.bComplex)
222  mState=sComplex;
223  else
224  {
225  CLAM_ASSERT(flags.bPolar || flags.bMagPhase || flags.bMagPhaseBPF,"IFFT_ooura: SetPrototypes(): No Spectrum Attributes!");
226  mState=sOther;
227  }
228  // TODO: Maybe should update the prototype in the port?
229 
230  return true;
231  }
232 
234  {
235  // @todo Check port prototypes, and set the state (or de
236  // backup state if disabled) acordingly.
237  CLAM_ASSERT(false,"IFFT_ooura::SetPrototypes: Not implemented.");
238  return false;
239  }
240 
242  {
243  mState=sOther;
244  return true;
245  }
246 
247  void IFFT_ooura::CheckTypes(const Spectrum& in, const Audio &out) const
248  {
249  CLAM_ASSERT(out.HasBuffer(),"IFFT Do: Float attribute required for Audio object.");
251  // Input object checking
252  if (out.GetSize()!=mSize) {
253  std::stringstream ss;
254  ss << "IFFT_ooura::Do: Wrong size in IFFT Audio output\n"
255  << " Expected: " << mSize*2+1 << ", used " << out.GetSize();
256  CLAM_ASSERT(0,ss.str().c_str());
257  }
258  if (in.GetSize() < mSize/2+1 ) { // ALGORITHM DEPENDENT CHECKING
259  std::stringstream ss;
260  ss << "IFFT_ooura::Do: not enough memory in input Spectrum.\n"
261  << " Expected: " << mSize/2+1 << ", used " << in.GetSize();
262  CLAM_ASSERT(0,ss.str().c_str());
263 
264  }
266  }
267 
268 
269 
270 
271 }; // CLAM
272