annotate tests/TestFFT.cpp @ 110:87ad66aaed32

FFT and window tests
author Chris Cannam
date Mon, 30 Sep 2013 16:50:38 +0100
parents
children f6ccde089491
rev   line source
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