FFT_numrec.cxx
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "FFT_numrec.hxx"
00024
00025 #include "Assert.hxx"
00026 #include "Audio.hxx"
00027 #include "Spectrum.hxx"
00028 #include "SpectrumConfig.hxx"
00029 #include "CLAM_Math.hxx"
00030 #include "ProcessingFactory.hxx"
00031
00032 extern "C" {
00033 #include "numrecipes_fft.h"
00034 }
00035
00036 namespace CLAM
00037 {
00038
00039 namespace Hidden
00040 {
00041 static const char * metadata[] = {
00042 "key", "FFT_numrec",
00043 "category", "Analysis",
00044 "description", "FFT_numrec",
00045 0
00046 };
00047 static FactoryRegistrator<ProcessingFactory, FFT_numrec> reg = metadata;
00048 }
00049
00050
00051 bool FFT_numrec::ConcreteConfigure(const ProcessingConfig& c)
00052 {
00053 FFT_base::ConcreteConfigure(c);
00054 if ( !isPowerOfTwo( mSize ) )
00055 {
00056 AddConfigErrorMessage("Configure failed: Numerical Recipes FFT algorithm does not"
00057 "accept non power of two buffers");
00058
00059 return false;
00060 }
00061
00062 return true;
00063 }
00064
00065 FFT_numrec::FFT_numrec()
00066 {
00067 Configure(FFTConfig());
00068 }
00069
00070 FFT_numrec::FFT_numrec(const FFTConfig &c)
00071 {
00072 Configure(c);
00073 };
00074
00075 FFT_numrec::~FFT_numrec()
00076 {
00077 }
00078
00079 bool FFT_numrec::Do()
00080 {
00081 mOutput.GetData().SetSize( mInput.GetSize()/2+1);
00082 bool toReturn = Do(mInput.GetAudio(), mOutput.GetData());
00083 mInput.Consume();
00084 mOutput.Produce();
00085 return toReturn;
00086 };
00087
00088 bool FFT_numrec::Do(const Audio& in, Spectrum &out)
00089 {
00090 TData *inbuffer;
00091
00092 CLAM_DEBUG_ASSERT(IsRunning(), "FFT_numrec: Do(): Not in execution mode");
00093
00094 out.SetSpectralRange(in.GetSampleRate()/2);
00095
00096 switch(mState) {
00097 case sComplex:
00098 inbuffer = in.GetBuffer().GetPtr();
00099
00100
00101
00102 for (int i=0; i<mSize; i++)
00103 fftbuffer[i]=inbuffer[i];
00104 realft(fftbuffer-1, mSize, 1);
00105 ToComplex(out);
00106 break;
00107 case sComplexSync:
00108 inbuffer = in.GetBuffer().GetPtr();
00109
00110
00111
00112 for (int i=0; i<mSize; i++)
00113 fftbuffer[i]=inbuffer[i];
00114 realft(fftbuffer-1, mSize, 1);
00115 ToComplex(out);
00116 out.SynchronizeTo(mComplexflags);
00117 break;
00118 case sOther:
00119 CheckTypes(in,out);
00120 inbuffer = in.GetBuffer().GetPtr();
00121
00122
00123
00124 for (int i=0; i<mSize; i++)
00125 fftbuffer[i]=inbuffer[i];
00126 realft(fftbuffer-1, mSize, 1);
00127 ToOther(out);
00128 break;
00129 default:
00130 CLAM_ASSERT(false, "FFT_numrec: Do(): Inconsistent state");
00131 }
00132
00133 return true;
00134
00135 }
00136
00137
00138 void FFT_numrec::ToComplex(Spectrum &out)
00139 {
00140 Array<Complex>* outbuffer;
00141
00142 outbuffer = &out.GetComplexArray();
00143 (*outbuffer)[0].SetReal(fftbuffer[0]);
00144 (*outbuffer)[0].SetImag(0);
00145 (*outbuffer)[mSize/2].SetReal(fftbuffer[1]);
00146 (*outbuffer)[mSize/2].SetImag(0);
00147
00148 for (int i=1; i< mSize/2; i++) {
00149 (*outbuffer)[i].SetReal(fftbuffer[2*i]);
00150 (*outbuffer)[i].SetImag(-fftbuffer[2*i+1]);
00151 }
00152
00153 outbuffer->SetSize(mSize/2+1);
00154 }
00155
00156
00157 };
00158