From f14548116070fe80157df5376620482048cc5b7b Mon Sep 17 00:00:00 2001 From: Paul Ferrand Date: Wed, 16 Sep 2020 14:48:36 +0200 Subject: [PATCH] Use the mod matrix in filters and eqs --- src/sfizz/EQPool.cpp | 60 +++++++++++++++++++-------------- src/sfizz/EQPool.h | 10 +++--- src/sfizz/FilterPool.cpp | 50 +++++++++++++++++---------- src/sfizz/FilterPool.h | 10 +++--- src/sfizz/modulations/ModId.cpp | 2 +- 5 files changed, 78 insertions(+), 54 deletions(-) diff --git a/src/sfizz/EQPool.cpp b/src/sfizz/EQPool.cpp index 20267647..59cdecb5 100644 --- a/src/sfizz/EQPool.cpp +++ b/src/sfizz/EQPool.cpp @@ -4,7 +4,7 @@ #include "SIMDHelpers.h" #include "SwapAndPop.h" -sfz::EQHolder::EQHolder(const Resources& resources) +sfz::EQHolder::EQHolder(Resources& resources) : resources(resources) { eq = absl::make_unique(); @@ -46,45 +46,53 @@ void sfz::EQHolder::setup(const Region& region, unsigned eqId, float velocity) lastGain += resources.midiState.getCCValue(mod.cc) * mod.data; lastGain = Default::filterGainRange.clamp(lastGain); + gainTarget = resources.modMatrix.findTarget(ModKey::createNXYZ(ModId::EqGain, region.id, eqId)); + bandwidthTarget = resources.modMatrix.findTarget(ModKey::createNXYZ(ModId::EqBandwidth, region.id, eqId)); + frequencyTarget = resources.modMatrix.findTarget(ModKey::createNXYZ(ModId::EqFrequency, region.id, eqId)); + // Initialize the EQ + DBG(baseFrequency << " " << baseBandwidth << " " << baseGain); eq->prepare(lastFrequency, lastBandwidth, lastGain); } void sfz::EQHolder::process(const float** inputs, float** outputs, unsigned numFrames) { - auto justCopy = [&]() { + if (description == nullptr) { for (unsigned channelIdx = 0; channelIdx < eq->channels(); channelIdx++) copy({ inputs[channelIdx], numFrames }, { outputs[channelIdx], numFrames }); - }; - - if (description == nullptr) { - justCopy(); return; } - // TODO: Once the midistate envelopes are done, add modulation in there! - // For now we take the last value - float lastFrequency = baseFrequency; - for (const auto& mod : description->frequencyCC) - lastFrequency += resources.midiState.getCCValue(mod.cc) * mod.data; - lastFrequency = Default::eqFrequencyRange.clamp(lastFrequency); + ModMatrix& mm = resources.modMatrix; + auto frequencySpan = resources.bufferPool.getBuffer(numFrames); + auto bandwidthSpan = resources.bufferPool.getBuffer(numFrames); + auto gainSpan = resources.bufferPool.getBuffer(numFrames); - float lastBandwidth = baseBandwidth; - for (const auto& mod : description->bandwidthCC) - lastBandwidth += resources.midiState.getCCValue(mod.cc) * mod.data; - lastBandwidth = Default::eqBandwidthRange.clamp(lastBandwidth); - - float lastGain = baseGain; - for (const auto& mod : description->gainCC) - lastGain += resources.midiState.getCCValue(mod.cc) * mod.data; - lastGain = Default::filterGainRange.clamp(lastGain); - - if (lastGain == 0.0f) { - justCopy(); + if (!frequencySpan || !bandwidthSpan || !gainSpan) return; - } - eq->process(inputs, outputs, lastFrequency, lastBandwidth, lastGain, numFrames); + fill(*frequencySpan, baseFrequency); + if (float* mod = mm.getModulation(frequencyTarget)) + add(absl::Span(mod, numFrames), *frequencySpan); + + fill(*bandwidthSpan, baseBandwidth); + if (float* mod = mm.getModulation(bandwidthTarget)) + add(absl::Span(mod, numFrames), *bandwidthSpan); + + fill(*gainSpan, baseGain); + if (float* mod = mm.getModulation(gainTarget)) + add(absl::Span(mod, numFrames), *gainSpan); + + DBG(frequencySpan->back() << " " << bandwidthSpan->back() << " " << gainSpan->back()); + + eq->processModulated( + inputs, + outputs, + frequencySpan->data(), + bandwidthSpan->data(), + gainSpan->data(), + numFrames + ); } void sfz::EQHolder::setSampleRate(float sampleRate) diff --git a/src/sfizz/EQPool.h b/src/sfizz/EQPool.h index dc4b65fa..f284e69e 100644 --- a/src/sfizz/EQPool.h +++ b/src/sfizz/EQPool.h @@ -14,7 +14,7 @@ class EQHolder { public: EQHolder() = delete; - EQHolder(const Resources& resources); + EQHolder(Resources& resources); /** * @brief Setup a new EQ from a region and an index * @@ -42,15 +42,15 @@ public: */ void reset(); private: - const Resources& resources; + Resources& resources; const EQDescription* description; std::unique_ptr eq; float baseBandwidth { Default::eqBandwidth }; float baseFrequency { Default::eqFrequency1 }; float baseGain { Default::eqGain }; - ModMatrix::TargetId eqGainTarget; - ModMatrix::TargetId eqFrequencyTarget; - ModMatrix::TargetId eqBandwidthTarget; + ModMatrix::TargetId gainTarget; + ModMatrix::TargetId frequencyTarget; + ModMatrix::TargetId bandwidthTarget; }; } diff --git a/src/sfizz/FilterPool.cpp b/src/sfizz/FilterPool.cpp index 5362e8a3..d60accad 100644 --- a/src/sfizz/FilterPool.cpp +++ b/src/sfizz/FilterPool.cpp @@ -5,7 +5,7 @@ #include #include -sfz::FilterHolder::FilterHolder(const Resources& resources) +sfz::FilterHolder::FilterHolder(Resources& resources) : resources(resources) { filter = absl::make_unique(); @@ -57,6 +57,11 @@ void sfz::FilterHolder::setup(const Region& region, unsigned filterId, int noteN lastGain += resources.midiState.getCCValue(mod.cc) * mod.data; lastGain = Default::filterGainRange.clamp(lastGain); + ModMatrix& mm = resources.modMatrix; + gainTarget = mm.findTarget(ModKey::createNXYZ(ModId::FilGain, region.id, filterId)); + cutoffTarget = mm.findTarget(ModKey::createNXYZ(ModId::FilCutoff, region.id, filterId)); + resonanceTarget = mm.findTarget(ModKey::createNXYZ(ModId::FilResonance, region.id, filterId)); + // Initialize the filter filter->prepare(lastCutoff, lastResonance, lastGain); } @@ -69,25 +74,36 @@ void sfz::FilterHolder::process(const float** inputs, float** outputs, unsigned return; } - // TODO: Once the midistate envelopes are done, add modulation in there! - // For now we take the last value - // TODO: the template deduction could be automatic here? - float lastCutoff = baseCutoff; - for (const auto& mod : description->cutoffCC) - lastCutoff *= centsFactor(resources.midiState.getCCValue(mod.cc) * mod.data); - lastCutoff = Default::filterCutoffRange.clamp(lastCutoff); + ModMatrix& mm = resources.modMatrix; + auto cutoffSpan = resources.bufferPool.getBuffer(numFrames); + auto resonanceSpan = resources.bufferPool.getBuffer(numFrames); + auto gainSpan = resources.bufferPool.getBuffer(numFrames); - float lastResonance = baseResonance; - for (const auto& mod : description->resonanceCC) - lastResonance += resources.midiState.getCCValue(mod.cc) * mod.data; - lastResonance = Default::filterResonanceRange.clamp(lastResonance); + if (!cutoffSpan || !resonanceSpan || !gainSpan) + return; - float lastGain = baseGain; - for (const auto& mod : description->gainCC) - lastGain += resources.midiState.getCCValue(mod.cc) * mod.data; - lastGain = Default::filterGainRange.clamp(lastGain); + fill(*cutoffSpan, baseCutoff); + if (float* mod = mm.getModulation(cutoffTarget)) { + for (size_t i = 0; i < numFrames; ++i) + (*cutoffSpan)[i] *= centsFactor(mod[i]); + } - filter->process(inputs, outputs, lastCutoff, lastResonance, lastGain, numFrames); + fill(*resonanceSpan, baseResonance); + if (float* mod = mm.getModulation(resonanceTarget)) + add(absl::Span(mod, numFrames), *resonanceSpan); + + fill(*gainSpan, baseGain); + if (float* mod = mm.getModulation(gainTarget)) + add(absl::Span(mod, numFrames), *gainSpan); + + filter->processModulated( + inputs, + outputs, + cutoffSpan->data(), + resonanceSpan->data(), + gainSpan->data(), + numFrames + ); } diff --git a/src/sfizz/FilterPool.h b/src/sfizz/FilterPool.h index b3709cea..9e7f0522 100644 --- a/src/sfizz/FilterPool.h +++ b/src/sfizz/FilterPool.h @@ -15,7 +15,7 @@ class FilterHolder { public: FilterHolder() = delete; - FilterHolder(const Resources& resources); + FilterHolder(Resources& resources); /** * @brief Setup a new filter based on a filter description, and a triggering note parameters. * @@ -44,15 +44,15 @@ public: */ void reset(); private: - const Resources& resources; + Resources& resources; const FilterDescription* description; std::unique_ptr filter; float baseCutoff { Default::filterCutoff }; float baseResonance { Default::filterResonance }; float baseGain { Default::filterGain }; - ModMatrix::TargetId filterGainTarget; - ModMatrix::TargetId filterCutoffTarget; - ModMatrix::TargetId filterResonanceTarget; + ModMatrix::TargetId gainTarget; + ModMatrix::TargetId cutoffTarget; + ModMatrix::TargetId resonanceTarget; using filterRandomDist = std::uniform_int_distribution; filterRandomDist dist { 0, sfz::Default::filterRandom }; }; diff --git a/src/sfizz/modulations/ModId.cpp b/src/sfizz/modulations/ModId.cpp index 4ee37055..9d19e10e 100644 --- a/src/sfizz/modulations/ModId.cpp +++ b/src/sfizz/modulations/ModId.cpp @@ -49,7 +49,7 @@ int ModIds::flags(ModId id) noexcept case ModId::FilCutoff: return kModIsPerVoice|kModIsAdditive; case ModId::FilResonance: - return kModIsPerVoice|kModIsMultiplicative; + return kModIsPerVoice|kModIsAdditive; case ModId::EqGain: return kModIsPerVoice|kModIsAdditive; case ModId::EqFrequency: