From 0331739520a2c7c80bc21bb0bb95c52b9d8b726c Mon Sep 17 00:00:00 2001 From: Paul Fd Date: Wed, 5 Feb 2020 09:44:12 +0100 Subject: [PATCH] Added missing parts and pre-reserve the filters or EQs when necessary --- src/sfizz/Defaults.h | 11 ++++-- src/sfizz/FilterDescription.h | 2 ++ src/sfizz/Region.cpp | 68 +++++++++++++++++++++++++---------- tests/RegionT.cpp | 33 +++++++++++++++++ 4 files changed, 93 insertions(+), 21 deletions(-) diff --git a/src/sfizz/Defaults.h b/src/sfizz/Defaults.h index 8a7a171b..fed2e6c7 100644 --- a/src/sfizz/Defaults.h +++ b/src/sfizz/Defaults.h @@ -125,22 +125,29 @@ namespace Default constexpr Range rtDecayRange { 0.0f, 200.0f }; // Performance parameters: Filters + constexpr float numFilters { 2 }; constexpr float filterCutoff { 0 }; constexpr float filterResonance { 0 }; + constexpr float filterGain { 0 }; constexpr int filterKeytrack { 0 }; constexpr uint8_t filterKeycenter { 60 }; constexpr int filterRandom { 60 }; constexpr int filterVeltrack { 0 }; constexpr int filterCutoffCC { 0 }; constexpr float filterResonanceCC { 0 }; - constexpr Range filterCutoffRange { 0.0f, 96000.0f }; + constexpr float filterGainCC { 0 }; + constexpr Range filterCutoffRange { 0.0f, 20000.0f }; constexpr Range filterCutoffModRange { -9600, 9600 }; + constexpr Range filterGainRange { -96.0f, 24.0f }; + constexpr Range filterGainModRange { -96.0f, 24.0f }; constexpr Range filterKeytrackRange { 0, 1200 }; constexpr Range filterRandomRange { 0, 9600 }; constexpr Range filterVeltrackRange { -9600, 9600 }; - constexpr Range filterResonanceRange { 0, 40 }; + constexpr Range filterResonanceRange { 0.0f, 40.0f }; + constexpr Range filterResonanceModRange { 0.0f, 40.0f }; // Performance parameters: EQ + constexpr float numEQs { 3 }; constexpr float eqBandwidth { 1.0f }; constexpr float eqBandwidthCC { 0.0f }; constexpr float eqFrequencyUnset { 0.0f }; diff --git a/src/sfizz/FilterDescription.h b/src/sfizz/FilterDescription.h index 1bd21a6e..547e765b 100644 --- a/src/sfizz/FilterDescription.h +++ b/src/sfizz/FilterDescription.h @@ -10,6 +10,7 @@ struct FilterDescription { float cutoff { Default::filterCutoff }; float resonance { Default::filterCutoff }; + float gain { Default::filterGain }; int keytrack { Default::filterKeytrack }; uint8_t keycenter { Default::filterKeycenter }; int veltrack { Default::filterVeltrack }; @@ -17,5 +18,6 @@ struct FilterDescription FilterType type { FilterType::kFilterLpf2p }; CCMap cutoffCC { Default::filterCutoffCC }; CCMap resonanceCC { Default::filterResonanceCC }; + CCMap gainCC { Default::filterGainCC }; }; } diff --git a/src/sfizz/Region.cpp b/src/sfizz/Region.cpp index fb585b6a..408719a2 100644 --- a/src/sfizz/Region.cpp +++ b/src/sfizz/Region.cpp @@ -16,11 +16,14 @@ #include template -bool extendIfNecessary(std::vector& vec, unsigned size) +bool extendIfNecessary(std::vector& vec, unsigned size, unsigned defaultCapacity) { if (size == 0) return false; + if (vec.capacity() == 0) + vec.reserve(defaultCapacity); + if (vec.size() < size) vec.resize(size); @@ -397,7 +400,7 @@ bool sfz::Region::parseOpcode(const Opcode& opcode) case hash("cutoff"): { const auto filterIndex { backParameter.value_or(1) - 1 }; - if (!extendIfNecessary(filters, filterIndex + 1)) + if (!extendIfNecessary(filters, filterIndex + 1, Default::numFilters)) return false; setValueFromOpcode(opcode, filters[filterIndex].cutoff, Default::filterCutoffRange); } @@ -405,7 +408,7 @@ bool sfz::Region::parseOpcode(const Opcode& opcode) case hash("resonance"): { const auto filterIndex { backParameter.value_or(1) - 1 }; - if (!extendIfNecessary(filters, filterIndex + 1)) + if (!extendIfNecessary(filters, filterIndex + 1, Default::numFilters)) return false; setValueFromOpcode(opcode, filters[filterIndex].resonance, Default::filterResonanceRange); } @@ -416,7 +419,7 @@ bool sfz::Region::parseOpcode(const Opcode& opcode) return false; const auto filterIndex { opcode.firstParameter().value_or(1) - 1 }; - if (!extendIfNecessary(filters, filterIndex + 1)) + if (!extendIfNecessary(filters, filterIndex + 1, Default::numFilters)) return false; setValueFromOpcode( @@ -432,20 +435,20 @@ bool sfz::Region::parseOpcode(const Opcode& opcode) return false; const auto filterIndex { opcode.firstParameter().value_or(1) - 1 }; - if (!extendIfNecessary(filters, filterIndex + 1)) + if (!extendIfNecessary(filters, filterIndex + 1, Default::numFilters)) return false; setValueFromOpcode( opcode, filters[filterIndex].resonanceCC[*backParameter], - Default::filterResonanceRange + Default::filterResonanceModRange ); } break; case hash("fil_keytrack"): { const auto filterIndex { opcode.firstParameter().value_or(1) - 1 }; - if (!extendIfNecessary(filters, filterIndex + 1)) + if (!extendIfNecessary(filters, filterIndex + 1, Default::numFilters)) return false; setValueFromOpcode(opcode, filters[filterIndex].keytrack, Default::filterKeytrackRange); @@ -454,7 +457,7 @@ bool sfz::Region::parseOpcode(const Opcode& opcode) case hash("fil_keycenter"): { const auto filterIndex { opcode.firstParameter().value_or(1) - 1 }; - if (!extendIfNecessary(filters, filterIndex + 1)) + if (!extendIfNecessary(filters, filterIndex + 1, Default::numFilters)) return false; setValueFromOpcode(opcode, filters[filterIndex].keycenter, Default::keyRange); @@ -463,7 +466,7 @@ bool sfz::Region::parseOpcode(const Opcode& opcode) case hash("fil_veltrack"): { const auto filterIndex { opcode.firstParameter().value_or(1) - 1 }; - if (!extendIfNecessary(filters, filterIndex + 1)) + if (!extendIfNecessary(filters, filterIndex + 1, Default::numFilters)) return false; setValueFromOpcode(opcode, filters[filterIndex].veltrack, Default::filterVeltrackRange); @@ -472,16 +475,41 @@ bool sfz::Region::parseOpcode(const Opcode& opcode) case hash("fil_random"): { const auto filterIndex { opcode.firstParameter().value_or(1) - 1 }; - if (!extendIfNecessary(filters, filterIndex + 1)) + if (!extendIfNecessary(filters, filterIndex + 1, Default::numFilters)) return false; setValueFromOpcode(opcode, filters[filterIndex].random, Default::filterRandomRange); } break; + case hash("fil_gain"): + { + const auto filterIndex { opcode.firstParameter().value_or(1) - 1 }; + if (!extendIfNecessary(filters, filterIndex + 1, Default::numFilters)) + return false; + + setValueFromOpcode(opcode, filters[filterIndex].gain, Default::filterGainRange); + } + break; + case hash("fil_gaincc"): + { + if (!backParameter) + return false; + + const auto filterIndex { opcode.firstParameter().value_or(1) - 1 }; + if (!extendIfNecessary(filters, filterIndex + 1, Default::numFilters)) + return false; + + setValueFromOpcode( + opcode, + filters[filterIndex].gainCC[*backParameter], + Default::filterGainModRange + ); + } + break; case hash("fil_type"): { const auto filterIndex { opcode.firstParameter().value_or(1) - 1 }; - if (!extendIfNecessary(filters, filterIndex + 1)) + if (!extendIfNecessary(filters, filterIndex + 1, Default::numFilters)) return false; switch (hash(opcode.value)) { @@ -505,6 +533,7 @@ bool sfz::Region::parseOpcode(const Opcode& opcode) case hash("pink"): filters[filterIndex].type = FilterType::kFilterPink; break; case hash("lsh"): filters[filterIndex].type = FilterType::kFilterLsh; break; case hash("hsh"): filters[filterIndex].type = FilterType::kFilterHsh; break; + case hash("pkf_2p"): [[fallthrough]]; case hash("peq"): filters[filterIndex].type = FilterType::kFilterPeq; break; default: filters[filterIndex].type = FilterType::kFilterNone; @@ -512,13 +541,14 @@ bool sfz::Region::parseOpcode(const Opcode& opcode) } } break; + // Performance parameters: EQ case hash("eq_bw"): { const auto eqNumber = opcode.firstParameter(); if (!eqNumber || *eqNumber == 0) return false; - if (!extendIfNecessary(equalizers, *eqNumber)) + if (!extendIfNecessary(equalizers, *eqNumber, Default::numEQs)) return false; setValueFromOpcode(opcode, equalizers[*eqNumber - 1].bandwidth, Default::eqBandwidthRange); } @@ -531,7 +561,7 @@ bool sfz::Region::parseOpcode(const Opcode& opcode) return false; if (!backParameter) return false; - if (!extendIfNecessary(equalizers, *eqNumber)) + if (!extendIfNecessary(equalizers, *eqNumber, Default::numEQs)) return false; setValueFromOpcode(opcode, equalizers[*eqNumber - 1].bandwidthCC[*backParameter], Default::eqBandwidthModRange); @@ -542,7 +572,7 @@ bool sfz::Region::parseOpcode(const Opcode& opcode) const auto eqNumber = opcode.firstParameter(); if (!eqNumber || *eqNumber == 0) return false; - if (!extendIfNecessary(equalizers, *eqNumber)) + if (!extendIfNecessary(equalizers, *eqNumber, Default::numEQs)) return false; setValueFromOpcode(opcode, equalizers[*eqNumber - 1].frequency, Default::eqFrequencyRange); } @@ -555,7 +585,7 @@ bool sfz::Region::parseOpcode(const Opcode& opcode) return false; if (!backParameter) return false; - if (!extendIfNecessary(equalizers, *eqNumber)) + if (!extendIfNecessary(equalizers, *eqNumber, Default::numEQs)) return false; setValueFromOpcode(opcode, equalizers[*eqNumber - 1].frequencyCC[*backParameter], Default::eqFrequencyModRange); @@ -569,7 +599,7 @@ bool sfz::Region::parseOpcode(const Opcode& opcode) return false; if (!check2 || *check2 != 2 || opcode.parameterPositions[1] != 6) return false; // was eqN_vel3freq or something else than eqN_vel2freq - if (!extendIfNecessary(equalizers, *eqNumber)) + if (!extendIfNecessary(equalizers, *eqNumber, Default::numEQs)) return false; setValueFromOpcode(opcode, equalizers[*eqNumber - 1].vel2frequency, Default::eqFrequencyModRange); @@ -580,7 +610,7 @@ bool sfz::Region::parseOpcode(const Opcode& opcode) const auto eqNumber = opcode.firstParameter(); if (!eqNumber || *eqNumber == 0) return false; - if (!extendIfNecessary(equalizers, *eqNumber)) + if (!extendIfNecessary(equalizers, *eqNumber, Default::numEQs)) return false; setValueFromOpcode(opcode, equalizers[*eqNumber - 1].gain, Default::eqGainRange); } @@ -593,7 +623,7 @@ bool sfz::Region::parseOpcode(const Opcode& opcode) return false; if (!backParameter) return false; - if (!extendIfNecessary(equalizers, *eqNumber)) + if (!extendIfNecessary(equalizers, *eqNumber, Default::numEQs)) return false; setValueFromOpcode(opcode, equalizers[*eqNumber - 1].gainCC[*backParameter], Default::eqGainModRange); @@ -607,7 +637,7 @@ bool sfz::Region::parseOpcode(const Opcode& opcode) return false; if (!check2 || *check2 != 2 || opcode.parameterPositions[1] != 6) return false; // was eqN_vel3gain or something else than eqN_vel2gain - if (!extendIfNecessary(equalizers, *eqNumber)) + if (!extendIfNecessary(equalizers, *eqNumber, Default::numEQs)) return false; setValueFromOpcode(opcode, equalizers[*eqNumber - 1].vel2gain, Default::eqGainModRange); diff --git a/tests/RegionT.cpp b/tests/RegionT.cpp index 35ea0597..20b05507 100644 --- a/tests/RegionT.cpp +++ b/tests/RegionT.cpp @@ -1041,9 +1041,11 @@ TEST_CASE("[Region] Parsing opcodes") REQUIRE(region.filters[0].keycenter == 60); REQUIRE(region.filters[0].type == sfz::FilterType::kFilterLpf2p); REQUIRE(region.filters[0].keytrack == 0); + REQUIRE(region.filters[0].gain == 0); REQUIRE(region.filters[0].veltrack == 0); REQUIRE(region.filters[0].resonance == 0.0f); REQUIRE(region.filters[0].cutoffCC.empty()); + REQUIRE(region.filters[0].gainCC.empty()); REQUIRE(region.filters[0].resonanceCC.empty()); region.parseOpcode({ "cutoff2", "5000" }); @@ -1053,9 +1055,11 @@ TEST_CASE("[Region] Parsing opcodes") REQUIRE(region.filters[1].keycenter == 60); REQUIRE(region.filters[1].type == sfz::FilterType::kFilterLpf2p); REQUIRE(region.filters[1].keytrack == 0); + REQUIRE(region.filters[1].gain == 0); REQUIRE(region.filters[1].veltrack == 0); REQUIRE(region.filters[1].resonance == 0.0f); REQUIRE(region.filters[1].cutoffCC.empty()); + REQUIRE(region.filters[1].gainCC.empty()); REQUIRE(region.filters[1].resonanceCC.empty()); region.parseOpcode({ "cutoff4", "50" }); @@ -1066,16 +1070,20 @@ TEST_CASE("[Region] Parsing opcodes") REQUIRE(region.filters[2].keycenter == 60); REQUIRE(region.filters[2].type == sfz::FilterType::kFilterLpf2p); REQUIRE(region.filters[2].keytrack == 0); + REQUIRE(region.filters[2].gain == 0); REQUIRE(region.filters[2].veltrack == 0); REQUIRE(region.filters[2].resonance == 0.0f); REQUIRE(region.filters[2].cutoffCC.empty()); + REQUIRE(region.filters[2].gainCC.empty()); REQUIRE(region.filters[2].resonanceCC.empty()); REQUIRE(region.filters[3].keycenter == 60); REQUIRE(region.filters[3].type == sfz::FilterType::kFilterLpf2p); REQUIRE(region.filters[3].keytrack == 0); + REQUIRE(region.filters[3].gain == 0); REQUIRE(region.filters[3].veltrack == 0); REQUIRE(region.filters[3].resonance == 0.0f); REQUIRE(region.filters[3].cutoffCC.empty()); + REQUIRE(region.filters[3].gainCC.empty()); REQUIRE(region.filters[3].resonanceCC.empty()); } @@ -1086,6 +1094,12 @@ TEST_CASE("[Region] Parsing opcodes") REQUIRE(region.filters[2].cutoff == 50.0f); region.parseOpcode({ "resonance2", "3" }); REQUIRE(region.filters[1].resonance == 3.0f); + region.parseOpcode({ "fil2_gain", "-5" }); + REQUIRE(region.filters[1].gain == -5.0f); + region.parseOpcode({ "fil_gain", "5" }); + REQUIRE(region.filters[0].gain == 5.0f); + region.parseOpcode({ "fil1_gain", "-5" }); + REQUIRE(region.filters[0].gain == -5.0f); region.parseOpcode({ "fil2_veltrack", "-100" }); REQUIRE(region.filters[1].veltrack == -100); region.parseOpcode({ "fil3_keytrack", "100" }); @@ -1097,6 +1111,10 @@ TEST_CASE("[Region] Parsing opcodes") region.parseOpcode({ "resonance3_cc24", "10" }); REQUIRE(region.filters[2].resonanceCC.contains(24)); REQUIRE(region.filters[2].resonanceCC[24] == 10); + region.parseOpcode({ "fil2_gaincc12", "-50" }); + REQUIRE(region.filters[1].gainCC.contains(12)); + REQUIRE(region.filters[1].gainCC[12] == -50.0f); + } SECTION("Filter values") @@ -1138,6 +1156,21 @@ TEST_CASE("[Region] Parsing opcodes") REQUIRE(region.filters[0].keycenter == 127); region.parseOpcode({ "fil_keycenter", "c4" }); REQUIRE(region.filters[0].keycenter == 60); + + region.parseOpcode({ "fil_gain", "25" }); + REQUIRE(region.filters[0].gain == 24.0f); + region.parseOpcode({ "fil_gain", "-200" }); + REQUIRE(region.filters[0].gain == -96.0f); + + region.parseOpcode({ "cutoff_cc43", "10000" }); + REQUIRE(region.filters[0].cutoffCC[43] == 9600); + region.parseOpcode({ "cutoff_cc43", "-10000" }); + REQUIRE(region.filters[0].cutoffCC[43] == -9600); + + region.parseOpcode({ "resonance_cc43", "100" }); + REQUIRE(region.filters[0].resonanceCC[43] == 40.0f); + region.parseOpcode({ "resonance_cc43", "-5" }); + REQUIRE(region.filters[0].resonanceCC[43] == 0.0f); } SECTION("Filter types")