Fix CC modulations, having their source depth to 0
This commit is contained in:
parent
5ffd36393f
commit
b0e102c77e
11 changed files with 54 additions and 43 deletions
|
|
@ -1550,7 +1550,7 @@ bool sfz::Region::processGenericCc(const Opcode& opcode, Range<float> range, con
|
|||
else {
|
||||
connections.emplace_back();
|
||||
conn = &connections.back();
|
||||
conn->source = ModKey::createCC(ccNumber, 0, 0, 0, 0);
|
||||
conn->source = ModKey::createCC(ccNumber, 0, 0, 0);
|
||||
conn->target = target;
|
||||
}
|
||||
|
||||
|
|
@ -1558,7 +1558,7 @@ bool sfz::Region::processGenericCc(const Opcode& opcode, Range<float> range, con
|
|||
ModKey::Parameters p = conn->source.parameters();
|
||||
switch (opcode.category) {
|
||||
case kOpcodeOnCcN:
|
||||
setValueFromOpcode(opcode, p.value, range);
|
||||
setValueFromOpcode(opcode, conn->sourceDepth, range);
|
||||
break;
|
||||
case kOpcodeCurveCcN:
|
||||
setValueFromOpcode(opcode, p.curve, Default::curveCCRange);
|
||||
|
|
|
|||
|
|
@ -145,11 +145,11 @@ void sfz::Synth::buildRegion(const std::vector<Opcode>& regionOpcodes)
|
|||
// Create default connections
|
||||
constexpr unsigned defaultSmoothness = 10;
|
||||
lastRegion->getOrCreateConnection(
|
||||
ModKey::createCC(7, 4, defaultSmoothness, 100, 0),
|
||||
ModKey::createNXYZ(ModId::Amplitude, lastRegion->id)).sourceDepth = 1.0f;
|
||||
ModKey::createCC(7, 4, defaultSmoothness, 0),
|
||||
ModKey::createNXYZ(ModId::Amplitude, lastRegion->id)).sourceDepth = 100.0f;
|
||||
lastRegion->getOrCreateConnection(
|
||||
ModKey::createCC(10, 1, defaultSmoothness, 100, 0),
|
||||
ModKey::createNXYZ(ModId::Pan, lastRegion->id)).sourceDepth = 1.0f;
|
||||
ModKey::createCC(10, 1, defaultSmoothness, 0),
|
||||
ModKey::createNXYZ(ModId::Pan, lastRegion->id)).sourceDepth = 100.0f;
|
||||
|
||||
//
|
||||
auto parseOpcodes = [&](const std::vector<Opcode>& opcodes) {
|
||||
|
|
|
|||
|
|
@ -30,13 +30,12 @@ ModKey::Parameters& ModKey::Parameters::operator=(const Parameters& other) noexc
|
|||
return *this;
|
||||
}
|
||||
|
||||
ModKey ModKey::createCC(uint16_t cc, uint8_t curve, uint8_t smooth, float value, float step)
|
||||
ModKey ModKey::createCC(uint16_t cc, uint8_t curve, uint8_t smooth, float step)
|
||||
{
|
||||
ModKey::Parameters p;
|
||||
p.cc = cc;
|
||||
p.curve = curve;
|
||||
p.smooth = smooth;
|
||||
p.value = value;
|
||||
p.step = step;
|
||||
return ModKey(ModId::Controller, {}, p);
|
||||
}
|
||||
|
|
@ -69,7 +68,7 @@ std::string ModKey::toString() const
|
|||
case ModId::Controller:
|
||||
return absl::StrCat("Controller ", params_.cc,
|
||||
" {curve=", params_.curve, ", smooth=", params_.smooth,
|
||||
", value=", params_.value, ", step=", params_.step, "}");
|
||||
", step=", params_.step, "}");
|
||||
case ModId::Envelope:
|
||||
return absl::StrCat("EG ", 1 + params_.N, " {", region_.number(), "}");
|
||||
case ModId::LFO:
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ public:
|
|||
explicit ModKey(ModId id, NumericId<Region> region = {}, Parameters params = {})
|
||||
: id_(id), region_(region), params_(params), flags_(ModIds::flags(id_)) {}
|
||||
|
||||
static ModKey createCC(uint16_t cc, uint8_t curve, uint8_t smooth, float value, float step);
|
||||
static ModKey createCC(uint16_t cc, uint8_t curve, uint8_t smooth, float step);
|
||||
static ModKey createNXYZ(ModId id, NumericId<Region> region, uint8_t N = 0, uint8_t X = 0, uint8_t Y = 0, uint8_t Z = 0);
|
||||
|
||||
explicit operator bool() const noexcept { return id_ != ModId(); }
|
||||
|
|
@ -62,7 +62,7 @@ public:
|
|||
|
||||
union {
|
||||
//! Parameters if this key identifies a CC source
|
||||
struct { uint16_t cc; uint8_t curve, smooth; float value, step; };
|
||||
struct { uint16_t cc; uint8_t curve, smooth; float step; };
|
||||
//! Parameters otherwise, based on the related opcode
|
||||
// eg. `N` in `lfoN`, `N, X` in `lfoN_eqX`
|
||||
struct { uint8_t N, X, Y, Z; };
|
||||
|
|
|
|||
|
|
@ -20,7 +20,6 @@ size_t std::hash<sfz::ModKey>::operator()(const sfz::ModKey &key) const
|
|||
k = hashNumber(p.cc, k);
|
||||
k = hashNumber(p.curve, k);
|
||||
k = hashNumber(p.smooth, k);
|
||||
k = hashNumber(p.value, k);
|
||||
k = hashNumber(p.step, k);
|
||||
break;
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ void ControllerSource::generate(const ModKey& sourceKey, NumericId<Voice> voiceI
|
|||
const EventVector& events = ms.getCCEvents(p.cc);
|
||||
|
||||
auto transformValue = [p, &curve](float x) {
|
||||
return curve.evalNormalized(x) * p.value;
|
||||
return curve.evalNormalized(x);
|
||||
};
|
||||
|
||||
if (p.step > 0.0f)
|
||||
|
|
|
|||
|
|
@ -416,7 +416,7 @@ TEST_CASE("[Files] wrong (overlapping) replacement for defines")
|
|||
const ModKey target = ModKey::createNXYZ(ModId::Amplitude, synth.getRegionView(2)->getId());
|
||||
const RegionCCView view(*synth.getRegionView(2), target);
|
||||
REQUIRE(!view.empty());
|
||||
REQUIRE(view.at(10).value == 34.0f);
|
||||
REQUIRE(view.valueAt(10) == 34.0f);
|
||||
}
|
||||
|
||||
TEST_CASE("[Files] Specific bug: relative path with backslashes")
|
||||
|
|
|
|||
|
|
@ -93,10 +93,10 @@ width_oncc425=29
|
|||
|
||||
const std::string graph = synth.getResources().modMatrix.toDotGraph();
|
||||
REQUIRE(graph == createDefaultGraph({
|
||||
R"("Controller 20 {curve=3, smooth=0, value=59, step=0}" -> "Amplitude {0}")",
|
||||
R"("Controller 42 {curve=0, smooth=32, value=71, step=0}" -> "Pitch {0}")",
|
||||
R"("Controller 36 {curve=0, smooth=0, value=14.5, step=1.5}" -> "Pan {0}")",
|
||||
R"("Controller 425 {curve=0, smooth=0, value=29, step=0}" -> "Width {0}")",
|
||||
R"("Controller 20 {curve=3, smooth=0, step=0}" -> "Amplitude {0}")",
|
||||
R"("Controller 42 {curve=0, smooth=32, step=0}" -> "Pitch {0}")",
|
||||
R"("Controller 36 {curve=0, smooth=0, step=1.5}" -> "Pan {0}")",
|
||||
R"("Controller 425 {curve=0, smooth=0, step=0}" -> "Width {0}")",
|
||||
}));
|
||||
}
|
||||
|
||||
|
|
@ -112,9 +112,9 @@ TEST_CASE("[Modulations] Filter CC connections")
|
|||
|
||||
const std::string graph = synth.getResources().modMatrix.toDotGraph();
|
||||
REQUIRE(graph == createDefaultGraph({
|
||||
R"("Controller 1 {curve=0, smooth=10, value=2, step=0}" -> "FilterResonance {0, N=3}")",
|
||||
R"("Controller 2 {curve=2, smooth=0, value=100, step=0}" -> "FilterCutoff {0, N=2}")",
|
||||
R"("Controller 3 {curve=0, smooth=0, value=5, step=0.5}" -> "FilterGain {0, N=1}")",
|
||||
R"("Controller 1 {curve=0, smooth=10, step=0}" -> "FilterResonance {0, N=3}")",
|
||||
R"("Controller 2 {curve=2, smooth=0, step=0}" -> "FilterCutoff {0, N=2}")",
|
||||
R"("Controller 3 {curve=0, smooth=0, step=0.5}" -> "FilterGain {0, N=1}")",
|
||||
}));
|
||||
}
|
||||
|
||||
|
|
@ -130,9 +130,9 @@ TEST_CASE("[Modulations] EQ CC connections")
|
|||
|
||||
const std::string graph = synth.getResources().modMatrix.toDotGraph();
|
||||
REQUIRE(graph == createDefaultGraph({
|
||||
R"("Controller 1 {curve=0, smooth=10, value=2, step=0}" -> "EqBandwidth {0, N=3}")",
|
||||
R"("Controller 2 {curve=0, smooth=0, value=5, step=0.5}" -> "EqGain {0, N=1}")",
|
||||
R"("Controller 3 {curve=3, smooth=0, value=300, step=0}" -> "EqFrequency {0, N=2}")",
|
||||
R"("Controller 1 {curve=0, smooth=10, step=0}" -> "EqBandwidth {0, N=3}")",
|
||||
R"("Controller 2 {curve=0, smooth=0, step=0.5}" -> "EqGain {0, N=1}")",
|
||||
R"("Controller 3 {curve=3, smooth=0, step=0}" -> "EqFrequency {0, N=2}")",
|
||||
}));
|
||||
}
|
||||
|
||||
|
|
@ -248,8 +248,8 @@ TEST_CASE("[Modulations] FlexEG Ampeg target")
|
|||
|
||||
const std::string graph = synth.getResources().modMatrix.toDotGraph();
|
||||
REQUIRE(graph == createModulationDotGraph({
|
||||
R"("Controller 10 {curve=1, smooth=10, value=100, step=0}" -> "Pan {0}")",
|
||||
R"("Controller 7 {curve=4, smooth=10, value=100, step=0}" -> "Amplitude {0}")",
|
||||
R"("Controller 10 {curve=1, smooth=10, step=0}" -> "Pan {0}")",
|
||||
R"("Controller 7 {curve=4, smooth=10, step=0}" -> "Amplitude {0}")",
|
||||
R"("EG 1 {0}" -> "MasterAmplitude {0}")",
|
||||
}));
|
||||
}
|
||||
|
|
@ -272,8 +272,8 @@ TEST_CASE("[Modulations] FlexEG Ampeg target with 2 FlexEGs")
|
|||
|
||||
const std::string graph = synth.getResources().modMatrix.toDotGraph();
|
||||
REQUIRE(graph == createModulationDotGraph({
|
||||
R"("Controller 10 {curve=1, smooth=10, value=100, step=0}" -> "Pan {0}")",
|
||||
R"("Controller 7 {curve=4, smooth=10, value=100, step=0}" -> "Amplitude {0}")",
|
||||
R"("Controller 10 {curve=1, smooth=10, step=0}" -> "Pan {0}")",
|
||||
R"("Controller 7 {curve=4, smooth=10, step=0}" -> "Amplitude {0}")",
|
||||
R"("EG 2 {0}" -> "MasterAmplitude {0}")",
|
||||
}));
|
||||
}
|
||||
|
|
@ -298,8 +298,8 @@ TEST_CASE("[Modulations] FlexEG Ampeg target with multiple EGs targeting ampeg")
|
|||
|
||||
const std::string graph = synth.getResources().modMatrix.toDotGraph();
|
||||
REQUIRE(graph == createModulationDotGraph({
|
||||
R"("Controller 10 {curve=1, smooth=10, value=100, step=0}" -> "Pan {0}")",
|
||||
R"("Controller 7 {curve=4, smooth=10, value=100, step=0}" -> "Amplitude {0}")",
|
||||
R"("Controller 10 {curve=1, smooth=10, step=0}" -> "Pan {0}")",
|
||||
R"("Controller 7 {curve=4, smooth=10, step=0}" -> "Amplitude {0}")",
|
||||
R"("EG 1 {0}" -> "MasterAmplitude {0}")",
|
||||
}));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -572,7 +572,7 @@ TEST_CASE("[Region] Parsing opcodes")
|
|||
const RegionCCView view(region, target);
|
||||
REQUIRE(view.empty());
|
||||
region.parseOpcode({ "pan_oncc45", "4.2" });
|
||||
REQUIRE(view.at(45).value == 4.2_a);
|
||||
REQUIRE(view.valueAt(45) == 4.2_a);
|
||||
region.parseOpcode({ "pan_curvecc17", "18" });
|
||||
REQUIRE(view.at(17).curve == 18);
|
||||
region.parseOpcode({ "pan_curvecc17", "15482" });
|
||||
|
|
@ -612,7 +612,7 @@ TEST_CASE("[Region] Parsing opcodes")
|
|||
const RegionCCView view(region, target);
|
||||
REQUIRE(view.empty());
|
||||
region.parseOpcode({ "width_oncc45", "4.2" });
|
||||
REQUIRE(view.at(45).value == 4.2_a);
|
||||
REQUIRE(view.valueAt(45) == 4.2_a);
|
||||
region.parseOpcode({ "width_curvecc17", "18" });
|
||||
REQUIRE(view.at(17).curve == 18);
|
||||
region.parseOpcode({ "width_curvecc17", "15482" });
|
||||
|
|
@ -652,7 +652,7 @@ TEST_CASE("[Region] Parsing opcodes")
|
|||
const RegionCCView view(region, target);
|
||||
REQUIRE(view.empty());
|
||||
region.parseOpcode({ "position_oncc45", "4.2" });
|
||||
REQUIRE(view.at(45).value == 4.2_a);
|
||||
REQUIRE(view.valueAt(45) == 4.2_a);
|
||||
region.parseOpcode({ "position_curvecc17", "18" });
|
||||
REQUIRE(view.at(17).curve == 18);
|
||||
region.parseOpcode({ "position_curvecc17", "15482" });
|
||||
|
|
@ -1649,9 +1649,9 @@ TEST_CASE("[Region] Parsing opcodes")
|
|||
const RegionCCView view(region, target);
|
||||
REQUIRE(view.empty());
|
||||
region.parseOpcode({ "amplitude_cc1", "40" });
|
||||
REQUIRE(view.at(1).value == 40.0_a);
|
||||
REQUIRE(view.valueAt(1) == 40.0_a);
|
||||
region.parseOpcode({ "amplitude_oncc2", "30" });
|
||||
REQUIRE(view.at(2).value == 30.0_a);
|
||||
REQUIRE(view.valueAt(2) == 30.0_a);
|
||||
region.parseOpcode({ "amplitude_curvecc17", "18" });
|
||||
REQUIRE(view.at(17).curve == 18);
|
||||
region.parseOpcode({ "amplitude_curvecc17", "15482" });
|
||||
|
|
@ -1678,11 +1678,11 @@ TEST_CASE("[Region] Parsing opcodes")
|
|||
const RegionCCView view(region, target);
|
||||
REQUIRE(view.empty());
|
||||
region.parseOpcode({ "gain_cc1", "40" });
|
||||
REQUIRE(view.at(1).value == 40_a);
|
||||
REQUIRE(view.valueAt(1) == 40_a);
|
||||
region.parseOpcode({ "volume_oncc2", "-76" });
|
||||
REQUIRE(view.at(2).value == -76.0_a);
|
||||
REQUIRE(view.valueAt(2) == -76.0_a);
|
||||
region.parseOpcode({ "gain_oncc4", "-1" });
|
||||
REQUIRE(view.at(4).value == -1.0_a);
|
||||
REQUIRE(view.valueAt(4) == -1.0_a);
|
||||
region.parseOpcode({ "volume_curvecc17", "18" });
|
||||
REQUIRE(view.at(17).curve == 18);
|
||||
region.parseOpcode({ "volume_curvecc17", "15482" });
|
||||
|
|
@ -1709,11 +1709,11 @@ TEST_CASE("[Region] Parsing opcodes")
|
|||
const RegionCCView view(region, target);
|
||||
REQUIRE(view.empty());
|
||||
region.parseOpcode({ "pitch_cc1", "40" });
|
||||
REQUIRE(view.at(1).value == 40.0);
|
||||
REQUIRE(view.valueAt(1) == 40.0);
|
||||
region.parseOpcode({ "tune_oncc2", "-76" });
|
||||
REQUIRE(view.at(2).value == -76.0);
|
||||
REQUIRE(view.valueAt(2) == -76.0);
|
||||
region.parseOpcode({ "pitch_oncc4", "-1" });
|
||||
REQUIRE(view.at(4).value == -1.0);
|
||||
REQUIRE(view.valueAt(4) == -1.0);
|
||||
region.parseOpcode({ "tune_curvecc17", "18" });
|
||||
REQUIRE(view.at(17).curve == 18);
|
||||
region.parseOpcode({ "pitch_curvecc17", "15482" });
|
||||
|
|
|
|||
|
|
@ -35,6 +35,18 @@ sfz::ModKey::Parameters RegionCCView::at(int cc) const
|
|||
throw std::out_of_range("Region CC");
|
||||
}
|
||||
|
||||
float RegionCCView::valueAt(int cc) const
|
||||
{
|
||||
for (const sfz::Region::Connection& conn : region_.connections) {
|
||||
if (match(conn)) {
|
||||
const sfz::ModKey::Parameters p = conn.source.parameters();
|
||||
if (p.cc == cc)
|
||||
return conn.sourceDepth;
|
||||
}
|
||||
}
|
||||
throw std::out_of_range("Region CC");
|
||||
}
|
||||
|
||||
bool RegionCCView::match(const sfz::Region::Connection& conn) const
|
||||
{
|
||||
return conn.source.id() == sfz::ModId::Controller && conn.target == target_;
|
||||
|
|
@ -76,12 +88,12 @@ std::string createDefaultGraph(std::vector<std::string> lines, int numRegions)
|
|||
R"("AmplitudeEG {)", regionIdx, R"(}" -> "MasterAmplitude {)", regionIdx, R"(}")"
|
||||
));
|
||||
lines.push_back(absl::StrCat(
|
||||
R"("Controller 7 {curve=4, smooth=10, value=100, step=0}" -> "Amplitude {)",
|
||||
R"("Controller 7 {curve=4, smooth=10, step=0}" -> "Amplitude {)",
|
||||
regionIdx,
|
||||
R"(}")"
|
||||
));
|
||||
lines.push_back(absl::StrCat(
|
||||
R"("Controller 10 {curve=1, smooth=10, value=100, step=0}" -> "Pan {)",
|
||||
R"("Controller 10 {curve=1, smooth=10, step=0}" -> "Pan {)",
|
||||
regionIdx,
|
||||
R"(}")"
|
||||
));
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ public:
|
|||
size_t size() const;
|
||||
bool empty() const;
|
||||
sfz::ModKey::Parameters at(int cc) const;
|
||||
float valueAt(int cc) const;
|
||||
|
||||
private:
|
||||
bool match(const sfz::Region::Connection& conn) const;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue