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_fftw3.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 #include <fftw3.h>
00032
00033 namespace CLAM
00034 {
00035
00036 namespace Hidden
00037 {
00038 static const char * metadata[] = {
00039 "key", "FFT_fftw3",
00040 "category", "Analysis",
00041 "description", "FFT_fftw3",
00042 0
00043 };
00044 static FactoryRegistrator<ProcessingFactory, FFT_fftw3> reg = metadata;
00045 }
00046
00047 namespace Hidden
00048 {
00049 struct FFT_fftw3_Implementation
00050 {
00051 FFT_fftw3_Implementation(unsigned size)
00052 {
00053
00054 realInput = (double*) fftw_malloc(sizeof(double) * size);
00055 complexOutput = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * size);
00056 fftw_import_system_wisdom();
00057 plan = fftw_plan_dft_r2c_1d(size, realInput, complexOutput, FFTW_ESTIMATE);
00058 }
00059 ~FFT_fftw3_Implementation()
00060 {
00061 fftw_destroy_plan(plan);
00062 fftw_free(realInput);
00063 fftw_free(complexOutput);
00064 }
00065 double * realInput;
00066 fftw_complex * complexOutput;
00067 fftw_plan plan;
00068 };
00069 }
00070
00071
00072 bool FFT_fftw3::ConcreteConfigure(const ProcessingConfig& c)
00073 {
00074 int oldSize=mSize;
00075 FFT_base::ConcreteConfigure(c);
00076 if (mSize<=0)
00077 {
00078 AddConfigErrorMessage("Invalid zero or negative input size");
00079 return false;
00080 }
00081 if (mSize == oldSize) return true;
00082 SetupMemory();
00083 return true;
00084 }
00085
00086 void FFT_fftw3::ReleaseMemory()
00087 {
00088 if (_fftw3) delete _fftw3;
00089 }
00090
00091 void FFT_fftw3::SetupMemory()
00092 {
00093 ReleaseMemory();
00094 _fftw3 = new Hidden::FFT_fftw3_Implementation(mSize);
00095 }
00096
00097 FFT_fftw3::FFT_fftw3(const FFTConfig &c)
00098 : _fftw3(0)
00099 {
00100 Configure(c);
00101 }
00102
00103 FFT_fftw3::~FFT_fftw3()
00104 {
00105 ReleaseMemory();
00106 }
00107
00108 bool FFT_fftw3::Do()
00109 {
00110 mOutput.GetData().SetSize( mInput.GetSize()/2+1);
00111 bool toReturn = Do(mInput.GetAudio(), mOutput.GetData());
00112 mInput.Consume();
00113 mOutput.Produce();
00114 return toReturn;
00115 }
00116
00117 bool FFT_fftw3::Do(const Audio& in, Spectrum &out)
00118 {
00119 CLAM_DEBUG_ASSERT(IsRunning(),
00120 "FFT_fftw3: Do(): Not in execution mode");
00121 CLAM_BEGIN_DEBUG_CHECK
00122 CLAM_WARNING(isPowerOfTwo(mSize),
00123 "FFT_fftw3: Do(): Not a power of two");
00124 CLAM_END_DEBUG_CHECK
00125
00126 out.SetSpectralRange(in.GetSampleRate()/2);
00127 if (mState==sOther) CheckTypes(in,out);
00128 TData * inbuffer = in.GetBuffer().GetPtr();
00129 for (int i=0; i<mSize; i++)
00130 _fftw3->realInput[i] = inbuffer[i];
00131 fftw_execute(_fftw3->plan);
00132 if (mState!=sOther)
00133 ToComplex(out);
00134 else
00135 ToOther(out);
00136 if (mState==sComplexSync)
00137 out.SynchronizeTo(mComplexflags);
00138
00139 return true;
00140 }
00141
00142
00143 void FFT_fftw3::ToComplex(Spectrum &out)
00144 {
00145 Array<Complex>& outbuffer = out.GetComplexArray();
00146 outbuffer.Resize(mSize/2+1);
00147 outbuffer.SetSize(mSize/2+1);
00148 for (int i=0; i<mSize/2+1; i++)
00149 {
00150 outbuffer[i].SetReal(_fftw3->complexOutput[i][0]);
00151 outbuffer[i].SetImag(_fftw3->complexOutput[i][1]);
00152 }
00153 }
00154
00155 };
00156