FFT.cpp

Go to the documentation of this file.
00001 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
00002 
00003 #include "FFT.h"
00004 
00005 #include <fftw.h>
00006 
00007 FFT::FFT(unsigned int size) :
00008     m_size(size),
00009     m_table(0),
00010     m_spare(0)
00011 {
00012     if (m_size < 2) throw InvalidSize;
00013     if (m_size & (m_size-1)) throw InvalidSize;
00014 
00015     m_table = new int[m_size];
00016     
00017     unsigned int bits;
00018     unsigned int i, j, k, m;
00019 
00020     for (i = 0; ; ++i) {
00021         if (m_size & (1 << i)) {
00022             bits = i;
00023             break;
00024         }
00025     }
00026 
00027     for (i = 0; i < m_size; ++i) {
00028         
00029         m = i;
00030         
00031         for (j = k = 0; j < bits; ++j) {
00032             k = (k << 1) | (m & 1);
00033             m >>= 1;
00034         }
00035         
00036         m_table[i] = k;
00037     }
00038 
00039     m_spare = new double[m_size];
00040 }
00041 
00042 FFT::~FFT()
00043 {
00044     delete[] m_table;
00045     delete[] m_spare;
00046 }
00047 
00048 void
00049 FFT::tune()
00050 {
00051     double *a = new double[m_size];
00052     double *b = new double[m_size];
00053     double *c = new double[m_size];
00054     double *d = new double[m_size];
00055     fftw_complex *ac = new fftw_complex[m_size];
00056     
00057     for (unsigned int i = 0; i < m_size; ++i) {
00058         a[i] = drand48();
00059         b[i] = 0;
00060     }
00061 
00062     fftw_plan fplan = fftw_plan_dft_r2c_1d(m_size, a, ac, FFTW_MEASURE);
00063     fftw_plan iplan = fftw_plan_dft_c2r_1d(m_size, ac, a, FFTW_MEASURE);
00064 
00065     Profiler *profiler = new Profiler("FFT::tune: FFTW", true);
00066 
00067     for (unsigned int count = 0; count < 1000; ++count) {
00068         fftw_execute(fplan);
00069         fftw_execute(iplan);
00070     }
00071 
00072     delete profiler;
00073     
00074     for (unsigned int i = 0; i < m_size; ++i) {
00075         a[i] = drand48();
00076         b[i] = 0;
00077     }
00078 
00079     profiler = new Profiler("FFT::tune: basefft", true);
00080 
00081     for (unsigned int count = 0; count < 1000; ++count) {
00082         basefft(false, a, b, c, d);
00083         basefft(true, a, b, c, d);
00084     }
00085 
00086     delete profiler;
00087 }    
00088 
00089 void
00090 FFT::forward(double *realIn, double *realOut, double *imagOut)
00091 {
00092     basefft(false, realIn, 0, realOut, imagOut);
00093 }
00094 
00095 void
00096 FFT::inverse(double *realIn, double *imagIn, double *realOut)
00097 {
00098     basefft(true, realIn, imagIn, realOut, m_spare);
00099 }
00100 
00101 void
00102 FFT::basefft(bool inverse, double *ri, double *ii, double *ro, double *io)
00103 {
00104     if (!ri || !ro || !io) return;
00105 
00106     unsigned int i, j, k, m;
00107     unsigned int blockSize, blockEnd;
00108 
00109     double tr, ti;
00110 
00111     double angle = 2.0 * M_PI;
00112     if (inverse) angle = -angle;
00113 
00114     const unsigned int n = m_size;
00115 
00116     if (ii) {
00117         ro[table[0]] = ri[0];
00118         io[table[0]] = ii[0];
00119         for (i = 1; i <= n/2; ++i) {
00120             ro[table[i]] = ri[i];
00121             io[table[i]] = ii[i];
00122             ro[table[n-i]] = ri[i];
00123             io[table[n-i]] = -ii[i];
00124         }
00125     } else {
00126         for (i = 0; i < n; ++i) {
00127             ro[table[i]] = ri[i];
00128             io[table[i]] = 0.0;
00129         }
00130     }
00131 
00132     blockEnd = 1;
00133 
00134     for (blockSize = 2; blockSize <= n; blockSize <<= 1) {
00135 
00136         double delta = angle / (double)blockSize;
00137         double sm2 = -sin(-2 * delta);
00138         double sm1 = -sin(-delta);
00139         double cm2 = cos(-2 * delta);
00140         double cm1 = cos(-delta);
00141         double w = 2 * cm1;
00142         double ar[3], ai[3];
00143 
00144         for (i = 0; i < n; i += blockSize) {
00145 
00146             ar[2] = cm2;
00147             ar[1] = cm1;
00148 
00149             ai[2] = sm2;
00150             ai[1] = sm1;
00151 
00152             for (j = i, m = 0; m < blockEnd; j++, m++) {
00153 
00154                 ar[0] = w * ar[1] - ar[2];
00155                 ar[2] = ar[1];
00156                 ar[1] = ar[0];
00157 
00158                 ai[0] = w * ai[1] - ai[2];
00159                 ai[2] = ai[1];
00160                 ai[1] = ai[0];
00161 
00162                 k = j + blockEnd;
00163                 tr = ar[0] * ro[k] - ai[0] * io[k];
00164                 ti = ar[0] * io[k] + ai[0] * ro[k];
00165 
00166                 ro[k] = ro[j] - tr;
00167                 io[k] = io[j] - ti;
00168 
00169                 ro[j] += tr;
00170                 io[j] += ti;
00171             }
00172         }
00173 
00174         blockEnd = blockSize;
00175     }
00176 
00177 /* fftw doesn't normalise, so nor will we
00178 
00179     if (inverse) {
00180 
00181         double denom = (double)n;
00182 
00183         for (i = 0; i < n; i++) {
00184             ro[i] /= denom;
00185             io[i] /= denom;
00186         }
00187     }
00188 */
00189 }

Generated on Wed Feb 20 15:45:25 2008 for SonicVisualiser by  doxygen 1.5.1