Add sw_lolast/sw_hilast
This commit is contained in:
parent
9c3de9dadd
commit
5ea4b876df
5 changed files with 138 additions and 3 deletions
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue