From 94453e54acb0f5213264fe812ce4964ef003f59f Mon Sep 17 00:00:00 2001 From: kosme Date: Thu, 9 Mar 2023 22:28:40 -0600 Subject: [PATCH] Bump to version 1.6 --- changeLog.txt | 3 + library.json | 2 +- library.properties | 2 +- src/arduinoFFT.cpp | 896 +++++++++++++++++++++++---------------------- src/arduinoFFT.h | 176 +++++---- 5 files changed, 579 insertions(+), 500 deletions(-) diff --git a/changeLog.txt b/changeLog.txt index e2cb0fb..33612ef 100644 --- a/changeLog.txt +++ b/changeLog.txt @@ -1,3 +1,6 @@ +03/09/23 v1.6 +Include some functionality from development branch. + 01/27/20 v1.5.5 Lookup table for constants c1 and c2 used during FFT comupting. This increases the FFT computing speed in around 5%. diff --git a/library.json b/library.json index e1a5953..eae9358 100644 --- a/library.json +++ b/library.json @@ -20,7 +20,7 @@ "email": "contact@arduinoos.com" } ], - "version": "1.5.6", + "version": "1.6", "frameworks": ["arduino","mbed","espidf"], "platforms": "*", "headers": "arduinoFFT.h" diff --git a/library.properties b/library.properties index ea09fa2..ee5f5ec 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=arduinoFFT -version=1.5.6 +version=1.6 author=Enrique Condes maintainer=Enrique Condes sentence=A library for implementing floating point Fast Fourier Transform calculations on Arduino. diff --git a/src/arduinoFFT.cpp b/src/arduinoFFT.cpp index f1e6d61..15ab81f 100644 --- a/src/arduinoFFT.cpp +++ b/src/arduinoFFT.cpp @@ -21,489 +21,529 @@ #include "arduinoFFT.h" -arduinoFFT::arduinoFFT(void) -{ // Constructor - #warning("This method is deprecated and may be removed on future revisions.") +arduinoFFT::arduinoFFT(void) { // Constructor +#warning("This method is deprecated and may be removed on future revisions.") } -arduinoFFT::arduinoFFT(double *vReal, double *vImag, uint16_t samples, double samplingFrequency) -{// Constructor - this->_vReal = vReal; - this->_vImag = vImag; - this->_samples = samples; - this->_samplingFrequency = samplingFrequency; - this->_power = Exponent(samples); +arduinoFFT::arduinoFFT(double *vReal, double *vImag, uint16_t samples, + double samplingFrequency) { // Constructor + this->_vReal = vReal; + this->_vImag = vImag; + this->_samples = samples; + this->_samplingFrequency = samplingFrequency; + this->_power = Exponent(samples); } -arduinoFFT::~arduinoFFT(void) -{ -// Destructor +arduinoFFT::~arduinoFFT(void) { + // Destructor } -uint8_t arduinoFFT::Revision(void) -{ - return(FFT_LIB_REV); +uint8_t arduinoFFT::Revision(void) { return (FFT_LIB_REV); } + +void arduinoFFT::Compute(double *vReal, double *vImag, uint16_t samples, + FFTDirection dir) { +#warning("This method is deprecated and may be removed on future revisions.") + Compute(vReal, vImag, samples, Exponent(samples), dir); } -void arduinoFFT::Compute(double *vReal, double *vImag, uint16_t samples, uint8_t dir) -{ - #warning("This method is deprecated and may be removed on future revisions.") - Compute(vReal, vImag, samples, Exponent(samples), dir); -} - -void arduinoFFT::Compute(uint8_t dir) -{// Computes in-place complex-to-complex FFT / - // Reverse bits / - uint16_t j = 0; - for (uint16_t i = 0; i < (this->_samples - 1); i++) { - if (i < j) { - Swap(&this->_vReal[i], &this->_vReal[j]); - if(dir==FFT_REVERSE) - Swap(&this->_vImag[i], &this->_vImag[j]); - } - uint16_t k = (this->_samples >> 1); - while (k <= j) { - j -= k; - k >>= 1; - } - j += k; - } - // Compute the FFT / +void arduinoFFT::Compute(FFTDirection dir) { + // Computes in-place complex-to-complex FFT / + // Reverse bits / + uint16_t j = 0; + for (uint16_t i = 0; i < (this->_samples - 1); i++) { + if (i < j) { + Swap(&this->_vReal[i], &this->_vReal[j]); + if (dir == FFT_REVERSE) + Swap(&this->_vImag[i], &this->_vImag[j]); + } + uint16_t k = (this->_samples >> 1); + while (k <= j) { + j -= k; + k >>= 1; + } + j += k; + } +// Compute the FFT #ifdef __AVR__ - uint8_t index = 0; + uint8_t index = 0; #endif - double c1 = -1.0; - double c2 = 0.0; - uint16_t l2 = 1; - for (uint8_t l = 0; (l < this->_power); l++) { - uint16_t l1 = l2; - l2 <<= 1; - double u1 = 1.0; - double u2 = 0.0; - for (j = 0; j < l1; j++) { - for (uint16_t i = j; i < this->_samples; i += l2) { - uint16_t i1 = i + l1; - double t1 = u1 * this->_vReal[i1] - u2 * this->_vImag[i1]; - double t2 = u1 * this->_vImag[i1] + u2 * this->_vReal[i1]; - this->_vReal[i1] = this->_vReal[i] - t1; - this->_vImag[i1] = this->_vImag[i] - t2; - this->_vReal[i] += t1; - this->_vImag[i] += t2; - } - double z = ((u1 * c1) - (u2 * c2)); - u2 = ((u1 * c2) + (u2 * c1)); - u1 = z; - } + double c1 = -1.0; + double c2 = 0.0; + uint16_t l2 = 1; + for (uint8_t l = 0; (l < this->_power); l++) { + uint16_t l1 = l2; + l2 <<= 1; + double u1 = 1.0; + double u2 = 0.0; + for (j = 0; j < l1; j++) { + for (uint16_t i = j; i < this->_samples; i += l2) { + uint16_t i1 = i + l1; + double t1 = u1 * this->_vReal[i1] - u2 * this->_vImag[i1]; + double t2 = u1 * this->_vImag[i1] + u2 * this->_vReal[i1]; + this->_vReal[i1] = this->_vReal[i] - t1; + this->_vImag[i1] = this->_vImag[i] - t2; + this->_vReal[i] += t1; + this->_vImag[i] += t2; + } + double z = ((u1 * c1) - (u2 * c2)); + u2 = ((u1 * c2) + (u2 * c1)); + u1 = z; + } #ifdef __AVR__ - c2 = pgm_read_float_near(&(_c2[index])); - c1 = pgm_read_float_near(&(_c1[index])); - index++; + c2 = pgm_read_float_near(&(_c2[index])); + c1 = pgm_read_float_near(&(_c1[index])); + index++; #else - c2 = sqrt((1.0 - c1) / 2.0); - c1 = sqrt((1.0 + c1) / 2.0); + c2 = sqrt((1.0 - c1) / 2.0); + c1 = sqrt((1.0 + c1) / 2.0); #endif - if (dir == FFT_FORWARD) { - c2 = -c2; - } - } - // Scaling for reverse transform / - if (dir != FFT_FORWARD) { - for (uint16_t i = 0; i < this->_samples; i++) { - this->_vReal[i] /= this->_samples; - this->_vImag[i] /= this->_samples; - } - } + if (dir == FFT_FORWARD) { + c2 = -c2; + } + } + // Scaling for reverse transform / + if (dir != FFT_FORWARD) { + for (uint16_t i = 0; i < this->_samples; i++) { + this->_vReal[i] /= this->_samples; + this->_vImag[i] /= this->_samples; + } + } } -void arduinoFFT::Compute(double *vReal, double *vImag, uint16_t samples, uint8_t power, uint8_t dir) -{ // Computes in-place complex-to-complex FFT - // Reverse bits - #warning("This method is deprecated and may be removed on future revisions.") - uint16_t j = 0; - for (uint16_t i = 0; i < (samples - 1); i++) { - if (i < j) { - Swap(&vReal[i], &vReal[j]); - if(dir==FFT_REVERSE) - Swap(&vImag[i], &vImag[j]); - } - uint16_t k = (samples >> 1); - while (k <= j) { - j -= k; - k >>= 1; - } - j += k; - } - // Compute the FFT +void arduinoFFT::Compute(double *vReal, double *vImag, uint16_t samples, + uint8_t power, FFTDirection dir) { +// Computes in-place complex-to-complex FFT +// Reverse bits +#warning("This method is deprecated and may be removed on future revisions.") + uint16_t j = 0; + for (uint16_t i = 0; i < (samples - 1); i++) { + if (i < j) { + Swap(&vReal[i], &vReal[j]); + if (dir == FFT_REVERSE) + Swap(&vImag[i], &vImag[j]); + } + uint16_t k = (samples >> 1); + while (k <= j) { + j -= k; + k >>= 1; + } + j += k; + } +// Compute the FFT #ifdef __AVR__ - uint8_t index = 0; + uint8_t index = 0; #endif - double c1 = -1.0; - double c2 = 0.0; - uint16_t l2 = 1; - for (uint8_t l = 0; (l < power); l++) { - uint16_t l1 = l2; - l2 <<= 1; - double u1 = 1.0; - double u2 = 0.0; - for (j = 0; j < l1; j++) { - for (uint16_t i = j; i < samples; i += l2) { - uint16_t i1 = i + l1; - double t1 = u1 * vReal[i1] - u2 * vImag[i1]; - double t2 = u1 * vImag[i1] + u2 * vReal[i1]; - vReal[i1] = vReal[i] - t1; - vImag[i1] = vImag[i] - t2; - vReal[i] += t1; - vImag[i] += t2; - } - double z = ((u1 * c1) - (u2 * c2)); - u2 = ((u1 * c2) + (u2 * c1)); - u1 = z; - } + double c1 = -1.0; + double c2 = 0.0; + uint16_t l2 = 1; + for (uint8_t l = 0; (l < power); l++) { + uint16_t l1 = l2; + l2 <<= 1; + double u1 = 1.0; + double u2 = 0.0; + for (j = 0; j < l1; j++) { + for (uint16_t i = j; i < samples; i += l2) { + uint16_t i1 = i + l1; + double t1 = u1 * vReal[i1] - u2 * vImag[i1]; + double t2 = u1 * vImag[i1] + u2 * vReal[i1]; + vReal[i1] = vReal[i] - t1; + vImag[i1] = vImag[i] - t2; + vReal[i] += t1; + vImag[i] += t2; + } + double z = ((u1 * c1) - (u2 * c2)); + u2 = ((u1 * c2) + (u2 * c1)); + u1 = z; + } #ifdef __AVR__ - c2 = pgm_read_float_near(&(_c2[index])); - c1 = pgm_read_float_near(&(_c1[index])); - index++; + c2 = pgm_read_float_near(&(_c2[index])); + c1 = pgm_read_float_near(&(_c1[index])); + index++; #else - c2 = sqrt((1.0 - c1) / 2.0); - c1 = sqrt((1.0 + c1) / 2.0); + c2 = sqrt((1.0 - c1) / 2.0); + c1 = sqrt((1.0 + c1) / 2.0); #endif - if (dir == FFT_FORWARD) { - c2 = -c2; - } - } - // Scaling for reverse transform - if (dir != FFT_FORWARD) { - for (uint16_t i = 0; i < samples; i++) { - vReal[i] /= samples; - vImag[i] /= samples; - } - } + if (dir == FFT_FORWARD) { + c2 = -c2; + } + } + // Scaling for reverse transform + if (dir != FFT_FORWARD) { + for (uint16_t i = 0; i < samples; i++) { + vReal[i] /= samples; + vImag[i] /= samples; + } + } } -void arduinoFFT::ComplexToMagnitude() -{ // vM is half the size of vReal and vImag - for (uint16_t i = 0; i < this->_samples; i++) { - this->_vReal[i] = sqrt(sq(this->_vReal[i]) + sq(this->_vImag[i])); - } +void arduinoFFT::ComplexToMagnitude() { + // vM is half the size of vReal and vImag + for (uint16_t i = 0; i < this->_samples; i++) { + this->_vReal[i] = sqrt(sq(this->_vReal[i]) + sq(this->_vImag[i])); + } } -void arduinoFFT::ComplexToMagnitude(double *vReal, double *vImag, uint16_t samples) -{ // vM is half the size of vReal and vImag - #warning("This method is deprecated and may be removed on future revisions.") - for (uint16_t i = 0; i < samples; i++) { - vReal[i] = sqrt(sq(vReal[i]) + sq(vImag[i])); - } +void arduinoFFT::ComplexToMagnitude(double *vReal, double *vImag, + uint16_t samples) { +// vM is half the size of vReal and vImag +#warning("This method is deprecated and may be removed on future revisions.") + for (uint16_t i = 0; i < samples; i++) { + vReal[i] = sqrt(sq(vReal[i]) + sq(vImag[i])); + } } -void arduinoFFT::DCRemoval() -{ - // calculate the mean of vData - double mean = 0; - for (uint16_t i = 0; i < this->_samples; i++) - { - mean += this->_vReal[i]; - } - mean /= this->_samples; - // Subtract the mean from vData - for (uint16_t i = 0; i < this->_samples; i++) - { - this->_vReal[i] -= mean; - } +void arduinoFFT::DCRemoval() { + // calculate the mean of vData + double mean = 0; + for (uint16_t i = 0; i < this->_samples; i++) { + mean += this->_vReal[i]; + } + mean /= this->_samples; + // Subtract the mean from vData + for (uint16_t i = 0; i < this->_samples; i++) { + this->_vReal[i] -= mean; + } } -void arduinoFFT::DCRemoval(double *vData, uint16_t samples) -{ - // calculate the mean of vData - #warning("This method is deprecated and may be removed on future revisions.") - double mean = 0; - for (uint16_t i = 0; i < samples; i++) - { - mean += vData[i]; - } - mean /= samples; - // Subtract the mean from vData - for (uint16_t i = 0; i < samples; i++) - { - vData[i] -= mean; - } +void arduinoFFT::DCRemoval(double *vData, uint16_t samples) { +// calculate the mean of vData +#warning("This method is deprecated and may be removed on future revisions.") + double mean = 0; + for (uint16_t i = 0; i < samples; i++) { + mean += vData[i]; + } + mean /= samples; + // Subtract the mean from vData + for (uint16_t i = 0; i < samples; i++) { + vData[i] -= mean; + } } -void arduinoFFT::Windowing(uint8_t windowType, uint8_t dir) -{// Weighing factors are computed once before multiple use of FFT -// The weighing function is symmetric; half the weighs are recorded - double samplesMinusOne = (double(this->_samples) - 1.0); - for (uint16_t i = 0; i < (this->_samples >> 1); i++) { - double indexMinusOne = double(i); - double ratio = (indexMinusOne / samplesMinusOne); - double weighingFactor = 1.0; - // Compute and record weighting factor - switch (windowType) { - case FFT_WIN_TYP_RECTANGLE: // rectangle (box car) - weighingFactor = 1.0; - break; - case FFT_WIN_TYP_HAMMING: // hamming - weighingFactor = 0.54 - (0.46 * cos(twoPi * ratio)); - break; - case FFT_WIN_TYP_HANN: // hann - weighingFactor = 0.54 * (1.0 - cos(twoPi * ratio)); - break; - case FFT_WIN_TYP_TRIANGLE: // triangle (Bartlett) - #if defined(ESP8266) || defined(ESP32) - weighingFactor = 1.0 - ((2.0 * fabs(indexMinusOne - (samplesMinusOne / 2.0))) / samplesMinusOne); - #else - weighingFactor = 1.0 - ((2.0 * abs(indexMinusOne - (samplesMinusOne / 2.0))) / samplesMinusOne); - #endif - break; - case FFT_WIN_TYP_NUTTALL: // nuttall - weighingFactor = 0.355768 - (0.487396 * (cos(twoPi * ratio))) + (0.144232 * (cos(fourPi * ratio))) - (0.012604 * (cos(sixPi * ratio))); - break; - case FFT_WIN_TYP_BLACKMAN: // blackman - weighingFactor = 0.42323 - (0.49755 * (cos(twoPi * ratio))) + (0.07922 * (cos(fourPi * ratio))); - break; - case FFT_WIN_TYP_BLACKMAN_NUTTALL: // blackman nuttall - weighingFactor = 0.3635819 - (0.4891775 * (cos(twoPi * ratio))) + (0.1365995 * (cos(fourPi * ratio))) - (0.0106411 * (cos(sixPi * ratio))); - break; - case FFT_WIN_TYP_BLACKMAN_HARRIS: // blackman harris - weighingFactor = 0.35875 - (0.48829 * (cos(twoPi * ratio))) + (0.14128 * (cos(fourPi * ratio))) - (0.01168 * (cos(sixPi * ratio))); - break; - case FFT_WIN_TYP_FLT_TOP: // flat top - weighingFactor = 0.2810639 - (0.5208972 * cos(twoPi * ratio)) + (0.1980399 * cos(fourPi * ratio)); - break; - case FFT_WIN_TYP_WELCH: // welch - weighingFactor = 1.0 - sq((indexMinusOne - samplesMinusOne / 2.0) / (samplesMinusOne / 2.0)); - break; - } - if (dir == FFT_FORWARD) { - this->_vReal[i] *= weighingFactor; - this->_vReal[this->_samples - (i + 1)] *= weighingFactor; - } - else { - this->_vReal[i] /= weighingFactor; - this->_vReal[this->_samples - (i + 1)] /= weighingFactor; - } - } +void arduinoFFT::Windowing(FFTWindow windowType, FFTDirection dir) { + // Weighing factors are computed once before multiple use of FFT + // The weighing function is symmetric; half the weighs are recorded + double samplesMinusOne = (double(this->_samples) - 1.0); + for (uint16_t i = 0; i < (this->_samples >> 1); i++) { + double indexMinusOne = double(i); + double ratio = (indexMinusOne / samplesMinusOne); + double weighingFactor = 1.0; + // Compute and record weighting factor + switch (windowType) { + case FFT_WIN_TYP_RECTANGLE: // rectangle (box car) + weighingFactor = 1.0; + break; + case FFT_WIN_TYP_HAMMING: // hamming + weighingFactor = 0.54 - (0.46 * cos(twoPi * ratio)); + break; + case FFT_WIN_TYP_HANN: // hann + weighingFactor = 0.54 * (1.0 - cos(twoPi * ratio)); + break; + case FFT_WIN_TYP_TRIANGLE: // triangle (Bartlett) +#if defined(ESP8266) || defined(ESP32) + weighingFactor = + 1.0 - ((2.0 * fabs(indexMinusOne - (samplesMinusOne / 2.0))) / + samplesMinusOne); +#else + weighingFactor = + 1.0 - ((2.0 * abs(indexMinusOne - (samplesMinusOne / 2.0))) / + samplesMinusOne); +#endif + break; + case FFT_WIN_TYP_NUTTALL: // nuttall + weighingFactor = 0.355768 - (0.487396 * (cos(twoPi * ratio))) + + (0.144232 * (cos(fourPi * ratio))) - + (0.012604 * (cos(sixPi * ratio))); + break; + case FFT_WIN_TYP_BLACKMAN: // blackman + weighingFactor = 0.42323 - (0.49755 * (cos(twoPi * ratio))) + + (0.07922 * (cos(fourPi * ratio))); + break; + case FFT_WIN_TYP_BLACKMAN_NUTTALL: // blackman nuttall + weighingFactor = 0.3635819 - (0.4891775 * (cos(twoPi * ratio))) + + (0.1365995 * (cos(fourPi * ratio))) - + (0.0106411 * (cos(sixPi * ratio))); + break; + case FFT_WIN_TYP_BLACKMAN_HARRIS: // blackman harris + weighingFactor = 0.35875 - (0.48829 * (cos(twoPi * ratio))) + + (0.14128 * (cos(fourPi * ratio))) - + (0.01168 * (cos(sixPi * ratio))); + break; + case FFT_WIN_TYP_FLT_TOP: // flat top + weighingFactor = 0.2810639 - (0.5208972 * cos(twoPi * ratio)) + + (0.1980399 * cos(fourPi * ratio)); + break; + case FFT_WIN_TYP_WELCH: // welch + weighingFactor = 1.0 - sq((indexMinusOne - samplesMinusOne / 2.0) / + (samplesMinusOne / 2.0)); + break; + } + if (dir == FFT_FORWARD) { + this->_vReal[i] *= weighingFactor; + this->_vReal[this->_samples - (i + 1)] *= weighingFactor; + } else { + this->_vReal[i] /= weighingFactor; + this->_vReal[this->_samples - (i + 1)] /= weighingFactor; + } + } } - -void arduinoFFT::Windowing(double *vData, uint16_t samples, uint8_t windowType, uint8_t dir) -{// Weighing factors are computed once before multiple use of FFT +void arduinoFFT::Windowing(double *vData, uint16_t samples, + FFTWindow windowType, FFTDirection dir) { +// Weighing factors are computed once before multiple use of FFT // The weighing function is symetric; half the weighs are recorded - #warning("This method is deprecated and may be removed on future revisions.") - double samplesMinusOne = (double(samples) - 1.0); - for (uint16_t i = 0; i < (samples >> 1); i++) { - double indexMinusOne = double(i); - double ratio = (indexMinusOne / samplesMinusOne); - double weighingFactor = 1.0; - // Compute and record weighting factor - switch (windowType) { - case FFT_WIN_TYP_RECTANGLE: // rectangle (box car) - weighingFactor = 1.0; - break; - case FFT_WIN_TYP_HAMMING: // hamming - weighingFactor = 0.54 - (0.46 * cos(twoPi * ratio)); - break; - case FFT_WIN_TYP_HANN: // hann - weighingFactor = 0.54 * (1.0 - cos(twoPi * ratio)); - break; - case FFT_WIN_TYP_TRIANGLE: // triangle (Bartlett) - #if defined(ESP8266) || defined(ESP32) - weighingFactor = 1.0 - ((2.0 * fabs(indexMinusOne - (samplesMinusOne / 2.0))) / samplesMinusOne); - #else - weighingFactor = 1.0 - ((2.0 * abs(indexMinusOne - (samplesMinusOne / 2.0))) / samplesMinusOne); - #endif - break; - case FFT_WIN_TYP_NUTTALL: // nuttall - weighingFactor = 0.355768 - (0.487396 * (cos(twoPi * ratio))) + (0.144232 * (cos(fourPi * ratio))) - (0.012604 * (cos(sixPi * ratio))); - break; - case FFT_WIN_TYP_BLACKMAN: // blackman - weighingFactor = 0.42323 - (0.49755 * (cos(twoPi * ratio))) + (0.07922 * (cos(fourPi * ratio))); - break; - case FFT_WIN_TYP_BLACKMAN_NUTTALL: // blackman nuttall - weighingFactor = 0.3635819 - (0.4891775 * (cos(twoPi * ratio))) + (0.1365995 * (cos(fourPi * ratio))) - (0.0106411 * (cos(sixPi * ratio))); - break; - case FFT_WIN_TYP_BLACKMAN_HARRIS: // blackman harris - weighingFactor = 0.35875 - (0.48829 * (cos(twoPi * ratio))) + (0.14128 * (cos(fourPi * ratio))) - (0.01168 * (cos(sixPi * ratio))); - break; - case FFT_WIN_TYP_FLT_TOP: // flat top - weighingFactor = 0.2810639 - (0.5208972 * cos(twoPi * ratio)) + (0.1980399 * cos(fourPi * ratio)); - break; - case FFT_WIN_TYP_WELCH: // welch - weighingFactor = 1.0 - sq((indexMinusOne - samplesMinusOne / 2.0) / (samplesMinusOne / 2.0)); - break; - } - if (dir == FFT_FORWARD) { - vData[i] *= weighingFactor; - vData[samples - (i + 1)] *= weighingFactor; - } - else { - vData[i] /= weighingFactor; - vData[samples - (i + 1)] /= weighingFactor; - } - } +#warning("This method is deprecated and may be removed on future revisions.") + double samplesMinusOne = (double(samples) - 1.0); + for (uint16_t i = 0; i < (samples >> 1); i++) { + double indexMinusOne = double(i); + double ratio = (indexMinusOne / samplesMinusOne); + double weighingFactor = 1.0; + // Compute and record weighting factor + switch (windowType) { + case FFT_WIN_TYP_RECTANGLE: // rectangle (box car) + weighingFactor = 1.0; + break; + case FFT_WIN_TYP_HAMMING: // hamming + weighingFactor = 0.54 - (0.46 * cos(twoPi * ratio)); + break; + case FFT_WIN_TYP_HANN: // hann + weighingFactor = 0.54 * (1.0 - cos(twoPi * ratio)); + break; + case FFT_WIN_TYP_TRIANGLE: // triangle (Bartlett) +#if defined(ESP8266) || defined(ESP32) + weighingFactor = + 1.0 - ((2.0 * fabs(indexMinusOne - (samplesMinusOne / 2.0))) / + samplesMinusOne); +#else + weighingFactor = + 1.0 - ((2.0 * abs(indexMinusOne - (samplesMinusOne / 2.0))) / + samplesMinusOne); +#endif + break; + case FFT_WIN_TYP_NUTTALL: // nuttall + weighingFactor = 0.355768 - (0.487396 * (cos(twoPi * ratio))) + + (0.144232 * (cos(fourPi * ratio))) - + (0.012604 * (cos(sixPi * ratio))); + break; + case FFT_WIN_TYP_BLACKMAN: // blackman + weighingFactor = 0.42323 - (0.49755 * (cos(twoPi * ratio))) + + (0.07922 * (cos(fourPi * ratio))); + break; + case FFT_WIN_TYP_BLACKMAN_NUTTALL: // blackman nuttall + weighingFactor = 0.3635819 - (0.4891775 * (cos(twoPi * ratio))) + + (0.1365995 * (cos(fourPi * ratio))) - + (0.0106411 * (cos(sixPi * ratio))); + break; + case FFT_WIN_TYP_BLACKMAN_HARRIS: // blackman harris + weighingFactor = 0.35875 - (0.48829 * (cos(twoPi * ratio))) + + (0.14128 * (cos(fourPi * ratio))) - + (0.01168 * (cos(sixPi * ratio))); + break; + case FFT_WIN_TYP_FLT_TOP: // flat top + weighingFactor = 0.2810639 - (0.5208972 * cos(twoPi * ratio)) + + (0.1980399 * cos(fourPi * ratio)); + break; + case FFT_WIN_TYP_WELCH: // welch + weighingFactor = 1.0 - sq((indexMinusOne - samplesMinusOne / 2.0) / + (samplesMinusOne / 2.0)); + break; + } + if (dir == FFT_FORWARD) { + vData[i] *= weighingFactor; + vData[samples - (i + 1)] *= weighingFactor; + } else { + vData[i] /= weighingFactor; + vData[samples - (i + 1)] /= weighingFactor; + } + } } -double arduinoFFT::MajorPeak() -{ - double maxY = 0; - uint16_t IndexOfMaxY = 0; - //If sampling_frequency = 2 * max_frequency in signal, - //value would be stored at position samples/2 - for (uint16_t i = 1; i < ((this->_samples >> 1) + 1); i++) { - if ((this->_vReal[i-1] < this->_vReal[i]) && (this->_vReal[i] > this->_vReal[i+1])) { - if (this->_vReal[i] > maxY) { - maxY = this->_vReal[i]; - IndexOfMaxY = i; - } - } - } - double delta = 0.5 * ((this->_vReal[IndexOfMaxY-1] - this->_vReal[IndexOfMaxY+1]) / (this->_vReal[IndexOfMaxY-1] - (2.0 * this->_vReal[IndexOfMaxY]) + this->_vReal[IndexOfMaxY+1])); - double interpolatedX = ((IndexOfMaxY + delta) * this->_samplingFrequency) / (this->_samples-1); - if(IndexOfMaxY==(this->_samples >> 1)) //To improve calculation on edge values - interpolatedX = ((IndexOfMaxY + delta) * this->_samplingFrequency) / (this->_samples); - // returned value: interpolated frequency peak apex - return(interpolatedX); +double arduinoFFT::MajorPeak() { + double maxY = 0; + uint16_t IndexOfMaxY = 0; + // If sampling_frequency = 2 * max_frequency in signal, + // value would be stored at position samples/2 + for (uint16_t i = 1; i < ((this->_samples >> 1) + 1); i++) { + if ((this->_vReal[i - 1] < this->_vReal[i]) && + (this->_vReal[i] > this->_vReal[i + 1])) { + if (this->_vReal[i] > maxY) { + maxY = this->_vReal[i]; + IndexOfMaxY = i; + } + } + } + double delta = + 0.5 * + ((this->_vReal[IndexOfMaxY - 1] - this->_vReal[IndexOfMaxY + 1]) / + (this->_vReal[IndexOfMaxY - 1] - (2.0 * this->_vReal[IndexOfMaxY]) + + this->_vReal[IndexOfMaxY + 1])); + double interpolatedX = + ((IndexOfMaxY + delta) * this->_samplingFrequency) / (this->_samples - 1); + if (IndexOfMaxY == + (this->_samples >> 1)) // To improve calculation on edge values + interpolatedX = + ((IndexOfMaxY + delta) * this->_samplingFrequency) / (this->_samples); + // returned value: interpolated frequency peak apex + return (interpolatedX); } -void arduinoFFT::MajorPeak(double *f, double *v) -{ - double maxY = 0; - uint16_t IndexOfMaxY = 0; - //If sampling_frequency = 2 * max_frequency in signal, - //value would be stored at position samples/2 - for (uint16_t i = 1; i < ((this->_samples >> 1) + 1); i++) { - if ((this->_vReal[i - 1] < this->_vReal[i]) && (this->_vReal[i] > this->_vReal[i + 1])) { - if (this->_vReal[i] > maxY) { - maxY = this->_vReal[i]; - IndexOfMaxY = i; - } - } - } - double delta = 0.5 * ((this->_vReal[IndexOfMaxY - 1] - this->_vReal[IndexOfMaxY + 1]) / (this->_vReal[IndexOfMaxY - 1] - (2.0 * this->_vReal[IndexOfMaxY]) + this->_vReal[IndexOfMaxY + 1])); - double interpolatedX = ((IndexOfMaxY + delta) * this->_samplingFrequency) / (this->_samples - 1); - if (IndexOfMaxY == (this->_samples >> 1)) //To improve calculation on edge values - interpolatedX = ((IndexOfMaxY + delta) * this->_samplingFrequency) / (this->_samples); - // returned value: interpolated frequency peak apex - *f = interpolatedX; - #if defined(ESP8266) || defined(ESP32) - *v = fabs(this->_vReal[IndexOfMaxY - 1] - (2.0 * this->_vReal[IndexOfMaxY]) + this->_vReal[IndexOfMaxY + 1]); - #else - *v = abs(this->_vReal[IndexOfMaxY - 1] - (2.0 * this->_vReal[IndexOfMaxY]) + this->_vReal[IndexOfMaxY + 1]); - #endif +void arduinoFFT::MajorPeak(double *f, double *v) { + double maxY = 0; + uint16_t IndexOfMaxY = 0; + // If sampling_frequency = 2 * max_frequency in signal, + // value would be stored at position samples/2 + for (uint16_t i = 1; i < ((this->_samples >> 1) + 1); i++) { + if ((this->_vReal[i - 1] < this->_vReal[i]) && + (this->_vReal[i] > this->_vReal[i + 1])) { + if (this->_vReal[i] > maxY) { + maxY = this->_vReal[i]; + IndexOfMaxY = i; + } + } + } + double delta = + 0.5 * + ((this->_vReal[IndexOfMaxY - 1] - this->_vReal[IndexOfMaxY + 1]) / + (this->_vReal[IndexOfMaxY - 1] - (2.0 * this->_vReal[IndexOfMaxY]) + + this->_vReal[IndexOfMaxY + 1])); + double interpolatedX = + ((IndexOfMaxY + delta) * this->_samplingFrequency) / (this->_samples - 1); + if (IndexOfMaxY == + (this->_samples >> 1)) // To improve calculation on edge values + interpolatedX = + ((IndexOfMaxY + delta) * this->_samplingFrequency) / (this->_samples); + // returned value: interpolated frequency peak apex + *f = interpolatedX; +#if defined(ESP8266) || defined(ESP32) + *v = fabs(this->_vReal[IndexOfMaxY - 1] - (2.0 * this->_vReal[IndexOfMaxY]) + + this->_vReal[IndexOfMaxY + 1]); +#else + *v = abs(this->_vReal[IndexOfMaxY - 1] - (2.0 * this->_vReal[IndexOfMaxY]) + + this->_vReal[IndexOfMaxY + 1]); +#endif } -double arduinoFFT::MajorPeak(double *vD, uint16_t samples, double samplingFrequency) -{ - #warning("This method is deprecated and may be removed on future revisions.") - double maxY = 0; - uint16_t IndexOfMaxY = 0; - //If sampling_frequency = 2 * max_frequency in signal, - //value would be stored at position samples/2 - for (uint16_t i = 1; i < ((samples >> 1) + 1); i++) { - if ((vD[i-1] < vD[i]) && (vD[i] > vD[i+1])) { - if (vD[i] > maxY) { - maxY = vD[i]; - IndexOfMaxY = i; - } - } - } - double delta = 0.5 * ((vD[IndexOfMaxY-1] - vD[IndexOfMaxY+1]) / (vD[IndexOfMaxY-1] - (2.0 * vD[IndexOfMaxY]) + vD[IndexOfMaxY+1])); - double interpolatedX = ((IndexOfMaxY + delta) * samplingFrequency) / (samples-1); - if(IndexOfMaxY==(samples >> 1)) //To improve calculation on edge values - interpolatedX = ((IndexOfMaxY + delta) * samplingFrequency) / (samples); - // returned value: interpolated frequency peak apex - return(interpolatedX); +double arduinoFFT::MajorPeak(double *vD, uint16_t samples, + double samplingFrequency) { +#warning("This method is deprecated and may be removed on future revisions.") + double maxY = 0; + uint16_t IndexOfMaxY = 0; + // If sampling_frequency = 2 * max_frequency in signal, + // value would be stored at position samples/2 + for (uint16_t i = 1; i < ((samples >> 1) + 1); i++) { + if ((vD[i - 1] < vD[i]) && (vD[i] > vD[i + 1])) { + if (vD[i] > maxY) { + maxY = vD[i]; + IndexOfMaxY = i; + } + } + } + double delta = + 0.5 * + ((vD[IndexOfMaxY - 1] - vD[IndexOfMaxY + 1]) / + (vD[IndexOfMaxY - 1] - (2.0 * vD[IndexOfMaxY]) + vD[IndexOfMaxY + 1])); + double interpolatedX = + ((IndexOfMaxY + delta) * samplingFrequency) / (samples - 1); + if (IndexOfMaxY == (samples >> 1)) // To improve calculation on edge values + interpolatedX = ((IndexOfMaxY + delta) * samplingFrequency) / (samples); + // returned value: interpolated frequency peak apex + return (interpolatedX); } -void arduinoFFT::MajorPeak(double *vD, uint16_t samples, double samplingFrequency, double *f, double *v) -{ - #warning("This method is deprecated and may be removed on future revisions.") - double maxY = 0; - uint16_t IndexOfMaxY = 0; - //If sampling_frequency = 2 * max_frequency in signal, - //value would be stored at position samples/2 - for (uint16_t i = 1; i < ((samples >> 1) + 1); i++) { - if ((vD[i - 1] < vD[i]) && (vD[i] > vD[i + 1])) { - if (vD[i] > maxY) { - maxY = vD[i]; - IndexOfMaxY = i; - } - } - } - double delta = 0.5 * ((vD[IndexOfMaxY - 1] - vD[IndexOfMaxY + 1]) / (vD[IndexOfMaxY - 1] - (2.0 * vD[IndexOfMaxY]) + vD[IndexOfMaxY + 1])); - double interpolatedX = ((IndexOfMaxY + delta) * samplingFrequency) / (samples - 1); - //double popo = - if (IndexOfMaxY == (samples >> 1)) //To improve calculation on edge values - interpolatedX = ((IndexOfMaxY + delta) * samplingFrequency) / (samples); - // returned value: interpolated frequency peak apex - *f = interpolatedX; - #if defined(ESP8266) || defined(ESP32) - *v = fabs(vD[IndexOfMaxY - 1] - (2.0 * vD[IndexOfMaxY]) + vD[IndexOfMaxY + 1]); - #else - *v = abs(vD[IndexOfMaxY - 1] - (2.0 * vD[IndexOfMaxY]) + vD[IndexOfMaxY + 1]); - #endif +void arduinoFFT::MajorPeak(double *vD, uint16_t samples, + double samplingFrequency, double *f, double *v) { +#warning("This method is deprecated and may be removed on future revisions.") + double maxY = 0; + uint16_t IndexOfMaxY = 0; + // If sampling_frequency = 2 * max_frequency in signal, + // value would be stored at position samples/2 + for (uint16_t i = 1; i < ((samples >> 1) + 1); i++) { + if ((vD[i - 1] < vD[i]) && (vD[i] > vD[i + 1])) { + if (vD[i] > maxY) { + maxY = vD[i]; + IndexOfMaxY = i; + } + } + } + double delta = + 0.5 * + ((vD[IndexOfMaxY - 1] - vD[IndexOfMaxY + 1]) / + (vD[IndexOfMaxY - 1] - (2.0 * vD[IndexOfMaxY]) + vD[IndexOfMaxY + 1])); + double interpolatedX = + ((IndexOfMaxY + delta) * samplingFrequency) / (samples - 1); + // double popo = + if (IndexOfMaxY == (samples >> 1)) // To improve calculation on edge values + interpolatedX = ((IndexOfMaxY + delta) * samplingFrequency) / (samples); + // returned value: interpolated frequency peak apex + *f = interpolatedX; +#if defined(ESP8266) || defined(ESP32) + *v = + fabs(vD[IndexOfMaxY - 1] - (2.0 * vD[IndexOfMaxY]) + vD[IndexOfMaxY + 1]); +#else + *v = abs(vD[IndexOfMaxY - 1] - (2.0 * vD[IndexOfMaxY]) + vD[IndexOfMaxY + 1]); +#endif } -double arduinoFFT::MajorPeakParabola() -{ - double maxY = 0; - uint16_t IndexOfMaxY = 0; - //If sampling_frequency = 2 * max_frequency in signal, - //value would be stored at position samples/2 - for (uint16_t i = 1; i < ((this->_samples >> 1) + 1); i++) - { - if ((this->_vReal[i-1] < this->_vReal[i]) && (this->_vReal[i] > this->_vReal[i+1])) - { - if (this->_vReal[i] > maxY) - { - maxY = this->_vReal[i]; - IndexOfMaxY = i; - } - } - } +double arduinoFFT::MajorPeakParabola() { + double maxY = 0; + uint16_t IndexOfMaxY = 0; + // If sampling_frequency = 2 * max_frequency in signal, + // value would be stored at position samples/2 + for (uint16_t i = 1; i < ((this->_samples >> 1) + 1); i++) { + if ((this->_vReal[i - 1] < this->_vReal[i]) && + (this->_vReal[i] > this->_vReal[i + 1])) { + if (this->_vReal[i] > maxY) { + maxY = this->_vReal[i]; + IndexOfMaxY = i; + } + } + } - double freq = 0; - if( IndexOfMaxY>0 ) - { - // Assume the three points to be on a parabola - double a,b,c; - Parabola(IndexOfMaxY-1, this->_vReal[IndexOfMaxY-1], IndexOfMaxY, this->_vReal[IndexOfMaxY], IndexOfMaxY+1, this->_vReal[IndexOfMaxY+1], &a, &b, &c); + double freq = 0; + if (IndexOfMaxY > 0) { + // Assume the three points to be on a parabola + double a, b, c; + Parabola(IndexOfMaxY - 1, this->_vReal[IndexOfMaxY - 1], IndexOfMaxY, + this->_vReal[IndexOfMaxY], IndexOfMaxY + 1, + this->_vReal[IndexOfMaxY + 1], &a, &b, &c); - // Peak is at the middle of the parabola - double x = -b/(2*a); + // Peak is at the middle of the parabola + double x = -b / (2 * a); - // And magnitude is at the extrema of the parabola if you want It... - // double y = a*x*x+b*x+c; + // And magnitude is at the extrema of the parabola if you want It... + // double y = a*x*x+b*x+c; - // Convert to frequency - freq = (x * this->_samplingFrequency) / (this->_samples); - } + // Convert to frequency + freq = (x * this->_samplingFrequency) / (this->_samples); + } - return freq; + return freq; } -void arduinoFFT::Parabola(double x1, double y1, double x2, double y2, double x3, double y3, double *a, double *b, double *c) -{ - double reversed_denom = 1/((x1 - x2) * (x1 - x3) * (x2 - x3)); +void arduinoFFT::Parabola(double x1, double y1, double x2, double y2, double x3, + double y3, double *a, double *b, double *c) { + double reversed_denom = 1 / ((x1 - x2) * (x1 - x3) * (x2 - x3)); - *a = (x3 * (y2 - y1) + x2 * (y1 - y3) + x1 * (y3 - y2)) * reversed_denom; - *b = (x3*x3 * (y1 - y2) + x2*x2 * (y3 - y1) + x1*x1 * (y2 - y3)) * reversed_denom; - *c = (x2 * x3 * (x2 - x3) * y1 + x3 * x1 * (x3 - x1) * y2 + x1 * x2 * (x1 - x2) * y3) *reversed_denom; + *a = (x3 * (y2 - y1) + x2 * (y1 - y3) + x1 * (y3 - y2)) * reversed_denom; + *b = (x3 * x3 * (y1 - y2) + x2 * x2 * (y3 - y1) + x1 * x1 * (y2 - y3)) * + reversed_denom; + *c = (x2 * x3 * (x2 - x3) * y1 + x3 * x1 * (x3 - x1) * y2 + + x1 * x2 * (x1 - x2) * y3) * + reversed_denom; } -uint8_t arduinoFFT::Exponent(uint16_t value) -{ - #warning("This method may not be accessible on future revisions.") - // Calculates the base 2 logarithm of a value - uint8_t result = 0; - while (((value >> result) & 1) != 1) result++; - return(result); +uint8_t arduinoFFT::Exponent(uint16_t value) { +#warning("This method may not be accessible on future revisions.") + // Calculates the base 2 logarithm of a value + uint8_t result = 0; + while (((value >> result) & 1) != 1) + result++; + return (result); } // Private functions -void arduinoFFT::Swap(double *x, double *y) -{ - double temp = *x; - *x = *y; - *y = temp; +void arduinoFFT::Swap(double *x, double *y) { + double temp = *x; + *x = *y; + *y = temp; } diff --git a/src/arduinoFFT.h b/src/arduinoFFT.h index 7883145..4878d01 100644 --- a/src/arduinoFFT.h +++ b/src/arduinoFFT.h @@ -19,97 +19,133 @@ */ -#ifndef arduinoFFT_h /* Prevent loading library twice */ -#define arduinoFFT_h +#ifndef ArduinoFFT_h /* Prevent loading library twice */ +#define ArduinoFFT_h #ifdef ARDUINO - #if ARDUINO >= 100 - #include "Arduino.h" - #else - #include "WProgram.h" /* This is where the standard Arduino code lies */ - #endif +#if ARDUINO >= 100 +#include "Arduino.h" #else - #include - #include - #ifdef __AVR__ - #include - #include - #endif - #include - #include "defs.h" - #include "types.h" +#include "WProgram.h" /* This is where the standard Arduino code lies */ +#endif +#else +#include +#include + +#ifdef __AVR__ +#include +#include +#endif +#include "defs.h" +#include "types.h" +#include + #endif -#define FFT_LIB_REV 0x14 +// Define this to use a low-precision square root approximation instead of the +// regular sqrt() call +// This might only work for specific use cases, but is significantly faster. +// Only works for ArduinoFFT. +// #define FFT_SQRT_APPROXIMATION + +#ifdef FFT_SQRT_APPROXIMATION +#include +#else +#define sqrt_internal sqrt +#endif + +enum class FFTDirection { Reverse, Forward }; + +enum class FFTWindow { + Rectangle, // rectangle (Box car) + Hamming, // hamming + Hann, // hann + Triangle, // triangle (Bartlett) + Nuttall, // nuttall + Blackman, // blackman + Blackman_Nuttall, // blackman nuttall + Blackman_Harris, // blackman harris + Flat_top, // flat top + Welch // welch +}; +#define FFT_LIB_REV 0x15 /* Custom constants */ -#define FFT_FORWARD 0x01 -#define FFT_REVERSE 0x00 +#define FFT_FORWARD FFTDirection::Forward +#define FFT_REVERSE FFTDirection::Reverse /* Windowing type */ -#define FFT_WIN_TYP_RECTANGLE 0x00 /* rectangle (Box car) */ -#define FFT_WIN_TYP_HAMMING 0x01 /* hamming */ -#define FFT_WIN_TYP_HANN 0x02 /* hann */ -#define FFT_WIN_TYP_TRIANGLE 0x03 /* triangle (Bartlett) */ -#define FFT_WIN_TYP_NUTTALL 0x04 /* nuttall */ -#define FFT_WIN_TYP_BLACKMAN 0x05 /* blackman */ -#define FFT_WIN_TYP_BLACKMAN_NUTTALL 0x06 /* blackman nuttall */ -#define FFT_WIN_TYP_BLACKMAN_HARRIS 0x07 /* blackman harris*/ -#define FFT_WIN_TYP_FLT_TOP 0x08 /* flat top */ -#define FFT_WIN_TYP_WELCH 0x09 /* welch */ +#define FFT_WIN_TYP_RECTANGLE FFTWindow::Rectangle /* rectangle (Box car) */ +#define FFT_WIN_TYP_HAMMING FFTWindow::Hamming /* hamming */ +#define FFT_WIN_TYP_HANN FFTWindow::Hann /* hann */ +#define FFT_WIN_TYP_TRIANGLE FFTWindow::Triangle /* triangle (Bartlett) */ +#define FFT_WIN_TYP_NUTTALL FFTWindow::Nuttall /* nuttall */ +#define FFT_WIN_TYP_BLACKMAN FFTWindow::Blackman /* blackman */ +#define FFT_WIN_TYP_BLACKMAN_NUTTALL \ + FFTWindow::Blackman_Nuttall /* blackman nuttall */ +#define FFT_WIN_TYP_BLACKMAN_HARRIS \ + FFTWindow::Blackman_Harris /* blackman harris*/ +#define FFT_WIN_TYP_FLT_TOP FFTWindow::Flat_top /* flat top */ +#define FFT_WIN_TYP_WELCH FFTWindow::Welch /* welch */ /*Mathematial constants*/ #define twoPi 6.28318531 #define fourPi 12.56637061 #define sixPi 18.84955593 #ifdef __AVR__ - static const double _c1[]PROGMEM = {0.0000000000, 0.7071067812, 0.9238795325, 0.9807852804, - 0.9951847267, 0.9987954562, 0.9996988187, 0.9999247018, - 0.9999811753, 0.9999952938, 0.9999988235, 0.9999997059, - 0.9999999265, 0.9999999816, 0.9999999954, 0.9999999989, - 0.9999999997}; - static const double _c2[]PROGMEM = {1.0000000000, 0.7071067812, 0.3826834324, 0.1950903220, - 0.0980171403, 0.0490676743, 0.0245412285, 0.0122715383, - 0.0061358846, 0.0030679568, 0.0015339802, 0.0007669903, - 0.0003834952, 0.0001917476, 0.0000958738, 0.0000479369, - 0.0000239684}; +static const double _c1[] PROGMEM = { + 0.0000000000, 0.7071067812, 0.9238795325, 0.9807852804, 0.9951847267, + 0.9987954562, 0.9996988187, 0.9999247018, 0.9999811753, 0.9999952938, + 0.9999988235, 0.9999997059, 0.9999999265, 0.9999999816, 0.9999999954, + 0.9999999989, 0.9999999997}; +static const double _c2[] PROGMEM = { + 1.0000000000, 0.7071067812, 0.3826834324, 0.1950903220, 0.0980171403, + 0.0490676743, 0.0245412285, 0.0122715383, 0.0061358846, 0.0030679568, + 0.0015339802, 0.0007669903, 0.0003834952, 0.0001917476, 0.0000958738, + 0.0000479369, 0.0000239684}; #endif class arduinoFFT { public: - /* Constructor */ - arduinoFFT(void); - arduinoFFT(double *vReal, double *vImag, uint16_t samples, double samplingFrequency); - /* Destructor */ - ~arduinoFFT(void); - /* Functions */ - uint8_t Revision(void); - uint8_t Exponent(uint16_t value); + /* Constructor */ + arduinoFFT(void); + arduinoFFT(double *vReal, double *vImag, uint16_t samples, + double samplingFrequency); + /* Destructor */ + ~arduinoFFT(void); + /* Functions */ + uint8_t Revision(void); + uint8_t Exponent(uint16_t value); - void ComplexToMagnitude(double *vReal, double *vImag, uint16_t samples); - void Compute(double *vReal, double *vImag, uint16_t samples, uint8_t dir); - void Compute(double *vReal, double *vImag, uint16_t samples, uint8_t power, uint8_t dir); - void DCRemoval(double *vData, uint16_t samples); - double MajorPeak(double *vD, uint16_t samples, double samplingFrequency); - void MajorPeak(double *vD, uint16_t samples, double samplingFrequency, double *f, double *v); - void Windowing(double *vData, uint16_t samples, uint8_t windowType, uint8_t dir); + void ComplexToMagnitude(double *vReal, double *vImag, uint16_t samples); + void Compute(double *vReal, double *vImag, uint16_t samples, + FFTDirection dir); + void Compute(double *vReal, double *vImag, uint16_t samples, uint8_t power, + FFTDirection dir); + void DCRemoval(double *vData, uint16_t samples); + double MajorPeak(double *vD, uint16_t samples, double samplingFrequency); + void MajorPeak(double *vD, uint16_t samples, double samplingFrequency, + double *f, double *v); + void Windowing(double *vData, uint16_t samples, FFTWindow windowType, + FFTDirection dir); - void ComplexToMagnitude(); - void Compute(uint8_t dir); - void DCRemoval(); - double MajorPeak(); - void MajorPeak(double *f, double *v); - void Windowing(uint8_t windowType, uint8_t dir); + void ComplexToMagnitude(); + void Compute(FFTDirection dir); + void DCRemoval(); + double MajorPeak(); + void MajorPeak(double *f, double *v); + void Windowing(FFTWindow windowType, FFTDirection dir); - double MajorPeakParabola(); + double MajorPeakParabola(); private: - /* Variables */ - uint16_t _samples; - double _samplingFrequency; - double *_vReal; - double *_vImag; - uint8_t _power; - /* Functions */ - void Swap(double *x, double *y); - void Parabola(double x1, double y1, double x2, double y2, double x3, double y3, double *a, double *b, double *c); + /* Variables */ + uint16_t _samples; + double _samplingFrequency; + double *_vReal; + double *_vImag; + uint8_t _power; + /* Functions */ + void Swap(double *x, double *y); + void Parabola(double x1, double y1, double x2, double y2, double x3, + double y3, double *a, double *b, double *c); }; #endif