Mercurial > hg > libxtract
comparison tests/xttest_scalar.cpp @ 267:41fe82c7ff80
Add more F0 tests
author | Jamie Bullock <jamie@jamiebullock.com> |
---|---|
date | Tue, 11 Nov 2014 16:15:28 +0000 |
parents | ecd6f2cf1346 |
children | b371ffcecb74 |
comparison
equal
deleted
inserted
replaced
266:5f15c7be9e0e | 267:41fe82c7ff80 |
---|---|
1 | 1 |
2 #include "xttest_util.hpp" | 2 #include "xttest_util.hpp" |
3 | 3 |
4 #include "xtract/xtract_scalar.h" | 4 #include "xtract/xtract_scalar.h" |
5 #include "xtract/libxtract.h" | |
5 | 6 |
6 #include "catch.hpp" | 7 #include "catch.hpp" |
7 | 8 |
8 | 9 |
9 SCENARIO( "F0 is correctly detected for a clean sine wave", "[xtract_f0]" ) | 10 SCENARIO( "F0 is correctly detected for a sine wave", "[xtract_f0]" ) |
10 { | 11 { |
12 uint16_t expected = 0; | |
13 uint16_t actual = 0; | |
14 | |
15 GIVEN( "a 512 sample block with a sample rate of 44100" ) | |
16 { | |
17 uint32_t blocksize = 512; | |
18 double samplerate = 44100; | |
19 double result = -1.0; | |
20 double amplitude = 1.0; | |
21 double table[blocksize]; | |
22 | |
23 WHEN( "the frequency is 86.1328125 Hz" ) // period of exactly 512 samples: 1 cycles in the block | |
24 { | |
25 double frequency = 86.1328125; | |
26 | |
27 xttest_gen_sine(table, blocksize, samplerate, frequency, amplitude); | |
28 int rv = xtract_f0(table, blocksize, &samplerate, &result); | |
29 | |
30 THEN( "frequency detection fails correctly (XTRACT_NO_RESULT is returned, result set to 0.0)" ) | |
31 { | |
32 REQUIRE(rv == XTRACT_NO_RESULT); | |
33 REQUIRE(result == 0.0); | |
34 } | |
35 } | |
36 | |
37 WHEN( "the frequency is 172.265625 Hz" ) // period of exactly 256 samples: 2 cycles in the block | |
38 { | |
39 double frequency = 172.265625; | |
40 | |
41 xttest_gen_sine(table, blocksize, samplerate, frequency, amplitude); | |
42 int rv = xtract_f0(table, blocksize, &samplerate, &result); | |
43 | |
44 THEN( "frequency detection fails correctly (XTRACT_NO_RESULT is returned, result set to 0.0)" ) | |
45 { | |
46 REQUIRE(rv == XTRACT_NO_RESULT); | |
47 REQUIRE(result == 0.0); | |
48 } | |
49 } | |
50 | |
51 WHEN( "the frequency is 344.53125 Hz" ) // period of exactly 128 samples: 4 cycles in the block | |
52 { | |
53 double frequency = 344.53125; | |
54 | |
55 xttest_gen_sine(table, blocksize, samplerate, frequency, amplitude); | |
56 xtract_f0(table, blocksize, &samplerate, &result); | |
57 | |
58 THEN( "the detected F0 is accurate to the nearest MIDI cent" ) | |
59 { | |
60 actual = xttest_ftom(result); | |
61 expected = xttest_ftom(frequency); | |
62 CAPTURE( actual ); | |
63 CAPTURE( expected ); | |
64 REQUIRE(actual == expected); | |
65 } | |
66 | |
67 | |
68 WHEN( "the amplitude is 0.01" ) // Only test a different amplitude for one case | |
69 { | |
70 double amplitude = 0.01; | |
71 | |
72 xttest_gen_sine(table, blocksize, samplerate, frequency, amplitude); | |
73 xtract_f0(table, blocksize, &samplerate, &result); | |
74 | |
75 THEN( "the detected F0 is accurate to the nearest MIDI cent" ) | |
76 { | |
77 actual = xttest_ftom(result); | |
78 expected = xttest_ftom(frequency); | |
79 CAPTURE( actual ); | |
80 CAPTURE( expected ); | |
81 REQUIRE(actual == expected); | |
82 } | |
83 } | |
84 } | |
85 } | |
86 | |
11 GIVEN( "a 1024 sample block with a sample rate of 44100" ) | 87 GIVEN( "a 1024 sample block with a sample rate of 44100" ) |
12 { | 88 { |
13 uint32_t blocksize = 1024; | 89 uint32_t blocksize = 1024; |
14 double samplerate = 44100; | 90 double samplerate = 44100; |
15 double result = 0.0; | 91 double result = -1.0; |
16 double table[blocksize]; | 92 double table[blocksize]; |
17 | 93 |
18 WHEN( "the frequency is 344.53125 Hz" ) // This will give a period of exactly 128 samples: 8 cycles in the block | 94 WHEN( "the frequency is 86.1328125 Hz" ) // period of exactly 512 samples: 2 cycles in the block |
95 { | |
96 double frequency = 86.1328125; | |
97 double amplitude = 1.0; | |
98 | |
99 xttest_gen_sine(table, blocksize, samplerate, frequency, amplitude); | |
100 int rv = xtract_f0(table, blocksize, &samplerate, &result); | |
101 | |
102 THEN( "frequency detection fails correctly (XTRACT_NO_RESULT is returned, result set to 0.0)" ) | |
103 { | |
104 REQUIRE(rv == XTRACT_NO_RESULT); | |
105 REQUIRE(result == 0.0); | |
106 } | |
107 } | |
108 | |
109 WHEN( "the frequency is 172.265625 Hz" ) // period of exactly 256 samples: 4 cycles in the block | |
110 { | |
111 double frequency = 172.265625; | |
112 double amplitude = 1.0; | |
113 | |
114 xttest_gen_sine(table, blocksize, samplerate, frequency, amplitude); | |
115 xtract_f0(table, blocksize, &samplerate, &result); | |
116 | |
117 THEN( "the detected F0 is accurate to the nearest MIDI cent" ) | |
118 { | |
119 actual = xttest_ftom(result); | |
120 expected = xttest_ftom(frequency); | |
121 CAPTURE( actual ); | |
122 CAPTURE( expected ); | |
123 REQUIRE(actual == expected); | |
124 } | |
125 } | |
126 | |
127 WHEN( "the frequency is 344.53125 Hz" ) // period of exactly 128 samples: 8 cycles in the block | |
19 { | 128 { |
20 double frequency = 344.53125; | 129 double frequency = 344.53125; |
21 double min = frequency * 0.995; | 130 expected = xttest_ftom(frequency); |
22 double max = frequency * 1.005; | 131 CAPTURE( expected ); |
23 | 132 |
24 WHEN( "the amplitude is 1.0" ) | 133 WHEN( "the amplitude is 1.0" ) |
25 { | 134 { |
26 double amplitude = 1.0; | 135 double amplitude = 1.0; |
27 | 136 |
28 xttest_gen_sine(table, blocksize, samplerate, frequency, amplitude); | 137 xttest_gen_sine(table, blocksize, samplerate, frequency, amplitude); |
29 xtract_f0(table, blocksize, &samplerate, &result); | 138 xtract_f0(table, blocksize, &samplerate, &result); |
30 CAPTURE( result ); | 139 |
31 | 140 THEN( "the detected F0 is accurate to the nearest MIDI cent" ) |
32 THEN( "the detected F0 is in the range 344.53125 ± 0.5%" ) | 141 { |
33 { | 142 actual = xttest_ftom(result); |
34 REQUIRE(result < max); | 143 CAPTURE( actual ); |
35 REQUIRE(result > min); | 144 REQUIRE(actual == expected); |
36 } | 145 } |
37 } | 146 } |
38 WHEN( "the amplitude is 0.1" ) | 147 |
148 WHEN( "the amplitude is 0.01" ) // Only test a different amplitude for one case | |
149 { | |
150 double amplitude = 0.01; | |
151 | |
152 xttest_gen_sine(table, blocksize, samplerate, frequency, amplitude); | |
153 xtract_f0(table, blocksize, &samplerate, &result); | |
154 | |
155 THEN( "the detected F0 is accurate to the nearest MIDI cent" ) | |
156 { | |
157 actual = xttest_ftom(result); | |
158 CAPTURE( actual ); | |
159 REQUIRE(actual == expected); | |
160 } | |
161 } | |
162 | |
163 WHEN( "white noise is added at 10%" ) // Only test noise for one case | |
39 { | 164 { |
40 double amplitude = 0.1; | 165 double amplitude = 0.1; |
41 | 166 double noise[blocksize]; |
167 | |
168 xttest_gen_sine(table, blocksize, samplerate, frequency, 1.0 - amplitude); | |
169 xttest_gen_noise(noise, blocksize, amplitude); | |
170 xttest_add(table, noise, blocksize); | |
171 xtract_f0(table, blocksize, &samplerate, &result); | |
172 | |
173 THEN( "the detected F0 is accurate to the nearest MIDI cent" ) | |
174 { | |
175 actual = xttest_ftom(result); | |
176 CAPTURE( actual ); | |
177 REQUIRE(actual == expected); | |
178 } | |
179 } | |
180 | |
181 WHEN( "white noise is added at 20%" ) | |
182 { | |
183 double amplitude = 0.2; | |
184 double noise[blocksize]; | |
185 | |
186 xttest_gen_sine(table, blocksize, samplerate, frequency, 1.0 - amplitude); | |
187 xttest_gen_noise(noise, blocksize, amplitude); | |
188 xttest_add(table, noise, blocksize); | |
189 xtract_f0(table, blocksize, &samplerate, &result); | |
190 | |
191 THEN( "the detected F0 is accurate to the nearest MIDI cent" ) | |
192 { | |
193 actual = xttest_ftom(result); | |
194 CAPTURE( actual ); | |
195 REQUIRE(actual == expected); | |
196 } | |
197 } | |
198 | |
199 WHEN( "white noise is added at 25%" ) | |
200 { | |
201 double amplitude = 0.25; | |
202 double noise[blocksize]; | |
203 | |
204 xttest_gen_sine(table, blocksize, samplerate, frequency, 1.0 - amplitude); | |
205 xttest_gen_noise(noise, blocksize, amplitude); | |
206 xttest_add(table, noise, blocksize); | |
207 xtract_f0(table, blocksize, &samplerate, &result); | |
208 | |
209 THEN( "the detected F0 is accurate to the nearest semitone" ) | |
210 { | |
211 actual = xttest_ftom(result); | |
212 uint16_t min = expected - 100; | |
213 uint16_t max = expected + 100; | |
214 CAPTURE( actual ); | |
215 REQUIRE( actual > min ); | |
216 REQUIRE( actual < max ); | |
217 } | |
218 } | |
219 | |
220 WHEN( "white noise is added at 30%" ) | |
221 { | |
222 double amplitude = 0.25; | |
223 double noise[blocksize]; | |
224 | |
225 xttest_gen_sine(table, blocksize, samplerate, frequency, 1.0 - amplitude); | |
226 xttest_gen_noise(noise, blocksize, amplitude); | |
227 xttest_add(table, noise, blocksize); | |
228 xtract_f0(table, blocksize, &samplerate, &result); | |
229 | |
230 THEN( "the detected F0 is accurate to the nearest quarter-tone" ) | |
231 { | |
232 actual = xttest_ftom(result); | |
233 uint16_t min = expected - 50; | |
234 uint16_t max = expected + 50; | |
235 CAPTURE( actual ); | |
236 REQUIRE( actual > min ); | |
237 REQUIRE( actual < max ); | |
238 } | |
239 } | |
240 | |
241 WHEN( "white noise is added at 35%" ) | |
242 { | |
243 double amplitude = 0.35; | |
244 double noise[blocksize]; | |
245 | |
246 xttest_gen_sine(table, blocksize, samplerate, frequency, 1.0 - amplitude); | |
247 xttest_gen_noise(noise, blocksize, amplitude); | |
248 xttest_add(table, noise, blocksize); | |
249 xtract_f0(table, blocksize, &samplerate, &result); | |
250 | |
251 THEN( "the detected F0 is inaccurate by more than one semitone" ) | |
252 { | |
253 actual = xttest_ftom(result); | |
254 uint16_t difference = abs(expected - actual); | |
255 CAPTURE( actual ); | |
256 REQUIRE( difference > 100 ); | |
257 } | |
258 } | |
259 } | |
260 } | |
261 | |
262 GIVEN( "a 1024 sample block with a sample rate of 11025" ) | |
263 { | |
264 uint32_t blocksize = 1024; | |
265 double samplerate = 11025; | |
266 double result = -1.0; | |
267 double table[blocksize]; | |
268 | |
269 WHEN( "the frequency is 86.1328125 Hz" ) // period of exactly 512 samples: 2 cycles in the block | |
270 { | |
271 double frequency = 86.1328125; | |
272 double amplitude = 1.0; | |
273 | |
274 xttest_gen_sine(table, blocksize, samplerate, frequency, amplitude); | |
275 int rv = xtract_f0(table, blocksize, &samplerate, &result); | |
276 | |
277 THEN( "the detected F0 is accurate to the nearest MIDI cent" ) | |
278 { | |
279 actual = xttest_ftom(result); | |
280 expected = xttest_ftom(frequency); | |
281 CAPTURE( actual ); | |
282 CAPTURE( expected ); | |
283 REQUIRE(actual == expected); | |
284 } | |
285 } | |
286 | |
287 WHEN( "the frequency is 172.265625 Hz" ) // period of exactly 256 samples: 4 cycles in the block | |
288 { | |
289 double frequency = 172.265625; | |
290 double amplitude = 1.0; | |
291 | |
292 xttest_gen_sine(table, blocksize, samplerate, frequency, amplitude); | |
293 xtract_f0(table, blocksize, &samplerate, &result); | |
294 | |
295 THEN( "the detected F0 is accurate to the nearest MIDI cent" ) | |
296 { | |
297 actual = xttest_ftom(result); | |
298 expected = xttest_ftom(frequency); | |
299 CAPTURE( actual ); | |
300 CAPTURE( expected ); | |
301 REQUIRE(actual == expected); | |
302 } | |
303 } | |
304 | |
305 WHEN( "the frequency is 344.53125 Hz" ) // period of exactly 128 samples: 8 cycles in the block | |
306 { | |
307 double frequency = 344.53125; | |
308 expected = xttest_ftom(frequency); | |
309 CAPTURE( expected ); | |
310 | |
311 WHEN( "the amplitude is 1.0" ) | |
312 { | |
313 double amplitude = 1.0; | |
314 | |
42 xttest_gen_sine(table, blocksize, samplerate, frequency, amplitude); | 315 xttest_gen_sine(table, blocksize, samplerate, frequency, amplitude); |
43 xtract_f0(table, blocksize, &samplerate, &result); | 316 xtract_f0(table, blocksize, &samplerate, &result); |
44 CAPTURE( result ); | 317 |
45 | 318 THEN( "the detected F0 is accurate to the nearest MIDI cent" ) |
46 THEN( "the detected F0 is in the range 344.53125 ± 0.5%" ) | 319 { |
47 { | 320 actual = xttest_ftom(result); |
48 REQUIRE(result < max); | 321 CAPTURE( actual ); |
49 REQUIRE(result > min); | 322 REQUIRE(actual == expected); |
50 } | 323 } |
51 } | 324 } |
325 | |
326 WHEN( "the amplitude is 0.01" ) // Only test a different amplitude for one case | |
327 { | |
328 double amplitude = 0.01; | |
329 | |
330 xttest_gen_sine(table, blocksize, samplerate, frequency, amplitude); | |
331 xtract_f0(table, blocksize, &samplerate, &result); | |
332 | |
333 THEN( "the detected F0 is accurate to the nearest MIDI cent" ) | |
334 { | |
335 actual = xttest_ftom(result); | |
336 CAPTURE( actual ); | |
337 REQUIRE(actual == expected); | |
338 } | |
339 } | |
340 | |
341 WHEN( "white noise is added at 20%" ) | |
342 { | |
343 double amplitude = 0.2; | |
344 double noise[blocksize]; | |
345 | |
346 xttest_gen_sine(table, blocksize, samplerate, frequency, 1.0 - amplitude); | |
347 xttest_gen_noise(noise, blocksize, amplitude); | |
348 xttest_add(table, noise, blocksize); | |
349 xtract_f0(table, blocksize, &samplerate, &result); | |
350 | |
351 THEN( "the detected F0 is accurate to the nearest quarter-tone" ) | |
352 { | |
353 actual = xttest_ftom(result); | |
354 uint16_t min = expected - 50; | |
355 uint16_t max = expected + 50; | |
356 CAPTURE( actual ); | |
357 REQUIRE( actual > min ); | |
358 REQUIRE( actual < max ); | |
359 } | |
360 } | |
361 | |
362 WHEN( "white noise is added at 40%" ) | |
363 { | |
364 double amplitude = 0.4; | |
365 double noise[blocksize]; | |
366 | |
367 xttest_gen_sine(table, blocksize, samplerate, frequency, 1.0 - amplitude); | |
368 xttest_gen_noise(noise, blocksize, amplitude); | |
369 xttest_add(table, noise, blocksize); | |
370 xtract_f0(table, blocksize, &samplerate, &result); | |
371 | |
372 THEN( "the detected F0 is accurate to the nearest semi-tone" ) | |
373 { | |
374 actual = xttest_ftom(result); | |
375 uint16_t min = expected - 100; | |
376 uint16_t max = expected + 100; | |
377 CAPTURE( actual ); | |
378 REQUIRE( actual > min ); | |
379 REQUIRE( actual < max ); | |
380 } | |
381 } | |
382 | |
383 WHEN( "white noise is added at 60%" ) | |
384 { | |
385 double amplitude = 0.6; | |
386 double noise[blocksize]; | |
387 | |
388 xttest_gen_sine(table, blocksize, samplerate, frequency, 1.0 - amplitude); | |
389 xttest_gen_noise(noise, blocksize, amplitude); | |
390 xttest_add(table, noise, blocksize); | |
391 xtract_f0(table, blocksize, &samplerate, &result); | |
392 | |
393 THEN( "the detected F0 is accurate to the nearest semi-tone" ) | |
394 { | |
395 actual = xttest_ftom(result); | |
396 uint16_t min = expected - 100; | |
397 uint16_t max = expected + 100; | |
398 CAPTURE( actual ); | |
399 REQUIRE( actual > min ); | |
400 REQUIRE( actual < max ); | |
401 } | |
402 } | |
403 | |
404 WHEN( "white noise is added at 80%" ) | |
405 { | |
406 double amplitude = 0.8; | |
407 double noise[blocksize]; | |
408 | |
409 xttest_gen_sine(table, blocksize, samplerate, frequency, 1.0 - amplitude); | |
410 xttest_gen_noise(noise, blocksize, amplitude); | |
411 xttest_add(table, noise, blocksize); | |
412 xtract_f0(table, blocksize, &samplerate, &result); | |
413 | |
414 THEN( "the detected F0 is inaccurate by more than one semitone" ) | |
415 { | |
416 actual = xttest_ftom(result); | |
417 uint16_t difference = abs(expected - actual); | |
418 CAPTURE( actual ); | |
419 REQUIRE( difference > 100 ); | |
420 } | |
421 } | |
422 } | |
423 } | |
424 | |
425 GIVEN( "a 2048 sample block with a sample rate of 44100" ) | |
426 { | |
427 uint32_t blocksize = 2048; | |
428 double samplerate = 44100; | |
429 double result = -1.0; | |
430 double table[blocksize]; | |
431 | |
432 WHEN( "the frequency is 43.06640625 Hz" ) // period of exactly 256 samples: 2 cycles in the block | |
433 { | |
434 double frequency = 43.06640625; | |
435 double amplitude = 1.0; | |
436 | |
437 xttest_gen_sine(table, blocksize, samplerate, frequency, amplitude); | |
438 int rv = xtract_f0(table, blocksize, &samplerate, &result); | |
439 | |
440 THEN( "frequency detection fails correctly (XTRACT_NO_RESULT is returned, result set to 0.0)" ) | |
441 { | |
442 REQUIRE(rv == XTRACT_NO_RESULT); | |
443 REQUIRE(result == 0.0); | |
444 } | |
445 } | |
446 | |
447 WHEN( "the frequency is 86.1328125 Hz" ) // period of exactly 512 samples: 4 cycles in the block | |
448 { | |
449 double frequency = 86.1328125; | |
450 double amplitude = 1.0; | |
451 | |
452 xttest_gen_sine(table, blocksize, samplerate, frequency, amplitude); | |
453 int rv = xtract_f0(table, blocksize, &samplerate, &result); | |
454 | |
455 THEN( "the detected F0 is accurate to the nearest MIDI cent" ) | |
456 { | |
457 actual = xttest_ftom(result); | |
458 expected = xttest_ftom(frequency); | |
459 CAPTURE( actual ); | |
460 CAPTURE( expected ); | |
461 REQUIRE(actual == expected); | |
462 } | |
463 } | |
464 | |
465 WHEN( "the frequency is 172.265625 Hz" ) // period of exactly 256 samples: 8 cycles in the block | |
466 { | |
467 double frequency = 172.265625; | |
468 double amplitude = 1.0; | |
469 | |
470 xttest_gen_sine(table, blocksize, samplerate, frequency, amplitude); | |
471 xtract_f0(table, blocksize, &samplerate, &result); | |
472 | |
473 THEN( "the detected F0 is accurate to the nearest MIDI cent" ) | |
474 { | |
475 actual = xttest_ftom(result); | |
476 expected = xttest_ftom(frequency); | |
477 CAPTURE( actual ); | |
478 CAPTURE( expected ); | |
479 REQUIRE(actual == expected); | |
480 } | |
481 } | |
482 | |
483 WHEN( "the frequency is 344.53125 Hz" ) // period of exactly 128 samples: 16 cycles in the block | |
484 { | |
485 double frequency = 344.53125; | |
486 | |
487 WHEN( "the amplitude is 1.0" ) | |
488 { | |
489 double amplitude = 1.0; | |
490 | |
491 xttest_gen_sine(table, blocksize, samplerate, frequency, amplitude); | |
492 xtract_f0(table, blocksize, &samplerate, &result); | |
493 | |
494 THEN( "the detected F0 is accurate to the nearest MIDI cent" ) | |
495 { | |
496 actual = xttest_ftom(result); | |
497 expected = xttest_ftom(frequency); | |
498 CAPTURE( actual ); | |
499 CAPTURE( expected ); | |
500 REQUIRE(actual == expected); | |
501 } | |
502 } | |
52 } | 503 } |
53 } | 504 } |
54 } | 505 } |