linearEnvelope is now a free function

This commit is contained in:
Paul Ferrand 2020-03-30 21:23:59 +02:00
parent 922cbde6c5
commit 1523a14ee8
3 changed files with 42 additions and 40 deletions

View file

@ -8,8 +8,6 @@
#include <array>
#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<class T, class F>
void linearEnvelope(T&& modifier, absl::Span<float> 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<float>(envelope.subspan(lastDelay, length), lastValue, step);
lastDelay += length;
}
fill<float>(envelope.subspan(lastDelay), lastValue);
}
private:

View file

@ -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<T>& crossfadeRange, U value, SfzCrossfadeCur
return 1.0f;
}
template<class F>
void linearEnvelope(const EventVector& events, absl::Span<float> 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<float>(envelope.subspan(lastDelay, length), lastValue, step);
lastDelay += length;
}
fill<float>(envelope.subspan(lastDelay), lastValue);
}
} // namespace sfz

View file

@ -262,10 +262,7 @@ void sfz::Voice::ampStageMono(AudioSpan<float> buffer) noexcept
const auto numSamples = buffer.getNumFrames();
const auto leftBuffer = buffer.getSpan(0);
using namespace std::placeholders;
const auto xfinBind = std::bind(crossfadeIn<float, float>, _1, _2, region->crossfadeCCCurve);
const auto xfoutBind = std::bind(crossfadeIn<float, float>, _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<float> buffer) noexcept
// Amplitude envelope
fill<float>(*modulationSpan, baseGain);
for (auto& mod : region->amplitudeCC) {
resources.midiState.linearEnvelope(mod, *tempSpan, gainModifier<float>);
const auto events = resources.midiState.getEvents(mod.cc);
linearEnvelope(events, *tempSpan, [&mod](float x) { return x * mod.value; });
applyGain<float>(*tempSpan, *modulationSpan);
}
applyGain<float>(*modulationSpan, leftBuffer);
@ -283,11 +281,13 @@ void sfz::Voice::ampStageMono(AudioSpan<float> buffer) noexcept
// Crossfade envelopes
fill<float>(*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<float>(*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<float>(*tempSpan, *modulationSpan);
}
applyGain<float>(*modulationSpan, leftBuffer);
@ -307,20 +307,18 @@ void sfz::Voice::ampStageStereo(AudioSpan<float> 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<float, float>, _1, _2, region->crossfadeCCCurve);
const auto xfoutBind = std::bind(crossfadeIn<float, float>, _1, _2, region->crossfadeCCCurve);
// Amplitude envelope
fill<float>(*modulationSpan, baseGain);
for (auto& mod : region->amplitudeCC) {
resources.midiState.linearEnvelope(mod, *tempSpan, gainModifier<float>);
const auto events = resources.midiState.getEvents(mod.cc);
linearEnvelope(events, *tempSpan, [&mod](float x) { return x * mod.value; });
applyGain<float>(*tempSpan, *modulationSpan);
}
buffer.applyGain(*modulationSpan);
@ -329,11 +327,13 @@ void sfz::Voice::ampStageStereo(AudioSpan<float> buffer) noexcept
// Crossfade envelopes
fill<float>(*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<float>(*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<float>(*tempSpan, *modulationSpan);
}
buffer.applyGain(*modulationSpan);
@ -366,7 +366,8 @@ void sfz::Voice::panStageMono(AudioSpan<float> buffer) noexcept
// Apply panning
fill<float>(*modulationSpan, region->pan);
for (auto& mod : region->panCC) {
resources.midiState.linearEnvelope(mod, *tempSpan, gainModifier<float>);
const auto events = resources.midiState.getEvents(mod.cc);
linearEnvelope(events, *tempSpan, [&mod](float x) { return x * mod.value; });
add<float>(*tempSpan, *modulationSpan);
}
pan<float>(*modulationSpan, leftBuffer, rightBuffer);
@ -388,7 +389,8 @@ void sfz::Voice::panStageStereo(AudioSpan<float> buffer) noexcept
// panningModulation(*modulationSpan);
fill<float>(*modulationSpan, region->pan);
for (auto& mod : region->panCC) {
resources.midiState.linearEnvelope(mod, *tempSpan, gainModifier<float>);
const auto events = resources.midiState.getEvents(mod.cc);
linearEnvelope(events, *tempSpan, [&mod](float x) { return x * mod.value; });
add<float>(*tempSpan, *modulationSpan);
}
pan<float>(*modulationSpan, leftBuffer, rightBuffer);
@ -397,7 +399,8 @@ void sfz::Voice::panStageStereo(AudioSpan<float> buffer) noexcept
// widthModulation(*modulationSpan);
fill<float>(*modulationSpan, region->width);
for (auto& mod : region->widthCC) {
resources.midiState.linearEnvelope(mod, *tempSpan, gainModifier<float>);
const auto events = resources.midiState.getEvents(mod.cc);
linearEnvelope(events, *tempSpan, [&mod](float x) { return x * mod.value; });
add<float>(*tempSpan, *modulationSpan);
}
width<float>(*modulationSpan, leftBuffer, rightBuffer);
@ -405,7 +408,8 @@ void sfz::Voice::panStageStereo(AudioSpan<float> buffer) noexcept
// positionModulation(*modulationSpan);
fill<float>(*modulationSpan, region->position);
for (auto& mod : region->positionCC) {
resources.midiState.linearEnvelope(mod, *tempSpan, gainModifier<float>);
const auto events = resources.midiState.getEvents(mod.cc);
linearEnvelope(events, *tempSpan, [&mod](float x) { return x * mod.value; });
add<float>(*tempSpan, *modulationSpan);
}
pan<float>(*modulationSpan, leftBuffer, rightBuffer);