From 17594241e7d5d6fca5990e39d576d9f948683070 Mon Sep 17 00:00:00 2001 From: Paul Fd Date: Wed, 30 Dec 2020 01:16:39 +0100 Subject: [PATCH] Read booleans as a template overload --- src/sfizz/Defaults.cpp | 7 +++++++ src/sfizz/Defaults.h | 26 +++++++++++++++----------- src/sfizz/FlexEGDescription.h | 2 +- src/sfizz/Opcode.cpp | 16 ++++++++++++++++ src/sfizz/Range.h | 4 +++- src/sfizz/Region.cpp | 17 +++++------------ src/sfizz/Region.h | 9 ++++----- src/sfizz/effects/Compressor.cpp | 5 ++--- src/sfizz/effects/Gate.cpp | 6 ++---- tests/FilesT.cpp | 20 ++++++++++---------- tests/RegionValuesT.cpp | 4 ++-- 11 files changed, 67 insertions(+), 49 deletions(-) diff --git a/src/sfizz/Defaults.cpp b/src/sfizz/Defaults.cpp index b7a77769..aa768dd7 100644 --- a/src/sfizz/Defaults.cpp +++ b/src/sfizz/Defaults.cpp @@ -14,6 +14,7 @@ extern const OpcodeSpec sampleEnd { uint32_t_max, Range(0, u extern const OpcodeSpec sampleCount { 0, Range(0, uint32_t_max), 0 }; extern const OpcodeSpec loopRange { 0, Range(0, uint32_t_max), 0 }; extern const OpcodeSpec loopCrossfade { 1e-3, Range(1e-3, 1.0f), kEnforceLowerBound | kEnforceUpperBound }; +extern const OpcodeSpec oscillator { OscillatorEnabled::Auto, Range(OscillatorEnabled::Auto, OscillatorEnabled::On), 0 }; extern const OpcodeSpec oscillatorPhase { 0.0f, Range(0.0f, 1.0f), 0 }; extern const OpcodeSpec oscillatorMode { 0, Range(0, 2), kIgnoreOOB }; extern const OpcodeSpec oscillatorMulti { 1, Range(1, config::oscillatorsPerVoice), kIgnoreOOB }; @@ -37,6 +38,8 @@ extern const OpcodeSpec smoothCC { 0, Range(0, 100), kIgnoreOO extern const OpcodeSpec curveCC { 0, Range(0, 255), kIgnoreOOB }; extern const OpcodeSpec sustainCC { 64, Range(0, 127), kIgnoreOOB }; extern const OpcodeSpec sustainThreshold { 0.0039f, Range(0.0f, 1.0f), kIgnoreOOB }; +extern const OpcodeSpec checkSustain { true, Range(0, 1), 0 }; +extern const OpcodeSpec checkSostenuto { true, Range(0, 1), 0 }; extern const OpcodeSpec bpm { 0.0f, Range(0.0f, 500.0f), kEnforceLowerBound }; extern const OpcodeSpec sequence { 1, Range(1, 100), kIgnoreOOB }; extern const OpcodeSpec volume { 0.0f, Range(-144.0f, 48.0f), 0 }; @@ -57,6 +60,7 @@ extern const OpcodeSpec ampKeytrack { 0.0f, Range(-96.0f, 12.0f), extern const OpcodeSpec ampVeltrack { 100.0f, Range(-100.0f, 100.0f), kIgnoreOOB }; extern const OpcodeSpec ampVelcurve { 0.0f, Range(0.0f, 1.0f), kEnforceLowerBound | kEnforceUpperBound }; extern const OpcodeSpec ampRandom { 0.0f, Range(0.0f, 24.0f), kEnforceLowerBound }; +extern const OpcodeSpec rtDead { false, Range(0, 1), 0 }; extern const OpcodeSpec rtDecay { 0.0f, Range(0.0f, 200.0f), kEnforceLowerBound }; extern const OpcodeSpec filterCutoff { 0.0f, Range(0.0f, 20000.0f), kEnforceLowerBound | kEnforceUpperBound }; extern const OpcodeSpec filterCutoffMod { 0.0f, Range(-12000.0f, 12000.0f), kEnforceLowerBound }; @@ -105,6 +109,7 @@ extern const OpcodeSpec egPercent { 0.0f, Range(0.0f, 100.0f), kEn extern const OpcodeSpec egPercentMod { 0.0f, Range(-100.0f, 100.0f), 0 }; extern const OpcodeSpec egDepth { 0.0f, Range(-12000.0f, 12000.0f), 0 }; extern const OpcodeSpec egVel2Depth { 0.0f, Range(-12000.0f, 12000.0f), 0 }; +extern const OpcodeSpec flexEGAmpeg { false, Range(0, 1), 0 }; extern const OpcodeSpec flexEGDynamic { 0, Range(0, 1), kIgnoreOOB }; extern const OpcodeSpec flexEGSustain { 0, Range(0, 100), kIgnoreOOB }; extern const OpcodeSpec flexEGPointTime { 0.0f, Range(0.0f, 100.0f), kEnforceLowerBound }; @@ -123,6 +128,7 @@ extern const OpcodeSpec distoDepth { 0.0f, Range(0.0f, 100.0f), kE extern const OpcodeSpec distoStages { 1, Range(1, maxDistoStages), kEnforceLowerBound }; extern const OpcodeSpec compAttack { 0.005f, Range(0.0f, 10.0f), kEnforceLowerBound }; extern const OpcodeSpec compRelease { 0.05f, Range(0.0f, 10.0f), kEnforceLowerBound }; +extern const OpcodeSpec compSTLink { false, Range(0, 1), 0 }; extern const OpcodeSpec compThreshold { 0.0f, Range(-100.0f, 0.0f), kIgnoreOOB }; extern const OpcodeSpec compRatio { 1.0f, Range(1.0f, 50.0f), kIgnoreOOB }; extern const OpcodeSpec compGain { 0.0f, Range(-100.0f, 100.0f), 0 }; @@ -130,6 +136,7 @@ extern const OpcodeSpec fverbSize { 0.0f, Range(0.0f, 100.0f), kEn extern const OpcodeSpec fverbPredelay { 0.0f, Range(0.0f, 10.0f), kEnforceLowerBound }; extern const OpcodeSpec fverbTone { 100.0f, Range(0.0f, 100.0f), kIgnoreOOB }; extern const OpcodeSpec fverbDamp { 0.0f, Range(0.0f, 100.0f), kIgnoreOOB }; +extern const OpcodeSpec gateSTLink { false, Range(0, 1), 0 }; extern const OpcodeSpec gateAttack { 0.005f, Range(0.0f, 10.0f), kEnforceLowerBound }; extern const OpcodeSpec gateRelease { 0.05f, Range(0.0f, 10.0f), kEnforceLowerBound }; extern const OpcodeSpec gateHold { 0.0f, Range(0.0f, 10.0f), kEnforceLowerBound }; diff --git a/src/sfizz/Defaults.h b/src/sfizz/Defaults.h index 899094d1..9025265e 100644 --- a/src/sfizz/Defaults.h +++ b/src/sfizz/Defaults.h @@ -29,16 +29,18 @@ #include #include -enum class SfzTrigger { attack, release, release_key, first, legato }; -enum class SfzLoopMode { no_loop, one_shot, loop_continuous, loop_sustain }; -enum class SfzOffMode { fast, normal, time }; -enum class SfzVelocityOverride { current, previous }; -enum class SfzCrossfadeCurve { gain, power }; -enum class SfzSelfMask { mask, dontMask }; +enum class SfzTrigger { attack = 0, release, release_key, first, legato }; +enum class SfzLoopMode { no_loop = 0, one_shot, loop_continuous, loop_sustain }; +enum class SfzOffMode { fast = 0, normal, time }; +enum class SfzVelocityOverride { current = 0, previous }; +enum class SfzCrossfadeCurve { gain = 0, power }; +enum class SfzSelfMask { mask = 0, dontMask }; namespace sfz { +enum class OscillatorEnabled { Auto = -1, Off = 0, On = 1 }; + enum OpcodeFlags : int { kIgnoreOOB = 1, kEnforceLowerBound = 1 << 1, @@ -66,6 +68,7 @@ namespace Default extern const OpcodeSpec loopRange; extern const OpcodeSpec loopCrossfade; extern const OpcodeSpec oscillatorPhase; + extern const OpcodeSpec oscillator; extern const OpcodeSpec oscillatorMode; extern const OpcodeSpec oscillatorMulti; extern const OpcodeSpec oscillatorDetune; @@ -87,6 +90,8 @@ namespace Default extern const OpcodeSpec curveCC; extern const OpcodeSpec smoothCC; extern const OpcodeSpec sustainCC; + extern const OpcodeSpec checkSustain; + extern const OpcodeSpec checkSostenuto; extern const OpcodeSpec sustainThreshold; extern const OpcodeSpec bpm; extern const OpcodeSpec sequence; @@ -108,6 +113,7 @@ namespace Default extern const OpcodeSpec ampVeltrack; extern const OpcodeSpec ampVelcurve; extern const OpcodeSpec ampRandom; + extern const OpcodeSpec rtDead; extern const OpcodeSpec rtDecay; extern const OpcodeSpec filterCutoff; extern const OpcodeSpec filterCutoffMod; @@ -156,6 +162,7 @@ namespace Default extern const OpcodeSpec egPercentMod; extern const OpcodeSpec egDepth; extern const OpcodeSpec egVel2Depth; + extern const OpcodeSpec flexEGAmpeg; extern const OpcodeSpec flexEGDynamic; extern const OpcodeSpec flexEGSustain; extern const OpcodeSpec flexEGPointTime; @@ -175,6 +182,7 @@ namespace Default extern const OpcodeSpec compAttack; extern const OpcodeSpec compRelease; extern const OpcodeSpec compThreshold; + extern const OpcodeSpec compSTLink; extern const OpcodeSpec compRatio; extern const OpcodeSpec compGain; extern const OpcodeSpec fverbSize; @@ -183,6 +191,7 @@ namespace Default extern const OpcodeSpec fverbDamp; extern const OpcodeSpec gateAttack; extern const OpcodeSpec gateRelease; + extern const OpcodeSpec gateSTLink; extern const OpcodeSpec gateHold; extern const OpcodeSpec gateThreshold; extern const OpcodeSpec lofiBitred; @@ -190,11 +199,6 @@ namespace Default extern const OpcodeSpec rectify; extern const OpcodeSpec stringsNumber; - // Boolean default values - constexpr bool rtDead { false }; - constexpr bool checkSustain { true }; // sustain_sw - constexpr bool checkSostenuto { true }; // sostenuto_sw - // Default/max count for objects constexpr int numEQs { 3 }; constexpr int numFilters { 2 }; diff --git a/src/sfizz/FlexEGDescription.h b/src/sfizz/FlexEGDescription.h index 84d9078c..7788329d 100644 --- a/src/sfizz/FlexEGDescription.h +++ b/src/sfizz/FlexEGDescription.h @@ -35,7 +35,7 @@ struct FlexEGDescription { int sustain { Default::flexEGSustain.value }; // index of the sustain point (default to 0 in ARIA) std::vector points; // ARIA - bool ampeg = false; // replaces the SFZv1 AmpEG (lowest with this bit wins) + bool ampeg { Default::flexEGAmpeg.value }; // replaces the SFZv1 AmpEG (lowest with this bit wins) }; } // namespace sfz diff --git a/src/sfizz/Opcode.cpp b/src/sfizz/Opcode.cpp index 87f2e109..e7e3222a 100644 --- a/src/sfizz/Opcode.cpp +++ b/src/sfizz/Opcode.cpp @@ -294,6 +294,22 @@ absl::optional readBooleanFromOpcode(const Opcode& opcode) return absl::nullopt; } +template <> +absl::optional Opcode::read(OpcodeSpec) const +{ + auto v = readBooleanFromOpcode(*this); + if (!v) + return absl::nullopt; + + return *v ? OscillatorEnabled::On : OscillatorEnabled::Off; +} + +template <> +absl::optional Opcode::read(OpcodeSpec) const +{ + return readBooleanFromOpcode(*this); +} + } // namespace sfz std::ostream &operator<<(std::ostream &os, const sfz::Opcode &opcode) diff --git a/src/sfizz/Range.h b/src/sfizz/Range.h index 7bbe369f..04240553 100644 --- a/src/sfizz/Range.h +++ b/src/sfizz/Range.h @@ -19,7 +19,9 @@ namespace sfz */ template class Range { - static_assert(std::is_arithmetic::value, "The Type should be arithmetic"); + // static_assert(std::is_arithmetic::value + // || (std::is_enum::value && std::is_same::type, int>::value), + // "The Type should be arithmetic"); public: constexpr Range() = default; diff --git a/src/sfizz/Region.cpp b/src/sfizz/Region.cpp index 57848885..cc73a2d1 100644 --- a/src/sfizz/Region.cpp +++ b/src/sfizz/Region.cpp @@ -163,8 +163,7 @@ bool sfz::Region::parseOpcode(const Opcode& rawOpcode) oscillatorPhase = (*value >= 0) ? wrapPhase(*value) : -1.0f; break; case hash("oscillator"): - if (auto value = readBooleanFromOpcode(opcode)) - oscillatorEnabled = *value ? OscillatorEnabled::On : OscillatorEnabled::Off; + oscillatorEnabled = opcode.read(Default::oscillator).value_or(oscillatorEnabled); break; case hash("oscillator_mode"): oscillatorMode = opcode.read(Default::oscillatorMode).value_or(oscillatorMode); @@ -243,13 +242,7 @@ bool sfz::Region::parseOpcode(const Opcode& rawOpcode) } break; case hash("rt_dead"): - if (opcode.value == "on") { - rtDead = true; - } else if (opcode.value == "off") { - rtDead = false; - } else { - DBG("Unkown rt_dead value:" << opcode.value); - } + rtDead = opcode.read(Default::rtDead).value_or(rtDead); break; // Region logic: key mapping case hash("lokey"): @@ -387,10 +380,10 @@ bool sfz::Region::parseOpcode(const Opcode& rawOpcode) sustainThreshold = normalizeCC(*value); break; case hash("sustain_sw"): - checkSustain = readBooleanFromOpcode(opcode).value_or(Default::checkSustain); + checkSustain = opcode.read(Default::checkSustain).value_or(checkSustain); break; case hash("sostenuto_sw"): - checkSostenuto = readBooleanFromOpcode(opcode).value_or(Default::checkSostenuto); + checkSostenuto = opcode.read(Default::checkSostenuto).value_or(checkSostenuto); break; // Region logic: internal conditions case hash("lochanaft"): @@ -1263,7 +1256,7 @@ bool sfz::Region::parseOpcode(const Opcode& rawOpcode) return false; if (!extendIfNecessary(flexEGs, egNumber, Default::numFlexEGs)) return false; - if (auto ampeg = readBooleanFromOpcode(opcode)) { + if (auto ampeg = opcode.read(Default::flexEGAmpeg)) { FlexEGDescription& desc = flexEGs[egNumber - 1]; if (desc.ampeg != *ampeg) { desc.ampeg = *ampeg; diff --git a/src/sfizz/Region.h b/src/sfizz/Region.h index 87f39984..d7784767 100644 --- a/src/sfizz/Region.h +++ b/src/sfizz/Region.h @@ -332,8 +332,7 @@ struct Region { // Wavetable oscillator float oscillatorPhase { Default::oscillatorPhase.value }; - enum class OscillatorEnabled { Auto = -1, Off = 0, On = 1 }; - OscillatorEnabled oscillatorEnabled { OscillatorEnabled::Auto }; // oscillator + OscillatorEnabled oscillatorEnabled { Default::oscillator.value }; // oscillator bool hasWavetableSample { false }; // (set according to sample file) int oscillatorMode { Default::oscillatorMode.value }; int oscillatorMulti { Default::oscillatorMulti.value }; @@ -349,7 +348,7 @@ struct Region { absl::optional notePolyphony {}; // note_polyphony uint32_t polyphony { config::maxVoices }; // polyphony SfzSelfMask selfMask { Default::selfMask }; - bool rtDead { Default::rtDead }; + bool rtDead { Default::rtDead.value }; // Region logic: key mapping Range keyRange { Default::key.bounds }; //lokey, hikey and key @@ -366,8 +365,8 @@ struct Region { absl::optional previousKeyswitch {}; // sw_previous absl::optional defaultSwitch {}; SfzVelocityOverride velocityOverride { Default::velocityOverride }; // sw_vel - bool checkSustain { Default::checkSustain }; // sustain_sw - bool checkSostenuto { Default::checkSostenuto }; // sostenuto_sw + bool checkSustain { Default::checkSustain.value }; // sustain_sw + bool checkSostenuto { Default::checkSostenuto.value }; // sostenuto_sw uint16_t sustainCC { Default::sustainCC.value }; // sustain_cc float sustainThreshold { Default::sustainThreshold.value }; // sustain_cc diff --git a/src/sfizz/effects/Compressor.cpp b/src/sfizz/effects/Compressor.cpp index 06b805ee..94f4b242 100644 --- a/src/sfizz/effects/Compressor.cpp +++ b/src/sfizz/effects/Compressor.cpp @@ -31,7 +31,7 @@ namespace fx { struct Compressor::Impl { faustCompressor _compressor[2]; - bool _stlink = false; + bool _stlink { Default::compSTLink.value }; float _inputGain { Default::compGain.value }; AudioBuffer _tempBuffer2x { 2, _oversampling * config::defaultSamplesPerBlock }; AudioBuffer _gain2x { 2, _oversampling * config::defaultSamplesPerBlock }; @@ -191,8 +191,7 @@ namespace fx { impl._inputGain = db2mag(*value); break; case hash("comp_stlink"): - if (auto value = readBooleanFromOpcode(opc)) - impl._stlink = *value; + impl._stlink = opc.read(Default::compSTLink).value_or(impl._stlink); break; } } diff --git a/src/sfizz/effects/Gate.cpp b/src/sfizz/effects/Gate.cpp index 792060e6..a4a916a3 100644 --- a/src/sfizz/effects/Gate.cpp +++ b/src/sfizz/effects/Gate.cpp @@ -34,7 +34,7 @@ namespace fx { struct Gate::Impl { faustGate _gate[2]; - bool _stlink = false; + bool _stlink { Default::gateSTLink.value }; float _inputGain = 1.0; AudioBuffer _tempBuffer2x { 2, _oversampling * config::defaultSamplesPerBlock }; AudioBuffer _gain2x { 2, _oversampling * config::defaultSamplesPerBlock }; @@ -190,9 +190,7 @@ namespace fx { } break; case hash("gate_stlink"): - if (auto value = readBooleanFromOpcode(opc)) - impl._stlink = *value; - break; + impl._stlink = opc.read(Default::gateSTLink).value_or(impl._stlink); } } diff --git a/tests/FilesT.cpp b/tests/FilesT.cpp index 1072d188..2ed037a7 100644 --- a/tests/FilesT.cpp +++ b/tests/FilesT.cpp @@ -282,7 +282,7 @@ TEST_CASE("[Files] Channels (channels_multi.sfz)") REQUIRE(!region->isStereo()); REQUIRE(region->isGenerator()); REQUIRE(region->isOscillator()); - REQUIRE(region->oscillatorEnabled == Region::OscillatorEnabled::Auto); + REQUIRE(region->oscillatorEnabled == OscillatorEnabled::Auto); // generator with multi region = synth.getRegionView(regionNumber++); @@ -290,7 +290,7 @@ TEST_CASE("[Files] Channels (channels_multi.sfz)") REQUIRE(region->isStereo()); REQUIRE(region->isGenerator()); REQUIRE(region->isOscillator()); - REQUIRE(region->oscillatorEnabled == Region::OscillatorEnabled::Auto); + REQUIRE(region->oscillatorEnabled == OscillatorEnabled::Auto); // explicit wavetable region = synth.getRegionView(regionNumber++); @@ -298,7 +298,7 @@ TEST_CASE("[Files] Channels (channels_multi.sfz)") REQUIRE(!region->isStereo()); REQUIRE(!region->isGenerator()); REQUIRE(region->isOscillator()); - REQUIRE(region->oscillatorEnabled == Region::OscillatorEnabled::On); + REQUIRE(region->oscillatorEnabled == OscillatorEnabled::On); // explicit wavetable with multi region = synth.getRegionView(regionNumber++); @@ -306,7 +306,7 @@ TEST_CASE("[Files] Channels (channels_multi.sfz)") REQUIRE(region->isStereo()); REQUIRE(!region->isGenerator()); REQUIRE(region->isOscillator()); - REQUIRE(region->oscillatorEnabled == Region::OscillatorEnabled::On); + REQUIRE(region->oscillatorEnabled == OscillatorEnabled::On); // explicit disabled wavetable region = synth.getRegionView(regionNumber++); @@ -314,7 +314,7 @@ TEST_CASE("[Files] Channels (channels_multi.sfz)") REQUIRE(!region->isStereo()); REQUIRE(!region->isGenerator()); REQUIRE(!region->isOscillator()); - REQUIRE(region->oscillatorEnabled == Region::OscillatorEnabled::Off); + REQUIRE(region->oscillatorEnabled == OscillatorEnabled::Off); // explicit disabled wavetable with multi region = synth.getRegionView(regionNumber++); @@ -322,7 +322,7 @@ TEST_CASE("[Files] Channels (channels_multi.sfz)") REQUIRE(!region->isStereo()); REQUIRE(!region->isGenerator()); REQUIRE(!region->isOscillator()); - REQUIRE(region->oscillatorEnabled == Region::OscillatorEnabled::Off); + REQUIRE(region->oscillatorEnabled == OscillatorEnabled::Off); // implicit wavetable (sound file < 3000 frames) region = synth.getRegionView(regionNumber++); @@ -330,7 +330,7 @@ TEST_CASE("[Files] Channels (channels_multi.sfz)") REQUIRE(!region->isStereo()); REQUIRE(!region->isGenerator()); REQUIRE(region->isOscillator()); - REQUIRE(region->oscillatorEnabled == Region::OscillatorEnabled::Auto); + REQUIRE(region->oscillatorEnabled == OscillatorEnabled::Auto); // implicit non-wavetable (sound file >= 3000 frames) region = synth.getRegionView(regionNumber++); @@ -338,7 +338,7 @@ TEST_CASE("[Files] Channels (channels_multi.sfz)") REQUIRE(!region->isStereo()); REQUIRE(!region->isGenerator()); REQUIRE(!region->isOscillator()); - REQUIRE(region->oscillatorEnabled == Region::OscillatorEnabled::Auto); + REQUIRE(region->oscillatorEnabled == OscillatorEnabled::Auto); // generator with multi=1 (single) region = synth.getRegionView(regionNumber++); @@ -346,7 +346,7 @@ TEST_CASE("[Files] Channels (channels_multi.sfz)") REQUIRE(!region->isStereo()); REQUIRE(region->isGenerator()); REQUIRE(region->isOscillator()); - REQUIRE(region->oscillatorEnabled == Region::OscillatorEnabled::Auto); + REQUIRE(region->oscillatorEnabled == OscillatorEnabled::Auto); // generator with multi=2 (ring modulation) region = synth.getRegionView(regionNumber++); @@ -354,7 +354,7 @@ TEST_CASE("[Files] Channels (channels_multi.sfz)") REQUIRE(!region->isStereo()); REQUIRE(region->isGenerator()); REQUIRE(region->isOscillator()); - REQUIRE(region->oscillatorEnabled == Region::OscillatorEnabled::Auto); + REQUIRE(region->oscillatorEnabled == OscillatorEnabled::Auto); } TEST_CASE("[Files] wrong (overlapping) replacement for defines") diff --git a/tests/RegionValuesT.cpp b/tests/RegionValuesT.cpp index 0e2a38c0..a3e02417 100644 --- a/tests/RegionValuesT.cpp +++ b/tests/RegionValuesT.cpp @@ -2347,7 +2347,7 @@ TEST_CASE("[Values] Sustain switch") "/region0/sustain_sw,T : { }", "/region1/sustain_sw,F : { }", "/region2/sustain_sw,T : { }", - "/region3/sustain_sw,T : { }", + "/region3/sustain_sw,F : { }", }; REQUIRE(messageList == expected); } @@ -2373,7 +2373,7 @@ TEST_CASE("[Values] Sostenuto switch") "/region0/sostenuto_sw,T : { }", "/region1/sostenuto_sw,F : { }", "/region2/sostenuto_sw,T : { }", - "/region3/sostenuto_sw,T : { }", + "/region3/sostenuto_sw,F : { }", }; REQUIRE(messageList == expected); }