annotate tests/TestFFT.cpp @ 118:4920d100b290 pvoc

Don't use tabs
author Chris Cannam
date Wed, 02 Oct 2013 18:22:06 +0100
parents f6ccde089491
children 6ec45e85ed81
rev   line source
Chris@118 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@110 2
Chris@110 3 #include "dsp/transforms/FFT.h"
Chris@110 4
Chris@110 5 #define BOOST_TEST_DYN_LINK
Chris@110 6 #define BOOST_TEST_MAIN
Chris@110 7
Chris@110 8 #include <boost/test/unit_test.hpp>
Chris@110 9
Chris@110 10 BOOST_AUTO_TEST_SUITE(TestFFT)
Chris@110 11
Chris@110 12 #define COMPARE_CONST(a, n) \
Chris@110 13 for (int cmp_i = 0; cmp_i < (int)(sizeof(a)/sizeof(a[0])); ++cmp_i) { \
Chris@110 14 BOOST_CHECK_SMALL(a[cmp_i] - n, 1e-14); \
Chris@110 15 }
Chris@110 16
Chris@110 17 #define COMPARE_ARRAY(a, b) \
Chris@110 18 for (int cmp_i = 0; cmp_i < (int)(sizeof(a)/sizeof(a[0])); ++cmp_i) { \
Chris@110 19 BOOST_CHECK_SMALL(a[cmp_i] - b[cmp_i], 1e-14); \
Chris@110 20 }
Chris@110 21
Chris@114 22 //!!! need at least one test with complex time-domain signal
Chris@110 23
Chris@110 24 BOOST_AUTO_TEST_CASE(forwardArrayBounds)
Chris@110 25 {
Chris@110 26 // initialise bins to something recognisable, so we can tell
Chris@110 27 // if they haven't been written
Chris@110 28 double in[] = { 1, 1, -1, -1 };
Chris@110 29 double re[] = { 999, 999, 999, 999, 999, 999 };
Chris@110 30 double im[] = { 999, 999, 999, 999, 999, 999 };
Chris@110 31 FFT(4).process(false, in, 0, re+1, im+1);
Chris@110 32 // And check we haven't overrun the arrays
Chris@110 33 BOOST_CHECK_EQUAL(re[0], 999.0);
Chris@110 34 BOOST_CHECK_EQUAL(im[0], 999.0);
Chris@110 35 BOOST_CHECK_EQUAL(re[5], 999.0);
Chris@110 36 BOOST_CHECK_EQUAL(im[5], 999.0);
Chris@110 37 }
Chris@110 38
Chris@114 39 BOOST_AUTO_TEST_CASE(r_forwardArrayBounds)
Chris@114 40 {
Chris@114 41 // initialise bins to something recognisable, so we can tell
Chris@114 42 // if they haven't been written
Chris@114 43 double in[] = { 1, 1, -1, -1 };
Chris@114 44 double re[] = { 999, 999, 999, 999, 999, 999 };
Chris@114 45 double im[] = { 999, 999, 999, 999, 999, 999 };
Chris@114 46 FFTReal(4).forward(in, re+1, im+1);
Chris@114 47 // And check we haven't overrun the arrays
Chris@114 48 BOOST_CHECK_EQUAL(re[0], 999.0);
Chris@114 49 BOOST_CHECK_EQUAL(im[0], 999.0);
Chris@114 50 BOOST_CHECK_EQUAL(re[5], 999.0);
Chris@114 51 BOOST_CHECK_EQUAL(im[5], 999.0);
Chris@114 52 }
Chris@114 53
Chris@110 54 BOOST_AUTO_TEST_CASE(inverseArrayBounds)
Chris@110 55 {
Chris@110 56 // initialise bins to something recognisable, so we can tell
Chris@110 57 // if they haven't been written
Chris@114 58 double re[] = { 0, 1, 0, 1 };
Chris@114 59 double im[] = { 0, -2, 0, 2 };
Chris@110 60 double outre[] = { 999, 999, 999, 999, 999, 999 };
Chris@110 61 double outim[] = { 999, 999, 999, 999, 999, 999 };
Chris@114 62 FFT(4).process(true, re, im, outre+1, outim+1);
Chris@110 63 // And check we haven't overrun the arrays
Chris@110 64 BOOST_CHECK_EQUAL(outre[0], 999.0);
Chris@110 65 BOOST_CHECK_EQUAL(outim[0], 999.0);
Chris@110 66 BOOST_CHECK_EQUAL(outre[5], 999.0);
Chris@110 67 BOOST_CHECK_EQUAL(outim[5], 999.0);
Chris@110 68 }
Chris@110 69
Chris@114 70 BOOST_AUTO_TEST_CASE(r_inverseArrayBounds)
Chris@114 71 {
Chris@114 72 // initialise bins to something recognisable, so we can tell
Chris@114 73 // if they haven't been written
Chris@114 74 double re[] = { 0, 1, 0 };
Chris@114 75 double im[] = { 0, -2, 0 };
Chris@114 76 double outre[] = { 999, 999, 999, 999, 999, 999 };
Chris@114 77 FFTReal(4).inverse(re, im, outre+1);
Chris@114 78 // And check we haven't overrun the arrays
Chris@114 79 BOOST_CHECK_EQUAL(outre[0], 999.0);
Chris@114 80 BOOST_CHECK_EQUAL(outre[5], 999.0);
Chris@114 81 }
Chris@114 82
Chris@114 83 BOOST_AUTO_TEST_CASE(dc)
Chris@114 84 {
Chris@114 85 // DC-only signal. The DC bin is purely real
Chris@114 86 double in[] = { 1, 1, 1, 1 };
Chris@114 87 double re[] = { 999, 999, 999, 999 };
Chris@114 88 double im[] = { 999, 999, 999, 999 };
Chris@114 89 FFT(4).process(false, in, 0, re, im);
Chris@114 90 BOOST_CHECK_EQUAL(re[0], 4.0);
Chris@114 91 BOOST_CHECK_EQUAL(re[1], 0.0);
Chris@114 92 BOOST_CHECK_EQUAL(re[2], 0.0);
Chris@114 93 BOOST_CHECK_EQUAL(re[3], 0.0);
Chris@114 94 COMPARE_CONST(im, 0.0);
Chris@114 95 double back[4];
Chris@114 96 double backim[4];
Chris@114 97 FFT(4).process(true, re, im, back, backim);
Chris@114 98 COMPARE_ARRAY(back, in);
Chris@114 99 COMPARE_CONST(backim, 0.0);
Chris@114 100 }
Chris@114 101
Chris@114 102 BOOST_AUTO_TEST_CASE(r_dc)
Chris@114 103 {
Chris@114 104 // DC-only signal. The DC bin is purely real
Chris@114 105 double in[] = { 1, 1, 1, 1 };
Chris@114 106 double re[] = { 999, 999, 999, 999 };
Chris@114 107 double im[] = { 999, 999, 999, 999 };
Chris@114 108 FFTReal(4).forward(in, re, im);
Chris@114 109 BOOST_CHECK_EQUAL(re[0], 4.0);
Chris@114 110 BOOST_CHECK_EQUAL(re[1], 0.0);
Chris@114 111 BOOST_CHECK_EQUAL(re[2], 0.0);
Chris@114 112 BOOST_CHECK_EQUAL(re[3], 0.0);
Chris@114 113 COMPARE_CONST(im, 0.0);
Chris@114 114 double back[4];
Chris@114 115 // check conjugates are reconstructed
Chris@114 116 re[3] = 999;
Chris@114 117 im[3] = 999;
Chris@114 118 FFTReal(4).inverse(re, im, back);
Chris@114 119 COMPARE_ARRAY(back, in);
Chris@114 120 }
Chris@114 121
Chris@114 122 BOOST_AUTO_TEST_CASE(sine)
Chris@114 123 {
Chris@114 124 // Sine. Output is purely imaginary
Chris@114 125 double in[] = { 0, 1, 0, -1 };
Chris@114 126 double re[] = { 999, 999, 999, 999 };
Chris@114 127 double im[] = { 999, 999, 999, 999 };
Chris@114 128 FFT(4).process(false, in, 0, re, im);
Chris@114 129 COMPARE_CONST(re, 0.0);
Chris@114 130 BOOST_CHECK_EQUAL(im[0], 0.0);
Chris@114 131 BOOST_CHECK_EQUAL(im[1], -2.0);
Chris@114 132 BOOST_CHECK_EQUAL(im[2], 0.0);
Chris@114 133 BOOST_CHECK_EQUAL(im[3], 2.0);
Chris@114 134 double back[4];
Chris@114 135 double backim[4];
Chris@114 136 FFT(4).process(true, re, im, back, backim);
Chris@114 137 COMPARE_ARRAY(back, in);
Chris@114 138 COMPARE_CONST(backim, 0.0);
Chris@114 139 }
Chris@114 140
Chris@114 141 BOOST_AUTO_TEST_CASE(r_sine)
Chris@114 142 {
Chris@114 143 // Sine. Output is purely imaginary
Chris@114 144 double in[] = { 0, 1, 0, -1 };
Chris@114 145 double re[] = { 999, 999, 999, 999 };
Chris@114 146 double im[] = { 999, 999, 999, 999 };
Chris@114 147 FFTReal(4).forward(in, re, im);
Chris@114 148 COMPARE_CONST(re, 0.0);
Chris@114 149 BOOST_CHECK_EQUAL(im[0], 0.0);
Chris@114 150 BOOST_CHECK_EQUAL(im[1], -2.0);
Chris@114 151 BOOST_CHECK_EQUAL(im[2], 0.0);
Chris@114 152 BOOST_CHECK_EQUAL(im[3], 2.0);
Chris@114 153 double back[4];
Chris@114 154 // check conjugates are reconstructed
Chris@114 155 re[3] = 999;
Chris@114 156 im[3] = 999;
Chris@114 157 FFTReal(4).inverse(re, im, back);
Chris@114 158 COMPARE_ARRAY(back, in);
Chris@114 159 }
Chris@114 160
Chris@114 161 BOOST_AUTO_TEST_CASE(cosine)
Chris@114 162 {
Chris@114 163 // Cosine. Output is purely real
Chris@114 164 double in[] = { 1, 0, -1, 0 };
Chris@114 165 double re[] = { 999, 999, 999, 999 };
Chris@114 166 double im[] = { 999, 999, 999, 999 };
Chris@114 167 FFT(4).process(false, in, 0, re, im);
Chris@114 168 BOOST_CHECK_EQUAL(re[0], 0.0);
Chris@114 169 BOOST_CHECK_EQUAL(re[1], 2.0);
Chris@114 170 BOOST_CHECK_EQUAL(re[2], 0.0);
Chris@114 171 BOOST_CHECK_EQUAL(re[3], 2.0);
Chris@114 172 COMPARE_CONST(im, 0.0);
Chris@114 173 double back[4];
Chris@114 174 double backim[4];
Chris@114 175 FFT(4).process(true, re, im, back, backim);
Chris@114 176 COMPARE_ARRAY(back, in);
Chris@114 177 COMPARE_CONST(backim, 0.0);
Chris@114 178 }
Chris@114 179
Chris@114 180 BOOST_AUTO_TEST_CASE(r_cosine)
Chris@114 181 {
Chris@114 182 // Cosine. Output is purely real
Chris@114 183 double in[] = { 1, 0, -1, 0 };
Chris@114 184 double re[] = { 999, 999, 999, 999 };
Chris@114 185 double im[] = { 999, 999, 999, 999 };
Chris@114 186 FFTReal(4).forward(in, re, im);
Chris@114 187 BOOST_CHECK_EQUAL(re[0], 0.0);
Chris@114 188 BOOST_CHECK_EQUAL(re[1], 2.0);
Chris@114 189 BOOST_CHECK_EQUAL(re[2], 0.0);
Chris@114 190 BOOST_CHECK_EQUAL(re[3], 2.0);
Chris@114 191 COMPARE_CONST(im, 0.0);
Chris@114 192 double back[4];
Chris@114 193 // check conjugates are reconstructed
Chris@114 194 re[3] = 999;
Chris@114 195 im[3] = 999;
Chris@114 196 FFTReal(4).inverse(re, im, back);
Chris@114 197 COMPARE_ARRAY(back, in);
Chris@114 198 }
Chris@114 199
Chris@114 200 BOOST_AUTO_TEST_CASE(sineCosine)
Chris@114 201 {
Chris@114 202 // Sine and cosine mixed
Chris@114 203 double in[] = { 0.5, 1, -0.5, -1 };
Chris@114 204 double re[] = { 999, 999, 999, 999 };
Chris@114 205 double im[] = { 999, 999, 999, 999 };
Chris@114 206 FFT(4).process(false, in, 0, re, im);
Chris@114 207 BOOST_CHECK_EQUAL(re[0], 0.0);
Chris@114 208 BOOST_CHECK_CLOSE(re[1], 1.0, 1e-12);
Chris@114 209 BOOST_CHECK_EQUAL(re[2], 0.0);
Chris@114 210 BOOST_CHECK_CLOSE(re[3], 1.0, 1e-12);
Chris@114 211 BOOST_CHECK_EQUAL(im[0], 0.0);
Chris@114 212 BOOST_CHECK_CLOSE(im[1], -2.0, 1e-12);
Chris@114 213 BOOST_CHECK_EQUAL(im[2], 0.0);
Chris@114 214 BOOST_CHECK_CLOSE(im[3], 2.0, 1e-12);
Chris@114 215 double back[4];
Chris@114 216 double backim[4];
Chris@114 217 FFT(4).process(true, re, im, back, backim);
Chris@114 218 COMPARE_ARRAY(back, in);
Chris@114 219 COMPARE_CONST(backim, 0.0);
Chris@114 220 }
Chris@114 221
Chris@114 222 BOOST_AUTO_TEST_CASE(r_sineCosine)
Chris@114 223 {
Chris@114 224 // Sine and cosine mixed
Chris@114 225 double in[] = { 0.5, 1, -0.5, -1 };
Chris@114 226 double re[] = { 999, 999, 999, 999 };
Chris@114 227 double im[] = { 999, 999, 999, 999 };
Chris@114 228 FFTReal(4).forward(in, re, im);
Chris@114 229 BOOST_CHECK_EQUAL(re[0], 0.0);
Chris@114 230 BOOST_CHECK_CLOSE(re[1], 1.0, 1e-12);
Chris@114 231 BOOST_CHECK_EQUAL(re[2], 0.0);
Chris@114 232 BOOST_CHECK_CLOSE(re[3], 1.0, 1e-12);
Chris@114 233 BOOST_CHECK_EQUAL(im[0], 0.0);
Chris@114 234 BOOST_CHECK_CLOSE(im[1], -2.0, 1e-12);
Chris@114 235 BOOST_CHECK_EQUAL(im[2], 0.0);
Chris@114 236 BOOST_CHECK_CLOSE(im[3], 2.0, 1e-12);
Chris@114 237 double back[4];
Chris@114 238 // check conjugates are reconstructed
Chris@114 239 re[3] = 999;
Chris@114 240 im[3] = 999;
Chris@114 241 FFTReal(4).inverse(re, im, back);
Chris@114 242 COMPARE_ARRAY(back, in);
Chris@114 243 }
Chris@114 244
Chris@114 245 BOOST_AUTO_TEST_CASE(nyquist)
Chris@114 246 {
Chris@114 247 double in[] = { 1, -1, 1, -1 };
Chris@114 248 double re[] = { 999, 999, 999, 999 };
Chris@114 249 double im[] = { 999, 999, 999, 999 };
Chris@114 250 FFT(4).process(false, in, 0, re, im);
Chris@114 251 BOOST_CHECK_EQUAL(re[0], 0.0);
Chris@114 252 BOOST_CHECK_EQUAL(re[1], 0.0);
Chris@114 253 BOOST_CHECK_EQUAL(re[2], 4.0);
Chris@114 254 BOOST_CHECK_EQUAL(re[3], 0.0);
Chris@114 255 COMPARE_CONST(im, 0.0);
Chris@114 256 double back[4];
Chris@114 257 double backim[4];
Chris@114 258 FFT(4).process(true, re, im, back, backim);
Chris@114 259 COMPARE_ARRAY(back, in);
Chris@114 260 COMPARE_CONST(backim, 0.0);
Chris@114 261 }
Chris@114 262
Chris@114 263 BOOST_AUTO_TEST_CASE(r_nyquist)
Chris@114 264 {
Chris@114 265 double in[] = { 1, -1, 1, -1 };
Chris@114 266 double re[] = { 999, 999, 999, 999 };
Chris@114 267 double im[] = { 999, 999, 999, 999 };
Chris@114 268 FFTReal(4).forward(in, re, im);
Chris@114 269 BOOST_CHECK_EQUAL(re[0], 0.0);
Chris@114 270 BOOST_CHECK_EQUAL(re[1], 0.0);
Chris@114 271 BOOST_CHECK_EQUAL(re[2], 4.0);
Chris@114 272 BOOST_CHECK_EQUAL(re[3], 0.0);
Chris@114 273 COMPARE_CONST(im, 0.0);
Chris@114 274 double back[4];
Chris@114 275 // check conjugates are reconstructed
Chris@114 276 re[3] = 999;
Chris@114 277 im[3] = 999;
Chris@114 278 FFTReal(4).inverse(re, im, back);
Chris@114 279 COMPARE_ARRAY(back, in);
Chris@114 280 }
Chris@114 281
Chris@114 282 BOOST_AUTO_TEST_CASE(dirac)
Chris@114 283 {
Chris@114 284 double in[] = { 1, 0, 0, 0 };
Chris@114 285 double re[] = { 999, 999, 999, 999 };
Chris@114 286 double im[] = { 999, 999, 999, 999 };
Chris@114 287 FFT(4).process(false, in, 0, re, im);
Chris@114 288 BOOST_CHECK_EQUAL(re[0], 1.0);
Chris@114 289 BOOST_CHECK_EQUAL(re[1], 1.0);
Chris@114 290 BOOST_CHECK_EQUAL(re[2], 1.0);
Chris@114 291 BOOST_CHECK_EQUAL(re[3], 1.0);
Chris@114 292 COMPARE_CONST(im, 0.0);
Chris@114 293 double back[4];
Chris@114 294 double backim[4];
Chris@114 295 FFT(4).process(true, re, im, back, backim);
Chris@114 296 COMPARE_ARRAY(back, in);
Chris@114 297 COMPARE_CONST(backim, 0.0);
Chris@114 298 }
Chris@114 299
Chris@114 300 BOOST_AUTO_TEST_CASE(r_dirac)
Chris@114 301 {
Chris@114 302 double in[] = { 1, 0, 0, 0 };
Chris@114 303 double re[] = { 999, 999, 999, 999 };
Chris@114 304 double im[] = { 999, 999, 999, 999 };
Chris@114 305 FFTReal(4).forward(in, re, im);
Chris@114 306 BOOST_CHECK_EQUAL(re[0], 1.0);
Chris@114 307 BOOST_CHECK_EQUAL(re[1], 1.0);
Chris@114 308 BOOST_CHECK_EQUAL(re[2], 1.0);
Chris@114 309 BOOST_CHECK_EQUAL(re[3], 1.0);
Chris@114 310 COMPARE_CONST(im, 0.0);
Chris@114 311 double back[4];
Chris@114 312 // check conjugates are reconstructed
Chris@114 313 re[3] = 999;
Chris@114 314 im[3] = 999;
Chris@114 315 FFTReal(4).inverse(re, im, back);
Chris@114 316 COMPARE_ARRAY(back, in);
Chris@114 317 }
Chris@114 318
Chris@110 319 BOOST_AUTO_TEST_SUITE_END()
Chris@110 320