Chris@110
|
1
|
Chris@110
|
2 #include "dsp/transforms/FFT.h"
|
Chris@110
|
3
|
Chris@110
|
4 #define BOOST_TEST_DYN_LINK
|
Chris@110
|
5 #define BOOST_TEST_MAIN
|
Chris@110
|
6
|
Chris@110
|
7 #include <boost/test/unit_test.hpp>
|
Chris@110
|
8
|
Chris@110
|
9 BOOST_AUTO_TEST_SUITE(TestFFT)
|
Chris@110
|
10
|
Chris@110
|
11 #define COMPARE_CONST(a, n) \
|
Chris@110
|
12 for (int cmp_i = 0; cmp_i < (int)(sizeof(a)/sizeof(a[0])); ++cmp_i) { \
|
Chris@110
|
13 BOOST_CHECK_SMALL(a[cmp_i] - n, 1e-14); \
|
Chris@110
|
14 }
|
Chris@110
|
15
|
Chris@110
|
16 #define COMPARE_ARRAY(a, b) \
|
Chris@110
|
17 for (int cmp_i = 0; cmp_i < (int)(sizeof(a)/sizeof(a[0])); ++cmp_i) { \
|
Chris@110
|
18 BOOST_CHECK_SMALL(a[cmp_i] - b[cmp_i], 1e-14); \
|
Chris@110
|
19 }
|
Chris@110
|
20
|
Chris@110
|
21 BOOST_AUTO_TEST_CASE(dc)
|
Chris@110
|
22 {
|
Chris@110
|
23 // DC-only signal. The DC bin is purely real
|
Chris@110
|
24 double in[] = { 1, 1, 1, 1 };
|
Chris@110
|
25 double re[4], im[4];
|
Chris@110
|
26 FFT(4).process(false, in, 0, re, im);
|
Chris@110
|
27 BOOST_CHECK_EQUAL(re[0], 4.0);
|
Chris@110
|
28 BOOST_CHECK_EQUAL(re[1], 0.0);
|
Chris@110
|
29 BOOST_CHECK_EQUAL(re[2], 0.0);
|
Chris@110
|
30 COMPARE_CONST(im, 0.0);
|
Chris@110
|
31 double back[4];
|
Chris@110
|
32 double backim[4];
|
Chris@110
|
33 FFT(4).process(true, re, im, back, backim);
|
Chris@110
|
34 COMPARE_ARRAY(back, in);
|
Chris@110
|
35 }
|
Chris@110
|
36
|
Chris@110
|
37 BOOST_AUTO_TEST_CASE(sine)
|
Chris@110
|
38 {
|
Chris@110
|
39 // Sine. Output is purely imaginary
|
Chris@110
|
40 double in[] = { 0, 1, 0, -1 };
|
Chris@110
|
41 double re[4], im[4];
|
Chris@110
|
42 FFT(4).process(false, in, 0, re, im);
|
Chris@110
|
43 COMPARE_CONST(re, 0.0);
|
Chris@110
|
44 BOOST_CHECK_EQUAL(im[0], 0.0);
|
Chris@110
|
45 BOOST_CHECK_EQUAL(im[1], -2.0);
|
Chris@110
|
46 BOOST_CHECK_EQUAL(im[2], 0.0);
|
Chris@110
|
47 double back[4];
|
Chris@110
|
48 double backim[4];
|
Chris@110
|
49 FFT(4).process(true, re, im, back, backim);
|
Chris@110
|
50 COMPARE_ARRAY(back, in);
|
Chris@110
|
51 }
|
Chris@110
|
52
|
Chris@110
|
53 BOOST_AUTO_TEST_CASE(cosine)
|
Chris@110
|
54 {
|
Chris@110
|
55 // Cosine. Output is purely real
|
Chris@110
|
56 double in[] = { 1, 0, -1, 0 };
|
Chris@110
|
57 double re[4], im[4];
|
Chris@110
|
58 FFT(4).process(false, in, 0, re, im);
|
Chris@110
|
59 BOOST_CHECK_EQUAL(re[0], 0.0);
|
Chris@110
|
60 BOOST_CHECK_EQUAL(re[1], 2.0);
|
Chris@110
|
61 BOOST_CHECK_EQUAL(re[2], 0.0);
|
Chris@110
|
62 COMPARE_CONST(im, 0.0);
|
Chris@110
|
63 double back[4];
|
Chris@110
|
64 double backim[4];
|
Chris@110
|
65 FFT(4).process(true, re, im, back, backim);
|
Chris@110
|
66 COMPARE_ARRAY(back, in);
|
Chris@110
|
67 }
|
Chris@110
|
68
|
Chris@110
|
69 BOOST_AUTO_TEST_CASE(sineCosine)
|
Chris@110
|
70 {
|
Chris@110
|
71 // Sine and cosine mixed
|
Chris@110
|
72 double in[] = { 0.5, 1, -0.5, -1 };
|
Chris@110
|
73 double re[4], im[4];
|
Chris@110
|
74 FFT(4).process(false, in, 0, re, im);
|
Chris@110
|
75 BOOST_CHECK_EQUAL(re[0], 0.0);
|
Chris@110
|
76 BOOST_CHECK_CLOSE(re[1], 1.0, 1e-12);
|
Chris@110
|
77 BOOST_CHECK_EQUAL(re[2], 0.0);
|
Chris@110
|
78 BOOST_CHECK_EQUAL(im[0], 0.0);
|
Chris@110
|
79 BOOST_CHECK_CLOSE(im[1], -2.0, 1e-12);
|
Chris@110
|
80 BOOST_CHECK_EQUAL(im[2], 0.0);
|
Chris@110
|
81 double back[4];
|
Chris@110
|
82 double backim[4];
|
Chris@110
|
83 FFT(4).process(true, re, im, back, backim);
|
Chris@110
|
84 COMPARE_ARRAY(back, in);
|
Chris@110
|
85 }
|
Chris@110
|
86
|
Chris@110
|
87 BOOST_AUTO_TEST_CASE(nyquist)
|
Chris@110
|
88 {
|
Chris@110
|
89 double in[] = { 1, -1, 1, -1 };
|
Chris@110
|
90 double re[4], im[4];
|
Chris@110
|
91 FFT(4).process(false, in, 0, re, im);
|
Chris@110
|
92 BOOST_CHECK_EQUAL(re[0], 0.0);
|
Chris@110
|
93 BOOST_CHECK_EQUAL(re[1], 0.0);
|
Chris@110
|
94 BOOST_CHECK_EQUAL(re[2], 4.0);
|
Chris@110
|
95 COMPARE_CONST(im, 0.0);
|
Chris@110
|
96 double back[4];
|
Chris@110
|
97 double backim[4];
|
Chris@110
|
98 FFT(4).process(true, re, im, back, backim);
|
Chris@110
|
99 COMPARE_ARRAY(back, in);
|
Chris@110
|
100 }
|
Chris@110
|
101
|
Chris@110
|
102 BOOST_AUTO_TEST_CASE(dirac)
|
Chris@110
|
103 {
|
Chris@110
|
104 double in[] = { 1, 0, 0, 0 };
|
Chris@110
|
105 double re[4], im[4];
|
Chris@110
|
106 FFT(4).process(false, in, 0, re, im);
|
Chris@110
|
107 BOOST_CHECK_EQUAL(re[0], 1.0);
|
Chris@110
|
108 BOOST_CHECK_EQUAL(re[1], 1.0);
|
Chris@110
|
109 BOOST_CHECK_EQUAL(re[2], 1.0);
|
Chris@110
|
110 COMPARE_CONST(im, 0.0);
|
Chris@110
|
111 double back[4];
|
Chris@110
|
112 double backim[4];
|
Chris@110
|
113 FFT(4).process(true, re, im, back, backim);
|
Chris@110
|
114 COMPARE_ARRAY(back, in);
|
Chris@110
|
115 }
|
Chris@110
|
116
|
Chris@110
|
117 BOOST_AUTO_TEST_CASE(forwardArrayBounds)
|
Chris@110
|
118 {
|
Chris@110
|
119 // initialise bins to something recognisable, so we can tell
|
Chris@110
|
120 // if they haven't been written
|
Chris@110
|
121 double in[] = { 1, 1, -1, -1 };
|
Chris@110
|
122 double re[] = { 999, 999, 999, 999, 999, 999 };
|
Chris@110
|
123 double im[] = { 999, 999, 999, 999, 999, 999 };
|
Chris@110
|
124 FFT(4).process(false, in, 0, re+1, im+1);
|
Chris@110
|
125 // And check we haven't overrun the arrays
|
Chris@110
|
126 BOOST_CHECK_EQUAL(re[0], 999.0);
|
Chris@110
|
127 BOOST_CHECK_EQUAL(im[0], 999.0);
|
Chris@110
|
128 BOOST_CHECK_EQUAL(re[5], 999.0);
|
Chris@110
|
129 BOOST_CHECK_EQUAL(im[5], 999.0);
|
Chris@110
|
130 }
|
Chris@110
|
131
|
Chris@110
|
132 BOOST_AUTO_TEST_CASE(inverseArrayBounds)
|
Chris@110
|
133 {
|
Chris@110
|
134 // initialise bins to something recognisable, so we can tell
|
Chris@110
|
135 // if they haven't been written
|
Chris@110
|
136 double re[] = { 0, 1, 0 };
|
Chris@110
|
137 double im[] = { 0, -2, 0 };
|
Chris@110
|
138 double outre[] = { 999, 999, 999, 999, 999, 999 };
|
Chris@110
|
139 double outim[] = { 999, 999, 999, 999, 999, 999 };
|
Chris@110
|
140 FFT(4).process(false, re, im, outre+1, outim+1);
|
Chris@110
|
141 // And check we haven't overrun the arrays
|
Chris@110
|
142 BOOST_CHECK_EQUAL(outre[0], 999.0);
|
Chris@110
|
143 BOOST_CHECK_EQUAL(outim[0], 999.0);
|
Chris@110
|
144 BOOST_CHECK_EQUAL(outre[5], 999.0);
|
Chris@110
|
145 BOOST_CHECK_EQUAL(outim[5], 999.0);
|
Chris@110
|
146 }
|
Chris@110
|
147
|
Chris@110
|
148 BOOST_AUTO_TEST_SUITE_END()
|
Chris@110
|
149
|