Skip to content

Commit 6ac68db

Browse files
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
1 parent cf79f91 commit 6ac68db

10 files changed

+8
-210
lines changed

src/Experimental.h

-4
Original file line numberDiff line numberDiff line change
@@ -107,10 +107,6 @@
107107
// Paul Licameli (PRL) 29 Nov 2014
108108
// #define EXPERIMENTAL_IMPROVED_SEEKING
109109

110-
// Philip Van Baren 01 July 2009
111-
// Replace RealFFT() and PowerSpectrum function to use (faster) RealFFTf function
112-
#define EXPERIMENTAL_USE_REALFFTF
113-
114110
// RBD, 1 Sep 2008
115111
// Enables MIDI Output of NoteTrack (MIDI) data during playback
116112
// USE_MIDI must be defined in order for EXPERIMENTAL_MIDI_OUT to work

src/FFT.cpp

+7-147
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
#include <stdio.h>
4747
#include <math.h>
4848

49+
#include "RealFFTf.h"
4950
#include "Experimental.h"
5051

5152
static int **gFFTBitTable = NULL;
@@ -110,10 +111,6 @@ void InitFFT()
110111
}
111112
}
112113

113-
#ifdef EXPERIMENTAL_USE_REALFFTF
114-
#include "RealFFTf.h"
115-
#endif
116-
117114
void DeinitFFT()
118115
{
119116
if (gFFTBitTable) {
@@ -122,10 +119,8 @@ void DeinitFFT()
122119
}
123120
delete[] gFFTBitTable;
124121
}
125-
#ifdef EXPERIMENTAL_USE_REALFFTF
126122
// Deallocate any unused RealFFTf tables
127123
CleanupFFT();
128-
#endif
129124
}
130125

131126
inline int FastReverseBits(int i, int NumBits)
@@ -238,22 +233,11 @@ void FFT(int NumSamples,
238233
/*
239234
* Real Fast Fourier Transform
240235
*
241-
* This function was based on the code in Numerical Recipes in C.
242-
* In Num. Rec., the inner loop is based on a single 1-based array
243-
* of interleaved real and imaginary numbers. Because we have two
244-
* separate zero-based arrays, our indices are quite different.
245-
* Here is the correspondence between Num. Rec. indices and our indices:
246-
*
247-
* i1 <-> real[i]
248-
* i2 <-> imag[i]
249-
* i3 <-> real[n/2-i]
250-
* i4 <-> imag[n/2-i]
236+
* This is merely a wrapper of RealFFTf() from RealFFTf.h.
251237
*/
252238

253239
void RealFFT(int NumSamples, float *RealIn, float *RealOut, float *ImagOut)
254240
{
255-
#ifdef EXPERIMENTAL_USE_REALFFTF
256-
// Remap to RealFFTf() function
257241
int i;
258242
HFFT hFFT = GetFFT(NumSamples);
259243
float *pFFT = new float[NumSamples];
@@ -280,62 +264,8 @@ void RealFFT(int NumSamples, float *RealIn, float *RealOut, float *ImagOut)
280264
}
281265
delete [] pFFT;
282266
ReleaseFFT(hFFT);
283-
284-
#else
285-
286-
int Half = NumSamples / 2;
287-
int i;
288-
289-
float theta = M_PI / Half;
290-
291-
float *tmpReal = new float[Half];
292-
float *tmpImag = new float[Half];
293-
294-
for (i = 0; i < Half; i++) {
295-
tmpReal[i] = RealIn[2 * i];
296-
tmpImag[i] = RealIn[2 * i + 1];
297-
}
298-
299-
FFT(Half, 0, tmpReal, tmpImag, RealOut, ImagOut);
300-
301-
float wtemp = float (sin(0.5 * theta));
302-
303-
float wpr = -2.0 * wtemp * wtemp;
304-
float wpi = -1.0 * float (sin(theta));
305-
float wr = 1.0 + wpr;
306-
float wi = wpi;
307-
308-
int i3;
309-
310-
float h1r, h1i, h2r, h2i;
311-
312-
for (i = 1; i < Half / 2; i++) {
313-
314-
i3 = Half - i;
315-
316-
h1r = 0.5 * (RealOut[i] + RealOut[i3]);
317-
h1i = 0.5 * (ImagOut[i] - ImagOut[i3]);
318-
h2r = 0.5 * (ImagOut[i] + ImagOut[i3]);
319-
h2i = -0.5 * (RealOut[i] - RealOut[i3]);
320-
321-
RealOut[i] = h1r + wr * h2r - wi * h2i;
322-
ImagOut[i] = h1i + wr * h2i + wi * h2r;
323-
RealOut[i3] = h1r - wr * h2r + wi * h2i;
324-
ImagOut[i3] = -h1i + wr * h2i + wi * h2r;
325-
326-
wr = (wtemp = wr) * wpr - wi * wpi + wr;
327-
wi = wi * wpr + wtemp * wpi + wi;
328-
}
329-
330-
RealOut[0] = (h1r = RealOut[0]) + ImagOut[0];
331-
ImagOut[0] = h1r - ImagOut[0];
332-
333-
delete[]tmpReal;
334-
delete[]tmpImag;
335-
#endif //EXPERIMENTAL_USE_REALFFTF
336267
}
337268

338-
#ifdef EXPERIMENTAL_USE_REALFFTF
339269
/*
340270
* InverseRealFFT
341271
*
@@ -344,10 +274,11 @@ void RealFFT(int NumSamples, float *RealIn, float *RealOut, float *ImagOut)
344274
* and as a result the output is purely real.
345275
* Only the first half of RealIn and ImagIn are used due to this
346276
* symmetry assumption.
277+
*
278+
* This is merely a wrapper of InverseRealFFTf() from RealFFTf.h.
347279
*/
348280
void InverseRealFFT(int NumSamples, float *RealIn, float *ImagIn, float *RealOut)
349281
{
350-
// Remap to RealFFTf() function
351282
int i;
352283
HFFT hFFT = GetFFT(NumSamples);
353284
float *pFFT = new float[NumSamples];
@@ -373,24 +304,20 @@ void InverseRealFFT(int NumSamples, float *RealIn, float *ImagIn, float *RealOut
373304
delete [] pFFT;
374305
ReleaseFFT(hFFT);
375306
}
376-
#endif // EXPERIMENTAL_USE_REALFFTF
377307

378308
/*
379309
* PowerSpectrum
380310
*
381-
* This function computes the same as RealFFT, above, but
382-
* adds the squares of the real and imaginary part of each
383-
* coefficient, extracting the power and throwing away the
384-
* phase.
311+
* This function uses RealFFTf() from RealFFTf.h to perform the real
312+
* FFT computation, and then squares the real and imaginary part of
313+
* each coefficient, extracting the power and throwing away the phase.
385314
*
386315
* For speed, it does not call RealFFT, but duplicates some
387316
* of its code.
388317
*/
389318

390319
void PowerSpectrum(int NumSamples, float *In, float *Out)
391320
{
392-
#ifdef EXPERIMENTAL_USE_REALFFTF
393-
// Remap to RealFFTf() function
394321
int i;
395322
HFFT hFFT = GetFFT(NumSamples);
396323
float *pFFT = new float[NumSamples];
@@ -411,73 +338,6 @@ void PowerSpectrum(int NumSamples, float *In, float *Out)
411338
Out[i] = pFFT[1]*pFFT[1];
412339
delete [] pFFT;
413340
ReleaseFFT(hFFT);
414-
415-
#else // EXPERIMENTAL_USE_REALFFTF
416-
417-
int Half = NumSamples / 2;
418-
int i;
419-
420-
float theta = M_PI / Half;
421-
422-
float *tmpReal = new float[Half];
423-
float *tmpImag = new float[Half];
424-
float *RealOut = new float[Half];
425-
float *ImagOut = new float[Half];
426-
427-
for (i = 0; i < Half; i++) {
428-
tmpReal[i] = In[2 * i];
429-
tmpImag[i] = In[2 * i + 1];
430-
}
431-
432-
FFT(Half, 0, tmpReal, tmpImag, RealOut, ImagOut);
433-
434-
float wtemp = float (sin(0.5 * theta));
435-
436-
float wpr = -2.0 * wtemp * wtemp;
437-
float wpi = -1.0 * float (sin(theta));
438-
float wr = 1.0 + wpr;
439-
float wi = wpi;
440-
441-
int i3;
442-
443-
float h1r, h1i, h2r, h2i, rt, it;
444-
445-
for (i = 1; i < Half / 2; i++) {
446-
447-
i3 = Half - i;
448-
449-
h1r = 0.5 * (RealOut[i] + RealOut[i3]);
450-
h1i = 0.5 * (ImagOut[i] - ImagOut[i3]);
451-
h2r = 0.5 * (ImagOut[i] + ImagOut[i3]);
452-
h2i = -0.5 * (RealOut[i] - RealOut[i3]);
453-
454-
rt = h1r + wr * h2r - wi * h2i;
455-
it = h1i + wr * h2i + wi * h2r;
456-
457-
Out[i] = rt * rt + it * it;
458-
459-
rt = h1r - wr * h2r + wi * h2i;
460-
it = -h1i + wr * h2i + wi * h2r;
461-
462-
Out[i3] = rt * rt + it * it;
463-
464-
wr = (wtemp = wr) * wpr - wi * wpi + wr;
465-
wi = wi * wpr + wtemp * wpi + wi;
466-
}
467-
468-
rt = (h1r = RealOut[0]) + ImagOut[0];
469-
it = h1r - ImagOut[0];
470-
Out[0] = rt * rt + it * it;
471-
472-
rt = RealOut[Half / 2];
473-
it = ImagOut[Half / 2];
474-
Out[Half / 2] = rt * rt + it * it;
475-
476-
delete[]tmpReal;
477-
delete[]tmpImag;
478-
delete[]RealOut;
479-
delete[]ImagOut;
480-
#endif // EXPERIMENTAL_USE_REALFFTF
481341
}
482342

483343
/*

src/FFT.h

-4
Original file line numberDiff line numberDiff line change
@@ -77,13 +77,9 @@ void RealFFT(int NumSamples,
7777
* Computes an Inverse FFT when the input data is conjugate symmetric
7878
* so the output is purely real. NumSamples must be a power of
7979
* two.
80-
* Requires: EXPERIMENTAL_USE_REALFFTF
8180
*/
82-
#include "Experimental.h"
83-
#ifdef EXPERIMENTAL_USE_REALFFTF
8481
void InverseRealFFT(int NumSamples,
8582
float *RealIn, float *ImagIn, float *RealOut);
86-
#endif
8783

8884
/*
8985
* Computes a FFT of complex input and returns complex output.

src/FreqWindow.cpp

-17
Original file line numberDiff line numberDiff line change
@@ -1255,11 +1255,7 @@ bool SpectrumAnalyst::Calculate(Algorithm alg, int windowFunc,
12551255
case EnhancedAutocorrelation:
12561256

12571257
// Take FFT
1258-
#ifdef EXPERIMENTAL_USE_REALFFTF
12591258
RealFFT(mWindowSize, in, out, out2);
1260-
#else
1261-
FFT(mWindowSize, false, in, NULL, out, out2);
1262-
#endif
12631259
// Compute power
12641260
for (int i = 0; i < mWindowSize; i++)
12651261
in[i] = (out[i] * out[i]) + (out2[i] * out2[i]);
@@ -1277,24 +1273,15 @@ bool SpectrumAnalyst::Calculate(Algorithm alg, int windowFunc,
12771273
in[i] = pow(in[i], 1.0f / 3.0f);
12781274
}
12791275
// Take FFT
1280-
#ifdef EXPERIMENTAL_USE_REALFFTF
12811276
RealFFT(mWindowSize, in, out, out2);
1282-
#else
1283-
FFT(mWindowSize, false, in, NULL, out, out2);
1284-
#endif
12851277

12861278
// Take real part of result
12871279
for (int i = 0; i < half; i++)
12881280
mProcessed[i] += out[i];
12891281
break;
12901282

12911283
case Cepstrum:
1292-
#ifdef EXPERIMENTAL_USE_REALFFTF
12931284
RealFFT(mWindowSize, in, out, out2);
1294-
#else
1295-
FFT(mWindowSize, false, in, NULL, out, out2);
1296-
#endif
1297-
12981285
// Compute log power
12991286
// Set a sane lower limit assuming maximum time amplitude of 1.0
13001287
{
@@ -1309,11 +1296,7 @@ bool SpectrumAnalyst::Calculate(Algorithm alg, int windowFunc,
13091296
in[i] = log(power);
13101297
}
13111298
// Take IFFT
1312-
#ifdef EXPERIMENTAL_USE_REALFFTF
13131299
InverseRealFFT(mWindowSize, in, NULL, out);
1314-
#else
1315-
FFT(mWindowSize, true, in, NULL, out, out2);
1316-
#endif
13171300

13181301
// Take real part of result
13191302
for (int i = 0; i < half; i++)

src/Spectrum.cpp

-9
Original file line numberDiff line numberDiff line change
@@ -52,11 +52,7 @@ bool ComputeSpectrum(const float * data, int width,
5252

5353
if (autocorrelation) {
5454
// Take FFT
55-
#ifdef EXPERIMENTAL_USE_REALFFTF
5655
RealFFT(windowSize, in, out, out2);
57-
#else
58-
FFT(windowSize, false, in, NULL, out, out2);
59-
#endif
6056
// Compute power
6157
for (i = 0; i < windowSize; i++)
6258
in[i] = (out[i] * out[i]) + (out2[i] * out2[i]);
@@ -68,12 +64,7 @@ bool ComputeSpectrum(const float * data, int width,
6864
in[i] = powf(in[i], 1.0f / 3.0f);
6965

7066
// Take FFT
71-
#ifdef EXPERIMENTAL_USE_REALFFTF
7267
RealFFT(windowSize, in, out, out2);
73-
#else
74-
FFT(windowSize, false, in, NULL, out, out2);
75-
#endif
76-
7768
}
7869
else
7970
PowerSpectrum(windowSize, in, out);

src/WaveClip.cpp

+1-12
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
#include "Resample.h"
3535
#include "Project.h"
3636
#include "WaveTrack.h"
37+
#include "FFT.h"
3738

3839
#include "prefs/SpectrogramSettings.h"
3940

@@ -259,8 +260,6 @@ class WaveCache {
259260

260261
};
261262

262-
#ifdef EXPERIMENTAL_USE_REALFFTF
263-
#include "FFT.h"
264263
static void ComputeSpectrumUsingRealFFTf
265264
(float *buffer, HFFT hFFT, const float *window, int len, float *out)
266265
{
@@ -288,7 +287,6 @@ static void ComputeSpectrumUsingRealFFTf
288287
out[i] = 10.0*log10f(power);
289288
}
290289
}
291-
#endif // EXPERIMENTAL_USE_REALFFTF
292290

293291
WaveClip::WaveClip(DirManager *projDirManager, sampleFormat format, int rate)
294292
{
@@ -852,7 +850,6 @@ bool SpecCache::CalculateOneSpectrum
852850
if (copy)
853851
useBuffer = scratch;
854852

855-
#ifdef EXPERIMENTAL_USE_REALFFTF
856853
if (autocorrelation) {
857854
float *const results = &freq[half * xx];
858855
// This function does not mutate useBuffer
@@ -956,12 +953,6 @@ bool SpecCache::CalculateOneSpectrum
956953
results[ii] += gainFactors[ii];
957954
}
958955
}
959-
#else // EXPERIMENTAL_USE_REALFFTF
960-
// This function does not mutate scratch
961-
ComputeSpectrum(scratch, windowSize, windowSize,
962-
rate, results,
963-
autocorrelation, settings.windowType);
964-
#endif // EXPERIMENTAL_USE_REALFFTF
965956
}
966957
return result;
967958
}
@@ -972,9 +963,7 @@ void SpecCache::Populate
972963
sampleCount numSamples,
973964
double offset, double rate, double pixelsPerSecond)
974965
{
975-
#ifdef EXPERIMENTAL_USE_REALFFTF
976966
settings.CacheWindows();
977-
#endif
978967

979968
const int &frequencyGain = settings.frequencyGain;
980969
const int &windowSize = settings.windowSize;

src/WaveClip.h

-2
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,7 @@
2020
#include "xml/XMLTagHandler.h"
2121

2222
#include "Experimental.h"
23-
#ifdef EXPERIMENTAL_USE_REALFFTF
2423
#include "RealFFTf.h"
25-
#endif
2624

2725
#include <wx/gdicmn.h>
2826
#include <wx/longlong.h>

0 commit comments

Comments
 (0)