Mercurial > hg > svcore
comparison data/model/test/TestFFTModel.h @ 1744:b92bdcd4954b by-id
Update FFT model to ById
author | Chris Cannam |
---|---|
date | Tue, 02 Jul 2019 11:49:28 +0100 |
parents | 0e9840a381b5 |
children | 6d09d68165a4 |
comparison
equal
deleted
inserted
replaced
1743:7001b9570e37 | 1744:b92bdcd4954b |
---|---|
33 class TestFFTModel : public QObject | 33 class TestFFTModel : public QObject |
34 { | 34 { |
35 Q_OBJECT | 35 Q_OBJECT |
36 | 36 |
37 private: | 37 private: |
38 void test(DenseTimeValueModel *model, | 38 void test(ModelId model, // a DenseTimeValueModel |
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 FFTModel fftm(model, ch, window, windowSize, windowIncrement, fftSize); | 43 FFTModel fftm(model, ch, window, windowSize, windowIncrement, fftSize); |
86 QCOMPARE(imags[hs1], 999.f); | 86 QCOMPARE(imags[hs1], 999.f); |
87 } | 87 } |
88 } | 88 } |
89 } | 89 } |
90 | 90 |
91 ModelId makeMock(std::vector<Sort> sorts, int length, int pad) { | |
92 auto mwm = std::make_shared<MockWaveModel>(sorts, length, pad); | |
93 ModelById::add(mwm); | |
94 return mwm->getId(); | |
95 } | |
96 | |
97 void releaseMock(ModelId id) { | |
98 ModelById::release(id); | |
99 } | |
100 | |
91 private slots: | 101 private slots: |
92 | 102 |
93 // NB. FFTModel columns are centred on the sample frame, and in | 103 // NB. FFTModel columns are centred on the sample frame, and in |
94 // particular this means column 0 is centred at sample 0 (i.e. it | 104 // particular this means column 0 is centred at sample 0 (i.e. it |
95 // contains only half the window-size worth of real samples, the | 105 // contains only half the window-size worth of real samples, the |
99 // (rather than something with a step in it that is harder to | 109 // (rather than something with a step in it that is harder to |
100 // reason about the FFT of) and the results for subsequent columns | 110 // reason about the FFT of) and the results for subsequent columns |
101 // are those of our expected signal. | 111 // are those of our expected signal. |
102 | 112 |
103 void dc_simple_rect() { | 113 void dc_simple_rect() { |
104 MockWaveModel mwm({ DC }, 16, 4); | 114 auto mwm = makeMock({ DC }, 16, 4); |
105 test(&mwm, RectangularWindow, 8, 8, 8, 0, | 115 test(mwm, RectangularWindow, 8, 8, 8, 0, |
106 { { {}, {}, {}, {}, {} } }, 4); | 116 { { {}, {}, {}, {}, {} } }, 4); |
107 test(&mwm, RectangularWindow, 8, 8, 8, 1, | 117 test(mwm, RectangularWindow, 8, 8, 8, 1, |
108 { { { 4.f, 0.f }, {}, {}, {}, {} } }, 4); | 118 { { { 4.f, 0.f }, {}, {}, {}, {} } }, 4); |
109 test(&mwm, RectangularWindow, 8, 8, 8, 2, | 119 test(mwm, RectangularWindow, 8, 8, 8, 2, |
110 { { { 4.f, 0.f }, {}, {}, {}, {} } }, 4); | 120 { { { 4.f, 0.f }, {}, {}, {}, {} } }, 4); |
111 test(&mwm, RectangularWindow, 8, 8, 8, 3, | 121 test(mwm, RectangularWindow, 8, 8, 8, 3, |
112 { { {}, {}, {}, {}, {} } }, 4); | 122 { { {}, {}, {}, {}, {} } }, 4); |
123 releaseMock(mwm); | |
113 } | 124 } |
114 | 125 |
115 void dc_simple_hann() { | 126 void dc_simple_hann() { |
116 // The Hann window function is a simple sinusoid with period | 127 // The Hann window function is a simple sinusoid with period |
117 // equal to twice the window size, and it halves the DC energy | 128 // equal to twice the window size, and it halves the DC energy |
118 MockWaveModel mwm({ DC }, 16, 4); | 129 auto mwm = makeMock({ DC }, 16, 4); |
119 test(&mwm, HanningWindow, 8, 8, 8, 0, | 130 test(mwm, HanningWindow, 8, 8, 8, 0, |
120 { { {}, {}, {}, {}, {} } }, 4); | 131 { { {}, {}, {}, {}, {} } }, 4); |
121 test(&mwm, HanningWindow, 8, 8, 8, 1, | 132 test(mwm, HanningWindow, 8, 8, 8, 1, |
122 { { { 4.f, 0.f }, { 2.f, 0.f }, {}, {}, {} } }, 4); | 133 { { { 4.f, 0.f }, { 2.f, 0.f }, {}, {}, {} } }, 4); |
123 test(&mwm, HanningWindow, 8, 8, 8, 2, | 134 test(mwm, HanningWindow, 8, 8, 8, 2, |
124 { { { 4.f, 0.f }, { 2.f, 0.f }, {}, {}, {} } }, 4); | 135 { { { 4.f, 0.f }, { 2.f, 0.f }, {}, {}, {} } }, 4); |
125 test(&mwm, HanningWindow, 8, 8, 8, 3, | 136 test(mwm, HanningWindow, 8, 8, 8, 3, |
126 { { {}, {}, {}, {}, {} } }, 4); | 137 { { {}, {}, {}, {}, {} } }, 4); |
138 releaseMock(mwm); | |
127 } | 139 } |
128 | 140 |
129 void dc_simple_hann_halfoverlap() { | 141 void dc_simple_hann_halfoverlap() { |
130 MockWaveModel mwm({ DC }, 16, 4); | 142 auto mwm = makeMock({ DC }, 16, 4); |
131 test(&mwm, HanningWindow, 8, 4, 8, 0, | 143 test(mwm, HanningWindow, 8, 4, 8, 0, |
132 { { {}, {}, {}, {}, {} } }, 7); | 144 { { {}, {}, {}, {}, {} } }, 7); |
133 test(&mwm, HanningWindow, 8, 4, 8, 2, | 145 test(mwm, HanningWindow, 8, 4, 8, 2, |
134 { { { 4.f, 0.f }, { 2.f, 0.f }, {}, {}, {} } }, 7); | 146 { { { 4.f, 0.f }, { 2.f, 0.f }, {}, {}, {} } }, 7); |
135 test(&mwm, HanningWindow, 8, 4, 8, 3, | 147 test(mwm, HanningWindow, 8, 4, 8, 3, |
136 { { { 4.f, 0.f }, { 2.f, 0.f }, {}, {}, {} } }, 7); | 148 { { { 4.f, 0.f }, { 2.f, 0.f }, {}, {}, {} } }, 7); |
137 test(&mwm, HanningWindow, 8, 4, 8, 6, | 149 test(mwm, HanningWindow, 8, 4, 8, 6, |
138 { { {}, {}, {}, {}, {} } }, 7); | 150 { { {}, {}, {}, {}, {} } }, 7); |
151 releaseMock(mwm); | |
139 } | 152 } |
140 | 153 |
141 void sine_simple_rect() { | 154 void sine_simple_rect() { |
142 MockWaveModel mwm({ Sine }, 16, 4); | 155 auto mwm = makeMock({ Sine }, 16, 4); |
143 // Sine: output is purely imaginary. Note the sign is flipped | 156 // Sine: output is purely imaginary. Note the sign is flipped |
144 // (normally the first half of the output would have negative | 157 // (normally the first half of the output would have negative |
145 // sign for a sine starting at 0) because the model does an | 158 // sign for a sine starting at 0) because the model does an |
146 // FFT shift to centre the phase | 159 // FFT shift to centre the phase |
147 test(&mwm, RectangularWindow, 8, 8, 8, 0, | 160 test(mwm, RectangularWindow, 8, 8, 8, 0, |
148 { { {}, {}, {}, {}, {} } }, 4); | 161 { { {}, {}, {}, {}, {} } }, 4); |
149 test(&mwm, RectangularWindow, 8, 8, 8, 1, | 162 test(mwm, RectangularWindow, 8, 8, 8, 1, |
150 { { {}, { 0.f, 2.f }, {}, {}, {} } }, 4); | 163 { { {}, { 0.f, 2.f }, {}, {}, {} } }, 4); |
151 test(&mwm, RectangularWindow, 8, 8, 8, 2, | 164 test(mwm, RectangularWindow, 8, 8, 8, 2, |
152 { { {}, { 0.f, 2.f }, {}, {}, {} } }, 4); | 165 { { {}, { 0.f, 2.f }, {}, {}, {} } }, 4); |
153 test(&mwm, RectangularWindow, 8, 8, 8, 3, | 166 test(mwm, RectangularWindow, 8, 8, 8, 3, |
154 { { {}, {}, {}, {}, {} } }, 4); | 167 { { {}, {}, {}, {}, {} } }, 4); |
168 releaseMock(mwm); | |
155 } | 169 } |
156 | 170 |
157 void cosine_simple_rect() { | 171 void cosine_simple_rect() { |
158 MockWaveModel mwm({ Cosine }, 16, 4); | 172 auto mwm = makeMock({ Cosine }, 16, 4); |
159 // Cosine: output is purely real. Note the sign is flipped | 173 // Cosine: output is purely real. Note the sign is flipped |
160 // because the model does an FFT shift to centre the phase | 174 // because the model does an FFT shift to centre the phase |
161 test(&mwm, RectangularWindow, 8, 8, 8, 0, | 175 test(mwm, RectangularWindow, 8, 8, 8, 0, |
162 { { {}, {}, {}, {}, {} } }, 4); | 176 { { {}, {}, {}, {}, {} } }, 4); |
163 test(&mwm, RectangularWindow, 8, 8, 8, 1, | 177 test(mwm, RectangularWindow, 8, 8, 8, 1, |
164 { { {}, { -2.f, 0.f }, {}, {}, {} } }, 4); | 178 { { {}, { -2.f, 0.f }, {}, {}, {} } }, 4); |
165 test(&mwm, RectangularWindow, 8, 8, 8, 2, | 179 test(mwm, RectangularWindow, 8, 8, 8, 2, |
166 { { {}, { -2.f, 0.f }, {}, {}, {} } }, 4); | 180 { { {}, { -2.f, 0.f }, {}, {}, {} } }, 4); |
167 test(&mwm, RectangularWindow, 8, 8, 8, 3, | 181 test(mwm, RectangularWindow, 8, 8, 8, 3, |
168 { { {}, {}, {}, {}, {} } }, 4); | 182 { { {}, {}, {}, {}, {} } }, 4); |
183 releaseMock(mwm); | |
169 } | 184 } |
170 | 185 |
171 void twochan_simple_rect() { | 186 void twochan_simple_rect() { |
172 MockWaveModel mwm({ Sine, Cosine }, 16, 4); | 187 auto mwm = makeMock({ Sine, Cosine }, 16, 4); |
173 // Test that the two channels are read and converted separately | 188 // Test that the two channels are read and converted separately |
174 test(&mwm, RectangularWindow, 8, 8, 8, 0, | 189 test(mwm, RectangularWindow, 8, 8, 8, 0, |
175 { | 190 { |
176 { {}, {}, {}, {}, {} }, | 191 { {}, {}, {}, {}, {} }, |
177 { {}, {}, {}, {}, {} } | 192 { {}, {}, {}, {}, {} } |
178 }, 4); | 193 }, 4); |
179 test(&mwm, RectangularWindow, 8, 8, 8, 1, | 194 test(mwm, RectangularWindow, 8, 8, 8, 1, |
180 { | 195 { |
181 { {}, { 0.f, 2.f }, {}, {}, {} }, | 196 { {}, { 0.f, 2.f }, {}, {}, {} }, |
182 { {}, { -2.f, 0.f }, {}, {}, {} } | 197 { {}, { -2.f, 0.f }, {}, {}, {} } |
183 }, 4); | 198 }, 4); |
184 test(&mwm, RectangularWindow, 8, 8, 8, 2, | 199 test(mwm, RectangularWindow, 8, 8, 8, 2, |
185 { | 200 { |
186 { {}, { 0.f, 2.f }, {}, {}, {} }, | 201 { {}, { 0.f, 2.f }, {}, {}, {} }, |
187 { {}, { -2.f, 0.f }, {}, {}, {} } | 202 { {}, { -2.f, 0.f }, {}, {}, {} } |
188 }, 4); | 203 }, 4); |
189 test(&mwm, RectangularWindow, 8, 8, 8, 3, | 204 test(mwm, RectangularWindow, 8, 8, 8, 3, |
190 { | 205 { |
191 { {}, {}, {}, {}, {} }, | 206 { {}, {}, {}, {}, {} }, |
192 { {}, {}, {}, {}, {} } | 207 { {}, {}, {}, {}, {} } |
193 }, 4); | 208 }, 4); |
209 releaseMock(mwm); | |
194 } | 210 } |
195 | 211 |
196 void nyquist_simple_rect() { | 212 void nyquist_simple_rect() { |
197 MockWaveModel mwm({ Nyquist }, 16, 4); | 213 auto mwm = makeMock({ Nyquist }, 16, 4); |
198 // Again, the sign is flipped. This has the same amount of | 214 // Again, the sign is flipped. This has the same amount of |
199 // energy as the DC example | 215 // energy as the DC example |
200 test(&mwm, RectangularWindow, 8, 8, 8, 0, | 216 test(mwm, RectangularWindow, 8, 8, 8, 0, |
201 { { {}, {}, {}, {}, {} } }, 4); | 217 { { {}, {}, {}, {}, {} } }, 4); |
202 test(&mwm, RectangularWindow, 8, 8, 8, 1, | 218 test(mwm, RectangularWindow, 8, 8, 8, 1, |
203 { { {}, {}, {}, {}, { -4.f, 0.f } } }, 4); | 219 { { {}, {}, {}, {}, { -4.f, 0.f } } }, 4); |
204 test(&mwm, RectangularWindow, 8, 8, 8, 2, | 220 test(mwm, RectangularWindow, 8, 8, 8, 2, |
205 { { {}, {}, {}, {}, { -4.f, 0.f } } }, 4); | 221 { { {}, {}, {}, {}, { -4.f, 0.f } } }, 4); |
206 test(&mwm, RectangularWindow, 8, 8, 8, 3, | 222 test(mwm, RectangularWindow, 8, 8, 8, 3, |
207 { { {}, {}, {}, {}, {} } }, 4); | 223 { { {}, {}, {}, {}, {} } }, 4); |
224 releaseMock(mwm); | |
208 } | 225 } |
209 | 226 |
210 void dirac_simple_rect() { | 227 void dirac_simple_rect() { |
211 MockWaveModel mwm({ Dirac }, 16, 4); | 228 auto mwm = makeMock({ Dirac }, 16, 4); |
212 // The window scales by 0.5 and some signs are flipped. Only | 229 // The window scales by 0.5 and some signs are flipped. Only |
213 // column 1 has any data (the single impulse). | 230 // column 1 has any data (the single impulse). |
214 test(&mwm, RectangularWindow, 8, 8, 8, 0, | 231 test(mwm, RectangularWindow, 8, 8, 8, 0, |
215 { { {}, {}, {}, {}, {} } }, 4); | 232 { { {}, {}, {}, {}, {} } }, 4); |
216 test(&mwm, RectangularWindow, 8, 8, 8, 1, | 233 test(mwm, RectangularWindow, 8, 8, 8, 1, |
217 { { { 0.5f, 0.f }, { -0.5f, 0.f }, { 0.5f, 0.f }, { -0.5f, 0.f }, { 0.5f, 0.f } } }, 4); | 234 { { { 0.5f, 0.f }, { -0.5f, 0.f }, { 0.5f, 0.f }, { -0.5f, 0.f }, { 0.5f, 0.f } } }, 4); |
218 test(&mwm, RectangularWindow, 8, 8, 8, 2, | 235 test(mwm, RectangularWindow, 8, 8, 8, 2, |
219 { { {}, {}, {}, {}, {} } }, 4); | 236 { { {}, {}, {}, {}, {} } }, 4); |
220 test(&mwm, RectangularWindow, 8, 8, 8, 3, | 237 test(mwm, RectangularWindow, 8, 8, 8, 3, |
221 { { {}, {}, {}, {}, {} } }, 4); | 238 { { {}, {}, {}, {}, {} } }, 4); |
239 releaseMock(mwm); | |
222 } | 240 } |
223 | 241 |
224 void dirac_simple_rect_2() { | 242 void dirac_simple_rect_2() { |
225 MockWaveModel mwm({ Dirac }, 16, 8); | 243 auto mwm = makeMock({ Dirac }, 16, 8); |
226 // With 8 samples padding, the FFT shift places the first | 244 // With 8 samples padding, the FFT shift places the first |
227 // Dirac impulse at the start of column 1, thus giving all | 245 // Dirac impulse at the start of column 1, thus giving all |
228 // positive values | 246 // positive values |
229 test(&mwm, RectangularWindow, 8, 8, 8, 0, | 247 test(mwm, RectangularWindow, 8, 8, 8, 0, |
230 { { {}, {}, {}, {}, {} } }, 5); | 248 { { {}, {}, {}, {}, {} } }, 5); |
231 test(&mwm, RectangularWindow, 8, 8, 8, 1, | 249 test(mwm, RectangularWindow, 8, 8, 8, 1, |
232 { { { 0.5f, 0.f }, { 0.5f, 0.f }, { 0.5f, 0.f }, { 0.5f, 0.f }, { 0.5f, 0.f } } }, 5); | 250 { { { 0.5f, 0.f }, { 0.5f, 0.f }, { 0.5f, 0.f }, { 0.5f, 0.f }, { 0.5f, 0.f } } }, 5); |
233 test(&mwm, RectangularWindow, 8, 8, 8, 2, | 251 test(mwm, RectangularWindow, 8, 8, 8, 2, |
234 { { {}, {}, {}, {}, {} } }, 5); | 252 { { {}, {}, {}, {}, {} } }, 5); |
235 test(&mwm, RectangularWindow, 8, 8, 8, 3, | 253 test(mwm, RectangularWindow, 8, 8, 8, 3, |
236 { { {}, {}, {}, {}, {} } }, 5); | 254 { { {}, {}, {}, {}, {} } }, 5); |
237 test(&mwm, RectangularWindow, 8, 8, 8, 4, | 255 test(mwm, RectangularWindow, 8, 8, 8, 4, |
238 { { {}, {}, {}, {}, {} } }, 5); | 256 { { {}, {}, {}, {}, {} } }, 5); |
257 releaseMock(mwm); | |
239 } | 258 } |
240 | 259 |
241 void dirac_simple_rect_halfoverlap() { | 260 void dirac_simple_rect_halfoverlap() { |
242 MockWaveModel mwm({ Dirac }, 16, 4); | 261 auto mwm = makeMock({ Dirac }, 16, 4); |
243 test(&mwm, RectangularWindow, 8, 4, 8, 0, | 262 test(mwm, RectangularWindow, 8, 4, 8, 0, |
244 { { {}, {}, {}, {}, {} } }, 7); | 263 { { {}, {}, {}, {}, {} } }, 7); |
245 test(&mwm, RectangularWindow, 8, 4, 8, 1, | 264 test(mwm, RectangularWindow, 8, 4, 8, 1, |
246 { { { 0.5f, 0.f }, { 0.5f, 0.f }, { 0.5f, 0.f }, { 0.5f, 0.f }, { 0.5f, 0.f } } }, 7); | 265 { { { 0.5f, 0.f }, { 0.5f, 0.f }, { 0.5f, 0.f }, { 0.5f, 0.f }, { 0.5f, 0.f } } }, 7); |
247 test(&mwm, RectangularWindow, 8, 4, 8, 2, | 266 test(mwm, RectangularWindow, 8, 4, 8, 2, |
248 { { { 0.5f, 0.f }, { -0.5f, 0.f }, { 0.5f, 0.f }, { -0.5f, 0.f }, { 0.5f, 0.f } } }, 7); | 267 { { { 0.5f, 0.f }, { -0.5f, 0.f }, { 0.5f, 0.f }, { -0.5f, 0.f }, { 0.5f, 0.f } } }, 7); |
249 test(&mwm, RectangularWindow, 8, 4, 8, 3, | 268 test(mwm, RectangularWindow, 8, 4, 8, 3, |
250 { { {}, {}, {}, {}, {} } }, 7); | 269 { { {}, {}, {}, {}, {} } }, 7); |
270 releaseMock(mwm); | |
251 } | 271 } |
252 | 272 |
253 }; | 273 }; |
254 | 274 |
255 #endif | 275 #endif |