FourierTransform.cxx
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <cmath>
00023 #include "FourierTransform.hxx"
00024 #include <iostream>
00025
00026 #define SWAP(a,b) do {double swaptemp=(a); (a)=(b); (b)=swaptemp;} while(false)
00027
00028
00029
00030
00031 FourierTransform::FourierTransform(unsigned long int framesize, double datanorm, bool isComplex)
00032 : mFrameSize(framesize)
00033 , mIsComplex(isComplex)
00034 {
00035 _spectrum.resize(2*mFrameSize);
00036 #if USE_FFTW3
00037 _realInput = (double*) fftw_malloc(sizeof(double) * mFrameSize);
00038 _complexOutput = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * mFrameSize);
00039
00040 fftw_import_system_wisdom();
00041 if (isComplex)
00042 _plan = fftw_plan_dft_1d(framesize, _complexOutput, _complexOutput, 1, FFTW_ESTIMATE);
00043 else
00044 _plan = fftw_plan_dft_r2c_1d(framesize, _realInput, _complexOutput, FFTW_ESTIMATE);
00045 #endif
00046 }
00047
00048 FourierTransform::~FourierTransform()
00049 {
00050 #if USE_FFTW3
00051 fftw_destroy_plan(_plan);
00052 fftw_free(_realInput);
00053 fftw_free(_complexOutput);
00054 #endif
00055 }
00056
00057
00058
00059
00060
00061
00062
00063 void doFourierTransform(double * data, unsigned frameSize)
00064 {
00065
00066 const unsigned long n=frameSize<<1;
00067 for (unsigned long i=1, j=1; i<n; i+=2) {
00068 if (j>i) {
00069 SWAP(data[j], data[i]);
00070 SWAP(data[j+1], data[i+1]);
00071 }
00072 unsigned long m=frameSize;
00073 while (m >= 2 && j>m) {
00074 j-= m;
00075 m >>= 1;
00076 }
00077 j += (m);
00078 }
00079
00080 unsigned long istep;
00081 for (unsigned long mmax = 2; mmax<n; mmax = istep)
00082 {
00083 istep = mmax << 1;
00084 const double theta =(6.28318530717959/mmax);
00085 double wtemp = sin(0.5*theta);
00086 double wpr = -2.0*wtemp*wtemp;
00087 double wpi = sin(theta);
00088 double wr=1.0;
00089 double wi=0.0;
00090 for(unsigned long m=1; m<mmax; m+=2) {
00091 for (unsigned long i=m; i<=n; i+=istep) {
00092 unsigned long j = i+mmax;
00093 double tempr = float (wr*data[j] - wi*data[j+1]);
00094 double tempi = float (wr*data[j+1] + wi*data[j]);
00095 data[j] = data[i] - tempr;
00096 data[j+1] = data[i+1] - tempi;
00097 data[i] += tempr;
00098 data[i+1] += tempi;
00099 }
00100 wtemp=wr;
00101 wr = wtemp*wpr - wi*wpi + wr;
00102
00103 wi = wi*wpr + wtemp*wpi + wi;
00104 }
00105 }
00106 }
00107
00108 template <typename T>
00109 void FourierTransform::doItGeneric(const T * input)
00110 {
00111 double * spectrum = &_spectrum[0];
00112 #if USE_FFTW3
00113 fftw_complex * complexOutput = &_complexOutput[0];
00114 if (mIsComplex)
00115 {
00116 for (unsigned long i=0; i<mFrameSize; i++)
00117 {
00118 complexOutput[i][0] = input[i<<1];
00119 complexOutput[i][1] = input[(i<<1)+1];
00120 }
00121 fftw_execute(_plan);
00122 for (unsigned long i=0; i<mFrameSize*2; i+=2)
00123 {
00124 spectrum[i] = complexOutput[i/2][0];
00125 spectrum[i+1] = complexOutput[i/2][1];
00126 }
00127 }
00128 else
00129 {
00130 for (unsigned long i=0; i<mFrameSize; i++)
00131 {
00132 _realInput[i] = input[i];
00133 }
00134 fftw_execute(_plan);
00135 for (int i=0; i<mFrameSize; i+=2)
00136 {
00137 spectrum[i] = complexOutput[i/2][0];
00138 spectrum[i+1] = - complexOutput[i/2][1];
00139 }
00140 for (int i=1; i<mFrameSize; i+=2)
00141 {
00142 unsigned j = mFrameSize*2-i;
00143 spectrum[j] = complexOutput[i/2][0];
00144 spectrum[j+1] = complexOutput[i/2][1];
00145 }
00146 }
00147 #else
00148 if (mIsComplex)
00149 {
00150 for (unsigned long i=0; i<mFrameSize*2; i++)
00151 spectrum[i] = input[i];
00152 }
00153 else
00154 {
00155 for (unsigned long i=0; i<mFrameSize*2; i+=2)
00156 {
00157 spectrum[i] = input[i/2];
00158 spectrum[i+1] = 0.0;
00159 }
00160 }
00161 double * data = spectrum-1;
00162 doFourierTransform(data, mFrameSize);
00163 #endif
00164 }
00165
00166 void FourierTransform::doIt(const float * input)
00167 {
00168 doItGeneric(input);
00169 }
00170 void FourierTransform::doIt(const double * input)
00171 {
00172 doItGeneric(input);
00173 }
00174
00175
00176