1
0
mirror of https://github.com/cookiengineer/audacity synced 2026-02-16 15:57:52 +01:00

Code cleanup: removed the old real FFT code not used since at least 2009.

I confirmed that the currently used real FFT code in RealFFTf.cpp is faster
than the old one with a quick benchmark that calls PowerSpectrum() on 4-minute
audio file, with different sizes of computation windows:

Window_size: 256 method: new FFT time_s: 0.393
Window_size: 256 method: old FFT time_s: 1.065
Window_size: 1024 method: new FFT time_s: 0.38
Window_size: 1024 method: old FFT time_s: 0.958
Window_size: 4096 method: new FFT time_s: 0.413
Window_size: 4096 method: old FFT time_s: 1.084
Window_size: 16384 method: new FFT time_s: 0.518
Window_size: 16384 method: old FFT time_s: 1.338
Window_size: 65536 method: new FFT time_s: 0.655
Window_size: 65536 method: old FFT time_s: 1.524
Window_size: 262144 method: new FFT time_s: 0.735
Window_size: 262144 method: old FFT time_s: 1.873
This commit is contained in:
Raphaël Marinier
2016-06-25 16:23:56 +02:00
parent cf79f91da0
commit 6ac68db5be
10 changed files with 8 additions and 210 deletions

View File

@@ -46,6 +46,7 @@
#include <stdio.h>
#include <math.h>
#include "RealFFTf.h"
#include "Experimental.h"
static int **gFFTBitTable = NULL;
@@ -110,10 +111,6 @@ void InitFFT()
}
}
#ifdef EXPERIMENTAL_USE_REALFFTF
#include "RealFFTf.h"
#endif
void DeinitFFT()
{
if (gFFTBitTable) {
@@ -122,10 +119,8 @@ void DeinitFFT()
}
delete[] gFFTBitTable;
}
#ifdef EXPERIMENTAL_USE_REALFFTF
// Deallocate any unused RealFFTf tables
CleanupFFT();
#endif
}
inline int FastReverseBits(int i, int NumBits)
@@ -238,22 +233,11 @@ void FFT(int NumSamples,
/*
* Real Fast Fourier Transform
*
* This function was based on the code in Numerical Recipes in C.
* In Num. Rec., the inner loop is based on a single 1-based array
* of interleaved real and imaginary numbers. Because we have two
* separate zero-based arrays, our indices are quite different.
* Here is the correspondence between Num. Rec. indices and our indices:
*
* i1 <-> real[i]
* i2 <-> imag[i]
* i3 <-> real[n/2-i]
* i4 <-> imag[n/2-i]
* This is merely a wrapper of RealFFTf() from RealFFTf.h.
*/
void RealFFT(int NumSamples, float *RealIn, float *RealOut, float *ImagOut)
{
#ifdef EXPERIMENTAL_USE_REALFFTF
// Remap to RealFFTf() function
int i;
HFFT hFFT = GetFFT(NumSamples);
float *pFFT = new float[NumSamples];
@@ -280,62 +264,8 @@ void RealFFT(int NumSamples, float *RealIn, float *RealOut, float *ImagOut)
}
delete [] pFFT;
ReleaseFFT(hFFT);
#else
int Half = NumSamples / 2;
int i;
float theta = M_PI / Half;
float *tmpReal = new float[Half];
float *tmpImag = new float[Half];
for (i = 0; i < Half; i++) {
tmpReal[i] = RealIn[2 * i];
tmpImag[i] = RealIn[2 * i + 1];
}
FFT(Half, 0, tmpReal, tmpImag, RealOut, ImagOut);
float wtemp = float (sin(0.5 * theta));
float wpr = -2.0 * wtemp * wtemp;
float wpi = -1.0 * float (sin(theta));
float wr = 1.0 + wpr;
float wi = wpi;
int i3;
float h1r, h1i, h2r, h2i;
for (i = 1; i < Half / 2; i++) {
i3 = Half - i;
h1r = 0.5 * (RealOut[i] + RealOut[i3]);
h1i = 0.5 * (ImagOut[i] - ImagOut[i3]);
h2r = 0.5 * (ImagOut[i] + ImagOut[i3]);
h2i = -0.5 * (RealOut[i] - RealOut[i3]);
RealOut[i] = h1r + wr * h2r - wi * h2i;
ImagOut[i] = h1i + wr * h2i + wi * h2r;
RealOut[i3] = h1r - wr * h2r + wi * h2i;
ImagOut[i3] = -h1i + wr * h2i + wi * h2r;
wr = (wtemp = wr) * wpr - wi * wpi + wr;
wi = wi * wpr + wtemp * wpi + wi;
}
RealOut[0] = (h1r = RealOut[0]) + ImagOut[0];
ImagOut[0] = h1r - ImagOut[0];
delete[]tmpReal;
delete[]tmpImag;
#endif //EXPERIMENTAL_USE_REALFFTF
}
#ifdef EXPERIMENTAL_USE_REALFFTF
/*
* InverseRealFFT
*
@@ -344,10 +274,11 @@ void RealFFT(int NumSamples, float *RealIn, float *RealOut, float *ImagOut)
* and as a result the output is purely real.
* Only the first half of RealIn and ImagIn are used due to this
* symmetry assumption.
*
* This is merely a wrapper of InverseRealFFTf() from RealFFTf.h.
*/
void InverseRealFFT(int NumSamples, float *RealIn, float *ImagIn, float *RealOut)
{
// Remap to RealFFTf() function
int i;
HFFT hFFT = GetFFT(NumSamples);
float *pFFT = new float[NumSamples];
@@ -373,15 +304,13 @@ void InverseRealFFT(int NumSamples, float *RealIn, float *ImagIn, float *RealOut
delete [] pFFT;
ReleaseFFT(hFFT);
}
#endif // EXPERIMENTAL_USE_REALFFTF
/*
* PowerSpectrum
*
* This function computes the same as RealFFT, above, but
* adds the squares of the real and imaginary part of each
* coefficient, extracting the power and throwing away the
* phase.
* This function uses RealFFTf() from RealFFTf.h to perform the real
* FFT computation, and then squares the real and imaginary part of
* each coefficient, extracting the power and throwing away the phase.
*
* For speed, it does not call RealFFT, but duplicates some
* of its code.
@@ -389,8 +318,6 @@ void InverseRealFFT(int NumSamples, float *RealIn, float *ImagIn, float *RealOut
void PowerSpectrum(int NumSamples, float *In, float *Out)
{
#ifdef EXPERIMENTAL_USE_REALFFTF
// Remap to RealFFTf() function
int i;
HFFT hFFT = GetFFT(NumSamples);
float *pFFT = new float[NumSamples];
@@ -411,73 +338,6 @@ void PowerSpectrum(int NumSamples, float *In, float *Out)
Out[i] = pFFT[1]*pFFT[1];
delete [] pFFT;
ReleaseFFT(hFFT);
#else // EXPERIMENTAL_USE_REALFFTF
int Half = NumSamples / 2;
int i;
float theta = M_PI / Half;
float *tmpReal = new float[Half];
float *tmpImag = new float[Half];
float *RealOut = new float[Half];
float *ImagOut = new float[Half];
for (i = 0; i < Half; i++) {
tmpReal[i] = In[2 * i];
tmpImag[i] = In[2 * i + 1];
}
FFT(Half, 0, tmpReal, tmpImag, RealOut, ImagOut);
float wtemp = float (sin(0.5 * theta));
float wpr = -2.0 * wtemp * wtemp;
float wpi = -1.0 * float (sin(theta));
float wr = 1.0 + wpr;
float wi = wpi;
int i3;
float h1r, h1i, h2r, h2i, rt, it;
for (i = 1; i < Half / 2; i++) {
i3 = Half - i;
h1r = 0.5 * (RealOut[i] + RealOut[i3]);
h1i = 0.5 * (ImagOut[i] - ImagOut[i3]);
h2r = 0.5 * (ImagOut[i] + ImagOut[i3]);
h2i = -0.5 * (RealOut[i] - RealOut[i3]);
rt = h1r + wr * h2r - wi * h2i;
it = h1i + wr * h2i + wi * h2r;
Out[i] = rt * rt + it * it;
rt = h1r - wr * h2r + wi * h2i;
it = -h1i + wr * h2i + wi * h2r;
Out[i3] = rt * rt + it * it;
wr = (wtemp = wr) * wpr - wi * wpi + wr;
wi = wi * wpr + wtemp * wpi + wi;
}
rt = (h1r = RealOut[0]) + ImagOut[0];
it = h1r - ImagOut[0];
Out[0] = rt * rt + it * it;
rt = RealOut[Half / 2];
it = ImagOut[Half / 2];
Out[Half / 2] = rt * rt + it * it;
delete[]tmpReal;
delete[]tmpImag;
delete[]RealOut;
delete[]ImagOut;
#endif // EXPERIMENTAL_USE_REALFFTF
}
/*