CLAM-Development
1.1
|
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