26 #include "FastFourierTransform.h"
30 FastFourierTransform::FastFourierTransform(){
32 computeMagnitude =
true;
34 enableZeroPadding =
true;
36 windowFunction = RECTANGULAR_WINDOW;
39 infoLog.setProceedingText(
"[FastFourierTransform]");
40 warningLog.setProceedingText(
"[WARNING FastFourierTransform]");
41 errorLog.setProceedingText(
"[ERROR FastFourierTransform]");
48 this->initialized = rhs.initialized;
49 this->computeMagnitude = rhs.computeMagnitude;
50 this->computePhase = rhs.computePhase;
51 this->enableZeroPadding = rhs.enableZeroPadding;
52 this->windowSize = rhs.windowSize;
53 this->windowFunction = rhs.windowFunction;
54 this->averagePower = 0;
56 this->infoLog = rhs.infoLog;
57 this->warningLog = rhs.warningLog;
58 this->errorLog = rhs.errorLog;
60 if( rhs.initialized ){
61 this->init(rhs.windowSize,rhs.windowFunction,rhs.computeMagnitude,rhs.computePhase);
64 for(UINT i=0; i<this->windowSize; i++){
65 this->fftReal[i] = rhs.fftReal[i];
66 this->fftImag[i] = rhs.fftImag[i];
67 this->magnitude[i] = rhs.magnitude[i];
68 this->phase[i] = rhs.phase[i];
69 this->power[i] = rhs.power[i];
74 FastFourierTransform::~FastFourierTransform() {
81 this->initialized = rhs.initialized;
82 this->computeMagnitude = rhs.computeMagnitude;
83 this->computePhase = rhs.computePhase;
84 this->enableZeroPadding = rhs.enableZeroPadding;
85 this->windowSize = rhs.windowSize;
86 this->windowFunction = rhs.windowFunction;
87 this->averagePower = 0;
90 if( rhs.initialized ){
91 this->init(rhs.windowSize,rhs.windowFunction,rhs.computeMagnitude,rhs.computePhase);
94 for(UINT i=0; i<this->windowSize; i++){
95 this->fftReal[i] = rhs.fftReal[i];
96 this->fftImag[i] = rhs.fftImag[i];
97 this->magnitude[i] = rhs.magnitude[i];
98 this->phase[i] = rhs.phase[i];
99 this->power[i] = rhs.power[i];
106 bool FastFourierTransform::init(
const unsigned int windowSize,
const unsigned int windowFunction,
const bool computeMagnitude,
const bool computePhase,
const bool enableZeroPadding){
112 if( !isPowerOfTwo( windowSize ) ){
116 if( windowFunction != RECTANGULAR_WINDOW && windowFunction != BARTLETT_WINDOW &&
117 windowFunction != HAMMING_WINDOW && windowFunction != HANNING_WINDOW ){
123 this->windowSize = windowSize;
124 this->windowFunction = windowFunction;
125 this->computeMagnitude = computeMagnitude;
126 this->computePhase = computePhase;
127 this->enableZeroPadding = enableZeroPadding;
130 fftReal.
resize( windowSize );
131 fftImag.
resize( windowSize );
132 tmpReal.
resize( windowSize/2 );
133 tmpImag.
resize( windowSize/2 );
134 magnitude.
resize( windowSize );
135 phase.
resize( windowSize );
136 power.
resize( windowSize );
140 for(UINT i=0; i<windowSize/2; i++){
144 for(UINT i=0; i<windowSize; i++){
158 bool FastFourierTransform::computeFFT(
VectorFloat &data ){
165 if( !enableZeroPadding ){
166 if( (
unsigned int)data.size() != windowSize ){
167 errorLog <<
"The size of the data Vector (" << data.size() <<
") does not match the windowSize: " << windowSize << std::endl;
171 if( (
unsigned int)data.size() > windowSize ){
172 errorLog <<
"The size of the data Vector (" << data.size() <<
") is greater than the windowSize: " << windowSize << std::endl;
178 if( !windowData( data ) ){
183 if( enableZeroPadding ){
184 if( ((
unsigned int)data.size()) != windowSize ){
185 const unsigned int oldSize = (
unsigned int)data.size();
186 data.
resize( windowSize );
187 for(
unsigned int i=oldSize; i<windowSize; i++){
194 realFFT(data, &fftReal[0], &fftImag[0]);
198 for(
unsigned int i = 0; i<windowSize/2; i++){
200 if( computeMagnitude ){
201 power[i] = fftReal[i]*fftReal[i] + fftImag[i]*fftImag[i];
202 averagePower += power[i];
203 magnitude[i] = 2.0*sqrt( power[i] );
207 phase[i] = atan2(fftImag[i],fftReal[i]);
212 averagePower = averagePower / (Float)(windowSize/2);
217 bool FastFourierTransform::windowData(
VectorFloat &data ){
219 const unsigned int N = (
unsigned int)data.size();
220 const unsigned int K = N/2;
222 switch( windowFunction ){
223 case RECTANGULAR_WINDOW:
226 case BARTLETT_WINDOW:
227 for(
unsigned int i=0; i<K; i++) {
228 data[i] *= (i / (Float) (K));
229 data[i + K] *= (1.0 - (i / (Float)K));
234 for(
unsigned int i=0; i<N; i++)
235 data[i] *= 0.54 - 0.46 * cos(2 * PI * i / (N - 1));
239 for(
unsigned int i=0; i <N; i++)
240 data[i] *= 0.50 - 0.50 * cos(2 * PI * i / (N - 1));
251 VectorFloat FastFourierTransform::getMagnitudeData(){
255 const unsigned int N = windowSize/2;
258 for(
unsigned int i=0; i<N; i++){
259 magnitudeData[i] = magnitude[i];
262 return magnitudeData;
268 const unsigned int N = windowSize/2;
271 for(
unsigned int i=0; i<N; i++){
272 phaseData[i] = phase[i];
283 for(
unsigned int i=0; i<windowSize/2; i++){
284 powerData[i] = power[i];
290 Float FastFourierTransform::getAveragePower(){
294 Float* FastFourierTransform::getMagnitudeDataPtr(){
295 return &magnitude[0];
298 Float* FastFourierTransform::getPhaseDataPtr(){
302 Float* FastFourierTransform::getPowerDataPtr(){
321 bool FastFourierTransform::realFFT(
const VectorFloat &realIn, Float *realOut, Float *imagOut ){
322 int NumSamples = (int)windowSize;
323 int Half = NumSamples / 2;
326 Float theta = PI / Half;
328 for (i = 0; i < Half; i++) {
329 tmpReal[i] = realIn[2 * i];
330 tmpImag[i] = realIn[2 * i + 1];
333 if( !
FFT(Half, 0, &tmpReal[0], &tmpImag[0], realOut, imagOut) ){
337 Float wtemp = Float(sin(0.5 * theta));
339 Float wpr = -2.0 * wtemp * wtemp;
340 Float wpi = Float (sin(theta));
341 Float wr = 1.0 + wpr;
346 Float h1r, h1i, h2r, h2i;
348 for (i = 1; i < Half / 2; i++) {
352 h1r = 0.5 * (realOut[i] + realOut[i3]);
353 h1i = 0.5 * (imagOut[i] - imagOut[i3]);
354 h2r = 0.5 * (imagOut[i] + imagOut[i3]);
355 h2i = -0.5 * (realOut[i] - realOut[i3]);
357 realOut[i] = h1r + wr * h2r - wi * h2i;
358 imagOut[i] = h1i + wr * h2i + wi * h2r;
359 realOut[i3] = h1r - wr * h2r + wi * h2i;
360 imagOut[i3] = -h1i + wr * h2i + wi * h2r;
362 wr = (wtemp = wr) * wpr - wi * wpi + wr;
363 wi = wi * wpr + wtemp * wpi + wi;
366 realOut[0] = (h1r = realOut[0]) + imagOut[0];
367 imagOut[0] = h1r - imagOut[0];
372 bool FastFourierTransform::FFT(
int numSamples,
bool inverseTransform,Float *realIn, Float *imagIn, Float *realOut, Float *imagOut){
375 int BlockSize, BlockEnd;
377 Float angle_numerator = 2.0 * PI;
380 if( !isPowerOfTwo(numSamples) ) {
381 fprintf(stderr,
"%d is not a power of two\n", numSamples);
385 if( bitTable.size() == 0 ) initFFT();
387 if( inverseTransform ) angle_numerator = -angle_numerator;
389 NumBits = numberOfBitsNeeded(numSamples);
392 for(i = 0; i < numSamples; i++) {
393 j = fastReverseBits(i, NumBits);
394 realOut[j] = realIn[i];
395 imagOut[j] = (imagIn == NULL) ? 0.0 : imagIn[i];
400 for (BlockSize = 2; BlockSize <= numSamples; BlockSize <<= 1) {
402 Float delta_angle = angle_numerator / (Float) BlockSize;
404 Float sm2 = sin(-2 * delta_angle);
405 Float sm1 = sin(-delta_angle);
406 Float cm2 = cos(-2 * delta_angle);
407 Float cm1 = cos(-delta_angle);
409 Float ar0, ar1, ar2, ai0, ai1, ai2;
411 for (i = 0; i < numSamples; i += BlockSize) {
418 for (j = i, n = 0; n < BlockEnd; j++, n++) {
428 tr = ar0 * realOut[k] - ai0 * imagOut[k];
429 ti = ar0 * imagOut[k] + ai0 * realOut[k];
431 realOut[k] = realOut[j] - tr;
432 imagOut[k] = imagOut[j] - ti;
439 BlockEnd = BlockSize;
443 if( inverseTransform ){
444 Float denom = (Float) numSamples;
446 for(i = 0; i < numSamples; i++) {
455 int FastFourierTransform::numberOfBitsNeeded(
int powerOfTwo)
457 for (
int i = 0;; i++){
458 if (powerOfTwo & (1 << i)){
465 int FastFourierTransform::reverseBits(
int index,
int numBits)
469 for (i = rev = 0; i < numBits; i++) {
470 rev = (rev << 1) | (index & 1);
477 void FastFourierTransform::initFFT()
479 bitTable.
resize( MAX_FAST_BITS );
482 for (
int b = 1; b <= MAX_FAST_BITS; b++) {
484 bitTable[b - 1].
resize(len);
486 for (
int i = 0; i < len; i++)
487 bitTable[b - 1][i] = reverseBits(i, b);
493 inline int FastFourierTransform::fastReverseBits(
const int i,
const int numBits)
495 if (numBits <= MAX_FAST_BITS)
496 return bitTable[numBits - 1][i];
498 return reverseBits(i, numBits);
501 inline bool FastFourierTransform::isPowerOfTwo(
const unsigned int x){
502 if (x < 2)
return false;
503 if (x & (x - 1))
return false;
virtual bool resize(const unsigned int size)