From 1523a14ee83cc4a21a678b04a20feddeca7cd1f5 Mon Sep 17 00:00:00 2001 From: Paul Ferrand Date: Mon, 30 Mar 2020 21:23:59 +0200 Subject: [PATCH] linearEnvelope is now a free function --- src/sfizz/MidiState.h | 21 --------------------- src/sfizz/SfzHelpers.h | 19 +++++++++++++++++++ src/sfizz/Voice.cpp | 42 +++++++++++++++++++++++------------------- 3 files changed, 42 insertions(+), 40 deletions(-) diff --git a/src/sfizz/MidiState.h b/src/sfizz/MidiState.h index df8061cc..f09147f5 100644 --- a/src/sfizz/MidiState.h +++ b/src/sfizz/MidiState.h @@ -8,8 +8,6 @@ #include #include "CCMap.h" #include "Range.h" -#include "absl/types/span.h" -#include "SIMDHelpers.h" namespace sfz { @@ -125,25 +123,6 @@ public: const EventVector& getEvents(int ccIdx) const noexcept; - template - void linearEnvelope(T&& modifier, absl::Span envelope, F&& lambda) const - { - const auto eventList = getEvents(modifier.cc); - ASSERT(eventList.size() > 0); - ASSERT(eventList[0].delay == 0); - - auto lastValue = lambda(modifier.value, eventList[0].value); - auto lastDelay = eventList[0].delay; - for (unsigned i = 1; i < eventList.size(); ++ i) { - const auto event = eventList[i]; - const auto length = event.delay - lastDelay; - const auto step = (lambda(modifier.value, event.value) - lastValue)/ length; - lastValue = linearRamp(envelope.subspan(lastDelay, length), lastValue, step); - lastDelay += length; - } - fill(envelope.subspan(lastDelay), lastValue); - } - private: diff --git a/src/sfizz/SfzHelpers.h b/src/sfizz/SfzHelpers.h index 601d676f..15177dac 100644 --- a/src/sfizz/SfzHelpers.h +++ b/src/sfizz/SfzHelpers.h @@ -13,6 +13,7 @@ #include "Macros.h" #include "Config.h" #include "MathHelpers.h" +#include "SIMDHelpers.h" #include "absl/meta/type_traits.h" #include "Defaults.h" @@ -342,5 +343,23 @@ float crossfadeOut(const sfz::Range& crossfadeRange, U value, SfzCrossfadeCur return 1.0f; } +template +void linearEnvelope(const EventVector& events, absl::Span envelope, F&& lambda) +{ + ASSERT(events.size() > 0); + ASSERT(events[0].delay == 0); + + auto lastValue = lambda(events[0].value); + auto lastDelay = events[0].delay; + for (unsigned i = 1; i < events.size(); ++ i) { + const auto event = events[i]; + const auto length = event.delay - lastDelay; + const auto step = (lambda(event.value) - lastValue)/ length; + lastValue = linearRamp(envelope.subspan(lastDelay, length), lastValue, step); + lastDelay += length; + } + fill(envelope.subspan(lastDelay), lastValue); +} + } // namespace sfz diff --git a/src/sfizz/Voice.cpp b/src/sfizz/Voice.cpp index 4dc90a1c..c08b6d79 100644 --- a/src/sfizz/Voice.cpp +++ b/src/sfizz/Voice.cpp @@ -262,10 +262,7 @@ void sfz::Voice::ampStageMono(AudioSpan buffer) noexcept const auto numSamples = buffer.getNumFrames(); const auto leftBuffer = buffer.getSpan(0); - - using namespace std::placeholders; - const auto xfinBind = std::bind(crossfadeIn, _1, _2, region->crossfadeCCCurve); - const auto xfoutBind = std::bind(crossfadeIn, _1, _2, region->crossfadeCCCurve); + const auto xfCurve = region->crossfadeCCCurve; auto modulationSpan = resources.bufferPool.getBuffer(numSamples); auto tempSpan = resources.bufferPool.getBuffer(numSamples); @@ -275,7 +272,8 @@ void sfz::Voice::ampStageMono(AudioSpan buffer) noexcept // Amplitude envelope fill(*modulationSpan, baseGain); for (auto& mod : region->amplitudeCC) { - resources.midiState.linearEnvelope(mod, *tempSpan, gainModifier); + const auto events = resources.midiState.getEvents(mod.cc); + linearEnvelope(events, *tempSpan, [&mod](float x) { return x * mod.value; }); applyGain(*tempSpan, *modulationSpan); } applyGain(*modulationSpan, leftBuffer); @@ -283,11 +281,13 @@ void sfz::Voice::ampStageMono(AudioSpan buffer) noexcept // Crossfade envelopes fill(*modulationSpan, 1.0f); for (auto& mod : region->crossfadeCCInRange) { - resources.midiState.linearEnvelope(mod, *tempSpan, xfinBind); + const auto events = resources.midiState.getEvents(mod.cc); + linearEnvelope(events, *tempSpan, [&](float x) { return crossfadeIn(mod.value, x, xfCurve); }); applyGain(*tempSpan, *modulationSpan); } for (auto& mod : region->crossfadeCCOutRange) { - resources.midiState.linearEnvelope(mod, *tempSpan, xfoutBind); + const auto events = resources.midiState.getEvents(mod.cc); + linearEnvelope(events, *tempSpan, [&](float x) { return crossfadeOut(mod.value, x, xfCurve); }); applyGain(*tempSpan, *modulationSpan); } applyGain(*modulationSpan, leftBuffer); @@ -307,20 +307,18 @@ void sfz::Voice::ampStageStereo(AudioSpan buffer) noexcept const auto numSamples = buffer.getNumFrames(); + const auto xfCurve = region->crossfadeCCCurve; + auto modulationSpan = resources.bufferPool.getBuffer(numSamples); auto tempSpan = resources.bufferPool.getBuffer(numSamples); if (!modulationSpan || !tempSpan) return; - using namespace std::placeholders; - const auto xfinBind = std::bind(crossfadeIn, _1, _2, region->crossfadeCCCurve); - const auto xfoutBind = std::bind(crossfadeIn, _1, _2, region->crossfadeCCCurve); - - // Amplitude envelope fill(*modulationSpan, baseGain); for (auto& mod : region->amplitudeCC) { - resources.midiState.linearEnvelope(mod, *tempSpan, gainModifier); + const auto events = resources.midiState.getEvents(mod.cc); + linearEnvelope(events, *tempSpan, [&mod](float x) { return x * mod.value; }); applyGain(*tempSpan, *modulationSpan); } buffer.applyGain(*modulationSpan); @@ -329,11 +327,13 @@ void sfz::Voice::ampStageStereo(AudioSpan buffer) noexcept // Crossfade envelopes fill(*modulationSpan, 1.0f); for (auto& mod : region->crossfadeCCInRange) { - resources.midiState.linearEnvelope(mod, *tempSpan, xfinBind); + const auto events = resources.midiState.getEvents(mod.cc); + linearEnvelope(events, *tempSpan, [&](float x) { return crossfadeIn(mod.value, x, xfCurve); }); applyGain(*tempSpan, *modulationSpan); } for (auto& mod : region->crossfadeCCOutRange) { - resources.midiState.linearEnvelope(mod, *tempSpan, xfoutBind); + const auto events = resources.midiState.getEvents(mod.cc); + linearEnvelope(events, *tempSpan, [&](float x) { return crossfadeOut(mod.value, x, xfCurve); }); applyGain(*tempSpan, *modulationSpan); } buffer.applyGain(*modulationSpan); @@ -366,7 +366,8 @@ void sfz::Voice::panStageMono(AudioSpan buffer) noexcept // Apply panning fill(*modulationSpan, region->pan); for (auto& mod : region->panCC) { - resources.midiState.linearEnvelope(mod, *tempSpan, gainModifier); + const auto events = resources.midiState.getEvents(mod.cc); + linearEnvelope(events, *tempSpan, [&mod](float x) { return x * mod.value; }); add(*tempSpan, *modulationSpan); } pan(*modulationSpan, leftBuffer, rightBuffer); @@ -388,7 +389,8 @@ void sfz::Voice::panStageStereo(AudioSpan buffer) noexcept // panningModulation(*modulationSpan); fill(*modulationSpan, region->pan); for (auto& mod : region->panCC) { - resources.midiState.linearEnvelope(mod, *tempSpan, gainModifier); + const auto events = resources.midiState.getEvents(mod.cc); + linearEnvelope(events, *tempSpan, [&mod](float x) { return x * mod.value; }); add(*tempSpan, *modulationSpan); } pan(*modulationSpan, leftBuffer, rightBuffer); @@ -397,7 +399,8 @@ void sfz::Voice::panStageStereo(AudioSpan buffer) noexcept // widthModulation(*modulationSpan); fill(*modulationSpan, region->width); for (auto& mod : region->widthCC) { - resources.midiState.linearEnvelope(mod, *tempSpan, gainModifier); + const auto events = resources.midiState.getEvents(mod.cc); + linearEnvelope(events, *tempSpan, [&mod](float x) { return x * mod.value; }); add(*tempSpan, *modulationSpan); } width(*modulationSpan, leftBuffer, rightBuffer); @@ -405,7 +408,8 @@ void sfz::Voice::panStageStereo(AudioSpan buffer) noexcept // positionModulation(*modulationSpan); fill(*modulationSpan, region->position); for (auto& mod : region->positionCC) { - resources.midiState.linearEnvelope(mod, *tempSpan, gainModifier); + const auto events = resources.midiState.getEvents(mod.cc); + linearEnvelope(events, *tempSpan, [&mod](float x) { return x * mod.value; }); add(*tempSpan, *modulationSpan); } pan(*modulationSpan, leftBuffer, rightBuffer);