From 49bc72673808ebe9e20864b6f1bf04aeb53451ae Mon Sep 17 00:00:00 2001 From: Bim Overbohm Date: Wed, 19 Feb 2020 18:06:11 +0100 Subject: [PATCH] Add windowing compensation factors --- README.md | 18 +++++++++++++++--- src/arduinoFFT.h | 35 ++++++++++++++++++++++++++++------- 2 files changed, 43 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index feb4d7a..fe000f6 100644 --- a/README.md +++ b/README.md @@ -48,7 +48,7 @@ The type `T` can be `float` or `double`. `vReal` and `vImag` are pointers to arr * **~ArduinoFFT**(void); Destructor. * **complexToMagnitude**(); -Convert complex values to their magnitude and store in vReal. +Convert complex values to their magnitude and store in vReal. * **compute**(FFTDirection dir); Calcuates the Fast Fourier Transform. * **dcRemoval**(); @@ -57,7 +57,7 @@ Removes the DC component from the sample data. Looks for and returns the frequency of the biggest spike in the analyzed signal. * **revision**(); Returns the library revision. -* **windowing**(FFTWindow windowType, FFTDirection dir); +* **windowing**(FFTWindow windowType, FFTDirection dir, bool withCompensation = false); Performs a windowing function on the values array. The possible windowing options are: * Rectangle * Hamming @@ -66,10 +66,22 @@ Performs a windowing function on the values array. The possible windowing option * Nuttall * Blackman * Blackman_Nuttall - * Blackman_Harris + * Blackman_Harris * Flat_top * Welch + If `withCompensation` == true, the following compensation factors are used: + * Rectangle: 1.0 * 2.0 + * Hamming: 1.8549343278 * 2.0 + * Hann: 1.8554726898 * 2.0 + * Triangle: 2.0039186079 * 2.0 + * Nuttall: 2.8163172034 * 2.0 + * Blackman: 2.3673474360 * 2.0 + * Blackman Nuttall: 2.7557840395 * 2.0 + * Blackman Harris: 2.7929062517 * 2.0 + * Flat top: 3.5659039231 * 2.0 + * Welch: 1.5029392863 * 2.0 + ## Special flags You can define these before including arduinoFFT.h: diff --git a/src/arduinoFFT.h b/src/arduinoFFT.h index bb67f91..d47d6b6 100644 --- a/src/arduinoFFT.h +++ b/src/arduinoFFT.h @@ -208,10 +208,12 @@ public: } } - void windowing(FFTWindow windowType, FFTDirection dir) + void windowing(FFTWindow windowType, FFTDirection dir, bool withCompensation = false) { - // check if values are already pre-computed for the correct window type - if (_windowWeighingFactors && weighingFactorsComputed && weighingFactorsFFTWindow == windowType) + // check if values are already pre-computed for the correct window type and compensation + if (_windowWeighingFactors && _weighingFactorsComputed && + _weighingFactorsFFTWindow == windowType && + _weighingFactorsWithCompensation == withCompensation) { // yes. values are precomputed if (dir == FFTDirection::Forward) @@ -242,6 +244,7 @@ public: { // no. values need to be pre-computed or applied T samplesMinusOne = (T(this->_samples) - 1.0); + T compensationFactor = _WindowCompensationFactors[static_cast(windowType)]; for (uint_fast16_t i = 0; i < (this->_samples >> 1); i++) { T indexMinusOne = T(i); @@ -281,6 +284,10 @@ public: weighingFactor = 1.0 - sq((indexMinusOne - samplesMinusOne / 2.0) / (samplesMinusOne / 2.0)); break; } + if (withCompensation) + { + weighingFactor *= compensationFactor; + } if (_windowWeighingFactors) { _windowWeighingFactors[i] = weighingFactor; @@ -304,8 +311,9 @@ public: } } // mark cached values as pre-computed - weighingFactorsFFTWindow = windowType; - weighingFactorsComputed = true; + _weighingFactorsFFTWindow = windowType; + _weighingFactorsWithCompensation = withCompensation; + _weighingFactorsComputed = true; } } @@ -381,6 +389,18 @@ private: 0.0003834952, 0.0001917476, 0.0000958738, 0.0000479369, 0.0000239684}; #endif + static constexpr T _WindowCompensationFactors[10] = { + 1.0000000000 * 2.0, /* rectangle (Box car) */ + 1.8549343278 * 2.0, /* hamming */ + 1.8554726898 * 2.0, /* hann */ + 2.0039186079 * 2.0, /* triangle (Bartlett) */ + 2.8163172034 * 2.0, /* nuttall */ + 2.3673474360 * 2.0, /* blackman */ + 2.7557840395 * 2.0, /* blackman nuttall */ + 2.7929062517 * 2.0, /* blackman harris*/ + 3.5659039231 * 2.0, /* flat top */ + 1.5029392863 * 2.0 /* welch */ + }; // Mathematial constants #ifndef TWO_PI @@ -431,8 +451,9 @@ private: T *_vReal = nullptr; T *_vImag = nullptr; T * _windowWeighingFactors = nullptr; - FFTWindow weighingFactorsFFTWindow; - bool weighingFactorsComputed = false; + FFTWindow _weighingFactorsFFTWindow; + bool _weighingFactorsWithCompensation = false; + bool _weighingFactorsComputed = false; uint_fast8_t _power = 0; };