Allow to set a multiplier on source, needed for LFO

This commit is contained in:
Jean Pierre Cimalando 2020-07-28 13:52:38 +02:00
parent 4703b939ab
commit 0b20932e12
6 changed files with 28 additions and 21 deletions

View file

@ -940,9 +940,9 @@ bool sfz::Region::processGenericCc(const Opcode& opcode, Range<float> range, con
auto it = std::find_if(connections.begin(), connections.end(), auto it = std::find_if(connections.begin(), connections.end(),
[ccNumber, &target](const Connection& x) -> bool [ccNumber, &target](const Connection& x) -> bool
{ {
return x.first.id() == ModId::Controller && return x.source.id() == ModId::Controller &&
x.first.parameters().cc == ccNumber && x.source.parameters().cc == ccNumber &&
x.second == target; x.target == target;
}); });
Connection *conn; Connection *conn;
@ -951,12 +951,12 @@ bool sfz::Region::processGenericCc(const Opcode& opcode, Range<float> range, con
else { else {
connections.emplace_back(); connections.emplace_back();
conn = &connections.back(); conn = &connections.back();
conn->first = ModKey::createCC(ccNumber, 0, 0, 0, 0); conn->source = ModKey::createCC(ccNumber, 0, 0, 0, 0);
conn->second = target; conn->target = target;
} }
// //
ModKey::Parameters p = conn->first.parameters(); ModKey::Parameters p = conn->source.parameters();
switch (opcode.category) { switch (opcode.category) {
case kOpcodeOnCcN: case kOpcodeOnCcN:
setValueFromOpcode(opcode, p.value, range); setValueFromOpcode(opcode, p.value, range);
@ -977,7 +977,7 @@ bool sfz::Region::processGenericCc(const Opcode& opcode, Range<float> range, con
assert(false); assert(false);
break; break;
} }
conn->first = ModKey(ModId::Controller, {}, p); conn->source = ModKey(ModId::Controller, {}, p);
} }
return true; return true;

View file

@ -373,7 +373,11 @@ struct Region {
bool triggerOnNote { true }; bool triggerOnNote { true };
// Modulation matrix connections // Modulation matrix connections
typedef std::pair<ModKey, ModKey> Connection; struct Connection {
ModKey source;
ModKey target;
float sourceDepth = 1.0f;
};
std::vector<Connection> connections; std::vector<Connection> connections;
// Parent // Parent

View file

@ -1357,7 +1357,7 @@ void sfz::Synth::setupModMatrix()
for (const Region::Connection& conn : region->connections) { for (const Region::Connection& conn : region->connections) {
ModGenerator* gen = nullptr; ModGenerator* gen = nullptr;
switch (conn.first.id()) { switch (conn.source.id()) {
case ModId::Controller: case ModId::Controller:
gen = genController.get(); gen = genController.get();
break; break;
@ -1370,8 +1370,8 @@ void sfz::Synth::setupModMatrix()
if (!gen) if (!gen)
continue; continue;
ModMatrix::SourceId source = mm.registerSource(conn.first, *gen); ModMatrix::SourceId source = mm.registerSource(conn.source, *gen);
ModMatrix::TargetId target = mm.registerTarget(conn.second); ModMatrix::TargetId target = mm.registerTarget(conn.target);
ASSERT(source); ASSERT(source);
if (!source) { if (!source) {
@ -1385,7 +1385,7 @@ void sfz::Synth::setupModMatrix()
continue; continue;
} }
if (!mm.connect(source, target)) { if (!mm.connect(source, target, conn.sourceDepth)) {
DBG("[sfizz] Failed to connect modulation source and target"); DBG("[sfizz] Failed to connect modulation source and target");
ASSERTFALSE; ASSERTFALSE;
} }

View file

@ -34,7 +34,7 @@ struct ModMatrix::Impl {
}; };
struct ConnectionData { struct ConnectionData {
// nothing float sourceDepth_ {};
}; };
struct Target { struct Target {
@ -176,7 +176,7 @@ ModMatrix::TargetId ModMatrix::findTarget(const ModKey& key)
return TargetId(it->second); return TargetId(it->second);
} }
bool ModMatrix::connect(SourceId sourceId, TargetId targetId) bool ModMatrix::connect(SourceId sourceId, TargetId targetId, float sourceDepth)
{ {
Impl& impl = *impl_; Impl& impl = *impl_;
unsigned sourceIndex = sourceId.number(); unsigned sourceIndex = sourceId.number();
@ -186,7 +186,8 @@ bool ModMatrix::connect(SourceId sourceId, TargetId targetId)
return false; return false;
Impl::Target& target = impl.targets_[targetIndex]; Impl::Target& target = impl.targets_[targetIndex];
/*Impl::ConnectionData& conn =*/ target.connectedSources[sourceIndex]; Impl::ConnectionData& conn = target.connectedSources[sourceIndex];
conn.sourceDepth_ = sourceDepth;
return true; return true;
} }
@ -317,6 +318,7 @@ float* ModMatrix::getModulation(TargetId targetId)
// then add or multiply, depending on target flags // then add or multiply, depending on target flags
while (sourcesPos != sourcesEnd) { while (sourcesPos != sourcesEnd) {
Impl::Source &source = impl.sources_[sourcesPos->first]; Impl::Source &source = impl.sources_[sourcesPos->first];
const float sourceDepth = sourcesPos->second.sourceDepth_;
const int sourceFlags = source.key.flags(); const int sourceFlags = source.key.flags();
// only accept per-voice sources of the same region // only accept per-voice sources of the same region
@ -334,16 +336,16 @@ float* ModMatrix::getModulation(TargetId targetId)
source.gen->generate(source.key, impl.voiceId_, temp); source.gen->generate(source.key, impl.voiceId_, temp);
if (targetFlags & kModIsMultiplicative) { if (targetFlags & kModIsMultiplicative) {
for (uint32_t i = 0; i < numFrames; ++i) for (uint32_t i = 0; i < numFrames; ++i)
buffer[i] *= temp[i]; buffer[i] *= sourceDepth * temp[i];
} }
else if (targetFlags & kModIsPercentMultiplicative) { else if (targetFlags & kModIsPercentMultiplicative) {
for (uint32_t i = 0; i < numFrames; ++i) for (uint32_t i = 0; i < numFrames; ++i)
buffer[i] *= 0.01f * temp[i]; buffer[i] *= (0.01f * sourceDepth) * temp[i];
} }
else { else {
ASSERT(targetFlags & kModIsAdditive); ASSERT(targetFlags & kModIsAdditive);
for (uint32_t i = 0; i < numFrames; ++i) for (uint32_t i = 0; i < numFrames; ++i)
buffer[i] += temp[i]; buffer[i] += sourceDepth * temp[i];
} }
} }
} }

View file

@ -90,9 +90,10 @@ public:
* *
* @param sourceId source of the connection * @param sourceId source of the connection
* @param targetId target of the connection * @param targetId target of the connection
* @param sourceDepth amount which multiplies the source output
* @return true if the connection was successfully made, otherwise false * @return true if the connection was successfully made, otherwise false
*/ */
bool connect(SourceId sourceId, TargetId targetId); bool connect(SourceId sourceId, TargetId targetId, float sourceDepth);
/** /**
* @brief Reinitialize modulation sources overall. * @brief Reinitialize modulation sources overall.

View file

@ -27,7 +27,7 @@ sfz::ModKey::Parameters RegionCCView::at(int cc) const
{ {
for (const sfz::Region::Connection& conn : region_.connections) { for (const sfz::Region::Connection& conn : region_.connections) {
if (match(conn)) { if (match(conn)) {
const sfz::ModKey::Parameters p = conn.first.parameters(); const sfz::ModKey::Parameters p = conn.source.parameters();
if (p.cc == cc) if (p.cc == cc)
return p; return p;
} }
@ -37,5 +37,5 @@ sfz::ModKey::Parameters RegionCCView::at(int cc) const
bool RegionCCView::match(const sfz::Region::Connection& conn) const bool RegionCCView::match(const sfz::Region::Connection& conn) const
{ {
return conn.first.id() == sfz::ModId::Controller && conn.second == target_; return conn.source.id() == sfz::ModId::Controller && conn.target == target_;
} }