| @@ -969,10 +969,10 @@ void FFT::perform (const Complex<float>* input, Complex<float>* output, bool inv | |||
| engine->perform (input, output, inverse); | |||
| } | |||
| void FFT::performRealOnlyForwardTransform (float* inputOutputData, bool ignoreNeagtiveFreqs) const noexcept | |||
| void FFT::performRealOnlyForwardTransform (float* inputOutputData, bool ignoreNegativeFreqs) const noexcept | |||
| { | |||
| if (engine != nullptr) | |||
| engine->performRealOnlyForwardTransform (inputOutputData, ignoreNeagtiveFreqs); | |||
| engine->performRealOnlyForwardTransform (inputOutputData, ignoreNegativeFreqs); | |||
| } | |||
| void FFT::performRealOnlyInverseTransform (float* inputOutputData) const noexcept | |||
| @@ -981,18 +981,20 @@ void FFT::performRealOnlyInverseTransform (float* inputOutputData) const noexcep | |||
| engine->performRealOnlyInverseTransform (inputOutputData); | |||
| } | |||
| void FFT::performFrequencyOnlyForwardTransform (float* inputOutputData) const noexcept | |||
| void FFT::performFrequencyOnlyForwardTransform (float* inputOutputData, bool ignoreNegativeFreqs) const noexcept | |||
| { | |||
| if (size == 1) | |||
| return; | |||
| performRealOnlyForwardTransform (inputOutputData); | |||
| performRealOnlyForwardTransform (inputOutputData, ignoreNegativeFreqs); | |||
| auto* out = reinterpret_cast<Complex<float>*> (inputOutputData); | |||
| for (int i = 0; i < size; ++i) | |||
| const auto limit = ignoreNegativeFreqs ? (size / 2) + 1 : size; | |||
| for (int i = 0; i < limit; ++i) | |||
| inputOutputData[i] = std::abs (out[i]); | |||
| zeromem (&inputOutputData[size], static_cast<size_t> (size) * sizeof (float)); | |||
| zeromem (inputOutputData + limit, static_cast<size_t> (size * 2 - limit) * sizeof (float)); | |||
| } | |||
| } // namespace dsp | |||
| @@ -70,22 +70,22 @@ public: | |||
| As the coefficients of the negative frequencies (frequencies higher than | |||
| N/2 or pi) are the complex conjugate of their positive counterparts, | |||
| it may not be necessary to calculate them for your particular application. | |||
| You can use dontCalculateNegativeFrequencies to let the FFT | |||
| You can use onlyCalculateNonNegativeFrequencies to let the FFT | |||
| engine know that you do not plan on using them. Note that this is only a | |||
| hint: some FFT engines (currently only the Fallback engine), will still | |||
| calculate the negative frequencies even if dontCalculateNegativeFrequencies | |||
| calculate the negative frequencies even if onlyCalculateNonNegativeFrequencies | |||
| is true. | |||
| The size of the array passed in must be 2 * getSize(), and the first half | |||
| should contain your raw input sample data. On return, if | |||
| dontCalculateNegativeFrequencies is false, the array will contain size | |||
| onlyCalculateNonNegativeFrequencies is false, the array will contain size | |||
| complex real + imaginary parts data interleaved. If | |||
| dontCalculateNegativeFrequencies is true, the array will contain at least | |||
| onlyCalculateNonNegativeFrequencies is true, the array will contain at least | |||
| (size / 2) + 1 complex numbers. Both outputs can be passed to | |||
| performRealOnlyInverseTransform() in order to convert it back to reals. | |||
| */ | |||
| void performRealOnlyForwardTransform (float* inputOutputData, | |||
| bool dontCalculateNegativeFrequencies = false) const noexcept; | |||
| bool onlyCalculateNonNegativeFrequencies = false) const noexcept; | |||
| /** Performs a reverse operation to data created in performRealOnlyForwardTransform(). | |||
| @@ -99,8 +99,13 @@ public: | |||
| /** Takes an array and simply transforms it to the magnitude frequency response | |||
| spectrum. This may be handy for things like frequency displays or analysis. | |||
| The size of the array passed in must be 2 * getSize(). | |||
| On return, if onlyCalculateNonNegativeFrequencies is false, the array will contain size | |||
| magnitude values. If onlyCalculateNonNegativeFrequencies is true, the array will contain | |||
| at least size / 2 + 1 magnitude values. | |||
| */ | |||
| void performFrequencyOnlyForwardTransform (float* inputOutputData) const noexcept; | |||
| void performFrequencyOnlyForwardTransform (float* inputOutputData, | |||
| bool onlyCalculateNonNegativeFrequencies = false) const noexcept; | |||
| /** Returns the number of data points that this FFT was created to work with. */ | |||
| int getSize() const noexcept { return size; } | |||
| @@ -135,7 +135,7 @@ struct FFTUnitTest : public UnitTest | |||
| struct FrequencyOnlyTest | |||
| { | |||
| static void run(FFTUnitTest& u) | |||
| static void run (FFTUnitTest& u) | |||
| { | |||
| Random random (378272); | |||
| for (size_t order = 0; order <= 8; ++order) | |||
| @@ -144,19 +144,23 @@ struct FFTUnitTest : public UnitTest | |||
| FFT fft ((int) order); | |||
| HeapBlock<float> inout (n << 1), reference (n << 1); | |||
| HeapBlock<Complex<float>> frequency (n); | |||
| std::vector<float> inout ((size_t) n << 1), reference ((size_t) n << 1); | |||
| std::vector<Complex<float>> frequency (n); | |||
| fillRandom (random, inout.getData(), n); | |||
| zeromem (reference.getData(), sizeof (float) * ((size_t) n << 1)); | |||
| performReferenceFourier (inout.getData(), frequency.getData(), n, false); | |||
| fillRandom (random, inout.data(), n); | |||
| zeromem (reference.data(), sizeof (float) * ((size_t) n << 1)); | |||
| performReferenceFourier (inout.data(), frequency.data(), n, false); | |||
| for (size_t i = 0; i < n; ++i) | |||
| reference.getData()[i] = std::abs (frequency.getData()[i]); | |||
| fft.performFrequencyOnlyForwardTransform (inout.getData()); | |||
| u.expect (checkArrayIsSimilar (inout.getData(), reference.getData(), n)); | |||
| reference[i] = std::abs (frequency[i]); | |||
| for (auto ignoreNegative : { false, true }) | |||
| { | |||
| auto inoutCopy = inout; | |||
| fft.performFrequencyOnlyForwardTransform (inoutCopy.data(), ignoreNegative); | |||
| auto numMatching = ignoreNegative ? (n / 2) + 1 : n; | |||
| u.expect (checkArrayIsSimilar (inoutCopy.data(), reference.data(), numMatching)); | |||
| } | |||
| } | |||
| } | |||
| }; | |||