IFFT_fftw3.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 #include "IFFT_fftw3.hxx"
00023 #include "SpecTypeFlags.hxx"
00024 
00025 #include "Audio.hxx"
00026 #include "Spectrum.hxx"
00027 #include "ProcessingFactory.hxx"
00028 
00029 #include <fftw3.h>
00030 
00031 
00032 namespace CLAM {
00033 
00034 namespace Hidden
00035 {
00036         static const char * metadata[] = {
00037                 "key", "IFFT_fftw3",
00038                 "category", "Synthesis",
00039                 "description", "IFFT_fftw3",
00040                 0
00041         };
00042         static FactoryRegistrator<ProcessingFactory, IFFT_fftw3> reg = metadata;
00043 }
00044         
00045 struct IFFT_fftw3::Implementation
00046 {
00047         Implementation(unsigned size)
00048         {
00049                 // Special malloc which aligns to SIMD segment boundaries
00050                 _complexInput = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * size);
00051                 _realOutput = (double*) fftw_malloc(sizeof(double) * size);
00052                 fftw_import_system_wisdom();
00053                 _plan = fftw_plan_dft_c2r_1d(size, _complexInput, _realOutput, FFTW_ESTIMATE);
00054         }
00055         ~Implementation()
00056         {
00057                 fftw_destroy_plan(_plan);
00058                 fftw_free(_realOutput);
00059                 fftw_free(_complexInput);
00060         }
00061         fftw_plan _plan;
00062         fftw_complex * _complexInput;
00063         double * _realOutput;
00064 };
00065 
00066 IFFT_fftw3::IFFT_fftw3(const IFFTConfig &c)
00067         : _fftw3(0)
00068 { 
00069         Configure(c);
00070 };
00071 
00072 bool IFFT_fftw3::ConcreteConfigure(const ProcessingConfig& c)
00073 {
00074         CopyAsConcreteConfig(mConfig, c);
00075         mSize = CLAM_DEFAULT_IFFT_SIZE;
00076         if (mConfig.HasAudioSize()) {
00077                 CLAM_ASSERT (mConfig.GetAudioSize()>=0,"Wrong (negative) Size in IFFT Configuration.");
00078                 mSize = mConfig.GetAudioSize(); 
00079         }
00080         mOutput.SetSize( mSize );
00081         mOutput.SetHop( mSize );
00082 
00083         mState=sOther;
00084         SetupMemory();
00085         return true;
00086 }
00087 
00088 IFFT_fftw3::~IFFT_fftw3()
00089 {
00090         ReleaseMemory();
00091 }
00092 
00093 void IFFT_fftw3::ReleaseMemory()
00094 {
00095         if (_fftw3) delete _fftw3;
00096 }
00097 void IFFT_fftw3::SetupMemory()
00098 {
00099         ReleaseMemory();
00100         _fftw3 = new Implementation(mSize);
00101 }
00102 
00103 void IFFT_fftw3::CheckTypes(const Spectrum& in, const Audio &out) const
00104 {
00105         CLAM_ASSERT(out.HasBuffer(),"IFFT Do: Float attribute required for Audio object.");
00106         CLAM_BEGIN_CHECK
00107                 // Input object checking
00108                 if (out.GetSize()!=mSize) { 
00109                         std::stringstream ss;
00110                         ss << "IFFT_fftw3::Do: Wrong size in IFFT Audio output\n"
00111                            << "  Expected: " << mSize*2+1 << ", used " << out.GetSize();
00112                         CLAM_ASSERT(0,ss.str().c_str());
00113                 }
00114                 if (in.GetSize() < mSize/2+1 ) { // ALGORITHM DEPENDENT CHECKING
00115                         std::stringstream ss;
00116                         ss << "IFFT_fftw3::Do: not enough memory in input Spectrum.\n"
00117                            << "  Expected: " << mSize/2+1 << ", used " << in.GetSize();
00118                         CLAM_ASSERT(0,ss.str().c_str());
00119 
00120                 }
00121         CLAM_END_CHECK
00122 }
00123 /*
00124 void IFFT_fftw3::Attach(Spectrum &in, Audio& out)
00125 {
00126         mInput.Attach(in);
00127         mOutput.Attach(out);
00128 }
00129 */
00130 
00131 bool IFFT_fftw3::Do()
00132 {
00133         bool toReturn = Do(mInput.GetData(),mOutput.GetAudio());
00134         mInput.Consume();
00135         mOutput.Produce();
00136         return toReturn;
00137 };
00138 
00139 
00140 bool IFFT_fftw3::SetPrototypes(const Spectrum& in, const Audio &out)
00141 {
00142         CheckTypes(in,out);
00143 
00144         SpecTypeFlags flags; 
00145         in.GetType(flags);
00146 
00147         if (flags.bComplex)
00148                 mState=sComplex;
00149         else
00150         {
00151                 CLAM_ASSERT(flags.bPolar || flags.bMagPhase || flags.bMagPhaseBPF,"IFFT_fftw3: SetPrototypes(): No Spectrum Attributes!");
00152                 mState=sOther;
00153         }
00154         // TODO: Maybe should update the prototype in the port?
00155 
00156         return true;
00157 }
00158 
00159 bool IFFT_fftw3::UnsetPrototypes()
00160 {
00161         mState=sOther;
00162         return true;
00163 }
00164 
00165 
00166 bool IFFT_fftw3::Do( const Spectrum& in, Audio &out) const
00167 {
00168         CLAM_ASSERT(IsRunning() ,"IFFT_fftw3: Do(): Not in execution mode");
00169         CLAM_ASSERT(out.GetSize() == mSize,
00170                 "Not proper IFFT output size");
00171 
00172         if (mState==sComplex)
00173                 ComplexToRIFFTW(in);
00174         else
00175         {
00176                 CheckTypes(in,out);
00177                 OtherToRIFFTW(in);
00178         }
00179         fftw_execute(_fftw3->_plan);
00180         TData * outbuffer = out.GetBuffer().GetPtr();
00181         for (int i=0; i<mSize; i++)
00182                 outbuffer[i] = _fftw3->_realOutput[i];
00183 
00184         out.SetSampleRate(TData(in.GetSpectralRange()*2));
00185         return true;
00186 }
00187 
00188 bool IFFT_fftw3::SetPrototypes()
00189 {
00190         // @todo Check port prototypes, and set the state (or de
00191         // backup state if disabled) acordingly.
00192         CLAM_ASSERT(false,"IFFT_fftw3::SetPrototypes: Not implemented.");
00193         return false;
00194 }
00195 
00196 inline void IFFT_fftw3::ComplexToRIFFTW(const Spectrum &in) const
00197 {
00198         CLAM_ASSERT(in.HasComplexArray(), "Input spectrum has no complex array");
00199         const Array<Complex> & inbuffer = in.GetComplexArray();
00200         CLAM_ASSERT(inbuffer.Size() == mSize/2+1, "IFFT_fftw3::ComplexToRIFFTW: sizes doesn't match.");
00201         for (int i=0; i< inbuffer.Size(); i++)
00202         {
00203                 _fftw3->_complexInput[i][0] = inbuffer[i].Real()/mSize;
00204                 _fftw3->_complexInput[i][1] = inbuffer[i].Imag()/mSize;
00205         }
00206 /*
00207         // TODO: Use this code for the r2r format
00208         ifftbuffer[0]=(*inbuffer)[0].Real()/mSize;   // Real Values
00209         ifftbuffer[mSize/2]=(*inbuffer)[mSize/2].Real()/mSize;
00210         for (int i=1; i< mSize/2; i++) {
00211                 ifftbuffer[i] = (*inbuffer)[i].Real()/mSize;  
00212                 ifftbuffer[mSize-i] = (*inbuffer)[i].Imag()/mSize;
00213         }
00214         if (mSize&1)
00215                 ifftbuffer[mSize/2+1] = (*inbuffer)[mSize/2].Imag()/mSize;
00216 */
00217 }
00218 
00219 
00220 inline void IFFT_fftw3::OtherToRIFFTW(const Spectrum &in) const
00221 {
00222         if (in.HasComplexArray())
00223         {
00224                 ComplexToRIFFTW(in);
00225                 return;
00226         }
00227         SpecTypeFlags flags;
00228         Spectrum spec = in;
00229         spec.GetType(flags);
00230         flags.bComplex=1;
00231         spec.SetTypeSynchronize(flags);
00232         ComplexToRIFFTW(spec);
00233 }
00234 }
00235 
Generated by  doxygen 1.6.3