CLAM-Development  1.4.0
FFT_numrec.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 "FFT_numrec.hxx"
24 
25 #include "Assert.hxx"
26 #include "Audio.hxx"
27 #include "Spectrum.hxx"
28 #include "SpectrumConfig.hxx"
29 #include "CLAM_Math.hxx"
30 #include "ProcessingFactory.hxx"
31 
32 extern "C" {
33 #include "numrecipes_fft.h"
34 }
35 
36 namespace CLAM
37 {
38 
39 namespace Hidden
40 {
41  static const char * metadata[] = {
42  "key", "FFT_numrec",
43  "category", "Analysis",
44  "description", "FFT_numrec",
45  0
46  };
47  static FactoryRegistrator<ProcessingFactory, FFT_numrec> reg = metadata;
48 }
49 
50 
51  bool FFT_numrec::ConcreteConfigure(const ProcessingConfig& c)
52  {
54  if ( !isPowerOfTwo( mSize ) )
55  {
56  AddConfigErrorMessage("Configure failed: Numerical Recipes FFT algorithm does not"
57  "accept non power of two buffers");
58 
59  return false;
60  }
61 
62  return true;
63  }
64 
66  {
68  }
69 
71  {
72  Configure(c);
73  };
74 
76  {
77  }
78 
80  {
82  bool toReturn = Do(mInput.GetAudio(), mOutput.GetData());
83  mInput.Consume();
84  mOutput.Produce();
85  return toReturn;
86  };
87 
88  bool FFT_numrec::Do(const Audio& in, Spectrum &out)
89  {
90  TData *inbuffer;
91 
92  CLAM_DEBUG_ASSERT(IsRunning(), "FFT_numrec: Do(): Not in execution mode");
93 
94  out.SetSpectralRange(in.GetSampleRate()/2);
95 
96  switch(mState) {
97  case sComplex:
98  inbuffer = in.GetBuffer().GetPtr();
99  // Buffer dump. This is a kludge; the right way to do this
100  // is using a non-inplace version of realft (which would
101  // not reduce performance).
102  for (int i=0; i<mSize; i++)
103  fftbuffer[i]=inbuffer[i];
104  realft(fftbuffer-1, mSize, 1);
105  ToComplex(out);
106  break;
107  case sComplexSync:
108  inbuffer = in.GetBuffer().GetPtr();
109  // Buffer dump. This is a kludge; the right way to do this
110  // is using a non-inplace version of realft (which would
111  // not reduce performance).
112  for (int i=0; i<mSize; i++)
113  fftbuffer[i]=inbuffer[i];
114  realft(fftbuffer-1, mSize, 1);
115  ToComplex(out);
117  break;
118  case sOther:
119  CheckTypes(in,out);
120  inbuffer = in.GetBuffer().GetPtr();
121  // Buffer dump. This is a kludge; the right way to do this
122  // is using a non-inplace version of realft (which would
123  // not reduce performance).
124  for (int i=0; i<mSize; i++)
125  fftbuffer[i]=inbuffer[i];
126  realft(fftbuffer-1, mSize, 1);
127  ToOther(out);
128  break;
129  default:
130  CLAM_ASSERT(false, "FFT_numrec: Do(): Inconsistent state");
131  }
132 
133  return true;
134 
135  }
136 
137 
138  void FFT_numrec::ToComplex(Spectrum &out)
139  {
140  Array<Complex>* outbuffer;
141 
142  outbuffer = &out.GetComplexArray();
143  (*outbuffer)[0].SetReal(fftbuffer[0]); // Real Values
144  (*outbuffer)[0].SetImag(0); // Real Values
145  (*outbuffer)[mSize/2].SetReal(fftbuffer[1]);
146  (*outbuffer)[mSize/2].SetImag(0);
147 
148  for (int i=1; i< mSize/2; i++) {
149  (*outbuffer)[i].SetReal(fftbuffer[2*i]);
150  (*outbuffer)[i].SetImag(-fftbuffer[2*i+1]);
151  }
152 
153  outbuffer->SetSize(mSize/2+1);
154  }
155 
156 
157 };//namespace CLAM
158