matthiasm@0
|
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
|
matthiasm@0
|
2 /*
|
matthiasm@0
|
3 This file is Copyright (c) 2012 Chris Cannam
|
matthiasm@0
|
4
|
matthiasm@0
|
5 Permission is hereby granted, free of charge, to any person
|
matthiasm@0
|
6 obtaining a copy of this software and associated documentation
|
matthiasm@0
|
7 files (the "Software"), to deal in the Software without
|
matthiasm@0
|
8 restriction, including without limitation the rights to use, copy,
|
matthiasm@0
|
9 modify, merge, publish, distribute, sublicense, and/or sell copies
|
matthiasm@0
|
10 of the Software, and to permit persons to whom the Software is
|
matthiasm@0
|
11 furnished to do so, subject to the following conditions:
|
matthiasm@0
|
12
|
matthiasm@0
|
13 The above copyright notice and this permission notice shall be
|
matthiasm@0
|
14 included in all copies or substantial portions of the Software.
|
matthiasm@0
|
15
|
matthiasm@0
|
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
matthiasm@0
|
17 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
matthiasm@0
|
18 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
matthiasm@0
|
19 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
|
matthiasm@0
|
20 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
matthiasm@0
|
21 CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
matthiasm@0
|
22 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
matthiasm@0
|
23 */
|
matthiasm@0
|
24
|
matthiasm@0
|
25 /*
|
matthiasm@0
|
26 This unit test suite for the Vamp SDK FFT implementation is included
|
matthiasm@0
|
27 here mostly for illustrative purposes!
|
matthiasm@0
|
28 */
|
matthiasm@0
|
29
|
matthiasm@0
|
30 #include "vamp-sdk/FFT.h"
|
matthiasm@0
|
31
|
matthiasm@0
|
32 #define BOOST_TEST_DYN_LINK
|
matthiasm@0
|
33 #define BOOST_TEST_MAIN
|
matthiasm@0
|
34
|
matthiasm@0
|
35 #include <boost/test/unit_test.hpp>
|
matthiasm@0
|
36
|
matthiasm@0
|
37 BOOST_AUTO_TEST_SUITE(TestFFT)
|
matthiasm@0
|
38
|
matthiasm@0
|
39 #define COMPARE_CONST(a, n) \
|
matthiasm@0
|
40 for (int cmp_i = 0; cmp_i < (int)(sizeof(a)/sizeof(a[0])); ++cmp_i) { \
|
matthiasm@0
|
41 BOOST_CHECK_SMALL(a[cmp_i] - n, 1e-14); \
|
matthiasm@0
|
42 }
|
matthiasm@0
|
43
|
matthiasm@0
|
44 #define COMPARE_ARRAY(a, b) \
|
matthiasm@0
|
45 for (int cmp_i = 0; cmp_i < (int)(sizeof(a)/sizeof(a[0])); ++cmp_i) { \
|
matthiasm@0
|
46 BOOST_CHECK_SMALL(a[cmp_i] - b[cmp_i], 1e-14); \
|
matthiasm@0
|
47 }
|
matthiasm@0
|
48
|
matthiasm@0
|
49 BOOST_AUTO_TEST_CASE(dc)
|
matthiasm@0
|
50 {
|
matthiasm@0
|
51 // DC-only signal. The DC bin is purely real
|
matthiasm@0
|
52 double in[] = { 1, 1, 1, 1 };
|
matthiasm@0
|
53 double re[4], im[4];
|
matthiasm@0
|
54 Vamp::FFT::forward(4, in, 0, re, im);
|
matthiasm@0
|
55 BOOST_CHECK_EQUAL(re[0], 4.0);
|
matthiasm@0
|
56 BOOST_CHECK_EQUAL(re[1], 0.0);
|
matthiasm@0
|
57 BOOST_CHECK_EQUAL(re[2], 0.0);
|
matthiasm@0
|
58 COMPARE_CONST(im, 0.0);
|
matthiasm@0
|
59 double back[4];
|
matthiasm@0
|
60 double backim[4];
|
matthiasm@0
|
61 Vamp::FFT::inverse(4, re, im, back, backim);
|
matthiasm@0
|
62 COMPARE_ARRAY(back, in);
|
matthiasm@0
|
63 }
|
matthiasm@0
|
64
|
matthiasm@0
|
65 BOOST_AUTO_TEST_CASE(sine)
|
matthiasm@0
|
66 {
|
matthiasm@0
|
67 // Sine. Output is purely imaginary
|
matthiasm@0
|
68 double in[] = { 0, 1, 0, -1 };
|
matthiasm@0
|
69 double re[4], im[4];
|
matthiasm@0
|
70 Vamp::FFT::forward(4, in, 0, re, im);
|
matthiasm@0
|
71 COMPARE_CONST(re, 0.0);
|
matthiasm@0
|
72 BOOST_CHECK_EQUAL(im[0], 0.0);
|
matthiasm@0
|
73 BOOST_CHECK_EQUAL(im[1], -2.0);
|
matthiasm@0
|
74 BOOST_CHECK_EQUAL(im[2], 0.0);
|
matthiasm@0
|
75 double back[4];
|
matthiasm@0
|
76 double backim[4];
|
matthiasm@0
|
77 Vamp::FFT::inverse(4, re, im, back, backim);
|
matthiasm@0
|
78 COMPARE_ARRAY(back, in);
|
matthiasm@0
|
79 }
|
matthiasm@0
|
80
|
matthiasm@0
|
81 BOOST_AUTO_TEST_CASE(cosine)
|
matthiasm@0
|
82 {
|
matthiasm@0
|
83 // Cosine. Output is purely real
|
matthiasm@0
|
84 double in[] = { 1, 0, -1, 0 };
|
matthiasm@0
|
85 double re[4], im[4];
|
matthiasm@0
|
86 Vamp::FFT::forward(4, in, 0, re, im);
|
matthiasm@0
|
87 BOOST_CHECK_EQUAL(re[0], 0.0);
|
matthiasm@0
|
88 BOOST_CHECK_EQUAL(re[1], 2.0);
|
matthiasm@0
|
89 BOOST_CHECK_EQUAL(re[2], 0.0);
|
matthiasm@0
|
90 COMPARE_CONST(im, 0.0);
|
matthiasm@0
|
91 double back[4];
|
matthiasm@0
|
92 double backim[4];
|
matthiasm@0
|
93 Vamp::FFT::inverse(4, re, im, back, backim);
|
matthiasm@0
|
94 COMPARE_ARRAY(back, in);
|
matthiasm@0
|
95 }
|
matthiasm@0
|
96
|
matthiasm@0
|
97 BOOST_AUTO_TEST_CASE(sineCosine)
|
matthiasm@0
|
98 {
|
matthiasm@0
|
99 // Sine and cosine mixed
|
matthiasm@0
|
100 double in[] = { 0.5, 1, -0.5, -1 };
|
matthiasm@0
|
101 double re[4], im[4];
|
matthiasm@0
|
102 Vamp::FFT::forward(4, in, 0, re, im);
|
matthiasm@0
|
103 BOOST_CHECK_EQUAL(re[0], 0.0);
|
matthiasm@0
|
104 BOOST_CHECK_CLOSE(re[1], 1.0, 1e-12);
|
matthiasm@0
|
105 BOOST_CHECK_EQUAL(re[2], 0.0);
|
matthiasm@0
|
106 BOOST_CHECK_EQUAL(im[0], 0.0);
|
matthiasm@0
|
107 BOOST_CHECK_CLOSE(im[1], -2.0, 1e-12);
|
matthiasm@0
|
108 BOOST_CHECK_EQUAL(im[2], 0.0);
|
matthiasm@0
|
109 double back[4];
|
matthiasm@0
|
110 double backim[4];
|
matthiasm@0
|
111 Vamp::FFT::inverse(4, re, im, back, backim);
|
matthiasm@0
|
112 COMPARE_ARRAY(back, in);
|
matthiasm@0
|
113 }
|
matthiasm@0
|
114
|
matthiasm@0
|
115 BOOST_AUTO_TEST_CASE(nyquist)
|
matthiasm@0
|
116 {
|
matthiasm@0
|
117 double in[] = { 1, -1, 1, -1 };
|
matthiasm@0
|
118 double re[4], im[4];
|
matthiasm@0
|
119 Vamp::FFT::forward(4, in, 0, re, im);
|
matthiasm@0
|
120 BOOST_CHECK_EQUAL(re[0], 0.0);
|
matthiasm@0
|
121 BOOST_CHECK_EQUAL(re[1], 0.0);
|
matthiasm@0
|
122 BOOST_CHECK_EQUAL(re[2], 4.0);
|
matthiasm@0
|
123 COMPARE_CONST(im, 0.0);
|
matthiasm@0
|
124 double back[4];
|
matthiasm@0
|
125 double backim[4];
|
matthiasm@0
|
126 Vamp::FFT::inverse(4, re, im, back, backim);
|
matthiasm@0
|
127 COMPARE_ARRAY(back, in);
|
matthiasm@0
|
128 }
|
matthiasm@0
|
129
|
matthiasm@0
|
130 BOOST_AUTO_TEST_CASE(dirac)
|
matthiasm@0
|
131 {
|
matthiasm@0
|
132 double in[] = { 1, 0, 0, 0 };
|
matthiasm@0
|
133 double re[4], im[4];
|
matthiasm@0
|
134 Vamp::FFT::forward(4, in, 0, re, im);
|
matthiasm@0
|
135 BOOST_CHECK_EQUAL(re[0], 1.0);
|
matthiasm@0
|
136 BOOST_CHECK_EQUAL(re[1], 1.0);
|
matthiasm@0
|
137 BOOST_CHECK_EQUAL(re[2], 1.0);
|
matthiasm@0
|
138 COMPARE_CONST(im, 0.0);
|
matthiasm@0
|
139 double back[4];
|
matthiasm@0
|
140 double backim[4];
|
matthiasm@0
|
141 Vamp::FFT::inverse(4, re, im, back, backim);
|
matthiasm@0
|
142 COMPARE_ARRAY(back, in);
|
matthiasm@0
|
143 }
|
matthiasm@0
|
144
|
matthiasm@0
|
145 BOOST_AUTO_TEST_CASE(forwardArrayBounds)
|
matthiasm@0
|
146 {
|
matthiasm@0
|
147 // initialise bins to something recognisable, so we can tell
|
matthiasm@0
|
148 // if they haven't been written
|
matthiasm@0
|
149 double in[] = { 1, 1, -1, -1 };
|
matthiasm@0
|
150 double re[] = { 999, 999, 999, 999, 999, 999 };
|
matthiasm@0
|
151 double im[] = { 999, 999, 999, 999, 999, 999 };
|
matthiasm@0
|
152 Vamp::FFT::forward(4, in, 0, re+1, im+1);
|
matthiasm@0
|
153 // And check we haven't overrun the arrays
|
matthiasm@0
|
154 BOOST_CHECK_EQUAL(re[0], 999.0);
|
matthiasm@0
|
155 BOOST_CHECK_EQUAL(im[0], 999.0);
|
matthiasm@0
|
156 BOOST_CHECK_EQUAL(re[5], 999.0);
|
matthiasm@0
|
157 BOOST_CHECK_EQUAL(im[5], 999.0);
|
matthiasm@0
|
158 }
|
matthiasm@0
|
159
|
matthiasm@0
|
160 BOOST_AUTO_TEST_CASE(inverseArrayBounds)
|
matthiasm@0
|
161 {
|
matthiasm@0
|
162 // initialise bins to something recognisable, so we can tell
|
matthiasm@0
|
163 // if they haven't been written
|
matthiasm@0
|
164 double re[] = { 0, 1, 0 };
|
matthiasm@0
|
165 double im[] = { 0, -2, 0 };
|
matthiasm@0
|
166 double outre[] = { 999, 999, 999, 999, 999, 999 };
|
matthiasm@0
|
167 double outim[] = { 999, 999, 999, 999, 999, 999 };
|
matthiasm@0
|
168 Vamp::FFT::forward(4, re, im, outre+1, outim+1);
|
matthiasm@0
|
169 // And check we haven't overrun the arrays
|
matthiasm@0
|
170 BOOST_CHECK_EQUAL(outre[0], 999.0);
|
matthiasm@0
|
171 BOOST_CHECK_EQUAL(outim[0], 999.0);
|
matthiasm@0
|
172 BOOST_CHECK_EQUAL(outre[5], 999.0);
|
matthiasm@0
|
173 BOOST_CHECK_EQUAL(outim[5], 999.0);
|
matthiasm@0
|
174 }
|
matthiasm@0
|
175
|
matthiasm@0
|
176 BOOST_AUTO_TEST_SUITE_END()
|
matthiasm@0
|
177
|