diff --git a/src/sfizz/Opcode.cpp b/src/sfizz/Opcode.cpp index 673501d1..ff6cbc6d 100644 --- a/src/sfizz/Opcode.cpp +++ b/src/sfizz/Opcode.cpp @@ -210,16 +210,18 @@ absl::optional readOpcode(absl::string_view value, const Range readBooleanFromOpcode(const Opcode& opcode) { - switch (hash(opcode.value)) { - case hash("off"): // fallthrough - case hash("0"): + // Cakewalk-style booleans, case-insensitive + if (absl::EqualsIgnoreCase(opcode.value, "off")) return false; - case hash("on"): // fallthrough - case hash("1"): + if (absl::EqualsIgnoreCase(opcode.value, "on")) return true; - default: - return {}; - } + + // ARIA-style booleans? (seen in egN_dynamic=1 for example) + // TODO check this + if (auto value = readOpcode(opcode.value, Range::wholeRange())) + return *value != 0; + + return absl::nullopt; } template diff --git a/src/sfizz/Range.h b/src/sfizz/Range.h index 3b548535..7bbe369f 100644 --- a/src/sfizz/Range.h +++ b/src/sfizz/Range.h @@ -8,6 +8,7 @@ #include "MathHelpers.h" #include #include +#include namespace sfz { @@ -116,6 +117,17 @@ public: }; } + /** + * @brief Construct a range which covers the whole numeric domain + */ + static constexpr Range wholeRange() noexcept + { + return Range { + std::numeric_limits::min(), + std::numeric_limits::max(), + }; + } + private: Type _start { static_cast(0.0) }; Type _end { static_cast(0.0) }; diff --git a/tests/OpcodeT.cpp b/tests/OpcodeT.cpp index 771db749..a2ade6a7 100644 --- a/tests/OpcodeT.cpp +++ b/tests/OpcodeT.cpp @@ -280,3 +280,14 @@ TEST_CASE("[Opcode] readOpcode") REQUIRE( !sfz::readOpcode("garbage50.25", sfz::Range(-20, 100)) ); REQUIRE( !sfz::readOpcode("garbage", sfz::Range(-20, 100)) ); } + +TEST_CASE("[Opcode] readBooleanFromOpcode") +{ + REQUIRE(sfz::readBooleanFromOpcode({"", "1"}) == true); + REQUIRE(sfz::readBooleanFromOpcode({"", "0"}) == false); + REQUIRE(sfz::readBooleanFromOpcode({"", "777"}) == true); + REQUIRE(sfz::readBooleanFromOpcode({"", "on"}) == true); + REQUIRE(sfz::readBooleanFromOpcode({"", "off"}) == false); + REQUIRE(sfz::readBooleanFromOpcode({"", "On"}) == true); + REQUIRE(sfz::readBooleanFromOpcode({"", "oFf"}) == false); +}