Add support for "sustain_cc=" and "trigger=release_key"
This commit is contained in:
parent
792b62cc78
commit
c4e8675c04
6 changed files with 80 additions and 6 deletions
|
|
@ -44,7 +44,6 @@ namespace config {
|
|||
constexpr uint8_t gainSmoothing { 5 };
|
||||
constexpr unsigned powerTableSizeExponent { 11 };
|
||||
constexpr int maxFilePromises { maxVoices };
|
||||
constexpr int sustainCC { 64 };
|
||||
constexpr int allSoundOffCC { 120 };
|
||||
constexpr int resetCC { 121 };
|
||||
constexpr int allNotesOffCC { 123 };
|
||||
|
|
|
|||
|
|
@ -215,6 +215,7 @@ namespace Default
|
|||
constexpr float vel2release { 0.0f };
|
||||
constexpr float start { 0.0 };
|
||||
constexpr float sustain { 100.0 };
|
||||
constexpr uint16_t sustainCC { 64 };
|
||||
constexpr float vel2sustain { 0.0 };
|
||||
constexpr int depth { 0 };
|
||||
constexpr Range<float> egTimeRange { 0.0, 100.0 };
|
||||
|
|
|
|||
|
|
@ -273,6 +273,9 @@ bool sfz::Region::parseOpcode(const Opcode& rawOpcode)
|
|||
}
|
||||
break;
|
||||
|
||||
case hash("sustain_cc"):
|
||||
setValueFromOpcode(opcode, sustainCC, Default::ccNumberRange);
|
||||
break;
|
||||
case hash("sustain_sw"):
|
||||
checkSustain = readBooleanFromOpcode(opcode).value_or(Default::checkSustain);
|
||||
break;
|
||||
|
|
@ -984,7 +987,13 @@ bool sfz::Region::registerNoteOff(int noteNumber, float velocity, float randValu
|
|||
|
||||
const bool velOk = velocityRange.containsWithEnd(velocity);
|
||||
const bool randOk = randRange.contains(randValue);
|
||||
const bool releaseTrigger = (trigger == SfzTrigger::release || trigger == SfzTrigger::release_key);
|
||||
bool releaseTrigger = (trigger == SfzTrigger::release_key);
|
||||
if (trigger == SfzTrigger::release) {
|
||||
if (midiState.getCCValue(sustainCC) < config::halfCCThreshold)
|
||||
releaseTrigger = true;
|
||||
else
|
||||
noteIsOff = true;
|
||||
}
|
||||
return keyOk && velOk && randOk && releaseTrigger;
|
||||
}
|
||||
|
||||
|
|
@ -999,13 +1008,18 @@ bool sfz::Region::registerCC(int ccNumber, float ccValue) noexcept
|
|||
if (!isSwitchedOn())
|
||||
return false;
|
||||
|
||||
if (sustainCC == ccNumber && ccValue < config::halfCCThreshold && noteIsOff) {
|
||||
noteIsOff = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!triggerOnCC)
|
||||
return false;
|
||||
|
||||
if (ccTriggers.contains(ccNumber) && ccTriggers[ccNumber].containsWithEnd(ccValue))
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void sfz::Region::registerPitchWheel(float pitch) noexcept
|
||||
|
|
|
|||
|
|
@ -301,6 +301,7 @@ struct Region {
|
|||
SfzVelocityOverride velocityOverride { Default::velocityOverride }; // sw_vel
|
||||
bool checkSustain { Default::checkSustain }; // sustain_sw
|
||||
bool checkSostenuto { Default::checkSostenuto }; // sostenuto_sw
|
||||
uint16_t sustainCC { Default::sustainCC }; // sustain_cc
|
||||
|
||||
// Region logic: internal conditions
|
||||
Range<uint8_t> aftertouchRange { Default::aftertouchRange }; // hichanaft and lochanaft
|
||||
|
|
@ -373,6 +374,7 @@ private:
|
|||
bool pitchSwitched { true };
|
||||
bool bpmSwitched { true };
|
||||
bool aftertouchSwitched { true };
|
||||
bool noteIsOff { false };
|
||||
std::bitset<config::numCCs> ccSwitched;
|
||||
bool triggerOnCC { false };
|
||||
absl::string_view defaultPath { "" };
|
||||
|
|
|
|||
|
|
@ -198,7 +198,7 @@ void sfz::Voice::registerNoteOff(int delay, int noteNumber, float velocity) noex
|
|||
if (region->loopMode == SfzLoopMode::one_shot)
|
||||
return;
|
||||
|
||||
if (!region->checkSustain || resources.midiState.getCCValue(config::sustainCC) < config::halfCCThreshold)
|
||||
if (!region->checkSustain || resources.midiState.getCCValue(region->sustainCC) < config::halfCCThreshold)
|
||||
release(delay);
|
||||
}
|
||||
}
|
||||
|
|
@ -212,7 +212,7 @@ void sfz::Voice::registerCC(int delay, int ccNumber, float ccValue) noexcept
|
|||
if (state != State::playing)
|
||||
return;
|
||||
|
||||
if (region->checkSustain && noteIsOff && ccNumber == config::sustainCC && ccValue < config::halfCCThreshold)
|
||||
if (region->checkSustain && noteIsOff && ccNumber == region->sustainCC && ccValue < config::halfCCThreshold)
|
||||
release(delay);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1171,6 +1171,15 @@ TEST_CASE("[Region] Parsing opcodes")
|
|||
REQUIRE(region.checkSostenuto);
|
||||
}
|
||||
|
||||
SECTION("sustain_cc")
|
||||
{
|
||||
REQUIRE(region.sustainCC == 64);
|
||||
region.parseOpcode({ "sustain_cc", "63" });
|
||||
REQUIRE(region.sustainCC == 63);
|
||||
region.parseOpcode({ "sustain_cc", "-1" });
|
||||
REQUIRE(region.sustainCC == 0);
|
||||
}
|
||||
|
||||
SECTION("Filter stacking and cutoffs")
|
||||
{
|
||||
REQUIRE(region.filters.empty());
|
||||
|
|
@ -1685,3 +1694,52 @@ TEST_CASE("[Region] Non-conforming floating point values in integer opcodes")
|
|||
region.parseOpcode({ "pitch_keytrack", "-2.1" });
|
||||
REQUIRE(region.pitchKeytrack == -2);
|
||||
}
|
||||
|
||||
|
||||
TEST_CASE("[Region] Release and release key")
|
||||
{
|
||||
MidiState midiState;
|
||||
Region region { 0, midiState };
|
||||
region.parseOpcode({ "key", "63" });
|
||||
region.parseOpcode({ "sample", "*sine" });
|
||||
SECTION("Release key without sustain")
|
||||
{
|
||||
region.parseOpcode({ "trigger", "release_key" });
|
||||
midiState.ccEvent(0, 64, 0.0f);
|
||||
REQUIRE( !region.registerNoteOn(63, 0.5f, 0.0f) );
|
||||
REQUIRE( region.registerNoteOff(63, 0.5f, 0.0f) );
|
||||
}
|
||||
SECTION("Release key with sustain")
|
||||
{
|
||||
region.parseOpcode({ "trigger", "release_key" });
|
||||
midiState.ccEvent(0, 64, 1.0f);
|
||||
REQUIRE( !region.registerCC(64, 1.0f) );
|
||||
REQUIRE( !region.registerNoteOn(63, 0.5f, 0.0f) );
|
||||
REQUIRE( region.registerNoteOff(63, 0.5f, 0.0f) );
|
||||
midiState.ccEvent(0, 64, 0.0f);
|
||||
REQUIRE( !region.registerCC(64, 0.0f) );
|
||||
}
|
||||
SECTION("Release without sustain")
|
||||
{
|
||||
region.parseOpcode({ "trigger", "release" });
|
||||
midiState.ccEvent(0, 64, 0.0f);
|
||||
REQUIRE( !region.registerNoteOn(63, 0.5f, 0.0f) );
|
||||
REQUIRE( region.registerNoteOff(63, 0.5f, 0.0f) );
|
||||
}
|
||||
SECTION("Release with sustain")
|
||||
{
|
||||
region.parseOpcode({ "trigger", "release" });
|
||||
midiState.ccEvent(0, 64, 1.0f);
|
||||
REQUIRE( !region.registerNoteOn(63, 0.5f, 0.0f) );
|
||||
REQUIRE( !region.registerNoteOff(63, 0.5f, 0.0f) );
|
||||
}
|
||||
SECTION("Release with sustain")
|
||||
{
|
||||
region.parseOpcode({ "trigger", "release" });
|
||||
midiState.ccEvent(0, 64, 1.0f);
|
||||
REQUIRE( !region.registerNoteOn(63, 0.5f, 0.0f) );
|
||||
REQUIRE( !region.registerNoteOff(63, 0.5f, 0.0f) );
|
||||
midiState.ccEvent(0, 64, 0.0f);
|
||||
REQUIRE( region.registerCC(64, 0.0f) );
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue