comparison tests/TestFFT.cpp @ 335:0a632ac70945

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