Added missing parts and pre-reserve the filters or EQs when necessary

This commit is contained in:
Paul Fd 2020-02-05 09:44:12 +01:00
parent 3c0cfac953
commit 0331739520
4 changed files with 93 additions and 21 deletions

View file

@ -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 };

View file

@ -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 };
};
}

View file

@ -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);

View file

@ -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")