From 96fd3d9c67d971c6cc36e2aec4c8a0540affae7f Mon Sep 17 00:00:00 2001 From: Paul Ferrand Date: Sun, 14 Jun 2020 17:55:38 +0200 Subject: [PATCH] Move the "synth" tests mostly to inline files Easier to read --- tests/SynthT.cpp | 176 +++++++++--------- tests/TestFiles/Effects/base.sfz | 4 - tests/TestFiles/Effects/bitcrusher_1.sfz | 9 - tests/TestFiles/Effects/bitcrusher_2.sfz | 13 -- tests/TestFiles/Effects/bitcrusher_3.sfz | 13 -- tests/TestFiles/Effects/to_mix.sfz | 12 -- tests/TestFiles/curves.sfz | 10 - tests/TestFiles/envelope_one_shot.sfz | 12 -- tests/TestFiles/envelope_trigger_release.sfz | 13 -- .../envelope_trigger_release_key.sfz | 13 -- tests/TestFiles/master_polyphony.sfz | 7 - tests/TestFiles/polyphony.sfz | 5 - tests/TestFiles/sound_off.sfz | 2 - tests/TestFiles/velocity_endpoints.sfz | 2 - 14 files changed, 84 insertions(+), 207 deletions(-) delete mode 100644 tests/TestFiles/Effects/base.sfz delete mode 100644 tests/TestFiles/Effects/bitcrusher_1.sfz delete mode 100644 tests/TestFiles/Effects/bitcrusher_2.sfz delete mode 100644 tests/TestFiles/Effects/bitcrusher_3.sfz delete mode 100644 tests/TestFiles/Effects/to_mix.sfz delete mode 100644 tests/TestFiles/curves.sfz delete mode 100644 tests/TestFiles/envelope_one_shot.sfz delete mode 100644 tests/TestFiles/envelope_trigger_release.sfz delete mode 100644 tests/TestFiles/envelope_trigger_release_key.sfz delete mode 100644 tests/TestFiles/master_polyphony.sfz delete mode 100644 tests/TestFiles/polyphony.sfz delete mode 100644 tests/TestFiles/sound_off.sfz delete mode 100644 tests/TestFiles/velocity_endpoints.sfz diff --git a/tests/SynthT.cpp b/tests/SynthT.cpp index 08112bef..0d8918e3 100644 --- a/tests/SynthT.cpp +++ b/tests/SynthT.cpp @@ -124,7 +124,10 @@ TEST_CASE("[Synth] All notes offs/all sounds off") { sfz::Synth synth; synth.setNumVoices(8); - synth.loadSfzFile(fs::current_path() / "tests/TestFiles/sound_off.sfz"); + synth.loadSfzString(fs::current_path(), R"( + key=60 sample=*noise + key=62 sample=*noise + )"); synth.noteOn(0, 60, 63); synth.noteOn(0, 62, 63); REQUIRE( synth.getNumActiveVoices() == 2 ); @@ -152,15 +155,20 @@ TEST_CASE("[Synth] Releasing before the EG started smoothing (initial delay) kil { sfz::Synth synth; synth.setSamplesPerBlock(1024); + sfz::AudioBuffer buffer { 2, 1024 }; synth.setNumVoices(1); - synth.loadSfzFile(fs::current_path() / "tests/TestFiles/delay_release.sfz"); + synth.loadSfzString(fs::current_path(), R"( + ampeg_delay=0.005 ampeg_release=1 sample=*noise + )"); synth.noteOn(0, 60, 63); REQUIRE( !synth.getVoiceView(0)->isFree() ); synth.noteOff(100, 60, 63); + synth.renderBlock(buffer); REQUIRE( synth.getVoiceView(0)->isFree() ); synth.noteOn(200, 60, 63); REQUIRE( !synth.getVoiceView(0)->isFree() ); synth.noteOff(1000, 60, 63); + synth.renderBlock(buffer); REQUIRE( !synth.getVoiceView(0)->isFree() ); } @@ -170,7 +178,9 @@ TEST_CASE("[Synth] Releasing after the initial and normal mode does not trigger synth.setSamplesPerBlock(1024); sfz::AudioBuffer buffer(2, 1024); synth.setNumVoices(1); - synth.loadSfzFile(fs::current_path() / "tests/TestFiles/delay_release.sfz"); + synth.loadSfzString(fs::current_path(), R"( + ampeg_delay=0.005 ampeg_release=1 sample=*noise + )"); synth.noteOn(200, 60, 63); REQUIRE( !synth.getVoiceView(0)->isFree() ); synth.renderBlock(buffer); @@ -187,7 +197,11 @@ TEST_CASE("[Synth] Trigger=release and an envelope properly kills the voice at t synth.setSamplesPerBlock(480); sfz::AudioBuffer buffer(2, 480); synth.setNumVoices(1); - synth.loadSfzFile(fs::current_path() / "tests/TestFiles/envelope_trigger_release.sfz"); + synth.loadSfzString(fs::current_path(), R"( + lovel=0 hivel=127 + trigger=release sample=*noise loop_mode=one_shot + ampeg_attack=0.02 ampeg_decay=0.02 ampeg_release=0.1 ampeg_sustain=0 + )"); synth.noteOn(0, 60, 63); synth.noteOff(0, 60, 63); REQUIRE( !synth.getVoiceView(0)->isFree() ); @@ -210,7 +224,11 @@ TEST_CASE("[Synth] Trigger=release_key and an envelope properly kills the voice synth.setSamplesPerBlock(480); sfz::AudioBuffer buffer(2, 480); synth.setNumVoices(1); - synth.loadSfzFile(fs::current_path() / "tests/TestFiles/envelope_trigger_release_key.sfz"); + synth.loadSfzString(fs::current_path(), R"( + lovel=0 hivel=127 + trigger=release_key sample=*noise loop_mode=one_shot + ampeg_attack=0.02 ampeg_decay=0.02 ampeg_release=0.1 ampeg_sustain=0 + )"); synth.noteOn(0, 60, 63); synth.noteOff(0, 60, 63); REQUIRE( !synth.getVoiceView(0)->isFree() ); @@ -233,7 +251,11 @@ TEST_CASE("[Synth] loopmode=one_shot and an envelope properly kills the voice at synth.setSamplesPerBlock(480); sfz::AudioBuffer buffer(2, 480); synth.setNumVoices(1); - synth.loadSfzFile(fs::current_path() / "tests/TestFiles/envelope_one_shot.sfz"); + synth.loadSfzString(fs::current_path(), R"( + lovel=0 hivel=127 + sample=*noise loop_mode=one_shot + ampeg_attack=0.02 ampeg_decay=0.02 ampeg_release=0.1 ampeg_sustain=0 + )"); synth.noteOn(0, 60, 63); synth.noteOff(0, 60, 63); REQUIRE( !synth.getVoiceView(0)->isFree() ); @@ -256,27 +278,37 @@ TEST_CASE("[Synth] Number of effect buses and resetting behavior") sfz::AudioBuffer buffer { 2, blockSize }; REQUIRE( synth.getEffectBusView(0) == nullptr); // No effects at first - synth.loadSfzFile(fs::current_path() / "tests/TestFiles/Effects/base.sfz"); + synth.loadSfzString(fs::current_path(), R"( + lokey=0 hikey=127 sample=*sine + )"); REQUIRE( synth.getEffectBusView(0) != nullptr); // We have a main bus // Check that we can render blocks for (int i = 0; i < 100; ++i) synth.renderBlock(buffer); - synth.loadSfzFile(fs::current_path() / "tests/TestFiles/Effects/bitcrusher_2.sfz"); + synth.loadSfzString(fs::current_path(), R"( + lokey=0 hikey=127 sample=*sine effect1=100 + directtomain=50 fx1tomain=50 type=lofi bus=fx1 bitred=90 decim=10 + )"); REQUIRE( synth.getEffectBusView(0) != nullptr); // We have a main bus REQUIRE( synth.getEffectBusView(1) != nullptr); // and an FX bus // Check that we can render blocks for (int i = 0; i < 100; ++i) synth.renderBlock(buffer); - synth.loadSfzFile(fs::current_path() / "tests/TestFiles/Effects/base.sfz"); + synth.loadSfzString(fs::current_path(), R"( + lokey=0 hikey=127 sample=*sine + )"); REQUIRE( synth.getEffectBusView(0) != nullptr); // We have a main bus REQUIRE( synth.getEffectBusView(1) == nullptr); // and no FX bus // Check that we can render blocks for (int i = 0; i < 100; ++i) synth.renderBlock(buffer); - synth.loadSfzFile(fs::current_path() / "tests/TestFiles/Effects/bitcrusher_3.sfz"); + synth.loadSfzString(fs::current_path(), R"( + lokey=0 hikey=127 sample=*sine effect1=100 + directtomain=50 fx3tomain=50 type=lofi bus=fx3 bitred=90 decim=10 + )"); REQUIRE( synth.getEffectBusView(0) != nullptr); // We have a main bus REQUIRE( synth.getEffectBusView(1) == nullptr); // empty/uninitialized fx bus REQUIRE( synth.getEffectBusView(2) == nullptr); // empty/uninitialized fx bus @@ -290,7 +322,9 @@ TEST_CASE("[Synth] Number of effect buses and resetting behavior") TEST_CASE("[Synth] No effect in the main bus") { sfz::Synth synth; - synth.loadSfzFile(fs::current_path() / "tests/TestFiles/Effects/base.sfz"); + synth.loadSfzString(fs::current_path(), R"( + lokey=0 hikey=127 sample=*sine + )"); auto bus = synth.getEffectBusView(0); REQUIRE( bus != nullptr); // We have a main bus REQUIRE( bus->numEffects() == 0 ); @@ -301,7 +335,10 @@ TEST_CASE("[Synth] No effect in the main bus") TEST_CASE("[Synth] One effect") { sfz::Synth synth; - synth.loadSfzFile(fs::current_path() / "tests/TestFiles/Effects/bitcrusher_1.sfz"); + synth.loadSfzString(fs::current_path(), R"( + lokey=0 hikey=127 sample=*sine + type=lofi bitred=90 decim=10 + )"); auto bus = synth.getEffectBusView(0); REQUIRE( bus != nullptr); // We have a main bus REQUIRE( bus->numEffects() == 1 ); @@ -312,7 +349,10 @@ TEST_CASE("[Synth] One effect") TEST_CASE("[Synth] Effect on a second bus") { sfz::Synth synth; - synth.loadSfzFile(fs::current_path() / "tests/TestFiles/Effects/bitcrusher_2.sfz"); + synth.loadSfzString(fs::current_path(), R"( + lokey=0 hikey=127 sample=*sine effect1=100 + directtomain=50 fx1tomain=50 type=lofi bus=fx1 bitred=90 decim=10 + )"); auto bus = synth.getEffectBusView(0); REQUIRE( bus != nullptr); // We have a main bus REQUIRE( bus->numEffects() == 0 ); @@ -329,7 +369,10 @@ TEST_CASE("[Synth] Effect on a second bus") TEST_CASE("[Synth] Effect on a third bus") { sfz::Synth synth; - synth.loadSfzFile(fs::current_path() / "tests/TestFiles/Effects/bitcrusher_3.sfz"); + synth.loadSfzString(fs::current_path(), R"( + lokey=0 hikey=127 sample=*sine effect1=100 + directtomain=50 fx3tomain=50 type=lofi bus=fx3 bitred=90 decim=10 + )"); auto bus = synth.getEffectBusView(0); REQUIRE( bus != nullptr); // We have a main bus REQUIRE( bus->numEffects() == 0 ); @@ -345,7 +388,10 @@ TEST_CASE("[Synth] Effect on a third bus") TEST_CASE("[Synth] Gain to mix") { sfz::Synth synth; - synth.loadSfzFile(fs::current_path() / "tests/TestFiles/Effects/to_mix.sfz"); + synth.loadSfzString(fs::current_path(), R"( + lokey=0 hikey=127 sample=*sine effect1=100 + fx1tomix=50 bus=fx1 type=lofi bitred=90 decim=10 + )"); auto bus = synth.getEffectBusView(0); REQUIRE( bus != nullptr); // We have a main bus REQUIRE( bus->numEffects() == 0 ); @@ -358,75 +404,15 @@ TEST_CASE("[Synth] Gain to mix") REQUIRE( bus->gainToMix() == 0.5 ); } -TEST_CASE("[Synth] group polyphony limits") -{ - sfz::Synth synth; - synth.loadSfzFile(fs::current_path() / "tests/TestFiles/polyphony.sfz"); - synth.noteOn(0, 65, 64); - synth.noteOn(0, 65, 64); - synth.noteOn(0, 65, 64); - REQUIRE(synth.getNumActiveVoices() == 2); // group polyphony should block the last note -} - -TEST_CASE("[Synth] Self-masking") -{ - sfz::Synth synth; - synth.loadSfzFile(fs::current_path() / "tests/TestFiles/polyphony.sfz"); - synth.noteOn(0, 64, 63); - synth.noteOn(0, 64, 62); - synth.noteOn(0, 64, 64); - REQUIRE(synth.getNumActiveVoices() == 3); // One of these is releasing - REQUIRE(synth.getVoiceView(0)->getTriggerValue() == 63_norm); - REQUIRE(!synth.getVoiceView(0)->releasedOrFree()); - REQUIRE(synth.getVoiceView(1)->getTriggerValue() == 62_norm); - REQUIRE(synth.getVoiceView(1)->releasedOrFree()); // The lowest velocity voice is the masking candidate - REQUIRE(synth.getVoiceView(2)->getTriggerValue() == 64_norm); - REQUIRE(!synth.getVoiceView(2)->releasedOrFree()); -} - -TEST_CASE("[Synth] Not self-masking") -{ - sfz::Synth synth; - synth.loadSfzFile(fs::current_path() / "tests/TestFiles/polyphony.sfz"); - synth.noteOn(0, 66, 63); - synth.noteOn(0, 66, 62); - synth.noteOn(0, 66, 64); - REQUIRE(synth.getNumActiveVoices() == 3); // One of these is releasing - REQUIRE(synth.getVoiceView(0)->getTriggerValue() == 63_norm); - REQUIRE(synth.getVoiceView(0)->releasedOrFree()); // The first encountered voice is the masking candidate - REQUIRE(synth.getVoiceView(1)->getTriggerValue() == 62_norm); - REQUIRE(!synth.getVoiceView(1)->releasedOrFree()); - REQUIRE(synth.getVoiceView(2)->getTriggerValue() == 64_norm); - REQUIRE(!synth.getVoiceView(2)->releasedOrFree()); -} - -TEST_CASE("[Synth] Polyphony in master") -{ - sfz::Synth synth; - synth.loadSfzFile(fs::current_path() / "tests/TestFiles/master_polyphony.sfz"); - synth.noteOn(0, 65, 64); - synth.noteOn(0, 65, 64); - synth.noteOn(0, 65, 64); - REQUIRE(synth.getNumActiveVoices() == 2); // group polyphony should block the last note - synth.allSoundOff(); - REQUIRE(synth.getNumActiveVoices() == 0); - synth.noteOn(0, 63, 64); - synth.noteOn(0, 63, 64); - synth.noteOn(0, 63, 64); - REQUIRE(synth.getNumActiveVoices() == 2); // group polyphony should block the last note - synth.allSoundOff(); - REQUIRE(synth.getNumActiveVoices() == 0); - synth.noteOn(0, 61, 64); - synth.noteOn(0, 61, 64); - synth.noteOn(0, 61, 64); - REQUIRE(synth.getNumActiveVoices() == 3); -} - TEST_CASE("[Synth] Basic curves") { sfz::Synth synth; const auto& curves = synth.getResources().curves; - synth.loadSfzFile(fs::current_path() / "tests/TestFiles/curves.sfz"); + synth.loadSfzString(fs::current_path(), R"( + sample=*sine + curve_index=18 v000=0 v095=0.5 v127=1 + curve_index=17 v000=0 v095=0.5 v100=1 + )"); REQUIRE( synth.getNumCurves() == 19 ); REQUIRE( curves.getCurve(18).evalCC7(127) == 1.0f ); REQUIRE( curves.getCurve(18).evalCC7(95) == 0.5f ); @@ -439,7 +425,10 @@ TEST_CASE("[Synth] Basic curves") TEST_CASE("[Synth] Velocity points") { sfz::Synth synth; - synth.loadSfzFile(fs::current_path() / "tests/TestFiles/velocity_endpoints.sfz"); + synth.loadSfzString(fs::current_path(), R"( + amp_velcurve_064=1 sample=*sine + amp_velcurve_064=1 amp_veltrack=-100 sample=*sine + )"); REQUIRE( !synth.getRegionView(0)->velocityPoints.empty()); REQUIRE( synth.getRegionView(0)->velocityPoints[0].first == 64 ); REQUIRE( synth.getRegionView(0)->velocityPoints[0].second == 1.0_a ); @@ -451,7 +440,10 @@ TEST_CASE("[Synth] Velocity points") TEST_CASE("[Synth] velcurve") { sfz::Synth synth; - synth.loadSfzFile(fs::current_path() / "tests/TestFiles/velocity_endpoints.sfz"); + synth.loadSfzString(fs::current_path(), R"( + amp_velcurve_064=1 sample=*sine + amp_velcurve_064=1 amp_veltrack=-100 sample=*sine + )"); REQUIRE( synth.getRegionView(0)->velocityCurve(0_norm) == 0.0_a ); REQUIRE( synth.getRegionView(0)->velocityCurve(32_norm) == Approx(0.5f).margin(1e-2) ); REQUIRE( synth.getRegionView(0)->velocityCurve(64_norm) == 1.0_a ); @@ -468,13 +460,13 @@ TEST_CASE("[Synth] Region by identifier") { sfz::Synth synth; synth.loadSfzString("regionByIdentifier.sfz", R"( -sample=*sine -sample=*sine -sample=doesNotExist.wav -sample=*sine -sample=doesNotExist.wav -sample=*sine -)"); + sample=*sine + sample=*sine + sample=doesNotExist.wav + sample=*sine + sample=doesNotExist.wav + sample=*sine + )"); REQUIRE(synth.getNumRegions() == 4); REQUIRE(synth.getRegionView(0) == synth.getRegionById(NumericId{0})); @@ -492,9 +484,9 @@ TEST_CASE("[Synth] sample quality") sfz::Synth synth; synth.loadSfzString("tests/TestFiles/sampleQuality.sfz", R"( - sample=kick.wav key=60 - sample=kick.wav key=61 sample_quality=5 -)"); + sample=kick.wav key=60 + sample=kick.wav key=61 sample_quality=5 + )"); // default sample quality synth.noteOn(0, 60, 100); diff --git a/tests/TestFiles/Effects/base.sfz b/tests/TestFiles/Effects/base.sfz deleted file mode 100644 index 07b3874d..00000000 --- a/tests/TestFiles/Effects/base.sfz +++ /dev/null @@ -1,4 +0,0 @@ - -lokey=0 -hikey=127 -sample=*sine diff --git a/tests/TestFiles/Effects/bitcrusher_1.sfz b/tests/TestFiles/Effects/bitcrusher_1.sfz deleted file mode 100644 index dd28c5c4..00000000 --- a/tests/TestFiles/Effects/bitcrusher_1.sfz +++ /dev/null @@ -1,9 +0,0 @@ - -lokey=0 -hikey=127 -sample=*sine - - -type=lofi -bitred=90 -decim=10 diff --git a/tests/TestFiles/Effects/bitcrusher_2.sfz b/tests/TestFiles/Effects/bitcrusher_2.sfz deleted file mode 100644 index a0544f26..00000000 --- a/tests/TestFiles/Effects/bitcrusher_2.sfz +++ /dev/null @@ -1,13 +0,0 @@ - -lokey=0 -hikey=127 -sample=*sine -effect1=100 - - -directtomain=50 -fx1tomain=50 -type=lofi -bus=fx1 -bitred=90 -decim=10 diff --git a/tests/TestFiles/Effects/bitcrusher_3.sfz b/tests/TestFiles/Effects/bitcrusher_3.sfz deleted file mode 100644 index 51585e31..00000000 --- a/tests/TestFiles/Effects/bitcrusher_3.sfz +++ /dev/null @@ -1,13 +0,0 @@ - -lokey=0 -hikey=127 -sample=*sine -effect1=100 - - -directtomain=50 -fx3tomain=50 -type=lofi -bus=fx3 -bitred=90 -decim=10 diff --git a/tests/TestFiles/Effects/to_mix.sfz b/tests/TestFiles/Effects/to_mix.sfz deleted file mode 100644 index 65cd1837..00000000 --- a/tests/TestFiles/Effects/to_mix.sfz +++ /dev/null @@ -1,12 +0,0 @@ - -lokey=0 -hikey=127 -sample=*sine -effect1=100 - - -fx1tomix=50 -bus=fx1 -type=lofi -bitred=90 -decim=10 diff --git a/tests/TestFiles/curves.sfz b/tests/TestFiles/curves.sfz deleted file mode 100644 index 8c24cca4..00000000 --- a/tests/TestFiles/curves.sfz +++ /dev/null @@ -1,10 +0,0 @@ - sample=*sine -curve_index=18 -v000=0 -v095=0.5 -v127=1 - -curve_index=17 -v000=0 -v095=0.5 -v100=1 diff --git a/tests/TestFiles/envelope_one_shot.sfz b/tests/TestFiles/envelope_one_shot.sfz deleted file mode 100644 index 6d820825..00000000 --- a/tests/TestFiles/envelope_one_shot.sfz +++ /dev/null @@ -1,12 +0,0 @@ - - -lovel=0 -hivel=127 - - -sample=*noise -loop_mode=one_shot -ampeg_attack=0.02 -ampeg_decay=0.02 -ampeg_release=0.1 -ampeg_sustain=0 diff --git a/tests/TestFiles/envelope_trigger_release.sfz b/tests/TestFiles/envelope_trigger_release.sfz deleted file mode 100644 index e595433e..00000000 --- a/tests/TestFiles/envelope_trigger_release.sfz +++ /dev/null @@ -1,13 +0,0 @@ - - -lovel=0 -hivel=127 - - -trigger=release -sample=*noise -loop_mode=one_shot -ampeg_attack=0.02 -ampeg_decay=0.02 -ampeg_release=0.1 -ampeg_sustain=0 diff --git a/tests/TestFiles/envelope_trigger_release_key.sfz b/tests/TestFiles/envelope_trigger_release_key.sfz deleted file mode 100644 index 0eae14d6..00000000 --- a/tests/TestFiles/envelope_trigger_release_key.sfz +++ /dev/null @@ -1,13 +0,0 @@ - - -lovel=0 -hivel=127 - - -trigger=release_key -sample=*noise -loop_mode=one_shot -ampeg_attack=0.02 -ampeg_decay=0.02 -ampeg_release=0.1 -ampeg_sustain=0 diff --git a/tests/TestFiles/master_polyphony.sfz b/tests/TestFiles/master_polyphony.sfz deleted file mode 100644 index 88d7bd7a..00000000 --- a/tests/TestFiles/master_polyphony.sfz +++ /dev/null @@ -1,7 +0,0 @@ - polyphony=2 - group=2 - sample=*sine key=65 - group=3 - sample=*sine key=63 - // Empty master resets the polyphony - sample=*sine key=61 diff --git a/tests/TestFiles/polyphony.sfz b/tests/TestFiles/polyphony.sfz deleted file mode 100644 index 32aed2e9..00000000 --- a/tests/TestFiles/polyphony.sfz +++ /dev/null @@ -1,5 +0,0 @@ - sample=*sine key=63 - sample=*sine key=64 note_polyphony=2 - sample=*sine key=66 note_polyphony=2 note_selfmask=off - group=1 polyphony=2 - sample=*sine key=65 diff --git a/tests/TestFiles/sound_off.sfz b/tests/TestFiles/sound_off.sfz deleted file mode 100644 index b7b09c95..00000000 --- a/tests/TestFiles/sound_off.sfz +++ /dev/null @@ -1,2 +0,0 @@ - key=60 sample=dummy1.wav - key=62 sample=dummy2.wav diff --git a/tests/TestFiles/velocity_endpoints.sfz b/tests/TestFiles/velocity_endpoints.sfz deleted file mode 100644 index dd3808d7..00000000 --- a/tests/TestFiles/velocity_endpoints.sfz +++ /dev/null @@ -1,2 +0,0 @@ - amp_velcurve_064=1 sample=*sine - amp_velcurve_064=1 amp_veltrack=-100 sample=*sine