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 "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