annotate tests/TestPhaseVocoder.cpp @ 340:c99d83236f0d

Do actual phase unwrapping in the phase vocoder!
author Chris Cannam <c.cannam@qmul.ac.uk>
date Wed, 02 Oct 2013 15:05:34 +0100
parents 35db1b24a848
children 7f5b96734c83
rev   line source
c@337 1
c@337 2 #include "dsp/phasevocoder/PhaseVocoder.h"
c@337 3
c@337 4 #include "base/Window.h"
c@337 5
c@337 6 #define BOOST_TEST_DYN_LINK
c@337 7 #define BOOST_TEST_MAIN
c@337 8
c@337 9 #include <boost/test/unit_test.hpp>
c@337 10
c@337 11 BOOST_AUTO_TEST_SUITE(TestFFT)
c@337 12
c@337 13 #define COMPARE_CONST(a, n) \
c@337 14 for (int cmp_i = 0; cmp_i < (int)(sizeof(a)/sizeof(a[0])); ++cmp_i) { \
c@337 15 BOOST_CHECK_SMALL(a[cmp_i] - n, 1e-14); \
c@337 16 }
c@337 17
c@337 18 #define COMPARE_ARRAY(a, b) \
c@337 19 for (int cmp_i = 0; cmp_i < (int)(sizeof(a)/sizeof(a[0])); ++cmp_i) { \
c@337 20 BOOST_CHECK_SMALL(a[cmp_i] - b[cmp_i], 1e-14); \
c@337 21 }
c@337 22
c@337 23 #define COMPARE_ARRAY_EXACT(a, b) \
c@337 24 for (int cmp_i = 0; cmp_i < (int)(sizeof(a)/sizeof(a[0])); ++cmp_i) { \
c@337 25 BOOST_CHECK_EQUAL(a[cmp_i], b[cmp_i]); \
c@337 26 }
c@337 27
c@337 28 BOOST_AUTO_TEST_CASE(fullcycle)
c@337 29 {
c@340 30 // Cosine with one cycle exactly equal to pvoc hopsize. This is
c@340 31 // pretty much the most trivial case -- in fact it's
c@340 32 // indistinguishable from totally silent input (in the phase
c@340 33 // values) because the measured phases are zero throughout.
c@340 34
c@340 35 // We aren't windowing the input frame because (for once) it
c@340 36 // actually *is* just a short part of a continuous infinite
c@340 37 // sinusoid.
c@337 38
c@337 39 double frame[] = { 1, 0, -1, 0, 1, 0, -1, 0 };
c@337 40
c@340 41 PhaseVocoder pvoc(8, 4);
c@337 42
c@337 43 // Make these arrays one element too long at each end, so as to
c@337 44 // test for overruns. For frame size 8, we expect 8/2+1 = 5
c@337 45 // mag/phase pairs.
c@337 46 double mag[] = { 999, 999, 999, 999, 999, 999, 999 };
c@337 47 double phase[] = { 999, 999, 999, 999, 999, 999, 999 };
c@340 48 double unw[] = { 999, 999, 999, 999, 999, 999, 999 };
c@337 49
c@340 50 pvoc.process(frame, mag + 1, phase + 1, unw + 1);
c@337 51
c@337 52 double magExpected0[] = { 999, 0, 0, 4, 0, 0, 999 };
c@337 53 COMPARE_ARRAY_EXACT(mag, magExpected0);
c@337 54
c@337 55 double phaseExpected0[] = { 999, 0, 0, 0, 0, 0, 999 };
c@337 56 COMPARE_ARRAY_EXACT(phase, phaseExpected0);
c@337 57
c@340 58 double unwExpected0[] = { 999, 0, 0, 0, 0, 0, 999 };
c@340 59 COMPARE_ARRAY(unw, unwExpected0);
c@340 60
c@340 61 pvoc.process(frame, mag + 1, phase + 1, unw + 1);
c@337 62
c@337 63 double magExpected1[] = { 999, 0, 0, 4, 0, 0, 999 };
c@337 64 COMPARE_ARRAY_EXACT(mag, magExpected1);
c@337 65
c@340 66 double phaseExpected1[] = { 999, 0, 0, 0, 0, 0, 999 };
c@337 67 COMPARE_ARRAY(phase, phaseExpected1);
c@338 68
c@340 69 // Derivation of values:
c@340 70 //
c@340 71 // * Bin 0 (DC) always has phase 0 and expected phase 0
c@340 72 //
c@340 73 // * Bin 1 has expected phase pi (the hop size is half a cycle at
c@340 74 // its frequency), but measured phase 0 (because there is no
c@340 75 // signal in that bin). So it has phase error -pi, which is
c@340 76 // mapped into (-pi,pi] range as pi, giving an unwrapped phase
c@340 77 // of 2*pi.
c@340 78 //
c@340 79 // * Bin 2 has expected unwrapped phase 2*pi, measured phase 0,
c@340 80 // hence error 0 and unwrapped phase 2*pi.
c@340 81 //
c@340 82 // * Bin 3 is like bin 1: it has expected phase 3*pi, measured
c@340 83 // phase 0, so phase error -pi and unwrapped phase 4*pi.
c@340 84 //
c@340 85 // * Bin 4 (Nyquist) is like bin 2: expected phase 4*pi, measured
c@340 86 // phase 0, hence error 0 and unwrapped phase 4*pi.
c@340 87
c@340 88 double unwExpected1[] = { 999, 0, 2*M_PI, 2*M_PI, 4*M_PI, 4*M_PI, 999 };
c@340 89 COMPARE_ARRAY(unw, unwExpected1);
c@340 90
c@340 91 pvoc.process(frame, mag + 1, phase + 1, unw + 1);
c@338 92
c@338 93 double magExpected2[] = { 999, 0, 0, 4, 0, 0, 999 };
c@338 94 COMPARE_ARRAY_EXACT(mag, magExpected2);
c@338 95
c@340 96 double phaseExpected2[] = { 999, 0, 0, 0, 0, 0, 999 };
c@338 97 COMPARE_ARRAY(phase, phaseExpected2);
c@340 98
c@340 99 double unwExpected2[] = { 999, 0, 4*M_PI, 4*M_PI, 8*M_PI, 8*M_PI, 999 };
c@340 100 COMPARE_ARRAY(unw, unwExpected2);
c@337 101 }
c@337 102
c@340 103 //!!! signal that starts mid-phase
c@340 104
c@340 105
c@337 106 BOOST_AUTO_TEST_SUITE_END()
c@337 107