Mercurial > hg > svcore
comparison data/model/test/TestFFTModel.h @ 1088:5fab8e4f5f19
Start making the FFT model tests into proper tests
author | Chris Cannam |
---|---|
date | Fri, 12 Jun 2015 12:41:19 +0100 |
parents | 9f4505ac9072 |
children | 655cd4e68e9a 1517d4c60e88 |
comparison
equal
deleted
inserted
replaced
1087:dcf54a6964d0 | 1088:5fab8e4f5f19 |
---|---|
24 #include <QObject> | 24 #include <QObject> |
25 #include <QtTest> | 25 #include <QtTest> |
26 #include <QDir> | 26 #include <QDir> |
27 | 27 |
28 #include <iostream> | 28 #include <iostream> |
29 #include <complex> | |
29 | 30 |
30 using namespace std; | 31 using namespace std; |
31 | 32 |
32 class TestFFTModel : public QObject | 33 class TestFFTModel : public QObject |
33 { | 34 { |
34 Q_OBJECT | 35 Q_OBJECT |
35 | 36 |
37 private: | |
38 void test(DenseTimeValueModel *model, | |
39 WindowType window, int windowSize, int windowIncrement, int fftSize, | |
40 int columnNo, vector<vector<complex<float>>> expectedValues, | |
41 int expectedWidth) { | |
42 for (int ch = 0; in_range_for(expectedValues, ch); ++ch) { | |
43 for (int polar = 0; polar <= 1; ++polar) { | |
44 FFTModel fftm(model, ch, window, windowSize, windowIncrement, | |
45 fftSize, bool(polar)); | |
46 QCOMPARE(fftm.getWidth(), expectedWidth); | |
47 int hs1 = fftSize/2 + 1; | |
48 QCOMPARE(fftm.getHeight(), hs1); | |
49 vector<float> reals(hs1 + 1, 0.f); | |
50 vector<float> imags(hs1 + 1, 0.f); | |
51 reals[hs1] = 999.f; // overrun guards | |
52 imags[hs1] = 999.f; | |
53 fftm.getValuesAt(columnNo, &reals[0], &imags[0]); | |
54 for (int i = 0; i < hs1; ++i) { | |
55 float eRe = expectedValues[ch][i].real(); | |
56 float eIm = expectedValues[ch][i].imag(); | |
57 if (reals[i] != eRe || imags[i] != eIm) { | |
58 cerr << "ERROR: output is not as expected for column " | |
59 << i << " in channel " << ch << " (polar store = " | |
60 << polar << ")" << endl; | |
61 cerr << "expected : "; | |
62 for (int j = 0; j < hs1; ++j) { | |
63 cerr << expectedValues[ch][j] << " "; | |
64 } | |
65 cerr << "\nactual : "; | |
66 for (int j = 0; j < hs1; ++j) { | |
67 cerr << complex<float>(reals[j], imags[j]) << " "; | |
68 } | |
69 cerr << endl; | |
70 } | |
71 QCOMPARE(reals[i], eRe); | |
72 QCOMPARE(imags[i], eIm); | |
73 } | |
74 QCOMPARE(reals[hs1], 999.f); | |
75 QCOMPARE(imags[hs1], 999.f); | |
76 } | |
77 } | |
78 } | |
79 | |
36 private slots: | 80 private slots: |
37 | 81 |
38 void example() { | 82 // NB. FFTModel columns are centred on the sample frame, and in |
39 MockWaveModel mwm({ DC }, 16); | 83 // particular this means column 0 is centred at sample 0 (i.e. it |
40 FFTModel fftm(&mwm, 0, RectangularWindow, 8, 8, 8, false); | 84 // contains only half the window-size worth of real samples, the |
41 float reals[6], imags[6]; | 85 // others are 0-valued from before the origin). Generally in |
42 reals[5] = 999.f; // overrun guards | 86 // these tests we are padding our signal with half a window of |
43 imags[5] = 999.f; | 87 // zeros, in order that the result for column 0 is all zeros |
44 fftm.getValuesAt(0, reals, imags); | 88 // (rather than something with a step in it that is harder to |
45 cerr << "reals: " << reals[0] << "," << reals[1] << "," << reals[2] << "," << reals[3] << "," << reals[4] << endl; | 89 // reason about the FFT of) and the results for subsequent columns |
46 cerr << "imags: " << imags[0] << "," << imags[1] << "," << imags[2] << "," << imags[3] << "," << imags[4] << endl; | 90 // are those of our expected signal. |
47 QCOMPARE(reals[0], 4.f); // rectangular window scales by 0.5 | 91 |
48 QCOMPARE(reals[1], 0.f); | 92 void dc_simple_rect() { |
49 QCOMPARE(reals[2], 0.f); | 93 MockWaveModel mwm({ DC }, 16, 4); |
50 QCOMPARE(reals[3], 0.f); | 94 test(&mwm, RectangularWindow, 8, 8, 8, 0, |
51 QCOMPARE(reals[4], 0.f); | 95 { { {}, {}, {}, {}, {} } }, 4); |
52 QCOMPARE(reals[5], 999.f); | 96 test(&mwm, RectangularWindow, 8, 8, 8, 1, |
53 QCOMPARE(imags[5], 999.f); | 97 { { { 4.f, 0.f }, {}, {}, {}, {} } }, 4); |
54 imags[5] = 0.f; | 98 test(&mwm, RectangularWindow, 8, 8, 8, 2, |
55 COMPARE_ALL_TO_F(imags, 0.f); | 99 { { { 4.f, 0.f }, {}, {}, {}, {} } }, 4); |
100 test(&mwm, RectangularWindow, 8, 8, 8, 3, | |
101 { { { }, {}, {}, {}, {} } }, 4); | |
102 } | |
103 | |
104 void dc_simple_hann() { | |
105 // The Hann window function is a simple sinusoid with period | |
106 // equal to twice the window size, and it halves the DC energy | |
107 MockWaveModel mwm({ DC }, 16, 4); | |
108 test(&mwm, HanningWindow, 8, 8, 8, 0, | |
109 { { {}, {}, {}, {}, {} } }, 4); | |
110 test(&mwm, HanningWindow, 8, 8, 8, 1, | |
111 { { { 4.f, 0.f }, { 2.f, 0.f }, {}, {}, {} } }, 4); | |
112 test(&mwm, HanningWindow, 8, 8, 8, 2, | |
113 { { { 4.f, 0.f }, { 2.f, 0.f }, {}, {}, {} } }, 4); | |
114 test(&mwm, HanningWindow, 8, 8, 8, 3, | |
115 { { { }, {}, {}, {}, {} } }, 4); | |
56 } | 116 } |
57 | 117 |
58 }; | 118 }; |
59 | 119 |
60 #endif | 120 #endif |