FFT_numrec.cxx

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2001-2004 MUSIC TECHNOLOGY GROUP (MTG)
00003  *                         UNIVERSITAT POMPEU FABRA
00004  *
00005  *
00006  * This program is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation; either version 2 of the License, or
00009  * (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software
00018  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
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                         // Buffer dump. This is a kludge; the right way to do this
00100                         // is using a non-inplace version of realft (which would
00101                         // not reduce performance).
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                         // Buffer dump. This is a kludge; the right way to do this
00110                         // is using a non-inplace version of realft (which would
00111                         // not reduce performance).
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                         // Buffer dump. This is a kludge; the right way to do this
00122                         // is using a non-inplace version of realft (which would
00123                         // not reduce performance).
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]);   // Real Values
00144                 (*outbuffer)[0].SetImag(0);   // Real Values
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 };//namespace CLAM
00158 
Generated by  doxygen 1.6.3