Region Activation tests

This commit is contained in:
paul 2019-08-11 13:31:16 +02:00
parent fbefc2c84e
commit 70923b1478
4 changed files with 293 additions and 8 deletions

View file

@ -75,8 +75,10 @@ bool sfz::Region::parseOpcode(const Opcode& opcode)
case hash("lobend"): setRangeStartFromOpcode(opcode, bendRange, Default::bendRange); break;
case hash("hibend"): setRangeEndFromOpcode(opcode, bendRange, Default::bendRange); break;
case hash("locc"):
if (opcode.parameter)
setRangeStartFromOpcode(opcode, ccConditions[*opcode.parameter], Default::ccRange);
if (opcode.parameter)
{
setRangeStartFromOpcode(opcode, ccConditions[*opcode.parameter], Default::ccRange);
}
break;
case hash("hicc"):
if (opcode.parameter)
@ -84,10 +86,19 @@ bool sfz::Region::parseOpcode(const Opcode& opcode)
break;
case hash("sw_lokey"): setRangeStartFromOpcode(opcode, keyswitchRange, Default::keyRange); break;
case hash("sw_hikey"): setRangeEndFromOpcode(opcode, keyswitchRange, Default::keyRange); break;
case hash("sw_last"): setValueFromOpcode(opcode, keyswitch, Default::keyRange); break;
case hash("sw_down"): setValueFromOpcode(opcode, keyswitchDown, Default::keyRange); break;
case hash("sw_last"):
setValueFromOpcode(opcode, keyswitch, Default::keyRange);
keySwitched = false;
break;
case hash("sw_down"):
setValueFromOpcode(opcode, keyswitchDown, Default::keyRange);
keySwitched = false;
break;
case hash("sw_up"): setValueFromOpcode(opcode, keyswitchUp, Default::keyRange); break;
case hash("sw_previous"): setValueFromOpcode(opcode, previousNote, Default::keyRange); break;
case hash("sw_previous"):
setValueFromOpcode(opcode, previousNote, Default::keyRange);
previousKeySwitched = false;
break;
case hash("sw_vel"):
switch(hash(opcode.value))
{
@ -109,7 +120,10 @@ bool sfz::Region::parseOpcode(const Opcode& opcode)
case hash("lorand"): setRangeStartFromOpcode(opcode, randRange, Default::randRange); break;
case hash("hirand"): setRangeEndFromOpcode(opcode, randRange, Default::randRange); break;
case hash("seq_length"): setValueFromOpcode(opcode, sequenceLength, Default::sequenceRange); break;
case hash("seq_position"): setValueFromOpcode(opcode, sequencePosition, Default::sequenceRange); break;
case hash("seq_position"):
setValueFromOpcode(opcode, sequencePosition, Default::sequenceRange);
sequenceSwitched = (opcode.value == "1");
break;
// Region logic: triggers
case hash("trigger"):
switch(hash(opcode.value))

View file

@ -30,7 +30,6 @@ struct Region
void registerPitchWheel(int channel, int pitch);
void registerAftertouch(int channel, uint8_t aftertouch);
void registerTempo(float secondsPerQuarter);
bool prepare();
bool isStereo() const noexcept;
bool parseOpcode(const Opcode& opcode);
// Sound source: sample playback
@ -99,7 +98,6 @@ struct Region
SfzCrossfadeCurve crossfadeKeyCurve { Default::crossfadeKeyCurve };
SfzCrossfadeCurve crossfadeVelCurve { Default::crossfadeVelCurve };
// Performance parameters: pitch
uint8_t pitchKeycenter{Default::pitchKeycenter}; // pitch_keycenter
int pitchKeytrack{ Default::pitchKeytrack }; // pitch_keytrack

View file

@ -155,6 +155,7 @@ bool sfz::Synth::loadSfzFile(const std::filesystem::path& filename)
for (auto cc = region->keyRange.getStart(); cc <= region->keyRange.getEnd(); cc++)
ccActivationLists[cc].push_back(*currentRegion);
// Defaults
for (int ccIndex = 1; ccIndex < 128; ccIndex++)
region->registerCC(region->channelRange.getStart(), ccIndex, ccState[ccIndex]);
@ -163,6 +164,10 @@ bool sfz::Synth::loadSfzFile(const std::filesystem::path& filename)
region->registerNoteOn(region->channelRange.getStart(), *defaultSwitch, 127, 1.0);
region->registerNoteOff(region->channelRange.getStart(), *defaultSwitch, 0, 1.0);
}
region->registerPitchWheel(region->channelRange.getStart(), 0);
region->registerAftertouch(region->channelRange.getStart(), 0);
region->registerTempo(2.0f);
currentRegion++;
}

268
tests/RegionActivationT.cpp Normal file
View file

@ -0,0 +1,268 @@
#include "catch2/catch.hpp"
#include "../sources/Region.h"
using namespace Catch::literals;
TEST_CASE("Region activation", "Region tests")
{
sfz::Region region { };
region.parseOpcode({ "sample", "*sine" });
SECTION("Basic state")
{
region.registerCC(1, 4, 0);
REQUIRE( region.isSwitchedOn() );
}
SECTION("Single CC range")
{
region.parseOpcode({ "locc4", "56" });
region.parseOpcode({ "hicc4", "59" });
region.registerCC(1, 4, 0);
REQUIRE( !region.isSwitchedOn() );
region.registerCC(1, 4, 57);
REQUIRE( region.isSwitchedOn() );
region.registerCC(1, 4, 56);
REQUIRE( region.isSwitchedOn() );
region.registerCC(1, 4, 59);
REQUIRE( region.isSwitchedOn() );
region.registerCC(1, 4, 43);
REQUIRE( !region.isSwitchedOn() );
region.registerCC(1, 4, 65);
REQUIRE( !region.isSwitchedOn() );
region.registerCC(1, 6, 57);
REQUIRE( !region.isSwitchedOn() );
}
SECTION("Multiple CC ranges")
{
region.parseOpcode({ "locc4", "56" });
region.parseOpcode({ "hicc4", "59" });
region.parseOpcode({ "locc54", "18" });
region.parseOpcode({ "hicc54", "27" });
region.registerCC(1, 4, 0);
region.registerCC(1, 54, 0);
REQUIRE( !region.isSwitchedOn() );
region.registerCC(1, 4, 57);
REQUIRE( !region.isSwitchedOn() );
region.registerCC(1, 54, 19);
REQUIRE( region.isSwitchedOn() );
region.registerCC(1, 54, 18);
REQUIRE( region.isSwitchedOn() );
region.registerCC(1, 54, 27);
REQUIRE( region.isSwitchedOn() );
region.registerCC(1, 4, 56);
REQUIRE( region.isSwitchedOn() );
region.registerCC(1, 4, 59);
REQUIRE( region.isSwitchedOn() );
region.registerCC(1, 54, 2);
REQUIRE( !region.isSwitchedOn() );
region.registerCC(1, 54, 26);
REQUIRE( region.isSwitchedOn() );
region.registerCC(1, 4, 65);
REQUIRE( !region.isSwitchedOn() );
}
SECTION("Bend ranges")
{
region.parseOpcode({ "lobend", "56" });
region.parseOpcode({ "hibend", "243" });
region.registerPitchWheel(1, 0);
REQUIRE( !region.isSwitchedOn() );
region.registerPitchWheel(1, 56);
REQUIRE( region.isSwitchedOn() );
region.registerPitchWheel(1, 243);
REQUIRE( region.isSwitchedOn() );
region.registerPitchWheel(1, 245);
REQUIRE( !region.isSwitchedOn() );
}
SECTION("Aftertouch ranges")
{
region.parseOpcode({ "lochanaft", "56" });
region.parseOpcode({ "hichanaft", "68" });
region.registerAftertouch(1, 0);
REQUIRE( !region.isSwitchedOn() );
region.registerAftertouch(1, 56);
REQUIRE( region.isSwitchedOn() );
region.registerAftertouch(1, 68);
REQUIRE( region.isSwitchedOn() );
region.registerAftertouch(1, 98);
REQUIRE( !region.isSwitchedOn() );
}
SECTION("BPM ranges")
{
region.parseOpcode({ "lobpm", "56" });
region.parseOpcode({ "hibpm", "68" });
region.registerTempo(2.0f);
REQUIRE( !region.isSwitchedOn() );
region.registerTempo(0.90f);
REQUIRE( region.isSwitchedOn() );
region.registerTempo(1.01f);
REQUIRE( region.isSwitchedOn() );
region.registerTempo(1.1f);
REQUIRE( !region.isSwitchedOn() );
}
// TODO: add keyswitches
SECTION("Keyswitches: sw_last")
{
region.parseOpcode({ "sw_last", "40" });
REQUIRE( !region.isSwitchedOn() );
region.registerNoteOn(1, 40, 64, 0.5f);
REQUIRE( region.isSwitchedOn() );
region.registerNoteOff(1, 40, 64, 0.5f);
REQUIRE( region.isSwitchedOn() );
region.registerNoteOn(1, 41, 64, 0.5f);
REQUIRE( !region.isSwitchedOn() );
region.registerNoteOff(1, 41, 0, 0.5f);
}
SECTION("Keyswitches: sw_last with non-default keyswitch range")
{
region.parseOpcode({ "sw_lokey", "30" });
region.parseOpcode({ "sw_hikey", "50" });
region.parseOpcode({ "sw_last", "40" });
REQUIRE( !region.isSwitchedOn() );
region.registerNoteOn(1, 60, 64, 0.5f);
REQUIRE( !region.isSwitchedOn() );
region.registerNoteOff(1, 60, 0, 0.5f);
REQUIRE( !region.isSwitchedOn() );
region.registerNoteOn(1, 40, 64, 0.5f);
REQUIRE( region.isSwitchedOn() );
region.registerNoteOff(1, 40, 0, 0.5f);
REQUIRE( region.isSwitchedOn() );
region.registerNoteOn(1, 60, 64, 0.5f);
REQUIRE( region.isSwitchedOn() );
region.registerNoteOff(1, 60, 0, 0.5f);
region.registerNoteOn(1, 41, 64, 0.5f);
REQUIRE( !region.isSwitchedOn() );
region.registerNoteOff(1, 41, 0, 0.5f);
}
SECTION("Keyswitches: sw_down with non-default keyswitch range")
{
region.parseOpcode({ "sw_lokey", "30" });
region.parseOpcode({ "sw_hikey", "50" });
region.parseOpcode({ "sw_down", "40" });
REQUIRE( !region.isSwitchedOn() );
region.registerNoteOn(1, 60, 64, 0.5f);
REQUIRE( !region.isSwitchedOn() );
region.registerNoteOff(1, 60, 0, 0.5f);
REQUIRE( !region.isSwitchedOn() );
region.registerNoteOn(1, 40, 64, 0.5f);
REQUIRE( region.isSwitchedOn() );
region.registerNoteOff(1, 40, 0, 0.5f);
REQUIRE( !region.isSwitchedOn() );
region.registerNoteOn(1, 60, 64, 0.5f);
REQUIRE( !region.isSwitchedOn() );
region.registerNoteOff(1, 60, 0, 0.5f);
region.registerNoteOn(1, 41, 64, 0.5f);
REQUIRE( !region.isSwitchedOn() );
region.registerNoteOff(1, 41, 0, 0.5f);
}
SECTION("Keyswitches: sw_up with non-default keyswitch range")
{
region.parseOpcode({ "sw_lokey", "30" });
region.parseOpcode({ "sw_hikey", "50" });
region.parseOpcode({ "sw_up", "40" });
REQUIRE( region.isSwitchedOn() );
region.registerNoteOn(1, 40, 64, 0.5f);
REQUIRE( !region.isSwitchedOn() );
region.registerNoteOff(1, 40, 0, 0.5f);
REQUIRE( region.isSwitchedOn() );
region.registerNoteOn(1, 41, 64, 0.5f);
REQUIRE( region.isSwitchedOn() );
region.registerNoteOn(1, 40, 64, 0.5f);
REQUIRE( !region.isSwitchedOn() );
region.registerNoteOff(1, 40, 0, 0.5f);
region.registerNoteOff(1, 41, 0, 0.5f);
REQUIRE( region.isSwitchedOn() );
}
SECTION("Keyswitches: sw_previous")
{
region.parseOpcode({ "sw_previous", "40" });
REQUIRE( !region.isSwitchedOn() );
region.registerNoteOn(1, 40, 64, 0.5f);
REQUIRE( region.isSwitchedOn() );
region.registerNoteOff(1, 40, 0, 0.5f);
REQUIRE( region.isSwitchedOn() );
region.registerNoteOn(1, 41, 64, 0.5f);
REQUIRE( !region.isSwitchedOn() );
region.registerNoteOn(1, 40, 64, 0.5f);
REQUIRE( region.isSwitchedOn() );
region.registerNoteOff(1, 40, 0, 0.5f);
region.registerNoteOff(1, 41, 0, 0.5f);
REQUIRE( region.isSwitchedOn() );
region.registerNoteOn(1, 41, 64, 0.5f);
REQUIRE( !region.isSwitchedOn() );
region.registerNoteOff(1, 41, 0, 0.5f);
REQUIRE( !region.isSwitchedOn() );
}
SECTION("Sequences: length 2, default position")
{
region.parseOpcode({ "seq_length", "2" });
region.parseOpcode({ "seq_position", "1" });
region.parseOpcode({ "key", "40" });
REQUIRE( region.isSwitchedOn() );
region.registerNoteOn(1, 40, 64, 0.5f);
REQUIRE( !region.isSwitchedOn() );
region.registerNoteOff(1, 40, 0, 0.5f);
REQUIRE( !region.isSwitchedOn() );
region.registerNoteOn(1, 40, 64, 0.5f);
REQUIRE( region.isSwitchedOn() );
region.registerNoteOff(1, 40, 0, 0.5f);
REQUIRE( region.isSwitchedOn() );
region.registerNoteOn(1, 40, 64, 0.5f);
REQUIRE( !region.isSwitchedOn() );
region.registerNoteOff(1, 40, 0, 0.5f);
REQUIRE( !region.isSwitchedOn() );
}
SECTION("Sequences: length 2, position 2")
{
region.parseOpcode({ "seq_length", "2" });
region.parseOpcode({ "seq_position", "2" });
region.parseOpcode({ "key", "40" });
REQUIRE( !region.isSwitchedOn() );
region.registerNoteOn(1, 40, 64, 0.5f);
REQUIRE( region.isSwitchedOn() );
region.registerNoteOff(1, 40, 0, 0.5f);
REQUIRE( region.isSwitchedOn() );
region.registerNoteOn(1, 40, 64, 0.5f);
REQUIRE( !region.isSwitchedOn() );
region.registerNoteOff(1, 40, 0, 0.5f);
REQUIRE( !region.isSwitchedOn() );
region.registerNoteOn(1, 40, 64, 0.5f);
REQUIRE( region.isSwitchedOn() );
region.registerNoteOff(1, 40, 0, 0.5f);
REQUIRE( region.isSwitchedOn() );
}
SECTION("Sequences: length 3, position 2")
{
region.parseOpcode({ "seq_length", "3" });
region.parseOpcode({ "seq_position", "2" });
region.parseOpcode({ "key", "40" });
REQUIRE( !region.isSwitchedOn() );
region.registerNoteOn(1, 40, 64, 0.5f);
REQUIRE( region.isSwitchedOn() );
region.registerNoteOff(1, 40, 0, 0.5f);
REQUIRE( region.isSwitchedOn() );
region.registerNoteOn(1, 40, 64, 0.5f);
REQUIRE( !region.isSwitchedOn() );
region.registerNoteOff(1, 40, 0, 0.5f);
REQUIRE( !region.isSwitchedOn() );
region.registerNoteOn(1, 40, 64, 0.5f);
REQUIRE( !region.isSwitchedOn() );
region.registerNoteOff(1, 40, 0, 0.5f);
REQUIRE( !region.isSwitchedOn() );
region.registerNoteOn(1, 40, 64, 0.5f);
REQUIRE( region.isSwitchedOn() );
region.registerNoteOff(1, 40, 0, 0.5f);
REQUIRE( region.isSwitchedOn() );
}
}