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