32struct FFTUnitTest :
public UnitTest
35 :
UnitTest (
"FFT", UnitTestCategories::dsp)
38 static void fillRandom (Random& random, Complex<float>* buffer,
size_t n)
40 for (
size_t i = 0; i < n; ++i)
41 buffer[i] = Complex<float> ((2.0f * random.nextFloat()) - 1.0f,
42 (2.0f * random.nextFloat()) - 1.0f);
45 static void fillRandom (Random& random,
float* buffer,
size_t n)
47 for (
size_t i = 0; i < n; ++i)
48 buffer[i] = (2.0f * random.nextFloat()) - 1.0f;
51 static Complex<float> freqConvolution (
const Complex<float>* in,
float freq,
size_t n)
53 Complex<float> sum (0.0, 0.0);
54 for (
size_t i = 0; i < n; ++i)
55 sum += in[i] * exp (Complex<float> (0,
static_cast<float> (i) * freq));
60 static void performReferenceFourier (
const Complex<float>* in, Complex<float>* out,
61 size_t n,
bool reverse)
64 /
static_cast<float> (n));
66 for (
size_t i = 0; i < n; ++i)
67 out[i] = freqConvolution (in,
static_cast<float>(i) * base_freq, n);
70 static void performReferenceFourier (
const float* in, Complex<float>* out,
71 size_t n,
bool reverse)
73 HeapBlock<Complex<float>> buffer (n);
75 for (
size_t i = 0; i < n; ++i)
76 buffer.getData()[i] = Complex<float> (in[i], 0.0f);
79 /
static_cast<float> (n));
81 for (
size_t i = 0; i < n; ++i)
82 out[i] = freqConvolution (buffer.getData(),
static_cast<float>(i) * base_freq, n);
87 template <
typename Type>
88 static bool checkArrayIsSimilar (Type* a, Type* b,
size_t n)
noexcept
90 for (
size_t i = 0; i < n; ++i)
91 if (std::abs (a[i] - b[i]) > 1e-3f)
99 static void run (FFTUnitTest& u)
101 Random random (378272);
103 for (
size_t order = 0; order <= 8; ++order)
105 auto n = (1u << order);
107 FFT fft ((
int) order);
109 HeapBlock<float> input (n);
110 HeapBlock<Complex<float>> reference (n), output (n);
112 fillRandom (random, input.getData(), n);
113 performReferenceFourier (input.getData(), reference.getData(), n,
false);
116 zeromem (output.getData(), n * sizeof (Complex<float>));
117 memcpy (
reinterpret_cast<float*
> (output.getData()), input.getData(), n * sizeof (
float));
119 fft.performRealOnlyForwardTransform ((
float*) output.getData());
120 u.expect (checkArrayIsSimilar (reference.getData(), output.getData(), n));
123 zeromem (output.getData(), n * sizeof (Complex<float>));
124 memcpy (
reinterpret_cast<float*
> (output.getData()), input.getData(), n * sizeof (
float));
126 fft.performRealOnlyForwardTransform ((
float*) output.getData(),
true);
127 std::fill (reference.getData() + ((n >> 1) + 1), reference.getData() + n, std::complex<float> (0.0f));
128 u.expect (checkArrayIsSimilar (reference.getData(), output.getData(), (n >> 1) + 1));
130 memcpy (output.getData(), reference.getData(), n * sizeof (Complex<float>));
131 fft.performRealOnlyInverseTransform ((
float*) output.getData());
132 u.expect (checkArrayIsSimilar ((
float*) output.getData(), input.getData(), n));
137 struct FrequencyOnlyTest
139 static void run(FFTUnitTest& u)
141 Random random (378272);
142 for (
size_t order = 0; order <= 8; ++order)
144 auto n = (1u << order);
146 FFT fft ((
int) order);
148 HeapBlock<float> inout (n << 1), reference (n << 1);
149 HeapBlock<Complex<float>> frequency (n);
151 fillRandom (random, inout.getData(), n);
152 zeromem (reference.getData(), sizeof (
float) * (n << 1));
153 performReferenceFourier (inout.getData(), frequency.getData(), n,
false);
155 for (
size_t i = 0; i < n; ++i)
156 reference.getData()[i] = std::abs (frequency.getData()[i]);
158 fft.performFrequencyOnlyForwardTransform (inout.getData());
160 u.expect (checkArrayIsSimilar (inout.getData(), reference.getData(), n));
167 static void run(FFTUnitTest& u)
169 Random random (378272);
171 for (
size_t order = 0; order <= 7; ++order)
173 auto n = (1u << order);
175 FFT fft ((
int) order);
177 HeapBlock<Complex<float>> input (n), buffer (n), output (n), reference (n);
179 fillRandom (random, input.getData(), n);
180 performReferenceFourier (input.getData(), reference.getData(), n,
false);
182 memcpy (buffer.getData(), input.getData(), sizeof (Complex<float>) * n);
183 fft.perform (buffer.getData(), output.getData(),
false);
185 u.expect (checkArrayIsSimilar (output.getData(), reference.getData(), n));
187 memcpy (buffer.getData(), reference.getData(), sizeof (Complex<float>) * n);
188 fft.perform (buffer.getData(), output.getData(),
true);
191 u.expect (checkArrayIsSimilar (output.getData(), input.getData(), n));
196 template <
class TheTest>
197 void runTestForAllTypes (
const char* unitTestName)
201 TheTest::run (*
this);
204 void runTest()
override
206 runTestForAllTypes<RealTest> (
"Real input numbers Test");
207 runTestForAllTypes<FrequencyOnlyTest> (
"Frequency only Test");
208 runTestForAllTypes<ComplexTest> (
"Complex input numbers Test");
212static FFTUnitTest fftUnitTest;
UnitTest(const String &name, const String &category=String())
void beginTest(const String &testName)
static const FloatType twoPi