26 #define GRT_DLL_EXPORTS 27 #include "FastFourierTransform.h" 31 FastFourierTransform::FastFourierTransform(){
33 computeMagnitude =
true;
35 enableZeroPadding =
true;
37 windowFunction = RECTANGULAR_WINDOW;
45 this->initialized = rhs.initialized;
46 this->computeMagnitude = rhs.computeMagnitude;
47 this->computePhase = rhs.computePhase;
48 this->enableZeroPadding = rhs.enableZeroPadding;
49 this->windowSize = rhs.windowSize;
50 this->windowFunction = rhs.windowFunction;
51 this->averagePower = 0;
53 this->infoLog = rhs.infoLog;
54 this->warningLog = rhs.warningLog;
55 this->errorLog = rhs.errorLog;
57 if( rhs.initialized ){
58 this->init(rhs.windowSize,rhs.windowFunction,rhs.computeMagnitude,rhs.computePhase);
61 for(UINT i=0; i<this->windowSize; i++){
62 this->fftReal[i] = rhs.fftReal[i];
63 this->fftImag[i] = rhs.fftImag[i];
64 this->magnitude[i] = rhs.magnitude[i];
65 this->phase[i] = rhs.phase[i];
66 this->power[i] = rhs.power[i];
71 FastFourierTransform::~FastFourierTransform() {
78 this->initialized = rhs.initialized;
79 this->computeMagnitude = rhs.computeMagnitude;
80 this->computePhase = rhs.computePhase;
81 this->enableZeroPadding = rhs.enableZeroPadding;
82 this->windowSize = rhs.windowSize;
83 this->windowFunction = rhs.windowFunction;
84 this->averagePower = 0;
87 if( rhs.initialized ){
88 this->init(rhs.windowSize,rhs.windowFunction,rhs.computeMagnitude,rhs.computePhase);
91 for(UINT i=0; i<this->windowSize; i++){
92 this->fftReal[i] = rhs.fftReal[i];
93 this->fftImag[i] = rhs.fftImag[i];
94 this->magnitude[i] = rhs.magnitude[i];
95 this->phase[i] = rhs.phase[i];
96 this->power[i] = rhs.power[i];
103 bool FastFourierTransform::init(
const unsigned int windowSize,
const unsigned int windowFunction,
const bool computeMagnitude,
const bool computePhase,
const bool enableZeroPadding){
109 if( !isPowerOfTwo( windowSize ) ){
113 if( windowFunction != RECTANGULAR_WINDOW && windowFunction != BARTLETT_WINDOW &&
114 windowFunction != HAMMING_WINDOW && windowFunction != HANNING_WINDOW ){
120 this->windowSize = windowSize;
121 this->windowFunction = windowFunction;
122 this->computeMagnitude = computeMagnitude;
123 this->computePhase = computePhase;
124 this->enableZeroPadding = enableZeroPadding;
127 fftReal.
resize( windowSize );
128 fftImag.
resize( windowSize );
129 tmpReal.
resize( windowSize/2 );
130 tmpImag.
resize( windowSize/2 );
131 magnitude.
resize( windowSize );
132 phase.
resize( windowSize );
133 power.
resize( windowSize );
137 for(UINT i=0; i<windowSize/2; i++){
141 for(UINT i=0; i<windowSize; i++){
155 bool FastFourierTransform::computeFFT(
VectorFloat &data ){
162 if( !enableZeroPadding ){
163 if( (
unsigned int)data.size() != windowSize ){
164 errorLog <<
"The size of the data Vector (" << data.size() <<
") does not match the windowSize: " << windowSize << std::endl;
168 if( (
unsigned int)data.size() > windowSize ){
169 errorLog <<
"The size of the data Vector (" << data.size() <<
") is greater than the windowSize: " << windowSize << std::endl;
175 if( !windowData( data ) ){
180 if( enableZeroPadding ){
181 if( ((
unsigned int)data.size()) != windowSize ){
182 const unsigned int oldSize = (
unsigned int)data.size();
183 data.
resize( windowSize );
184 for(
unsigned int i=oldSize; i<windowSize; i++){
191 realFFT(data, &fftReal[0], &fftImag[0]);
195 for(
unsigned int i = 0; i<windowSize/2; i++){
197 if( computeMagnitude ){
198 power[i] = fftReal[i]*fftReal[i] + fftImag[i]*fftImag[i];
199 averagePower += power[i];
200 magnitude[i] = 2.0*sqrt( power[i] );
204 phase[i] = atan2(fftImag[i],fftReal[i]);
209 averagePower = averagePower / (Float)(windowSize/2);
214 bool FastFourierTransform::windowData(
VectorFloat &data ){
216 const unsigned int N = (
unsigned int)data.size();
217 const unsigned int K = N/2;
219 switch( windowFunction ){
220 case RECTANGULAR_WINDOW:
223 case BARTLETT_WINDOW:
224 for(
unsigned int i=0; i<K; i++) {
225 data[i] *= (i / (Float) (K));
226 data[i + K] *= (1.0 - (i / (Float)K));
231 for(
unsigned int i=0; i<N; i++)
232 data[i] *= 0.54 - 0.46 * cos(2 * PI * i / (N - 1));
236 for(
unsigned int i=0; i <N; i++)
237 data[i] *= 0.50 - 0.50 * cos(2 * PI * i / (N - 1));
248 VectorFloat FastFourierTransform::getMagnitudeData()
const {
252 const unsigned int N = windowSize/2;
255 for(
unsigned int i=0; i<N; i++){
256 magnitudeData[i] = magnitude[i];
259 return magnitudeData;
262 VectorFloat FastFourierTransform::getPhaseData()
const {
265 const unsigned int N = windowSize/2;
268 for(
unsigned int i=0; i<N; i++){
269 phaseData[i] = phase[i];
275 VectorFloat FastFourierTransform::getPowerData()
const {
280 for(
unsigned int i=0; i<windowSize/2; i++){
281 powerData[i] = power[i];
287 Float FastFourierTransform::getAveragePower()
const {
291 Float* FastFourierTransform::getMagnitudeDataPtr(){
292 return &magnitude[0];
295 Float* FastFourierTransform::getPhaseDataPtr(){
299 Float* FastFourierTransform::getPowerDataPtr(){
318 bool FastFourierTransform::realFFT(
const VectorFloat &realIn, Float *realOut, Float *imagOut ){
319 int NumSamples = (int)windowSize;
320 int Half = NumSamples / 2;
323 Float theta = PI / Half;
325 for (i = 0; i < Half; i++) {
326 tmpReal[i] = realIn[2 * i];
327 tmpImag[i] = realIn[2 * i + 1];
330 if( !
FFT(Half, 0, &tmpReal[0], &tmpImag[0], realOut, imagOut) ){
334 Float wtemp = Float(sin(0.5 * theta));
336 Float wpr = -2.0 * wtemp * wtemp;
337 Float wpi = Float (sin(theta));
338 Float wr = 1.0 + wpr;
343 Float h1r, h1i, h2r, h2i;
345 for (i = 1; i < Half / 2; i++) {
349 h1r = 0.5 * (realOut[i] + realOut[i3]);
350 h1i = 0.5 * (imagOut[i] - imagOut[i3]);
351 h2r = 0.5 * (imagOut[i] + imagOut[i3]);
352 h2i = -0.5 * (realOut[i] - realOut[i3]);
354 realOut[i] = h1r + wr * h2r - wi * h2i;
355 imagOut[i] = h1i + wr * h2i + wi * h2r;
356 realOut[i3] = h1r - wr * h2r + wi * h2i;
357 imagOut[i3] = -h1i + wr * h2i + wi * h2r;
359 wr = (wtemp = wr) * wpr - wi * wpi + wr;
360 wi = wi * wpr + wtemp * wpi + wi;
363 realOut[0] = (h1r = realOut[0]) + imagOut[0];
364 imagOut[0] = h1r - imagOut[0];
369 bool FastFourierTransform::FFT(
int numSamples,
bool inverseTransform,Float *realIn, Float *imagIn, Float *realOut, Float *imagOut){
372 int BlockSize, BlockEnd;
374 Float angle_numerator = 2.0 * PI;
377 if( !isPowerOfTwo(numSamples) ) {
378 fprintf(stderr,
"%d is not a power of two\n", numSamples);
382 if( bitTable.size() == 0 ) initFFT();
384 if( inverseTransform ) angle_numerator = -angle_numerator;
386 NumBits = numberOfBitsNeeded(numSamples);
389 for(i = 0; i < numSamples; i++) {
390 j = fastReverseBits(i, NumBits);
391 realOut[j] = realIn[i];
392 imagOut[j] = (imagIn == NULL) ? 0.0 : imagIn[i];
397 for (BlockSize = 2; BlockSize <= numSamples; BlockSize <<= 1) {
399 Float delta_angle = angle_numerator / (Float) BlockSize;
401 Float sm2 = sin(-2 * delta_angle);
402 Float sm1 = sin(-delta_angle);
403 Float cm2 = cos(-2 * delta_angle);
404 Float cm1 = cos(-delta_angle);
406 Float ar0, ar1, ar2, ai0, ai1, ai2;
408 for (i = 0; i < numSamples; i += BlockSize) {
415 for (j = i, n = 0; n < BlockEnd; j++, n++) {
425 tr = ar0 * realOut[k] - ai0 * imagOut[k];
426 ti = ar0 * imagOut[k] + ai0 * realOut[k];
428 realOut[k] = realOut[j] - tr;
429 imagOut[k] = imagOut[j] - ti;
436 BlockEnd = BlockSize;
440 if( inverseTransform ){
441 Float denom = (Float) numSamples;
443 for(i = 0; i < numSamples; i++) {
452 int FastFourierTransform::numberOfBitsNeeded(
int powerOfTwo)
454 for (
int i = 0;; i++){
455 if (powerOfTwo & (1 << i)){
462 int FastFourierTransform::reverseBits(
int index,
int numBits)
466 for (i = rev = 0; i < numBits; i++) {
467 rev = (rev << 1) | (index & 1);
474 void FastFourierTransform::initFFT()
476 bitTable.
resize( MAX_FAST_BITS );
479 for (
int b = 1; b <= MAX_FAST_BITS; b++) {
481 bitTable[b - 1].
resize(len);
483 for (
int i = 0; i < len; i++)
484 bitTable[b - 1][i] = reverseBits(i, b);
490 inline int FastFourierTransform::fastReverseBits(
const int i,
const int numBits)
492 if (numBits <= MAX_FAST_BITS)
493 return bitTable[numBits - 1][i];
495 return reverseBits(i, numBits);
498 inline bool FastFourierTransform::isPowerOfTwo(
const unsigned int x){
499 if (x < 2)
return false;
500 if (x & (x - 1))
return false;
virtual bool resize(const unsigned int size)