cannam@506: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ cannam@506: cannam@506: #include "dsp/signalconditioning/FiltFilt.h" cannam@506: cannam@506: #define BOOST_TEST_DYN_LINK cannam@506: #define BOOST_TEST_MAIN cannam@506: cannam@506: #include cannam@506: cannam@506: #include cannam@506: cannam@506: using namespace std; cannam@506: cannam@506: BOOST_AUTO_TEST_SUITE(TestFiltFilt) cannam@506: cannam@506: // Our FiltFilt is, apparently intentionally (?) a bit different from cannam@506: // the equivalents in MATLAB and Octave (which themselves also differ) cannam@506: // in how it handles transients at either end. While the three should cannam@506: // all be "roughly" the same, all produce slightly different values. cannam@506: // So the "expected" values here are, unfortunately, simply produced cannam@506: // by the function itself, in a process involving tracing the values cannam@506: // passed in to each of the filter stages within it and compared their cannam@506: // outputs against MATLAB. cannam@506: cannam@506: static vector iir_a { 1,5.75501989315662,16.326056867468,28.779190797823,34.2874379215653,28.137815126537,15.6064643257793,5.37874515231553,0.913800050254382,0.0,0.0 }; cannam@506: static vector iir_b { 0.0031954608137085,0.0180937089815597,0.0508407778575426,0.0895040074158415,0.107385387168148,0.0895040074158415,0.0508407778575426,0.0180937089815597,0.0031954608137085,0.0,0.0 }; cannam@506: cannam@506: BOOST_AUTO_TEST_CASE(long_zeroes) cannam@506: { cannam@506: vector a(iir_a); cannam@506: vector b(iir_b); cannam@506: cannam@506: vector zeroes(1000, 0.0); cannam@506: vector expected(zeroes); cannam@506: cannam@506: FiltFilt f({ a, b }); cannam@506: cannam@506: int n = expected.size(); cannam@506: vector out(n, 0.0); cannam@506: cannam@506: f.process(zeroes.data(), out.data(), n); cannam@506: cannam@506: double thresh = 1e-12; cannam@506: cannam@506: for (int i = 0; i < n; ++i) { cannam@506: BOOST_CHECK_SMALL(out[i] - expected[i], thresh); cannam@506: } cannam@506: } cannam@506: cannam@506: BOOST_AUTO_TEST_CASE(empty) cannam@506: { cannam@506: vector a(iir_a); cannam@506: vector b(iir_b); cannam@506: vector in; cannam@506: vector out; cannam@506: vector expected; cannam@506: cannam@506: FiltFilt f({ a, b }); cannam@506: cannam@506: f.process(in.data(), out.data(), 0); cannam@506: } cannam@506: cannam@506: BOOST_AUTO_TEST_CASE(single_value) cannam@506: { cannam@506: vector a(iir_a); cannam@506: vector b(iir_b); cannam@506: vector in({ 1.0 }); cannam@506: vector out({ 0.0 }); cannam@507: vector expected({ 0.000607783187363 }); cannam@506: cannam@506: FiltFilt f({ a, b }); cannam@506: cannam@506: f.process(in.data(), out.data(), 1); cannam@506: cannam@506: double thresh = 1e-12; cannam@506: cannam@506: BOOST_CHECK_SMALL(out[0] - expected[0], thresh); cannam@506: } cannam@506: cannam@506: BOOST_AUTO_TEST_CASE(shortish) cannam@506: { cannam@506: vector a(iir_a); cannam@506: vector b(iir_b); cannam@506: cannam@506: vector in { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 }; cannam@507: vector expected { 0.0183210564167, -0.0251812631055, 0.0182718199887, -0.00232894428926, -0.0131783133711, 0.0204387725824, -0.016092298975, 0.00402175146108, 0.00913732971217, -0.0158214509991, 0.0138601876508, -0.00455783828038, -0.00563875593951, 0.0121184171941, -0.011073916445, 0.00491681731861 }; cannam@506: cannam@506: FiltFilt f({ a, b }); cannam@506: cannam@506: int n = expected.size(); cannam@506: vector out(n, 0.0); cannam@506: cannam@506: f.process(in.data(), out.data(), n); cannam@506: cannam@506: double thresh = 1e-12; cannam@506: cannam@506: for (int i = 0; i < n; ++i) { cannam@506: BOOST_CHECK_SMALL(out[i] - expected[i], thresh); cannam@506: } cannam@506: } cannam@506: cannam@506: BOOST_AUTO_TEST_SUITE_END()