Match sforzando's behavior (use floor on steps)

This commit is contained in:
Paul Fd 2020-04-07 00:21:47 +02:00
parent e975877569
commit b9ba7fab0b
2 changed files with 9 additions and 9 deletions

View file

@ -88,7 +88,7 @@ void linearEnvelope(const EventVector& events, absl::Span<float> envelope, F&& l
return; return;
auto quantize = [step](float value) -> float { auto quantize = [step](float value) -> float {
return std::round(value / step) * step; return std::floor(value / step) * step;
}; };
const auto maxDelay = static_cast<int>(envelope.size() - 1); const auto maxDelay = static_cast<int>(envelope.size() - 1);
@ -158,7 +158,7 @@ void multiplicativeEnvelope(const EventVector& events, absl::Span<float> envelop
// log q log q // log q log q
// and log(b)\log(q) is between 0 and 1. // and log(b)\log(q) is between 0 and 1.
auto quantize = [logStep](float value) -> float { auto quantize = [logStep](float value) -> float {
return std::exp(logStep * std::round(std::log(value) / logStep)); return std::exp(logStep * std::floor(std::log(value) / logStep));
}; };
auto lastValue = quantize(lambda(events[0].value)); auto lastValue = quantize(lambda(events[0].value));
@ -191,12 +191,12 @@ void linearModifier(const sfz::Resources& resources, absl::Span<float> span, con
{ {
const auto events = resources.midiState.getCCEvents(ccData.cc); const auto events = resources.midiState.getCCEvents(ccData.cc);
const auto curve = resources.curves.getCurve(ccData.data.curve); const auto curve = resources.curves.getCurve(ccData.data.curve);
if (ccData.data.steps == 0) { if (ccData.data.steps < 2) {
linearEnvelope(events, span, [&ccData, &curve, &lambda](float x) { linearEnvelope(events, span, [&ccData, &curve, &lambda](float x) {
return lambda(curve.evalNormalized(x) * ccData.data.value); return lambda(curve.evalNormalized(x) * ccData.data.value);
}); });
} else { } else {
const float stepSize { ccData.data.value / ccData.data.steps }; const float stepSize { ccData.data.value / (ccData.data.steps - 1) };
linearEnvelope(events, span, [&ccData, &curve, &lambda](float x) { linearEnvelope(events, span, [&ccData, &curve, &lambda](float x) {
return lambda(curve.evalNormalized(x) * ccData.data.value); return lambda(curve.evalNormalized(x) * ccData.data.value);
}, stepSize); }, stepSize);
@ -208,13 +208,13 @@ void multiplicativeModifier(const sfz::Resources& resources, absl::Span<float> s
{ {
const auto events = resources.midiState.getCCEvents(ccData.cc); const auto events = resources.midiState.getCCEvents(ccData.cc);
const auto curve = resources.curves.getCurve(ccData.data.curve); const auto curve = resources.curves.getCurve(ccData.data.curve);
if (ccData.data.steps == 0) { if (ccData.data.steps < 2) {
multiplicativeEnvelope(events, span, [&ccData, &curve, &lambda](float x) { multiplicativeEnvelope(events, span, [&ccData, &curve, &lambda](float x) {
return lambda(curve.evalNormalized(x) * ccData.data.value); return lambda(curve.evalNormalized(x) * ccData.data.value);
}); });
} else { } else {
// FIXME: not sure about this step size for multiplicative envelopes // FIXME: not sure about this step size for multiplicative envelopes
const float stepSize { lambda(ccData.data.value / ccData.data.steps) }; const float stepSize { lambda(ccData.data.value / (ccData.data.steps - 1)) };
multiplicativeEnvelope(events, span, [&ccData, &curve, &lambda](float x) { multiplicativeEnvelope(events, span, [&ccData, &curve, &lambda](float x) {
return lambda(curve.evalNormalized(x) * ccData.data.value); return lambda(curve.evalNormalized(x) * ccData.data.value);
}, stepSize); }, stepSize);

View file

@ -137,7 +137,7 @@ TEST_CASE("[LinearEnvelope] Get quantized with unquantized targets")
{ 6, 1.9f } { 6, 1.9f }
}; };
std::array<float, 8> output; std::array<float, 8> output;
std::array<float, 8> expected { 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 2.0f, 2.0f }; std::array<float, 8> expected { 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f };
linearEnvelope(events, absl::MakeSpan(output), idModifier, 1.0f); linearEnvelope(events, absl::MakeSpan(output), idModifier, 1.0f);
REQUIRE(output == expected); REQUIRE(output == expected);
} }
@ -315,7 +315,7 @@ TEST_CASE("[linearModifiers] Compare with envelopes")
ccData.data.steps = 10; ccData.data.steps = 10;
linearEnvelope(resources.midiState.getCCEvents(20), absl::MakeSpan(envelope), [&ccData](float x) { linearEnvelope(resources.midiState.getCCEvents(20), absl::MakeSpan(envelope), [&ccData](float x) {
return ccData.data.value * (1 - x); return ccData.data.value * (1 - x);
}, ccData.data.value / ccData.data.steps); }, ccData.data.value / (ccData.data.steps - 1));
linearModifier(resources, absl::MakeSpan(output), ccData); linearModifier(resources, absl::MakeSpan(output), ccData);
REQUIRE(approxEqual<float>(output, envelope)); REQUIRE(approxEqual<float>(output, envelope));
} }
@ -367,7 +367,7 @@ TEST_CASE("[multiplicativeModifiers] Compare with envelopes")
ccData.data.steps = 10; ccData.data.steps = 10;
multiplicativeEnvelope(resources.midiState.getCCEvents(20), absl::MakeSpan(envelope), [&ccData](float x) { multiplicativeEnvelope(resources.midiState.getCCEvents(20), absl::MakeSpan(envelope), [&ccData](float x) {
return db2mag(ccData.data.value * (1 - x)); return db2mag(ccData.data.value * (1 - x));
}, db2mag(ccData.data.value / ccData.data.steps) ); }, db2mag(ccData.data.value / (ccData.data.steps - 1)) );
multiplicativeModifier(resources, absl::MakeSpan(output), ccData, [](float x) { multiplicativeModifier(resources, absl::MakeSpan(output), ccData, [](float x) {
return db2mag(x); return db2mag(x);
}); });