Add the modifier helpers to another file
This commit is contained in:
parent
9d6b2ede2f
commit
232eada0c4
7 changed files with 240 additions and 254 deletions
234
src/sfizz/ModifierHelpers.h
Normal file
234
src/sfizz/ModifierHelpers.h
Normal file
|
|
@ -0,0 +1,234 @@
|
|||
#pragma once
|
||||
|
||||
#include "Range.h"
|
||||
#include "Defaults.h"
|
||||
#include "SfzHelpers.h"
|
||||
#include "Resources.h"
|
||||
#include "absl/types/span.h"
|
||||
|
||||
namespace sfz {
|
||||
|
||||
/**
|
||||
* @brief Compute a crossfade in value with respect to a crossfade range (note, velocity, cc, ...)
|
||||
*/
|
||||
template <class T, class U>
|
||||
float crossfadeIn(const sfz::Range<T>& crossfadeRange, U value, SfzCrossfadeCurve curve)
|
||||
{
|
||||
if (value < crossfadeRange.getStart())
|
||||
return 0.0f;
|
||||
|
||||
const auto length = static_cast<float>(crossfadeRange.length());
|
||||
if (length == 0.0f)
|
||||
return 1.0f;
|
||||
|
||||
else if (value < crossfadeRange.getEnd()) {
|
||||
const auto crossfadePosition = static_cast<float>(value - crossfadeRange.getStart()) / length;
|
||||
if (curve == SfzCrossfadeCurve::power)
|
||||
return sqrt(crossfadePosition);
|
||||
if (curve == SfzCrossfadeCurve::gain)
|
||||
return crossfadePosition;
|
||||
}
|
||||
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Compute a crossfade out value with respect to a crossfade range (note, velocity, cc, ...)
|
||||
*/
|
||||
template <class T, class U>
|
||||
float crossfadeOut(const sfz::Range<T>& crossfadeRange, U value, SfzCrossfadeCurve curve)
|
||||
{
|
||||
if (value > crossfadeRange.getEnd())
|
||||
return 0.0f;
|
||||
|
||||
const auto length = static_cast<float>(crossfadeRange.length());
|
||||
if (length == 0.0f)
|
||||
return 1.0f;
|
||||
|
||||
else if (value > crossfadeRange.getStart()) {
|
||||
const auto crossfadePosition = static_cast<float>(value - crossfadeRange.getStart()) / length;
|
||||
if (curve == SfzCrossfadeCurve::power)
|
||||
return std::sqrt(1 - crossfadePosition);
|
||||
if (curve == SfzCrossfadeCurve::gain)
|
||||
return 1 - crossfadePosition;
|
||||
}
|
||||
|
||||
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);
|
||||
if (envelope.size() == 0)
|
||||
return;
|
||||
|
||||
const auto maxDelay = static_cast<int>(envelope.size() - 1);
|
||||
|
||||
auto lastValue = lambda(events[0].value);
|
||||
auto lastDelay = events[0].delay;
|
||||
for (unsigned i = 1; i < events.size() && lastDelay < maxDelay; ++i) {
|
||||
const auto length = min(events[i].delay, maxDelay) - lastDelay;
|
||||
const auto step = (lambda(events[i].value) - lastValue) / length;
|
||||
lastValue = linearRamp<float>(envelope.subspan(lastDelay, length), lastValue, step);
|
||||
lastDelay += length;
|
||||
}
|
||||
fill<float>(envelope.subspan(lastDelay), lastValue);
|
||||
}
|
||||
|
||||
template <class F>
|
||||
void linearEnvelope(const EventVector& events, absl::Span<float> envelope, F&& lambda, float step)
|
||||
{
|
||||
ASSERT(events.size() > 0);
|
||||
ASSERT(events[0].delay == 0);
|
||||
ASSERT(step != 0.0);
|
||||
|
||||
if (envelope.size() == 0)
|
||||
return;
|
||||
|
||||
auto quantize = [step](float value) -> float {
|
||||
return std::round(value / step) * step;
|
||||
};
|
||||
const auto maxDelay = static_cast<int>(envelope.size() - 1);
|
||||
|
||||
auto lastValue = quantize(lambda(events[0].value));
|
||||
auto lastDelay = events[0].delay;
|
||||
for (unsigned i = 1; i < events.size() && lastDelay < maxDelay; ++i) {
|
||||
const auto nextValue = quantize(lambda(events[i].value));
|
||||
const auto difference = std::abs(nextValue - lastValue);
|
||||
const auto length = min(events[i].delay, maxDelay) - lastDelay;
|
||||
|
||||
if (difference < step) {
|
||||
fill<float>(envelope.subspan(lastDelay, length), lastValue);
|
||||
lastValue = nextValue;
|
||||
lastDelay += length;
|
||||
continue;
|
||||
}
|
||||
|
||||
const auto numSteps = static_cast<int>(difference / step);
|
||||
const auto stepLength = static_cast<int>(length / numSteps);
|
||||
for (int i = 0; i < numSteps; ++i) {
|
||||
fill<float>(envelope.subspan(lastDelay, stepLength), lastValue);
|
||||
lastValue += lastValue <= nextValue ? step : -step;
|
||||
lastDelay += stepLength;
|
||||
}
|
||||
}
|
||||
fill<float>(envelope.subspan(lastDelay), lastValue);
|
||||
}
|
||||
|
||||
template <class F>
|
||||
void multiplicativeEnvelope(const EventVector& events, absl::Span<float> envelope, F&& lambda)
|
||||
{
|
||||
ASSERT(events.size() > 0);
|
||||
ASSERT(events[0].delay == 0);
|
||||
|
||||
if (envelope.size() == 0)
|
||||
return;
|
||||
const auto maxDelay = static_cast<int>(envelope.size() - 1);
|
||||
|
||||
auto lastValue = lambda(events[0].value);
|
||||
auto lastDelay = events[0].delay;
|
||||
for (unsigned i = 1; i < events.size() && lastDelay < maxDelay; ++i) {
|
||||
const auto length = min(events[i].delay, maxDelay) - lastDelay;
|
||||
const auto nextValue = lambda(events[i].value);
|
||||
const auto step = std::exp((std::log(nextValue) - std::log(lastValue)) / length);
|
||||
multiplicativeRamp<float>(envelope.subspan(lastDelay, length), lastValue, step);
|
||||
lastValue = nextValue;
|
||||
lastDelay += length;
|
||||
}
|
||||
fill<float>(envelope.subspan(lastDelay), lastValue);
|
||||
}
|
||||
|
||||
template <class F>
|
||||
void multiplicativeEnvelope(const EventVector& events, absl::Span<float> envelope, F&& lambda, float step)
|
||||
{
|
||||
ASSERT(events.size() > 0);
|
||||
ASSERT(events[0].delay == 0);
|
||||
ASSERT(step != 0.0f);
|
||||
|
||||
if (envelope.size() == 0)
|
||||
return;
|
||||
const auto maxDelay = static_cast<int>(envelope.size() - 1);
|
||||
|
||||
const auto logStep = std::log(step);
|
||||
// If we assume that a = b.q^r for b in (1, q) then
|
||||
// log a log b
|
||||
// ----- = ----- + r
|
||||
// log q log q
|
||||
// and log(b)\log(q) is between 0 and 1.
|
||||
auto quantize = [logStep](float value) -> float {
|
||||
return std::exp(logStep * std::round(std::log(value) / logStep));
|
||||
};
|
||||
|
||||
auto lastValue = quantize(lambda(events[0].value));
|
||||
auto lastDelay = events[0].delay;
|
||||
for (unsigned i = 1; i < events.size() && lastDelay < maxDelay; ++i) {
|
||||
const auto length = min(events[i].delay, maxDelay) - lastDelay;
|
||||
const auto nextValue = quantize(lambda(events[i].value));
|
||||
const auto difference = nextValue > lastValue ? nextValue / lastValue : lastValue / nextValue;
|
||||
|
||||
if (difference < step) {
|
||||
fill<float>(envelope.subspan(lastDelay, length), lastValue);
|
||||
lastValue = nextValue;
|
||||
lastDelay += length;
|
||||
continue;
|
||||
}
|
||||
|
||||
const auto numSteps = static_cast<int>(std::log(difference) / logStep);
|
||||
const auto stepLength = static_cast<int>(length / numSteps);
|
||||
for (int i = 0; i < numSteps; ++i) {
|
||||
fill<float>(envelope.subspan(lastDelay, stepLength), lastValue);
|
||||
lastValue = nextValue > lastValue ? lastValue * step : lastValue / step;
|
||||
lastDelay += stepLength;
|
||||
}
|
||||
}
|
||||
fill<float>(envelope.subspan(lastDelay), lastValue);
|
||||
}
|
||||
|
||||
template<class F>
|
||||
void linearModifier(const sfz::Resources& resources, absl::Span<float> span, const sfz::CCData<sfz::Modifier>& ccData, F&& lambda)
|
||||
{
|
||||
const auto events = resources.midiState.getCCEvents(ccData.cc);
|
||||
const auto curve = resources.curves.getCurve(ccData.data.curve);
|
||||
if (ccData.data.steps == 0) {
|
||||
linearEnvelope(events, span, [&ccData, &curve, &lambda](float x) {
|
||||
return lambda(curve.evalNormalized(x) * ccData.data.value);
|
||||
});
|
||||
} else {
|
||||
const float stepSize { ccData.data.value / ccData.data.steps };
|
||||
linearEnvelope(events, span, [&ccData, &curve, &lambda](float x) {
|
||||
return lambda(curve.evalNormalized(x) * ccData.data.value);
|
||||
}, stepSize);
|
||||
}
|
||||
}
|
||||
|
||||
template<class F>
|
||||
void multiplicativeModifier(const sfz::Resources& resources, absl::Span<float> span, const sfz::CCData<sfz::Modifier>& ccData, F&& lambda)
|
||||
{
|
||||
const auto events = resources.midiState.getCCEvents(ccData.cc);
|
||||
const auto curve = resources.curves.getCurve(ccData.data.curve);
|
||||
if (ccData.data.steps == 0) {
|
||||
multiplicativeEnvelope(events, span, [&ccData, &curve, &lambda](float x) {
|
||||
return lambda(curve.evalNormalized(x) * ccData.data.value);
|
||||
});
|
||||
} else {
|
||||
// FIXME: not sure about this step size for multiplicative envelopes
|
||||
const float stepSize { ccData.data.value / ccData.data.steps };
|
||||
multiplicativeEnvelope(events, span, [&ccData, &curve, &lambda](float x) {
|
||||
return lambda(curve.evalNormalized(x) * ccData.data.value);
|
||||
}, stepSize);
|
||||
}
|
||||
}
|
||||
|
||||
inline void linearModifier(const sfz::Resources& resources, absl::Span<float> span, const sfz::CCData<sfz::Modifier>& ccData)
|
||||
{
|
||||
linearModifier(resources, span, ccData, [](float x) { return x; });
|
||||
}
|
||||
|
||||
inline void multiplicativeModifier(const sfz::Resources& resources, absl::Span<float> span, const sfz::CCData<sfz::Modifier>& ccData)
|
||||
{
|
||||
multiplicativeModifier(resources, span, ccData, [](float x) { return x; });
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -5,13 +5,12 @@
|
|||
// If not, contact the sfizz maintainers at https://github.com/sfztools/sfizz
|
||||
|
||||
#include "Region.h"
|
||||
#include "Defaults.h"
|
||||
#include "MathHelpers.h"
|
||||
#include "Macros.h"
|
||||
#include "Debug.h"
|
||||
#include "Opcode.h"
|
||||
#include "StringViewHelpers.h"
|
||||
#include "MidiState.h"
|
||||
#include "ModifierHelpers.h"
|
||||
#include "absl/strings/str_replace.h"
|
||||
#include "absl/strings/str_cat.h"
|
||||
#include "absl/algorithm/container.h"
|
||||
|
|
|
|||
|
|
@ -14,10 +14,8 @@
|
|||
#include "Opcode.h"
|
||||
#include "AudioBuffer.h"
|
||||
#include "MidiState.h"
|
||||
#include "absl/strings/str_cat.h"
|
||||
#include "absl/types/optional.h"
|
||||
#include <bitset>
|
||||
#include <absl/types/optional.h>
|
||||
#include <random>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
|
|
|
|||
|
|
@ -264,200 +264,5 @@ bool findDefine(absl::string_view line, absl::string_view& variable, absl::strin
|
|||
*/
|
||||
bool findInclude(absl::string_view line, std::string& path);
|
||||
|
||||
/**
|
||||
* @brief multiply a value by a factor, in cents. To be used for pitch variations.
|
||||
*
|
||||
* @param base
|
||||
* @param modifier
|
||||
*/
|
||||
inline CXX14_CONSTEXPR float multiplyByCentsModifier(int modifier, float base)
|
||||
{
|
||||
return base * centsFactor(modifier);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline CXX14_CONSTEXPR float gainModifier(T modifier, float value)
|
||||
{
|
||||
return value * modifier;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Compute a crossfade in value with respect to a crossfade range (note, velocity, cc, ...)
|
||||
*/
|
||||
template <class T, class U>
|
||||
float crossfadeIn(const sfz::Range<T>& crossfadeRange, U value, SfzCrossfadeCurve curve)
|
||||
{
|
||||
if (value < crossfadeRange.getStart())
|
||||
return 0.0f;
|
||||
|
||||
const auto length = static_cast<float>(crossfadeRange.length());
|
||||
if (length == 0.0f)
|
||||
return 1.0f;
|
||||
|
||||
else if (value < crossfadeRange.getEnd()) {
|
||||
const auto crossfadePosition = static_cast<float>(value - crossfadeRange.getStart()) / length;
|
||||
if (curve == SfzCrossfadeCurve::power)
|
||||
return sqrt(crossfadePosition);
|
||||
if (curve == SfzCrossfadeCurve::gain)
|
||||
return crossfadePosition;
|
||||
}
|
||||
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Compute a crossfade out value with respect to a crossfade range (note, velocity, cc, ...)
|
||||
*/
|
||||
template <class T, class U>
|
||||
float crossfadeOut(const sfz::Range<T>& crossfadeRange, U value, SfzCrossfadeCurve curve)
|
||||
{
|
||||
if (value > crossfadeRange.getEnd())
|
||||
return 0.0f;
|
||||
|
||||
const auto length = static_cast<float>(crossfadeRange.length());
|
||||
if (length == 0.0f)
|
||||
return 1.0f;
|
||||
|
||||
else if (value > crossfadeRange.getStart()) {
|
||||
const auto crossfadePosition = static_cast<float>(value - crossfadeRange.getStart()) / length;
|
||||
if (curve == SfzCrossfadeCurve::power)
|
||||
return std::sqrt(1 - crossfadePosition);
|
||||
if (curve == SfzCrossfadeCurve::gain)
|
||||
return 1 - crossfadePosition;
|
||||
}
|
||||
|
||||
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);
|
||||
if (envelope.size() == 0)
|
||||
return;
|
||||
|
||||
const auto maxDelay = static_cast<int>(envelope.size() - 1);
|
||||
|
||||
auto lastValue = lambda(events[0].value);
|
||||
auto lastDelay = events[0].delay;
|
||||
for (unsigned i = 1; i < events.size() && lastDelay < maxDelay; ++i) {
|
||||
const auto length = min(events[i].delay, maxDelay) - lastDelay;
|
||||
const auto step = (lambda(events[i].value) - lastValue) / length;
|
||||
lastValue = linearRamp<float>(envelope.subspan(lastDelay, length), lastValue, step);
|
||||
lastDelay += length;
|
||||
}
|
||||
fill<float>(envelope.subspan(lastDelay), lastValue);
|
||||
}
|
||||
|
||||
template <class F>
|
||||
void linearEnvelope(const EventVector& events, absl::Span<float> envelope, F&& lambda, float step)
|
||||
{
|
||||
ASSERT(events.size() > 0);
|
||||
ASSERT(events[0].delay == 0);
|
||||
ASSERT(step != 0.0);
|
||||
|
||||
if (envelope.size() == 0)
|
||||
return;
|
||||
|
||||
auto quantize = [step](float value) -> float {
|
||||
return std::round(value / step) * step;
|
||||
};
|
||||
const auto maxDelay = static_cast<int>(envelope.size() - 1);
|
||||
|
||||
auto lastValue = quantize(lambda(events[0].value));
|
||||
auto lastDelay = events[0].delay;
|
||||
for (unsigned i = 1; i < events.size() && lastDelay < maxDelay; ++i) {
|
||||
const auto nextValue = quantize(lambda(events[i].value));
|
||||
const auto difference = std::abs(nextValue - lastValue);
|
||||
const auto length = min(events[i].delay, maxDelay) - lastDelay;
|
||||
|
||||
if (difference < step) {
|
||||
fill<float>(envelope.subspan(lastDelay, length), lastValue);
|
||||
lastValue = nextValue;
|
||||
lastDelay += length;
|
||||
continue;
|
||||
}
|
||||
|
||||
const auto numSteps = static_cast<int>(difference / step);
|
||||
const auto stepLength = static_cast<int>(length / numSteps);
|
||||
for (int i = 0; i < numSteps; ++i) {
|
||||
fill<float>(envelope.subspan(lastDelay, stepLength), lastValue);
|
||||
lastValue += lastValue <= nextValue ? step : -step;
|
||||
lastDelay += stepLength;
|
||||
}
|
||||
}
|
||||
fill<float>(envelope.subspan(lastDelay), lastValue);
|
||||
}
|
||||
|
||||
template <class F>
|
||||
void multiplicativeEnvelope(const EventVector& events, absl::Span<float> envelope, F&& lambda)
|
||||
{
|
||||
ASSERT(events.size() > 0);
|
||||
ASSERT(events[0].delay == 0);
|
||||
|
||||
if (envelope.size() == 0)
|
||||
return;
|
||||
const auto maxDelay = static_cast<int>(envelope.size() - 1);
|
||||
|
||||
auto lastValue = lambda(events[0].value);
|
||||
auto lastDelay = events[0].delay;
|
||||
for (unsigned i = 1; i < events.size() && lastDelay < maxDelay; ++i) {
|
||||
const auto length = min(events[i].delay, maxDelay) - lastDelay;
|
||||
const auto nextValue = lambda(events[i].value);
|
||||
const auto step = std::exp((std::log(nextValue) - std::log(lastValue)) / length);
|
||||
multiplicativeRamp<float>(envelope.subspan(lastDelay, length), lastValue, step);
|
||||
lastValue = nextValue;
|
||||
lastDelay += length;
|
||||
}
|
||||
fill<float>(envelope.subspan(lastDelay), lastValue);
|
||||
}
|
||||
|
||||
template <class F>
|
||||
void multiplicativeEnvelope(const EventVector& events, absl::Span<float> envelope, F&& lambda, float step)
|
||||
{
|
||||
ASSERT(events.size() > 0);
|
||||
ASSERT(events[0].delay == 0);
|
||||
ASSERT(step != 0.0f);
|
||||
|
||||
if (envelope.size() == 0)
|
||||
return;
|
||||
const auto maxDelay = static_cast<int>(envelope.size() - 1);
|
||||
|
||||
const auto logStep = std::log(step);
|
||||
// If we assume that a = b.q^r for b in (1, q) then
|
||||
// log a log b
|
||||
// ----- = ----- + r
|
||||
// log q log q
|
||||
// and log(b)\log(q) is between 0 and 1.
|
||||
auto quantize = [logStep](float value) -> float {
|
||||
return std::exp(logStep * std::round(std::log(value) / logStep));
|
||||
};
|
||||
|
||||
auto lastValue = quantize(lambda(events[0].value));
|
||||
auto lastDelay = events[0].delay;
|
||||
for (unsigned i = 1; i < events.size() && lastDelay < maxDelay; ++i) {
|
||||
const auto length = min(events[i].delay, maxDelay) - lastDelay;
|
||||
const auto nextValue = quantize(lambda(events[i].value));
|
||||
const auto difference = nextValue > lastValue ? nextValue / lastValue : lastValue / nextValue;
|
||||
|
||||
if (difference < step) {
|
||||
fill<float>(envelope.subspan(lastDelay, length), lastValue);
|
||||
lastValue = nextValue;
|
||||
lastDelay += length;
|
||||
continue;
|
||||
}
|
||||
|
||||
const auto numSteps = static_cast<int>(std::log(difference) / logStep);
|
||||
const auto stepLength = static_cast<int>(length / numSteps);
|
||||
for (int i = 0; i < numSteps; ++i) {
|
||||
fill<float>(envelope.subspan(lastDelay, stepLength), lastValue);
|
||||
lastValue = nextValue > lastValue ? lastValue * step : lastValue / step;
|
||||
lastDelay += stepLength;
|
||||
}
|
||||
}
|
||||
fill<float>(envelope.subspan(lastDelay), lastValue);
|
||||
}
|
||||
|
||||
} // namespace sfz
|
||||
|
||||
|
|
|
|||
|
|
@ -4,16 +4,14 @@
|
|||
// license. You should have receive a LICENSE.md file along with the code.
|
||||
// If not, contact the sfizz maintainers at https://github.com/sfztools/sfizz
|
||||
|
||||
#include "Macros.h"
|
||||
#include "Voice.h"
|
||||
#include "AudioSpan.h"
|
||||
#include "Config.h"
|
||||
#include "Macros.h"
|
||||
#include "Defaults.h"
|
||||
#include "ModifierHelpers.h"
|
||||
#include "MathHelpers.h"
|
||||
#include "SIMDHelpers.h"
|
||||
#include "SfzHelpers.h"
|
||||
#include "absl/algorithm/container.h"
|
||||
#include <memory>
|
||||
|
||||
sfz::Voice::Voice(sfz::Resources& resources)
|
||||
: resources(resources)
|
||||
|
|
@ -249,51 +247,6 @@ void sfz::Voice::renderBlock(AudioSpan<float> buffer) noexcept
|
|||
#endif
|
||||
}
|
||||
|
||||
template<class F>
|
||||
void linearModifier(const sfz::Resources& resources, absl::Span<float> span, const sfz::CCData<sfz::Modifier>& ccData, F&& lambda)
|
||||
{
|
||||
const auto events = resources.midiState.getCCEvents(ccData.cc);
|
||||
const auto curve = resources.curves.getCurve(ccData.data.curve);
|
||||
if (ccData.data.steps == 0) {
|
||||
linearEnvelope(events, span, [&ccData, &curve, &lambda](float x) {
|
||||
return lambda(curve.evalNormalized(x) * ccData.data.value);
|
||||
});
|
||||
} else {
|
||||
const float stepSize { ccData.data.value / ccData.data.steps };
|
||||
linearEnvelope(events, span, [&ccData, &curve, &lambda](float x) {
|
||||
return lambda(curve.evalNormalized(x) * ccData.data.value);
|
||||
}, stepSize);
|
||||
}
|
||||
}
|
||||
|
||||
template<class F>
|
||||
void multiplicativeModifier(const sfz::Resources& resources, absl::Span<float> span, const sfz::CCData<sfz::Modifier>& ccData, F&& lambda)
|
||||
{
|
||||
const auto events = resources.midiState.getCCEvents(ccData.cc);
|
||||
const auto curve = resources.curves.getCurve(ccData.data.curve);
|
||||
if (ccData.data.steps == 0) {
|
||||
multiplicativeEnvelope(events, span, [&ccData, &curve, &lambda](float x) {
|
||||
return lambda(curve.evalNormalized(x) * ccData.data.value);
|
||||
});
|
||||
} else {
|
||||
// FIXME: not sure about this step size for multiplicative envelopes
|
||||
const float stepSize { ccData.data.value / ccData.data.steps };
|
||||
multiplicativeEnvelope(events, span, [&ccData, &curve, &lambda](float x) {
|
||||
return lambda(curve.evalNormalized(x) * ccData.data.value);
|
||||
}, stepSize);
|
||||
}
|
||||
}
|
||||
|
||||
void linearModifier(const sfz::Resources& resources, absl::Span<float> span, const sfz::CCData<sfz::Modifier>& ccData)
|
||||
{
|
||||
linearModifier(resources, span, ccData, [](float x) { return x; });
|
||||
}
|
||||
|
||||
void multiplicativeModifier(const sfz::Resources& resources, absl::Span<float> span, const sfz::CCData<sfz::Modifier>& ccData)
|
||||
{
|
||||
multiplicativeModifier(resources, span, ccData, [](float x) { return x; });
|
||||
}
|
||||
|
||||
void sfz::Voice::amplitudeEnvelope(absl::Span<float> modulationSpan) noexcept
|
||||
{
|
||||
const auto numSamples = modulationSpan.size();
|
||||
|
|
|
|||
|
|
@ -10,13 +10,10 @@
|
|||
#include "HistoricalBuffer.h"
|
||||
#include "Region.h"
|
||||
#include "AudioBuffer.h"
|
||||
#include "MidiState.h"
|
||||
#include "Wavetables.h"
|
||||
#include "Resources.h"
|
||||
#include "AudioSpan.h"
|
||||
#include "LeakDetector.h"
|
||||
#include <absl/types/span.h>
|
||||
#include <atomic>
|
||||
#include "absl/types/span.h"
|
||||
#include <memory>
|
||||
#include <random>
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
// license. You should have receive a LICENSE.md file along with the code.
|
||||
// If not, contact the sfizz maintainers at https://github.com/sfztools/sfizz
|
||||
|
||||
#include "sfizz/SfzHelpers.h"
|
||||
#include "sfizz/ModifierHelpers.h"
|
||||
#include "sfizz/Buffer.h"
|
||||
#include "catch2/catch.hpp"
|
||||
#include <absl/algorithm/container.h>
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue