00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 
00034 
00035 
00036 
00038 
00039 
00040 #include <string.h>
00041 #include <math.h>
00042 
00043 
00044 #include "zplVecLib.h"
00045 #include "fft.h"
00046 
00047 #if !defined(_2PI)
00048 #define _2PI                    (float)(6.283185307179586476925286766559)    
00049 #endif
00050 
00051 class CzplfFFTGen : public CzplfFFT_If
00052 {
00053 public:
00054 
00055     
00057     CzplfFFTGen (int iBlockLength, int iZeroPadFactor, _Fft_Windows_ eWindowType);
00059     virtual ~CzplfFFTGen ();
00060 
00061 
00070     void           zplfFFT         (zCOMPLEX *pfDest, float *pfSrc);
00071 
00080     void           zplfIFFT        (float *pfDest, zCOMPLEX *pfSrc);
00081 
00082     int      m_eLastError;
00083 
00084 protected:
00085 
00086     int      BuildFFTTables ();
00087     void       FreeFFTTables ();
00088 
00089     float    *m_pfSinTable,
00090                 *m_pfCosTable;
00091 
00092 };
00093 
00094 
00095 
00096 CzplfFFTGen::CzplfFFTGen (int iBlockLength, int iZeroPadFactor, _Fft_Windows_ eWindowType)
00097 {
00098     m_eLastError    = 0;
00099     m_iBlockLength  = iBlockLength;
00100     m_iFFTLength    = m_iBlockLength * iZeroPadFactor;
00101 
00102     m_pfWindow      = 0;
00103     m_pfWindow      = zplfMalloc (m_iBlockLength);
00104 
00105     if (!m_pfWindow)
00106         m_eLastError    = -1;
00107     else
00108         this->CalculateWindow (eWindowType);
00109 
00110     m_pfSinTable    = 0;
00111     m_pfCosTable    = 0;
00112 
00113     m_eLastError   |= this->BuildFFTTables ();
00114 }
00115 
00116 
00117 CzplfFFTGen::~CzplfFFTGen ()
00118 {
00119     if (m_pfWindow)
00120         zplfFree (m_pfWindow);
00121 
00122     this->FreeFFTTables ();
00123 }
00124     
00125 
00126 void CzplfFFTGen::zplfFFT         (zCOMPLEX *pfDest, float *pfSrc)
00127 {
00128     ZASSERT ((pfDest == 0) || (pfSrc == 0));
00129     ZASSERT ((m_pfSinTable == 0) || (m_pfCosTable == 0) || (m_pfWindow == 0));
00130     ZASSERT (m_eLastError != 0);
00131 
00132     
00133     if (pfDest != pfSrc)
00134         memcpy (pfDest, pfSrc, sizeof (float) * m_iBlockLength);
00135 
00136     
00137     if (m_iFFTLength-m_iBlockLength > 0)
00138         zplfSetZero (&pfDest[m_iBlockLength], (m_iFFTLength - m_iBlockLength));
00139 
00140     
00141     zplfRealMul_I (pfDest, m_pfWindow, m_iBlockLength);
00142 
00143     
00144     zRealFFTSplitGeneric (pfDest, m_iFFTLength, m_pfSinTable, m_pfCosTable);
00145 
00146     return;
00147 }
00148 
00149 void CzplfFFTGen::zplfIFFT         (float *pfDest, zCOMPLEX *pfSrc)
00150 {
00151     ZASSERT ((pfDest == 0) || (pfSrc == 0));
00152     ZASSERT ((m_pfSinTable == 0) || (m_pfCosTable == 0) || (m_pfWindow == 0));
00153     ZASSERT (m_eLastError != 0);
00154 
00155     
00156     zRealIFFTSplitGeneric (pfSrc, m_iFFTLength, m_pfSinTable, m_pfCosTable);
00157 
00158     
00159     memcpy (pfDest, pfSrc, sizeof (float) * m_iBlockLength);
00160 
00161     return;
00162 }
00163 
00164 int CzplfFFTGen::BuildFFTTables ()
00165 {
00166     int    iQuarterBlockSize   = (m_iFFTLength>>3)-1;
00167     float  fPiBlock            = _2PI / m_iFFTLength,
00168             f3PiBlock           = 3.0F * fPiBlock;
00169 
00170     m_pfSinTable        = zplfMalloc (1+(iQuarterBlockSize<<1));
00171     if (m_pfSinTable == 0)
00172         return -1;
00173     m_pfCosTable        = zplfMalloc (1+(iQuarterBlockSize<<1));
00174     if (m_pfCosTable == 0)
00175         return -1;
00176 
00177     for (int i = 0; i < iQuarterBlockSize; i++)
00178     {
00179         m_pfSinTable[i]                     = sinf ((i+1) * fPiBlock);
00180         m_pfCosTable[i]                     = cosf ((i+1) * fPiBlock);
00181 
00182         m_pfSinTable[i+iQuarterBlockSize]   = sinf ((i+1) * f3PiBlock);
00183         m_pfCosTable[i+iQuarterBlockSize]   = cosf ((i+1) * f3PiBlock);
00184     }
00185 
00186     return 0;
00187 }
00188 
00189 void CzplfFFTGen::FreeFFTTables ()
00190 {
00191     if (m_pfSinTable)
00192         zplfFree (m_pfSinTable);
00193     if (m_pfCosTable)
00194         zplfFree (m_pfCosTable);
00195 }
00196 
00197 
00198 
00199 int zplfFFTCreateInstance_Gen (CzplfFFT_If*& pCFFT, int iBlockLength, int iZeroPadFactor, CzplfFFT_If::_Fft_Windows_ eWindowType)
00200 {
00201     int          rErr        = 0;
00202     CzplfFFTGen     *pCNewFFT   = 0;
00203     pCFFT                       = 0;
00204 
00205     
00206     if ((iZeroPadFactor <= 0))
00207         return -1;
00208     if ((iBlockLength <= 0))
00209         return -1;
00210     if ((iBlockLength%4 != 0))
00211         return -1;
00212     if ((iZeroPadFactor != Int2PowTwo (iZeroPadFactor)))
00213         return -1;
00214     if ((iBlockLength != Int2PowTwo (iBlockLength)))
00215         return -1;
00216     
00217     pCNewFFT = new CzplfFFTGen (iBlockLength, iZeroPadFactor, eWindowType);
00218     
00219     if ((pCNewFFT == 0) || (pCNewFFT->m_eLastError != 0))
00220         return -1;
00221     else
00222         pCFFT   = pCNewFFT;
00223 
00224     return 0;
00225 }
00226 
00227 
00228 int zplfFFTDestroyInstance_Gen (CzplfFFT_If*& pCFFT)
00229 {
00230     CzplfFFTGen     *pCRealFFT   = (CzplfFFTGen*)pCFFT;
00231     if (pCRealFFT == 0)
00232         return -1;
00233     
00234     delete pCRealFFT;
00235     pCFFT = 0;
00236 
00237     return 0;
00238 
00239 }