mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-10 23:44:24 +00:00
FFT: Allow performFrequencyOnlyForwardTransform to ignore negative frequencies
This commit is contained in:
parent
82df66100c
commit
bb724761f2
3 changed files with 33 additions and 22 deletions
|
|
@ -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]);
|
||||
reference[i] = std::abs (frequency[i]);
|
||||
|
||||
fft.performFrequencyOnlyForwardTransform (inout.getData());
|
||||
|
||||
u.expect (checkArrayIsSimilar (inout.getData(), reference.getData(), n));
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue