annotate test/TestFFT.cpp @ 164:a7d9c6142f8f tip

Added tag v1.2 for changeset 4a97f7638ffd
author Chris Cannam
date Thu, 06 Feb 2020 15:02:47 +0000
parents 99bac62ee2da
children
rev   line source
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