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 00023 #include "IFFT_ooura.hxx" 00024 #include "FFT_ooura.hxx" 00025 00026 #include "Assert.hxx" 00027 #include "Audio.hxx" 00028 #include "Spectrum.hxx" 00029 #include "SpectrumConfig.hxx" 00030 #include "CLAM_Math.hxx" 00031 #include "ProcessingFactory.hxx" 00032 00033 namespace CLAM { 00034 00035 namespace Hidden 00036 { 00037 static const char * metadata[] = { 00038 "key", "IFFT_ooura", 00039 "category", "Synthesis", 00040 "description", "IFFT_ooura", 00041 0 00042 }; 00043 static FactoryRegistrator<ProcessingFactory, IFFT_ooura> reg = metadata; 00044 } 00045 00046 00047 bool IFFT_ooura::ConcreteConfigure(const ProcessingConfig& c) { 00048 int oldSize=mSize; 00049 CopyAsConcreteConfig(mConfig, c); 00050 if (mConfig.HasAudioSize()) { 00051 CLAM_ASSERT (mConfig.GetAudioSize()>=0,"Wrong (negative) Size in IFFT Configuration."); 00052 mSize = mConfig.GetAudioSize(); 00053 if(mSize>0) 00054 { 00055 mOutput.SetSize( mSize ); 00056 mOutput.SetHop( mSize ); 00057 } 00058 } 00059 else 00060 mSize = CLAM_DEFAULT_IFFT_SIZE; 00061 00062 mState=sOther; 00063 mComplexflags.bComplex=1; 00064 mComplexflags.bMagPhase=0; 00065 if (mSize>0) { 00066 delete [] ifftbuffer; 00067 ifftbuffer = new TData[mSize]; 00068 } 00069 else ifftbuffer = 0; 00070 00071 if ( !isPowerOfTwo( mSize ) ) 00072 { 00073 AddConfigErrorMessage("Configure failed: IFFT Ooura algorithm only works for input buffers that are a power of two!"); 00074 return false; 00075 } 00076 if (mSize>0) { 00077 if (mSize != oldSize) { 00078 ReleaseMemory(); 00079 SetupMemory(); 00080 } 00081 return true; 00082 } 00083 ReleaseMemory(); 00084 return false; 00085 } 00086 00087 void IFFT_ooura::ReleaseMemory() { 00088 if (ip) { delete[] ip; ip = 0; } 00089 if (w) { delete[] w; w = 0; } 00090 } 00091 00092 void IFFT_ooura::SetupMemory() { 00093 int ipSize = (int)(2+(1<<(int)(log(mSize/2+0.5)/log(2.0))/2)); 00094 ip = new int[ipSize]; 00095 for (int i=0; i<ipSize; i++) ip[i] = 0; 00096 00097 int wSize = (int)(mSize*5/8-1); 00098 w = new TData[wSize]; 00099 for (int i=0; i<wSize; i++) w[i] = 0; 00100 } 00101 00102 IFFT_ooura::IFFT_ooura() 00103 : ip(0), w(0) 00104 { 00105 Configure(IFFTConfig()); 00106 } 00107 00108 IFFT_ooura::IFFT_ooura(const IFFTConfig &c) throw(ErrDynamicType) 00109 : ip(0), w(0) 00110 { 00111 Configure(c); 00112 }; 00113 00114 IFFT_ooura::~IFFT_ooura() 00115 { 00116 ReleaseMemory(); 00117 } 00118 00119 bool IFFT_ooura::Do() 00120 { 00121 bool toReturn = Do(mInput.GetData(),mOutput.GetAudio()); 00122 mInput.Consume(); 00123 mOutput.Produce(); 00124 return toReturn; 00125 } 00126 00127 bool IFFT_ooura::Do(const Spectrum& in, Audio &out) const{ 00128 TData* outbuffer = out.GetBuffer().GetPtr(); 00129 int i; 00130 00131 CLAM_DEBUG_ASSERT(IsRunning(), 00132 "IFFT_ooura: Do(): Not in execution mode"); 00133 00134 CLAM_DEBUG_ASSERT(isPowerOfTwo(mSize), 00135 "IFFT_ooura: Do(): Not a power of two"); 00136 00137 out.SetSampleRate(in.GetSpectralRange()*2); 00138 00139 TData twoOverSize = 2.0/mSize; 00140 00141 switch(mState) { 00142 case sComplex: 00143 ComplexToIFFTOoura(in); 00144 FFT_ooura::rdft(mSize, -1, ifftbuffer, ip, w); 00145 // Buffer dump. This is a kludge; the right way to do this 00146 // is using a non-inplace version of rdft (which would 00147 // not reduce performance). 00148 for (i=0; i<mSize; i++) 00149 outbuffer[i]=ifftbuffer[i]*twoOverSize; 00150 break; 00151 case sOther: 00152 OtherToIFFTOoura(in); 00153 FFT_ooura::rdft(mSize, -1, ifftbuffer, ip, w); 00154 // Buffer dump. This is a kludge; the right way to do this 00155 // is using a non-inplace version of rdft (which would 00156 // not reduce performance). 00157 for (i=0; i<mSize; i++) 00158 outbuffer[i]=ifftbuffer[i]*twoOverSize; 00159 00160 break; 00161 default: 00162 CLAM_ASSERT(false, "IFFT_ooura: Do(): Inconsistent state"); 00163 } 00164 00165 return true; 00166 } 00167 00168 void IFFT_ooura::ComplexToIFFTOoura(const Spectrum &in) const { 00169 int i; 00170 Array<Complex> inbuffer = in.GetComplexArray(); 00171 00172 ifftbuffer[0] = inbuffer[0].Real(); 00173 ifftbuffer[1] = inbuffer[mSize/2].Real(); 00174 00175 for (i=1; i<mSize/2; i++) { 00176 ifftbuffer[2*i] = inbuffer[i].Real(); 00177 ifftbuffer[2*i+1] = -inbuffer[i].Imag(); 00178 } 00179 } 00180 00181 inline void IFFT_ooura::OtherToIFFTOoura(const Spectrum &in) const 00182 { 00183 SpecTypeFlags flags; 00184 in.GetType(flags); 00185 /* if(flags.bMagPhase) 00186 { 00187 DataArray& inMag = in.GetMagBuffer(); 00188 DataArray& inPhase = in.GetPhaseBuffer(); 00189 ifftbuffer[0] = inMag[0]*CLAM_cos(inPhase[0]);//inbuffer[0].Real(); 00190 ifftbuffer[1] = inMag[mSize/2]*CLAM_cos(inPhase[mSize/2]);//inbuffer[mSize/2].Real(); 00191 int i; 00192 TData* ifftbuffer_iter1 = &(ifftbuffer[2]); 00193 TData* ifftbuffer_iter2 = &(ifftbuffer[3]); 00194 TData* inMag_iter = &(inMag[1]); 00195 TData* inPhase_iter = &(inPhase[1]); 00196 for (i=1; i<mSize/2; ifftbuffer_iter1+=2,ifftbuffer_iter2+=2, inMag_iter++, inPhase_iter++, i++) { 00197 *ifftbuffer_iter1 = (*inMag_iter)*CLAM_cos((*inPhase_iter)); 00198 *ifftbuffer_iter2 = (*inMag_iter)*CLAM_sin(*inPhase_iter); 00199 } 00200 00201 } 00202 else 00203 { 00204 */ Spectrum tmpSpec = in; 00205 if (!in.HasComplexArray()) { 00206 flags.bComplex=1; 00207 tmpSpec.SetTypeSynchronize(flags); 00208 } 00209 ComplexToIFFTOoura(tmpSpec); 00210 // } 00211 00212 } 00213 00214 bool IFFT_ooura::SetPrototypes(const Spectrum& in, const Audio &out) 00215 { 00216 CheckTypes(in,out); 00217 00218 SpecTypeFlags flags; 00219 in.GetType(flags); 00220 00221 if (flags.bComplex) 00222 mState=sComplex; 00223 else 00224 { 00225 CLAM_ASSERT(flags.bPolar || flags.bMagPhase || flags.bMagPhaseBPF,"IFFT_ooura: SetPrototypes(): No Spectrum Attributes!"); 00226 mState=sOther; 00227 } 00228 // TODO: Maybe should update the prototype in the port? 00229 00230 return true; 00231 } 00232 00233 bool IFFT_ooura::SetPrototypes() 00234 { 00235 // @todo Check port prototypes, and set the state (or de 00236 // backup state if disabled) acordingly. 00237 CLAM_ASSERT(false,"IFFT_ooura::SetPrototypes: Not implemented."); 00238 return false; 00239 } 00240 00241 bool IFFT_ooura::UnsetPrototypes() 00242 { 00243 mState=sOther; 00244 return true; 00245 } 00246 00247 void IFFT_ooura::CheckTypes(const Spectrum& in, const Audio &out) const 00248 { 00249 CLAM_ASSERT(out.HasBuffer(),"IFFT Do: Float attribute required for Audio object."); 00250 CLAM_BEGIN_CHECK 00251 // Input object checking 00252 if (out.GetSize()!=mSize) { 00253 std::stringstream ss; 00254 ss << "IFFT_ooura::Do: Wrong size in IFFT Audio output\n" 00255 << " Expected: " << mSize*2+1 << ", used " << out.GetSize(); 00256 CLAM_ASSERT(0,ss.str().c_str()); 00257 } 00258 if (in.GetSize() < mSize/2+1 ) { // ALGORITHM DEPENDENT CHECKING 00259 std::stringstream ss; 00260 ss << "IFFT_ooura::Do: not enough memory in input Spectrum.\n" 00261 << " Expected: " << mSize/2+1 << ", used " << in.GetSize(); 00262 CLAM_ASSERT(0,ss.str().c_str()); 00263 00264 } 00265 CLAM_END_CHECK 00266 } 00267 00268 00269 00270 00271 }; // CLAM 00272