diff options
author | Jamie Bullock <jamie@jamiebullock.com> | 2014-11-11 16:15:28 +0000 |
---|---|---|
committer | Jamie Bullock <jamie@jamiebullock.com> | 2014-11-11 16:15:28 +0000 |
commit | acb301168deafed61ff4c59910cc989d67e25f40 (patch) | |
tree | 0253a66770c124757d0e55a3d404e2eb937ea01b /tests/xttest_scalar.cpp | |
parent | 4dcfb2941e6e4cb123b217d0c30c14bf541d2127 (diff) | |
download | LibXtract-acb301168deafed61ff4c59910cc989d67e25f40.tar.gz LibXtract-acb301168deafed61ff4c59910cc989d67e25f40.tar.bz2 LibXtract-acb301168deafed61ff4c59910cc989d67e25f40.zip |
Add more F0 tests
Diffstat (limited to 'tests/xttest_scalar.cpp')
-rw-r--r-- | tests/xttest_scalar.cpp | 481 |
1 files changed, 466 insertions, 15 deletions
diff --git a/tests/xttest_scalar.cpp b/tests/xttest_scalar.cpp index 4a11486..09f1665 100644 --- a/tests/xttest_scalar.cpp +++ b/tests/xttest_scalar.cpp @@ -2,24 +2,133 @@ #include "xttest_util.hpp" #include "xtract/xtract_scalar.h" +#include "xtract/libxtract.h" #include "catch.hpp" -SCENARIO( "F0 is correctly detected for a clean sine wave", "[xtract_f0]" ) +SCENARIO( "F0 is correctly detected for a sine wave", "[xtract_f0]" ) { + uint16_t expected = 0; + uint16_t actual = 0; + + GIVEN( "a 512 sample block with a sample rate of 44100" ) + { + uint32_t blocksize = 512; + double samplerate = 44100; + double result = -1.0; + double amplitude = 1.0; + double table[blocksize]; + + WHEN( "the frequency is 86.1328125 Hz" ) // period of exactly 512 samples: 1 cycles in the block + { + double frequency = 86.1328125; + + xttest_gen_sine(table, blocksize, samplerate, frequency, amplitude); + int rv = xtract_f0(table, blocksize, &samplerate, &result); + + THEN( "frequency detection fails correctly (XTRACT_NO_RESULT is returned, result set to 0.0)" ) + { + REQUIRE(rv == XTRACT_NO_RESULT); + REQUIRE(result == 0.0); + } + } + + WHEN( "the frequency is 172.265625 Hz" ) // period of exactly 256 samples: 2 cycles in the block + { + double frequency = 172.265625; + + xttest_gen_sine(table, blocksize, samplerate, frequency, amplitude); + int rv = xtract_f0(table, blocksize, &samplerate, &result); + + THEN( "frequency detection fails correctly (XTRACT_NO_RESULT is returned, result set to 0.0)" ) + { + REQUIRE(rv == XTRACT_NO_RESULT); + REQUIRE(result == 0.0); + } + } + + WHEN( "the frequency is 344.53125 Hz" ) // period of exactly 128 samples: 4 cycles in the block + { + double frequency = 344.53125; + + xttest_gen_sine(table, blocksize, samplerate, frequency, amplitude); + xtract_f0(table, blocksize, &samplerate, &result); + + THEN( "the detected F0 is accurate to the nearest MIDI cent" ) + { + actual = xttest_ftom(result); + expected = xttest_ftom(frequency); + CAPTURE( actual ); + CAPTURE( expected ); + REQUIRE(actual == expected); + } + + + WHEN( "the amplitude is 0.01" ) // Only test a different amplitude for one case + { + double amplitude = 0.01; + + xttest_gen_sine(table, blocksize, samplerate, frequency, amplitude); + xtract_f0(table, blocksize, &samplerate, &result); + + THEN( "the detected F0 is accurate to the nearest MIDI cent" ) + { + actual = xttest_ftom(result); + expected = xttest_ftom(frequency); + CAPTURE( actual ); + CAPTURE( expected ); + REQUIRE(actual == expected); + } + } + } + } + GIVEN( "a 1024 sample block with a sample rate of 44100" ) { uint32_t blocksize = 1024; double samplerate = 44100; - double result = 0.0; + double result = -1.0; double table[blocksize]; - WHEN( "the frequency is 344.53125 Hz" ) // This will give a period of exactly 128 samples: 8 cycles in the block + WHEN( "the frequency is 86.1328125 Hz" ) // period of exactly 512 samples: 2 cycles in the block + { + double frequency = 86.1328125; + double amplitude = 1.0; + + xttest_gen_sine(table, blocksize, samplerate, frequency, amplitude); + int rv = xtract_f0(table, blocksize, &samplerate, &result); + + THEN( "frequency detection fails correctly (XTRACT_NO_RESULT is returned, result set to 0.0)" ) + { + REQUIRE(rv == XTRACT_NO_RESULT); + REQUIRE(result == 0.0); + } + } + + WHEN( "the frequency is 172.265625 Hz" ) // period of exactly 256 samples: 4 cycles in the block + { + double frequency = 172.265625; + double amplitude = 1.0; + + xttest_gen_sine(table, blocksize, samplerate, frequency, amplitude); + xtract_f0(table, blocksize, &samplerate, &result); + + THEN( "the detected F0 is accurate to the nearest MIDI cent" ) + { + actual = xttest_ftom(result); + expected = xttest_ftom(frequency); + CAPTURE( actual ); + CAPTURE( expected ); + REQUIRE(actual == expected); + } + } + + WHEN( "the frequency is 344.53125 Hz" ) // period of exactly 128 samples: 8 cycles in the block { double frequency = 344.53125; - double min = frequency * 0.995; - double max = frequency * 1.005; + expected = xttest_ftom(frequency); + CAPTURE( expected ); WHEN( "the amplitude is 1.0" ) { @@ -27,28 +136,370 @@ SCENARIO( "F0 is correctly detected for a clean sine wave", "[xtract_f0]" ) xttest_gen_sine(table, blocksize, samplerate, frequency, amplitude); xtract_f0(table, blocksize, &samplerate, &result); - CAPTURE( result ); - THEN( "the detected F0 is in the range 344.53125 ± 0.5%" ) + THEN( "the detected F0 is accurate to the nearest MIDI cent" ) { - REQUIRE(result < max); - REQUIRE(result > min); + actual = xttest_ftom(result); + CAPTURE( actual ); + REQUIRE(actual == expected); } } - WHEN( "the amplitude is 0.1" ) + + WHEN( "the amplitude is 0.01" ) // Only test a different amplitude for one case { - double amplitude = 0.1; + double amplitude = 0.01; xttest_gen_sine(table, blocksize, samplerate, frequency, amplitude); xtract_f0(table, blocksize, &samplerate, &result); - CAPTURE( result ); - THEN( "the detected F0 is in the range 344.53125 ± 0.5%" ) + THEN( "the detected F0 is accurate to the nearest MIDI cent" ) { - REQUIRE(result < max); - REQUIRE(result > min); + actual = xttest_ftom(result); + CAPTURE( actual ); + REQUIRE(actual == expected); } } + + WHEN( "white noise is added at 10%" ) // Only test noise for one case + { + double amplitude = 0.1; + double noise[blocksize]; + + xttest_gen_sine(table, blocksize, samplerate, frequency, 1.0 - amplitude); + xttest_gen_noise(noise, blocksize, amplitude); + xttest_add(table, noise, blocksize); + xtract_f0(table, blocksize, &samplerate, &result); + + THEN( "the detected F0 is accurate to the nearest MIDI cent" ) + { + actual = xttest_ftom(result); + CAPTURE( actual ); + REQUIRE(actual == expected); + } + } + + WHEN( "white noise is added at 20%" ) + { + double amplitude = 0.2; + double noise[blocksize]; + + xttest_gen_sine(table, blocksize, samplerate, frequency, 1.0 - amplitude); + xttest_gen_noise(noise, blocksize, amplitude); + xttest_add(table, noise, blocksize); + xtract_f0(table, blocksize, &samplerate, &result); + + THEN( "the detected F0 is accurate to the nearest MIDI cent" ) + { + actual = xttest_ftom(result); + CAPTURE( actual ); + REQUIRE(actual == expected); + } + } + + WHEN( "white noise is added at 25%" ) + { + double amplitude = 0.25; + double noise[blocksize]; + + xttest_gen_sine(table, blocksize, samplerate, frequency, 1.0 - amplitude); + xttest_gen_noise(noise, blocksize, amplitude); + xttest_add(table, noise, blocksize); + xtract_f0(table, blocksize, &samplerate, &result); + + THEN( "the detected F0 is accurate to the nearest semitone" ) + { + actual = xttest_ftom(result); + uint16_t min = expected - 100; + uint16_t max = expected + 100; + CAPTURE( actual ); + REQUIRE( actual > min ); + REQUIRE( actual < max ); + } + } + + WHEN( "white noise is added at 30%" ) + { + double amplitude = 0.25; + double noise[blocksize]; + + xttest_gen_sine(table, blocksize, samplerate, frequency, 1.0 - amplitude); + xttest_gen_noise(noise, blocksize, amplitude); + xttest_add(table, noise, blocksize); + xtract_f0(table, blocksize, &samplerate, &result); + + THEN( "the detected F0 is accurate to the nearest quarter-tone" ) + { + actual = xttest_ftom(result); + uint16_t min = expected - 50; + uint16_t max = expected + 50; + CAPTURE( actual ); + REQUIRE( actual > min ); + REQUIRE( actual < max ); + } + } + + WHEN( "white noise is added at 35%" ) + { + double amplitude = 0.35; + double noise[blocksize]; + + xttest_gen_sine(table, blocksize, samplerate, frequency, 1.0 - amplitude); + xttest_gen_noise(noise, blocksize, amplitude); + xttest_add(table, noise, blocksize); + xtract_f0(table, blocksize, &samplerate, &result); + + THEN( "the detected F0 is inaccurate by more than one semitone" ) + { + actual = xttest_ftom(result); + uint16_t difference = abs(expected - actual); + CAPTURE( actual ); + REQUIRE( difference > 100 ); + } + } + } + } + + GIVEN( "a 1024 sample block with a sample rate of 11025" ) + { + uint32_t blocksize = 1024; + double samplerate = 11025; + double result = -1.0; + double table[blocksize]; + + WHEN( "the frequency is 86.1328125 Hz" ) // period of exactly 512 samples: 2 cycles in the block + { + double frequency = 86.1328125; + double amplitude = 1.0; + + xttest_gen_sine(table, blocksize, samplerate, frequency, amplitude); + int rv = xtract_f0(table, blocksize, &samplerate, &result); + + THEN( "the detected F0 is accurate to the nearest MIDI cent" ) + { + actual = xttest_ftom(result); + expected = xttest_ftom(frequency); + CAPTURE( actual ); + CAPTURE( expected ); + REQUIRE(actual == expected); + } + } + + WHEN( "the frequency is 172.265625 Hz" ) // period of exactly 256 samples: 4 cycles in the block + { + double frequency = 172.265625; + double amplitude = 1.0; + + xttest_gen_sine(table, blocksize, samplerate, frequency, amplitude); + xtract_f0(table, blocksize, &samplerate, &result); + + THEN( "the detected F0 is accurate to the nearest MIDI cent" ) + { + actual = xttest_ftom(result); + expected = xttest_ftom(frequency); + CAPTURE( actual ); + CAPTURE( expected ); + REQUIRE(actual == expected); + } + } + + WHEN( "the frequency is 344.53125 Hz" ) // period of exactly 128 samples: 8 cycles in the block + { + double frequency = 344.53125; + expected = xttest_ftom(frequency); + CAPTURE( expected ); + + WHEN( "the amplitude is 1.0" ) + { + double amplitude = 1.0; + + xttest_gen_sine(table, blocksize, samplerate, frequency, amplitude); + xtract_f0(table, blocksize, &samplerate, &result); + + THEN( "the detected F0 is accurate to the nearest MIDI cent" ) + { + actual = xttest_ftom(result); + CAPTURE( actual ); + REQUIRE(actual == expected); + } + } + + WHEN( "the amplitude is 0.01" ) // Only test a different amplitude for one case + { + double amplitude = 0.01; + + xttest_gen_sine(table, blocksize, samplerate, frequency, amplitude); + xtract_f0(table, blocksize, &samplerate, &result); + + THEN( "the detected F0 is accurate to the nearest MIDI cent" ) + { + actual = xttest_ftom(result); + CAPTURE( actual ); + REQUIRE(actual == expected); + } + } + + WHEN( "white noise is added at 20%" ) + { + double amplitude = 0.2; + double noise[blocksize]; + + xttest_gen_sine(table, blocksize, samplerate, frequency, 1.0 - amplitude); + xttest_gen_noise(noise, blocksize, amplitude); + xttest_add(table, noise, blocksize); + xtract_f0(table, blocksize, &samplerate, &result); + + THEN( "the detected F0 is accurate to the nearest quarter-tone" ) + { + actual = xttest_ftom(result); + uint16_t min = expected - 50; + uint16_t max = expected + 50; + CAPTURE( actual ); + REQUIRE( actual > min ); + REQUIRE( actual < max ); + } + } + + WHEN( "white noise is added at 40%" ) + { + double amplitude = 0.4; + double noise[blocksize]; + + xttest_gen_sine(table, blocksize, samplerate, frequency, 1.0 - amplitude); + xttest_gen_noise(noise, blocksize, amplitude); + xttest_add(table, noise, blocksize); + xtract_f0(table, blocksize, &samplerate, &result); + + THEN( "the detected F0 is accurate to the nearest semi-tone" ) + { + actual = xttest_ftom(result); + uint16_t min = expected - 100; + uint16_t max = expected + 100; + CAPTURE( actual ); + REQUIRE( actual > min ); + REQUIRE( actual < max ); + } + } + + WHEN( "white noise is added at 60%" ) + { + double amplitude = 0.6; + double noise[blocksize]; + + xttest_gen_sine(table, blocksize, samplerate, frequency, 1.0 - amplitude); + xttest_gen_noise(noise, blocksize, amplitude); + xttest_add(table, noise, blocksize); + xtract_f0(table, blocksize, &samplerate, &result); + + THEN( "the detected F0 is accurate to the nearest semi-tone" ) + { + actual = xttest_ftom(result); + uint16_t min = expected - 100; + uint16_t max = expected + 100; + CAPTURE( actual ); + REQUIRE( actual > min ); + REQUIRE( actual < max ); + } + } + + WHEN( "white noise is added at 80%" ) + { + double amplitude = 0.8; + double noise[blocksize]; + + xttest_gen_sine(table, blocksize, samplerate, frequency, 1.0 - amplitude); + xttest_gen_noise(noise, blocksize, amplitude); + xttest_add(table, noise, blocksize); + xtract_f0(table, blocksize, &samplerate, &result); + + THEN( "the detected F0 is inaccurate by more than one semitone" ) + { + actual = xttest_ftom(result); + uint16_t difference = abs(expected - actual); + CAPTURE( actual ); + REQUIRE( difference > 100 ); + } + } + } + } + + GIVEN( "a 2048 sample block with a sample rate of 44100" ) + { + uint32_t blocksize = 2048; + double samplerate = 44100; + double result = -1.0; + double table[blocksize]; + + WHEN( "the frequency is 43.06640625 Hz" ) // period of exactly 256 samples: 2 cycles in the block + { + double frequency = 43.06640625; + double amplitude = 1.0; + + xttest_gen_sine(table, blocksize, samplerate, frequency, amplitude); + int rv = xtract_f0(table, blocksize, &samplerate, &result); + + THEN( "frequency detection fails correctly (XTRACT_NO_RESULT is returned, result set to 0.0)" ) + { + REQUIRE(rv == XTRACT_NO_RESULT); + REQUIRE(result == 0.0); + } + } + + WHEN( "the frequency is 86.1328125 Hz" ) // period of exactly 512 samples: 4 cycles in the block + { + double frequency = 86.1328125; + double amplitude = 1.0; + + xttest_gen_sine(table, blocksize, samplerate, frequency, amplitude); + int rv = xtract_f0(table, blocksize, &samplerate, &result); + + THEN( "the detected F0 is accurate to the nearest MIDI cent" ) + { + actual = xttest_ftom(result); + expected = xttest_ftom(frequency); + CAPTURE( actual ); + CAPTURE( expected ); + REQUIRE(actual == expected); + } + } + + WHEN( "the frequency is 172.265625 Hz" ) // period of exactly 256 samples: 8 cycles in the block + { + double frequency = 172.265625; + double amplitude = 1.0; + + xttest_gen_sine(table, blocksize, samplerate, frequency, amplitude); + xtract_f0(table, blocksize, &samplerate, &result); + + THEN( "the detected F0 is accurate to the nearest MIDI cent" ) + { + actual = xttest_ftom(result); + expected = xttest_ftom(frequency); + CAPTURE( actual ); + CAPTURE( expected ); + REQUIRE(actual == expected); + } + } + + WHEN( "the frequency is 344.53125 Hz" ) // period of exactly 128 samples: 16 cycles in the block + { + double frequency = 344.53125; + + WHEN( "the amplitude is 1.0" ) + { + double amplitude = 1.0; + + xttest_gen_sine(table, blocksize, samplerate, frequency, amplitude); + xtract_f0(table, blocksize, &samplerate, &result); + + THEN( "the detected F0 is accurate to the nearest MIDI cent" ) + { + actual = xttest_ftom(result); + expected = xttest_ftom(frequency); + CAPTURE( actual ); + CAPTURE( expected ); + REQUIRE(actual == expected); + } + } } } } |