Added sustain_sw; sostenuto_sw is parsed but not treated in code

This commit is contained in:
paulfd 2019-09-13 20:46:35 +02:00
parent 965321166c
commit ebd2b1906a
7 changed files with 60 additions and 6 deletions

View file

@ -31,7 +31,8 @@ namespace config {
constexpr int preloadSize { 8192 }; constexpr int preloadSize { 8192 };
constexpr int numChannels { 2 }; constexpr int numChannels { 2 };
constexpr int numVoices { 64 }; constexpr int numVoices { 64 };
constexpr int numLoadingThreads { 4 }; constexpr int sustainCC { 64 };
constexpr int halfCCThreshold { 64 };
constexpr int centPerSemitone { 100 }; constexpr int centPerSemitone { 100 };
constexpr float virtuallyZero { 0.00005f }; constexpr float virtuallyZero { 0.00005f };
constexpr float fastReleaseDuration { 0.01 }; constexpr float fastReleaseDuration { 0.01 };

View file

@ -142,5 +142,9 @@ namespace Default
inline constexpr Range<int> egDepthRange { -12000, 12000 }; inline constexpr Range<int> egDepthRange { -12000, 12000 };
inline constexpr Range<float> egOnCCTimeRange { -100.0, 100.0 }; inline constexpr Range<float> egOnCCTimeRange { -100.0, 100.0 };
inline constexpr Range<float> egOnCCPercentRange { -100.0, 100.0 }; inline constexpr Range<float> egOnCCPercentRange { -100.0, 100.0 };
// ***** SFZ v2 ********
inline constexpr bool checkSustain { true }; // sustain_sw
inline constexpr bool checkSostenuto { true }; // sostenuto_sw
} }
} }

View file

@ -26,6 +26,7 @@
#include "LeakDetector.h" #include "LeakDetector.h"
#include "Range.h" #include "Range.h"
#include "SfzHelpers.h" #include "SfzHelpers.h"
#include "StringViewHelpers.h"
#include <optional> #include <optional>
#include <string_view> #include <string_view>
@ -48,8 +49,12 @@ inline std::optional<ValueType> readOpcode(std::string_view value, const Range<V
{ {
if constexpr (std::is_integral<ValueType>::value) { if constexpr (std::is_integral<ValueType>::value) {
int64_t returnedValue; int64_t returnedValue;
if (!absl::SimpleAtoi(value, &returnedValue)) if (!absl::SimpleAtoi(value, &returnedValue)) {
return {}; float floatValue;
if (!absl::SimpleAtof(value, &floatValue))
return {};
returnedValue = static_cast<int64_t>(floatValue);
}
if (returnedValue > std::numeric_limits<ValueType>::max()) if (returnedValue > std::numeric_limits<ValueType>::max())
returnedValue = std::numeric_limits<ValueType>::max(); returnedValue = std::numeric_limits<ValueType>::max();
@ -66,6 +71,18 @@ inline std::optional<ValueType> readOpcode(std::string_view value, const Range<V
} }
} }
inline std::optional<bool> readBooleanFromOpcode(const Opcode& opcode)
{
switch (hash(opcode.value)) {
case hash("off"):
return false;
case hash("on"):
return true;
default:
return {};
}
}
template <class ValueType> template <class ValueType>
inline void setValueFromOpcode(const Opcode& opcode, ValueType& target, const Range<ValueType>& validRange) inline void setValueFromOpcode(const Opcode& opcode, ValueType& target, const Range<ValueType>& validRange)
{ {

View file

@ -22,8 +22,10 @@
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "Region.h" #include "Region.h"
#include "Defaults.h"
#include "MathHelpers.h" #include "MathHelpers.h"
#include "Debug.h" #include "Debug.h"
#include "Opcode.h"
#include "StringViewHelpers.h" #include "StringViewHelpers.h"
#include "absl/strings/str_replace.h" #include "absl/strings/str_replace.h"
#include <random> #include <random>
@ -183,6 +185,13 @@ bool sfz::Region::parseOpcode(const Opcode& opcode)
DBG("Unknown velocity mode: " << std::string(opcode.value)); DBG("Unknown velocity mode: " << std::string(opcode.value));
} }
break; 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 // Region logic: internal conditions
case hash("lochanaft"): case hash("lochanaft"):
setRangeStartFromOpcode(opcode, aftertouchRange, Default::aftertouchRange); setRangeStartFromOpcode(opcode, aftertouchRange, Default::aftertouchRange);

View file

@ -96,6 +96,8 @@ struct Region {
std::optional<uint8_t> keyswitchDown {}; // sw_down std::optional<uint8_t> keyswitchDown {}; // sw_down
std::optional<uint8_t> previousNote {}; // sw_previous std::optional<uint8_t> previousNote {}; // sw_previous
SfzVelocityOverride velocityOverride { Default::velocityOverride }; // sw_vel SfzVelocityOverride velocityOverride { Default::velocityOverride }; // sw_vel
bool checkSustain { Default::checkSustain }; // sustain_sw
bool checkSostenuto { Default::checkSostenuto }; // sostenuto_sw
// Region logic: internal conditions // Region logic: internal conditions
Range<uint8_t> aftertouchRange { Default::aftertouchRange }; // hichanaft and lochanaft Range<uint8_t> aftertouchRange { Default::aftertouchRange }; // hichanaft and lochanaft

View file

@ -23,6 +23,7 @@
#include "Voice.h" #include "Voice.h"
#include "AudioSpan.h" #include "AudioSpan.h"
#include "Config.h"
#include "Defaults.h" #include "Defaults.h"
#include "MathHelpers.h" #include "MathHelpers.h"
#include "SIMDHelpers.h" #include "SIMDHelpers.h"
@ -94,6 +95,7 @@ void sfz::Voice::startVoice(Region* region, int delay, int channel, int number,
sourcePosition = region->getOffset(); sourcePosition = region->getOffset();
floatPosition = static_cast<float>(sourcePosition); floatPosition = static_cast<float>(sourcePosition);
DBG("Offset: " << floatPosition);
initialDelay = delay + region->getDelay(); initialDelay = delay + region->getDelay();
baseFrequency = midiNoteFrequency(number) * pitchRatio; baseFrequency = midiNoteFrequency(number) * pitchRatio;
prepareEGEnvelope(delay, value); 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) if (region->loopMode == SfzLoopMode::one_shot)
return; return;
if (ccState[64] < 63) { if (!region->checkSustain || ccState[config::sustainCC] < config::halfCCThreshold)
release(delay); release(delay);
}
} }
} }
@ -162,7 +163,7 @@ void sfz::Voice::registerCC(int delay, int channel [[maybe_unused]], int ccNumbe
if (region == nullptr) if (region == nullptr)
return; return;
if (ccNumber == 64 && noteIsOff && ccValue < 63) if (ccNumber == config::sustainCC && noteIsOff && ccValue < config::halfCCThreshold)
release(delay); release(delay);
if (region->amplitudeCC && ccNumber == region->amplitudeCC->first) { if (region->amplitudeCC && ccNumber == region->amplitudeCC->first) {

View file

@ -1011,6 +1011,26 @@ TEST_CASE("[Region] Parsing opcodes")
REQUIRE(region.amplitudeEG.ccStart->second == -100.0f); REQUIRE(region.amplitudeEG.ccStart->second == -100.0f);
REQUIRE(region.amplitudeEG.ccSustain->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 // Specific region bugs