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"):
|
case hash("sw_hikey"):
|
||||||
break;
|
break;
|
||||||
case hash("sw_last"):
|
case hash("sw_last"):
|
||||||
setValueFromOpcode(opcode, lastKeyswitch, Default::keyRange);
|
if (!lastKeyswitchRange) {
|
||||||
keySwitched = false;
|
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;
|
break;
|
||||||
case hash("sw_label"):
|
case hash("sw_label"):
|
||||||
keyswitchLabel = opcode.value;
|
keyswitchLabel = opcode.value;
|
||||||
|
|
|
||||||
|
|
@ -348,6 +348,7 @@ struct Region {
|
||||||
Range<float> bendRange { Default::bendValueRange }; // hibend and lobend
|
Range<float> bendRange { Default::bendValueRange }; // hibend and lobend
|
||||||
CCMap<Range<float>> ccConditions { Default::ccValueRange };
|
CCMap<Range<float>> ccConditions { Default::ccValueRange };
|
||||||
absl::optional<uint8_t> lastKeyswitch {}; // sw_last
|
absl::optional<uint8_t> lastKeyswitch {}; // sw_last
|
||||||
|
absl::optional<Range<uint8_t>> lastKeyswitchRange {}; // sw_last
|
||||||
absl::optional<std::string> keyswitchLabel {};
|
absl::optional<std::string> keyswitchLabel {};
|
||||||
absl::optional<uint8_t> upKeyswitch {}; // sw_up
|
absl::optional<uint8_t> upKeyswitch {}; // sw_up
|
||||||
absl::optional<uint8_t> downKeyswitch {}; // sw_down
|
absl::optional<uint8_t> downKeyswitch {}; // sw_down
|
||||||
|
|
|
||||||
|
|
@ -178,6 +178,12 @@ void sfz::Synth::buildRegion(const std::vector<Opcode>& regionOpcodes)
|
||||||
if (lastRegion->lastKeyswitch)
|
if (lastRegion->lastKeyswitch)
|
||||||
lastKeyswitchLists[*lastRegion->lastKeyswitch].push_back(lastRegion.get());
|
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)
|
if (lastRegion->upKeyswitch)
|
||||||
upKeyswitchLists[*lastRegion->upKeyswitch].push_back(lastRegion.get());
|
upKeyswitchLists[*lastRegion->upKeyswitch].push_back(lastRegion.get());
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -402,7 +402,6 @@ TEST_CASE("[Keyswitches] sw_previous in range")
|
||||||
REQUIRE(synth.getRegionView(0)->isSwitchedOn());
|
REQUIRE(synth.getRegionView(0)->isSwitchedOn());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TEST_CASE("[Keyswitches] sw_previous out of range")
|
TEST_CASE("[Keyswitches] sw_previous out of range")
|
||||||
{
|
{
|
||||||
// The behavior is the same in this case, regardless of the keyrange
|
// 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);
|
synth.noteOn(0, 61, 64);
|
||||||
REQUIRE(!synth.getRegionView(0)->isSwitchedOn());
|
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);
|
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")
|
SECTION("sw_up")
|
||||||
{
|
{
|
||||||
REQUIRE(!region.upKeyswitch);
|
REQUIRE(!region.upKeyswitch);
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue