Mercurial > hg > qm-dsp
comparison tests/TestFFT.cpp @ 110:87ad66aaed32
FFT and window tests
author | Chris Cannam |
---|---|
date | Mon, 30 Sep 2013 16:50:38 +0100 |
parents | |
children | f6ccde089491 |
comparison
equal
deleted
inserted
replaced
109:627d364bbc82 | 110:87ad66aaed32 |
---|---|
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 |