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 }