From ebd2b1906a6225df804cff2a8530e463401a43fb Mon Sep 17 00:00:00 2001 From: paulfd Date: Fri, 13 Sep 2019 20:46:35 +0200 Subject: [PATCH] Added sustain_sw; sostenuto_sw is parsed but not treated in code --- sfizz/Config.h | 3 ++- sfizz/Defaults.h | 4 ++++ sfizz/Opcode.h | 21 +++++++++++++++++++-- sfizz/Region.cpp | 9 +++++++++ sfizz/Region.h | 2 ++ sfizz/Voice.cpp | 7 ++++--- tests/RegionT.cpp | 20 ++++++++++++++++++++ 7 files changed, 60 insertions(+), 6 deletions(-) diff --git a/sfizz/Config.h b/sfizz/Config.h index 5875e967..f7e1f7ca 100644 --- a/sfizz/Config.h +++ b/sfizz/Config.h @@ -31,7 +31,8 @@ namespace config { constexpr int preloadSize { 8192 }; constexpr int numChannels { 2 }; constexpr int numVoices { 64 }; - constexpr int numLoadingThreads { 4 }; + constexpr int sustainCC { 64 }; + constexpr int halfCCThreshold { 64 }; constexpr int centPerSemitone { 100 }; constexpr float virtuallyZero { 0.00005f }; constexpr float fastReleaseDuration { 0.01 }; diff --git a/sfizz/Defaults.h b/sfizz/Defaults.h index d8f1eab7..d56b3b04 100644 --- a/sfizz/Defaults.h +++ b/sfizz/Defaults.h @@ -142,5 +142,9 @@ namespace Default inline constexpr Range egDepthRange { -12000, 12000 }; inline constexpr Range egOnCCTimeRange { -100.0, 100.0 }; inline constexpr Range egOnCCPercentRange { -100.0, 100.0 }; + + // ***** SFZ v2 ******** + inline constexpr bool checkSustain { true }; // sustain_sw + inline constexpr bool checkSostenuto { true }; // sostenuto_sw } } \ No newline at end of file diff --git a/sfizz/Opcode.h b/sfizz/Opcode.h index d587471b..be818f86 100644 --- a/sfizz/Opcode.h +++ b/sfizz/Opcode.h @@ -26,6 +26,7 @@ #include "LeakDetector.h" #include "Range.h" #include "SfzHelpers.h" +#include "StringViewHelpers.h" #include #include @@ -48,8 +49,12 @@ inline std::optional readOpcode(std::string_view value, const Range::value) { int64_t returnedValue; - if (!absl::SimpleAtoi(value, &returnedValue)) - return {}; + if (!absl::SimpleAtoi(value, &returnedValue)) { + float floatValue; + if (!absl::SimpleAtof(value, &floatValue)) + return {}; + returnedValue = static_cast(floatValue); + } if (returnedValue > std::numeric_limits::max()) returnedValue = std::numeric_limits::max(); @@ -66,6 +71,18 @@ inline std::optional readOpcode(std::string_view value, const Range readBooleanFromOpcode(const Opcode& opcode) +{ + switch (hash(opcode.value)) { + case hash("off"): + return false; + case hash("on"): + return true; + default: + return {}; + } +} + template inline void setValueFromOpcode(const Opcode& opcode, ValueType& target, const Range& validRange) { diff --git a/sfizz/Region.cpp b/sfizz/Region.cpp index 5aea56e9..f9a10e60 100644 --- a/sfizz/Region.cpp +++ b/sfizz/Region.cpp @@ -22,8 +22,10 @@ // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "Region.h" +#include "Defaults.h" #include "MathHelpers.h" #include "Debug.h" +#include "Opcode.h" #include "StringViewHelpers.h" #include "absl/strings/str_replace.h" #include @@ -183,6 +185,13 @@ bool sfz::Region::parseOpcode(const Opcode& opcode) DBG("Unknown velocity mode: " << std::string(opcode.value)); } break; + + case hash("sustain_sw"): + checkSustain = readBooleanFromOpcode(opcode).value_or(Default::checkSustain); + break; + case hash("sostenuto_sw"): + checkSostenuto = readBooleanFromOpcode(opcode).value_or(Default::checkSostenuto); + break; // Region logic: internal conditions case hash("lochanaft"): setRangeStartFromOpcode(opcode, aftertouchRange, Default::aftertouchRange); diff --git a/sfizz/Region.h b/sfizz/Region.h index d373b685..3739c379 100644 --- a/sfizz/Region.h +++ b/sfizz/Region.h @@ -96,6 +96,8 @@ struct Region { std::optional keyswitchDown {}; // sw_down std::optional previousNote {}; // sw_previous SfzVelocityOverride velocityOverride { Default::velocityOverride }; // sw_vel + bool checkSustain { Default::checkSustain }; // sustain_sw + bool checkSostenuto { Default::checkSostenuto }; // sostenuto_sw // Region logic: internal conditions Range aftertouchRange { Default::aftertouchRange }; // hichanaft and lochanaft diff --git a/sfizz/Voice.cpp b/sfizz/Voice.cpp index 8f1e6f26..fdf69b3a 100644 --- a/sfizz/Voice.cpp +++ b/sfizz/Voice.cpp @@ -23,6 +23,7 @@ #include "Voice.h" #include "AudioSpan.h" +#include "Config.h" #include "Defaults.h" #include "MathHelpers.h" #include "SIMDHelpers.h" @@ -94,6 +95,7 @@ void sfz::Voice::startVoice(Region* region, int delay, int channel, int number, sourcePosition = region->getOffset(); floatPosition = static_cast(sourcePosition); + DBG("Offset: " << floatPosition); initialDelay = delay + region->getDelay(); baseFrequency = midiNoteFrequency(number) * pitchRatio; prepareEGEnvelope(delay, value); @@ -151,9 +153,8 @@ void sfz::Voice::registerNoteOff(int delay, int channel, int noteNumber, uint8_t if (region->loopMode == SfzLoopMode::one_shot) return; - if (ccState[64] < 63) { + if (!region->checkSustain || ccState[config::sustainCC] < config::halfCCThreshold) release(delay); - } } } @@ -162,7 +163,7 @@ void sfz::Voice::registerCC(int delay, int channel [[maybe_unused]], int ccNumbe if (region == nullptr) return; - if (ccNumber == 64 && noteIsOff && ccValue < 63) + if (ccNumber == config::sustainCC && noteIsOff && ccValue < config::halfCCThreshold) release(delay); if (region->amplitudeCC && ccNumber == region->amplitudeCC->first) { diff --git a/tests/RegionT.cpp b/tests/RegionT.cpp index 44afceeb..0f52cc79 100644 --- a/tests/RegionT.cpp +++ b/tests/RegionT.cpp @@ -1011,6 +1011,26 @@ TEST_CASE("[Region] Parsing opcodes") REQUIRE(region.amplitudeEG.ccStart->second == -100.0f); REQUIRE(region.amplitudeEG.ccSustain->second == -100.0f); } + + SECTION("sustain_sw and sostenuto_sw") + { + REQUIRE(region.checkSustain); + REQUIRE(region.checkSostenuto); + region.parseOpcode({ "sustain_sw", "off" }); + REQUIRE(!region.checkSustain); + region.parseOpcode({ "sustain_sw", "on" }); + REQUIRE(region.checkSustain); + region.parseOpcode({ "sustain_sw", "off" }); + region.parseOpcode({ "sustain_sw", "obladi" }); + REQUIRE(region.checkSustain); + region.parseOpcode({ "sostenuto_sw", "off" }); + REQUIRE(!region.checkSostenuto); + region.parseOpcode({ "sostenuto_sw", "on" }); + REQUIRE(region.checkSostenuto); + region.parseOpcode({ "sostenuto_sw", "off" }); + region.parseOpcode({ "sostenuto_sw", "obladi" }); + REQUIRE(region.checkSostenuto); + } } // Specific region bugs