IFFT_ooura.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 
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 
Generated by  doxygen 1.6.3