Added missing parts and pre-reserve the filters or EQs when necessary
This commit is contained in:
parent
3c0cfac953
commit
0331739520
4 changed files with 93 additions and 21 deletions
|
|
@ -125,22 +125,29 @@ namespace Default
|
|||
constexpr Range<float> 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<float> filterCutoffRange { 0.0f, 96000.0f };
|
||||
constexpr float filterGainCC { 0 };
|
||||
constexpr Range<float> filterCutoffRange { 0.0f, 20000.0f };
|
||||
constexpr Range<int> filterCutoffModRange { -9600, 9600 };
|
||||
constexpr Range<float> filterGainRange { -96.0f, 24.0f };
|
||||
constexpr Range<float> filterGainModRange { -96.0f, 24.0f };
|
||||
constexpr Range<int> filterKeytrackRange { 0, 1200 };
|
||||
constexpr Range<int> filterRandomRange { 0, 9600 };
|
||||
constexpr Range<int> filterVeltrackRange { -9600, 9600 };
|
||||
constexpr Range<float> filterResonanceRange { 0, 40 };
|
||||
constexpr Range<float> filterResonanceRange { 0.0f, 40.0f };
|
||||
constexpr Range<float> 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 };
|
||||
|
|
|
|||
|
|
@ -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<int> cutoffCC { Default::filterCutoffCC };
|
||||
CCMap<float> resonanceCC { Default::filterResonanceCC };
|
||||
CCMap<float> gainCC { Default::filterGainCC };
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,11 +16,14 @@
|
|||
#include <random>
|
||||
|
||||
template<class T>
|
||||
bool extendIfNecessary(std::vector<T>& vec, unsigned size)
|
||||
bool extendIfNecessary(std::vector<T>& 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);
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue