Mercurial > hg > svcore
comparison data/model/test/TestFFTModel.h @ 1091:bdebff3265ae simple-fft-model
Simplest naive FFTModel implementation (+ fill in tests)
author | Chris Cannam |
---|---|
date | Fri, 12 Jun 2015 18:08:57 +0100 |
parents | 655cd4e68e9a |
children | 0c351e061945 |
comparison
equal
deleted
inserted
replaced
1090:420fc961c0c4 | 1091:bdebff3265ae |
---|---|
38 void test(DenseTimeValueModel *model, | 38 void test(DenseTimeValueModel *model, |
39 WindowType window, int windowSize, int windowIncrement, int fftSize, | 39 WindowType window, int windowSize, int windowIncrement, int fftSize, |
40 int columnNo, vector<vector<complex<float>>> expectedValues, | 40 int columnNo, vector<vector<complex<float>>> expectedValues, |
41 int expectedWidth) { | 41 int expectedWidth) { |
42 for (int ch = 0; in_range_for(expectedValues, ch); ++ch) { | 42 for (int ch = 0; in_range_for(expectedValues, ch); ++ch) { |
43 for (int polar = 0; polar <= 1; ++polar) { | 43 FFTModel fftm(model, ch, window, windowSize, windowIncrement, fftSize); |
44 FFTModel fftm(model, ch, window, windowSize, windowIncrement, | 44 QCOMPARE(fftm.getWidth(), expectedWidth); |
45 fftSize, bool(polar)); | 45 int hs1 = fftSize/2 + 1; |
46 QCOMPARE(fftm.getWidth(), expectedWidth); | 46 QCOMPARE(fftm.getHeight(), hs1); |
47 int hs1 = fftSize/2 + 1; | 47 vector<float> reals(hs1 + 1, 0.f); |
48 QCOMPARE(fftm.getHeight(), hs1); | 48 vector<float> imags(hs1 + 1, 0.f); |
49 vector<float> reals(hs1 + 1, 0.f); | 49 reals[hs1] = 999.f; // overrun guards |
50 vector<float> imags(hs1 + 1, 0.f); | 50 imags[hs1] = 999.f; |
51 reals[hs1] = 999.f; // overrun guards | 51 fftm.getValuesAt(columnNo, &reals[0], &imags[0]); |
52 imags[hs1] = 999.f; | 52 for (int i = 0; i < hs1; ++i) { |
53 fftm.getValuesAt(columnNo, &reals[0], &imags[0]); | 53 float eRe = expectedValues[ch][i].real(); |
54 for (int i = 0; i < hs1; ++i) { | 54 float eIm = expectedValues[ch][i].imag(); |
55 float eRe = expectedValues[ch][i].real(); | 55 float thresh = 1e-5f; |
56 float eIm = expectedValues[ch][i].imag(); | 56 if (abs(reals[i] - eRe) > thresh || |
57 if (reals[i] != eRe || imags[i] != eIm) { | 57 abs(imags[i] - eIm) > thresh) { |
58 cerr << "ERROR: output is not as expected for column " | 58 cerr << "ERROR: output is not as expected for column " |
59 << i << " in channel " << ch << " (polar store = " | 59 << i << " in channel " << ch << endl; |
60 << polar << ")" << endl; | 60 cerr << "expected : "; |
61 cerr << "expected : "; | 61 for (int j = 0; j < hs1; ++j) { |
62 for (int j = 0; j < hs1; ++j) { | 62 cerr << expectedValues[ch][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 } | 63 } |
71 QCOMPARE(reals[i], eRe); | 64 cerr << "\nactual : "; |
72 QCOMPARE(imags[i], eIm); | 65 for (int j = 0; j < hs1; ++j) { |
66 cerr << complex<float>(reals[j], imags[j]) << " "; | |
67 } | |
68 cerr << endl; | |
73 } | 69 } |
74 QCOMPARE(reals[hs1], 999.f); | 70 COMPARE_FUZZIER_F(reals[i], eRe); |
75 QCOMPARE(imags[hs1], 999.f); | 71 COMPARE_FUZZIER_F(imags[i], eIm); |
76 } | 72 } |
73 QCOMPARE(reals[hs1], 999.f); | |
74 QCOMPARE(imags[hs1], 999.f); | |
77 } | 75 } |
78 } | 76 } |
79 | 77 |
80 private slots: | 78 private slots: |
81 | 79 |
115 { { {}, {}, {}, {}, {} } }, 4); | 113 { { {}, {}, {}, {}, {} } }, 4); |
116 } | 114 } |
117 | 115 |
118 void sine_simple_rect() { | 116 void sine_simple_rect() { |
119 MockWaveModel mwm({ Sine }, 16, 4); | 117 MockWaveModel mwm({ Sine }, 16, 4); |
118 // Sine: output is purely imaginary. Note the sign is flipped | |
119 // (normally the first half of the output would have negative | |
120 // sign for a sine starting at 0) because the model does an | |
121 // FFT shift to centre the phase | |
120 test(&mwm, RectangularWindow, 8, 8, 8, 0, | 122 test(&mwm, RectangularWindow, 8, 8, 8, 0, |
121 { { {}, {}, {}, {}, {} } }, 4); | 123 { { {}, {}, {}, {}, {} } }, 4); |
122 test(&mwm, RectangularWindow, 8, 8, 8, 1, | 124 test(&mwm, RectangularWindow, 8, 8, 8, 1, |
123 { { {}, { 0.f, 2.f }, {}, {}, {} } }, 4); | 125 { { {}, { 0.f, 2.f }, {}, {}, {} } }, 4); |
124 test(&mwm, RectangularWindow, 8, 8, 8, 2, | 126 test(&mwm, RectangularWindow, 8, 8, 8, 2, |
127 { { {}, {}, {}, {}, {} } }, 4); | 129 { { {}, {}, {}, {}, {} } }, 4); |
128 } | 130 } |
129 | 131 |
130 void cosine_simple_rect() { | 132 void cosine_simple_rect() { |
131 MockWaveModel mwm({ Cosine }, 16, 4); | 133 MockWaveModel mwm({ Cosine }, 16, 4); |
134 // Cosine: output is purely real. Note the sign is flipped | |
135 // because the model does an FFT shift to centre the phase | |
132 test(&mwm, RectangularWindow, 8, 8, 8, 0, | 136 test(&mwm, RectangularWindow, 8, 8, 8, 0, |
133 { { {}, {}, {}, {}, {} } }, 4); | 137 { { {}, {}, {}, {}, {} } }, 4); |
134 test(&mwm, RectangularWindow, 8, 8, 8, 1, | 138 test(&mwm, RectangularWindow, 8, 8, 8, 1, |
135 { { {}, { 2.f, 0.f }, {}, {}, {} } }, 4); | 139 { { {}, { -2.f, 0.f }, {}, {}, {} } }, 4); |
136 test(&mwm, RectangularWindow, 8, 8, 8, 2, | 140 test(&mwm, RectangularWindow, 8, 8, 8, 2, |
137 { { {}, { 2.f, 0.f }, {}, {}, {} } }, 4); | 141 { { {}, { -2.f, 0.f }, {}, {}, {} } }, 4); |
138 test(&mwm, RectangularWindow, 8, 8, 8, 3, | 142 test(&mwm, RectangularWindow, 8, 8, 8, 3, |
139 { { {}, {}, {}, {}, {} } }, 4); | 143 { { {}, {}, {}, {}, {} } }, 4); |
140 } | 144 } |
141 | 145 |
142 void nyquist_simple_rect() { | 146 void nyquist_simple_rect() { |
143 MockWaveModel mwm({ Nyquist }, 16, 4); | 147 MockWaveModel mwm({ Nyquist }, 16, 4); |
148 // Again, the sign is flipped. This has the same amount of | |
149 // energy as the DC example | |
144 test(&mwm, RectangularWindow, 8, 8, 8, 0, | 150 test(&mwm, RectangularWindow, 8, 8, 8, 0, |
145 { { {}, {}, {}, {}, {} } }, 4); | 151 { { {}, {}, {}, {}, {} } }, 4); |
146 test(&mwm, RectangularWindow, 8, 8, 8, 1, | 152 test(&mwm, RectangularWindow, 8, 8, 8, 1, |
147 { { {}, {}, {}, {}, { 2.f, 0.f } } }, 4); | 153 { { {}, {}, {}, {}, { -4.f, 0.f } } }, 4); |
148 test(&mwm, RectangularWindow, 8, 8, 8, 2, | 154 test(&mwm, RectangularWindow, 8, 8, 8, 2, |
149 { { {}, {}, {}, {}, { 2.f, 0.f } } }, 4); | 155 { { {}, {}, {}, {}, { -4.f, 0.f } } }, 4); |
150 test(&mwm, RectangularWindow, 8, 8, 8, 3, | 156 test(&mwm, RectangularWindow, 8, 8, 8, 3, |
151 { { {}, {}, {}, {}, {} } }, 4); | 157 { { {}, {}, {}, {}, {} } }, 4); |
152 } | 158 } |
153 | 159 |
154 void dirac_simple_rect() { | 160 void dirac_simple_rect() { |
155 MockWaveModel mwm({ Dirac }, 16, 4); | 161 MockWaveModel mwm({ Dirac }, 16, 4); |
162 // The window scales by 0.5 and some signs are flipped. Only | |
163 // column 1 has any data (the single impulse). | |
156 test(&mwm, RectangularWindow, 8, 8, 8, 0, | 164 test(&mwm, RectangularWindow, 8, 8, 8, 0, |
157 { { {}, {}, {}, {}, {} } }, 4); | 165 { { {}, {}, {}, {}, {} } }, 4); |
158 test(&mwm, RectangularWindow, 8, 8, 8, 1, | 166 test(&mwm, RectangularWindow, 8, 8, 8, 1, |
159 { { { 1.f, 0.f }, { 1.f, 0.f }, { 1.f, 0.f }, { 1.f, 0.f }, { 1.f, 0.f } } }, 4); | 167 { { { 0.5f, 0.f }, { -0.5f, 0.f }, { 0.5f, 0.f }, { -0.5f, 0.f }, { 0.5f, 0.f } } }, 4); |
160 test(&mwm, RectangularWindow, 8, 8, 8, 2, | 168 test(&mwm, RectangularWindow, 8, 8, 8, 2, |
161 { { { 1.f, 0.f }, { 1.f, 0.f }, { 1.f, 0.f }, { 1.f, 0.f }, { 1.f, 0.f } } }, 4); | 169 { { {}, {}, {}, {}, {} } }, 4); |
162 test(&mwm, RectangularWindow, 8, 8, 8, 3, | 170 test(&mwm, RectangularWindow, 8, 8, 8, 3, |
163 { { {}, {}, {}, {}, {} } }, 4); | 171 { { {}, {}, {}, {}, {} } }, 4); |
172 } | |
173 | |
174 void dirac_simple_rect_2() { | |
175 MockWaveModel mwm({ Dirac }, 16, 8); | |
176 // With 8 samples padding, the FFT shift places the first | |
177 // Dirac impulse at the start of column 1, thus giving all | |
178 // positive values | |
179 test(&mwm, RectangularWindow, 8, 8, 8, 0, | |
180 { { {}, {}, {}, {}, {} } }, 5); | |
181 test(&mwm, RectangularWindow, 8, 8, 8, 1, | |
182 { { { 0.5f, 0.f }, { 0.5f, 0.f }, { 0.5f, 0.f }, { 0.5f, 0.f }, { 0.5f, 0.f } } }, 5); | |
183 test(&mwm, RectangularWindow, 8, 8, 8, 2, | |
184 { { {}, {}, {}, {}, {} } }, 5); | |
185 test(&mwm, RectangularWindow, 8, 8, 8, 3, | |
186 { { {}, {}, {}, {}, {} } }, 5); | |
187 test(&mwm, RectangularWindow, 8, 8, 8, 4, | |
188 { { {}, {}, {}, {}, {} } }, 5); | |
164 } | 189 } |
165 | 190 |
166 }; | 191 }; |
167 | 192 |
168 #endif | 193 #endif |