linearEnvelope is now a free function
This commit is contained in:
parent
922cbde6c5
commit
1523a14ee8
3 changed files with 42 additions and 40 deletions
|
|
@ -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:
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue