Add sw_lolast/sw_hilast

This commit is contained in:
Paul Ferrand 2020-10-27 14:50:31 +01:00
parent 9c3de9dadd
commit 5ea4b876df
5 changed files with 138 additions and 3 deletions

View file

@ -296,8 +296,32 @@ bool sfz::Region::parseOpcode(const Opcode& rawOpcode)
case hash("sw_hikey"):
break;
case hash("sw_last"):
setValueFromOpcode(opcode, lastKeyswitch, Default::keyRange);
keySwitched = false;
if (!lastKeyswitchRange) {
setValueFromOpcode(opcode, lastKeyswitch, Default::keyRange);
keySwitched = false;
}
break;
case hash("sw_lolast"):
if (auto value = readOpcode(opcode.value, Default::keyRange)) {
if (!lastKeyswitchRange)
lastKeyswitchRange.emplace(*value, *value);
else
lastKeyswitchRange->setStart(*value);
keySwitched = false;
lastKeyswitch = absl::nullopt;
}
break;
case hash("sw_hilast"):
if (auto value = readOpcode(opcode.value, Default::keyRange)) {
if (!lastKeyswitchRange)
lastKeyswitchRange.emplace(*value, *value);
else
lastKeyswitchRange->setEnd(*value);
keySwitched = false;
lastKeyswitch = absl::nullopt;
}
break;
case hash("sw_label"):
keyswitchLabel = opcode.value;

View file

@ -348,6 +348,7 @@ struct Region {
Range<float> bendRange { Default::bendValueRange }; // hibend and lobend
CCMap<Range<float>> ccConditions { Default::ccValueRange };
absl::optional<uint8_t> lastKeyswitch {}; // sw_last
absl::optional<Range<uint8_t>> lastKeyswitchRange {}; // sw_last
absl::optional<std::string> keyswitchLabel {};
absl::optional<uint8_t> upKeyswitch {}; // sw_up
absl::optional<uint8_t> downKeyswitch {}; // sw_down

View file

@ -178,6 +178,12 @@ void sfz::Synth::buildRegion(const std::vector<Opcode>& regionOpcodes)
if (lastRegion->lastKeyswitch)
lastKeyswitchLists[*lastRegion->lastKeyswitch].push_back(lastRegion.get());
if (lastRegion->lastKeyswitchRange) {
auto& range = *lastRegion->lastKeyswitchRange;
for (uint8_t note = range.getStart(), end = range.getEnd(); note <= end; note++)
lastKeyswitchLists[note].push_back(lastRegion.get());
}
if (lastRegion->upKeyswitch)
upKeyswitchLists[*lastRegion->upKeyswitch].push_back(lastRegion.get());

View file

@ -402,7 +402,6 @@ TEST_CASE("[Keyswitches] sw_previous in range")
REQUIRE(synth.getRegionView(0)->isSwitchedOn());
}
TEST_CASE("[Keyswitches] sw_previous out of range")
{
// The behavior is the same in this case, regardless of the keyrange
@ -425,3 +424,66 @@ TEST_CASE("[Keyswitches] sw_previous out of range")
synth.noteOn(0, 61, 64);
REQUIRE(!synth.getRegionView(0)->isSwitchedOn());
}
TEST_CASE("[Keyswitches] sw_lolast and sw_hilast")
{
// The behavior is the same in this case, regardless of the keyrange
sfz::Synth synth;
synth.loadSfzString(fs::current_path() / "tests/TestFiles/sw_previous.sfz", R"(
<region> sw_lolast=57 sw_hilast=59 key=70 sample=*saw
<region> sw_lolast=60 sw_hilast=62 key=72 sample=*sine
)");
REQUIRE(!synth.getRegionView(0)->isSwitchedOn());
REQUIRE(!synth.getRegionView(1)->isSwitchedOn());
synth.noteOn(0, 51, 64);
REQUIRE(!synth.getRegionView(0)->isSwitchedOn());
REQUIRE(!synth.getRegionView(1)->isSwitchedOn());
synth.noteOn(0, 57, 64);
REQUIRE(synth.getRegionView(0)->isSwitchedOn());
REQUIRE(!synth.getRegionView(1)->isSwitchedOn());
synth.noteOn(0, 60, 64);
REQUIRE(!synth.getRegionView(0)->isSwitchedOn());
REQUIRE(synth.getRegionView(1)->isSwitchedOn());
synth.noteOn(0, 58, 64);
REQUIRE(synth.getRegionView(0)->isSwitchedOn());
REQUIRE(!synth.getRegionView(1)->isSwitchedOn());
synth.noteOn(0, 61, 64);
REQUIRE(!synth.getRegionView(0)->isSwitchedOn());
REQUIRE(synth.getRegionView(1)->isSwitchedOn());
synth.noteOn(0, 59, 64);
REQUIRE(synth.getRegionView(0)->isSwitchedOn());
REQUIRE(!synth.getRegionView(1)->isSwitchedOn());
synth.noteOn(0, 62, 64);
REQUIRE(!synth.getRegionView(0)->isSwitchedOn());
REQUIRE(synth.getRegionView(1)->isSwitchedOn());
}
TEST_CASE("[Keyswitches] sw_lolast and sw_hilast with sw_last")
{
// The behavior is the same in this case, regardless of the keyrange
sfz::Synth synth;
synth.loadSfzString(fs::current_path() / "tests/TestFiles/sw_previous.sfz", R"(
<region> sw_last=40 sw_lolast=57 sw_hilast=59 key=70 sample=*saw
<region> sw_lolast=60 sw_hilast=62 sw_last=41 key=72 sample=*sine
)");
REQUIRE(!synth.getRegionView(0)->isSwitchedOn());
REQUIRE(!synth.getRegionView(1)->isSwitchedOn());
synth.noteOn(0, 40, 64);
REQUIRE(!synth.getRegionView(0)->isSwitchedOn());
REQUIRE(!synth.getRegionView(1)->isSwitchedOn());
synth.noteOn(0, 41, 64);
REQUIRE(!synth.getRegionView(0)->isSwitchedOn());
REQUIRE(!synth.getRegionView(1)->isSwitchedOn());
synth.noteOn(0, 57, 64);
REQUIRE(synth.getRegionView(0)->isSwitchedOn());
REQUIRE(!synth.getRegionView(1)->isSwitchedOn());
synth.noteOn(0, 41, 64);
REQUIRE(synth.getRegionView(0)->isSwitchedOn());
REQUIRE(!synth.getRegionView(1)->isSwitchedOn());
synth.noteOn(0, 60, 64);
REQUIRE(!synth.getRegionView(0)->isSwitchedOn());
REQUIRE(synth.getRegionView(1)->isSwitchedOn());
synth.noteOn(0, 40, 64);
REQUIRE(!synth.getRegionView(0)->isSwitchedOn());
REQUIRE(synth.getRegionView(1)->isSwitchedOn());
}

View file

@ -362,6 +362,48 @@ TEST_CASE("[Region] Parsing opcodes")
REQUIRE(*region.lastKeyswitch == 0);
}
SECTION("sw_lolast/hilast")
{
REQUIRE(!region.lastKeyswitchRange);
region.parseOpcode({ "sw_lolast", "4" });
REQUIRE(region.lastKeyswitchRange);
REQUIRE(*region.lastKeyswitchRange == Range<uint8_t>(4, 4));
region.parseOpcode({ "sw_hilast", "128" });
REQUIRE(*region.lastKeyswitchRange == Range<uint8_t>(4, 127));
region.parseOpcode({ "sw_hilast", "63" });
REQUIRE(*region.lastKeyswitchRange == Range<uint8_t>(4, 63));
region.parseOpcode({ "sw_lolast", "64" });
REQUIRE(*region.lastKeyswitchRange == Range<uint8_t>(64, 64));
region.parseOpcode({ "sw_lolast", "-1" });
REQUIRE(*region.lastKeyswitchRange == Range<uint8_t>(0, 64));
}
SECTION("sw_hilast disables sw_last")
{
REQUIRE(!region.lastKeyswitchRange);
REQUIRE(!region.lastKeyswitch);
region.parseOpcode({ "sw_last", "4" });
REQUIRE(region.lastKeyswitch);
region.parseOpcode({ "sw_hilast", "63" });
REQUIRE(region.lastKeyswitchRange);
REQUIRE(!region.lastKeyswitch);
region.parseOpcode({ "sw_last", "4" });
REQUIRE(!region.lastKeyswitch);
}
SECTION("sw_lolast disables sw_last")
{
REQUIRE(!region.lastKeyswitchRange);
REQUIRE(!region.lastKeyswitch);
region.parseOpcode({ "sw_last", "4" });
REQUIRE(region.lastKeyswitch);
region.parseOpcode({ "sw_lolast", "63" });
REQUIRE(region.lastKeyswitchRange);
REQUIRE(!region.lastKeyswitch);
region.parseOpcode({ "sw_last", "4" });
REQUIRE(!region.lastKeyswitch);
}
SECTION("sw_up")
{
REQUIRE(!region.upKeyswitch);