Ported the old envelope tests to the new free functions

This commit is contained in:
Paul Ferrand 2020-03-31 00:18:24 +02:00
parent 5412593da9
commit bc60b19c4b
2 changed files with 168 additions and 264 deletions

View file

@ -348,11 +348,15 @@ void linearEnvelope(const EventVector& events, absl::Span<float> envelope, F&& l
{
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(); ++ i) {
const auto length = events[i].delay - lastDelay;
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;
@ -366,16 +370,21 @@ void linearEnvelope(const EventVector& events, absl::Span<float> envelope, F&& l
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(); ++ i) {
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 = events[i].delay - lastDelay;
const auto length = min(events[i].delay, maxDelay) - lastDelay;
if (difference < step) {
fill<float>(envelope.subspan(lastDelay, length), lastValue);
@ -401,10 +410,14 @@ void multiplicativeEnvelope(const EventVector& events, absl::Span<float> envelop
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(); ++ i) {
const auto length = events[i].delay - lastDelay;
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);
@ -420,7 +433,10 @@ void multiplicativeEnvelope(const EventVector& events, absl::Span<float> envelop
ASSERT(events.size() > 0);
ASSERT(events[0].delay == 0);
ASSERT(step != 0.0f);
DBG("Called the quantized version with step " << step);
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
@ -434,8 +450,8 @@ void multiplicativeEnvelope(const EventVector& events, absl::Span<float> envelop
auto lastValue = quantize(lambda(events[0].value));
auto lastDelay = events[0].delay;
for (unsigned i = 1; i < events.size(); ++ i) {
const auto length = events[i].delay - lastDelay;
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;

View file

@ -30,360 +30,248 @@ inline bool approxEqual(absl::Span<const Type> lhs, absl::Span<const Type> rhs,
return true;
}
TEST_CASE("[LinearEnvelope] Basic state")
const auto idModifier = [] (float x) { return x; };
const auto twiceModifier = [] (float x) { return 2 * x; };
const auto expModifier = [] (float x) { return std::exp(x); };
TEST_CASE("[Envelopes] Empty")
{
sfz::LinearEnvelope<float> envelope;
sfz::EventVector events {
{0, 0.0f}
};
std::array<float, 5> output;
std::array<float, 5> expected { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f };
envelope.getBlock(absl::MakeSpan(output));
std::array<float, 5> expectedMul { 1.0f, 1.0f, 1.0f, 1.0f, 1.0f };
linearEnvelope(events, absl::MakeSpan(output), idModifier);
REQUIRE(output == expected);
linearEnvelope(events, absl::MakeSpan(output), idModifier, 1.0f);
REQUIRE(output == expected);
multiplicativeEnvelope(events, absl::MakeSpan(output), expModifier);
REQUIRE(output == expectedMul);
multiplicativeEnvelope(events, absl::MakeSpan(output), expModifier, 2.0f);
REQUIRE(output == expectedMul);
}
TEST_CASE("[LinearEnvelope] Basic event")
TEST_CASE("[Envelopes] Linear basic")
{
sfz::LinearEnvelope<float> envelope;
envelope.registerEvent(4, 1.0f);
std::array<float, 8> output;
std::array<float, 8> expected { 0.25f, 0.5f, 0.75f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f };
envelope.getBlock(absl::MakeSpan(output));
sfz::EventVector events {
{0, 0.0f},
{4, 1.0f}
};
std::array<float, 9> output;
std::array<float, 9> expected { 0.0f, 0.25f, 0.5f, 0.75f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f };
linearEnvelope(events, absl::MakeSpan(output), idModifier);
REQUIRE(output == expected);
}
TEST_CASE("[LinearEnvelope] 2 events, close")
{
sfz::LinearEnvelope<float> envelope;
envelope.registerEvent(4, 1.0f);
envelope.registerEvent(5, 2.0f);
std::array<float, 8> output;
std::array<float, 8> expected { 0.25f, 0.5f, 0.75f, 1.0f, 2.0f, 2.0f, 2.0f, 2.0f };
envelope.getBlock(absl::MakeSpan(output));
sfz::EventVector events {
{0, 0.0f},
{4, 1.0f},
{5, 2.0f}
};
std::array<float, 9> output;
std::array<float, 9> expected { 0.0f, 0.25f, 0.5f, 0.75f, 1.0f, 2.0f, 2.0f, 2.0f, 2.0f };
linearEnvelope(events, absl::MakeSpan(output), idModifier);
REQUIRE(output == expected);
}
TEST_CASE("[LinearEnvelope] 2 events, far")
{
sfz::LinearEnvelope<float> envelope;
envelope.registerEvent(2, 1.0f);
envelope.registerEvent(6, 2.0f);
std::array<float, 8> output;
std::array<float, 8> expected { 0.5f, 1.0f, 1.25f, 1.5f, 1.75f, 2.0f, 2.0f, 2.0f };
envelope.getBlock(absl::MakeSpan(output));
REQUIRE(output == expected);
}
TEST_CASE("[LinearEnvelope] 2 events, reversed")
{
sfz::LinearEnvelope<float> envelope;
envelope.registerEvent(6, 2.0f);
envelope.registerEvent(2, 1.0f);
std::array<float, 8> output;
std::array<float, 8> expected { 0.5f, 1.0f, 1.25f, 1.5f, 1.75f, 2.0f, 2.0f, 2.0f };
envelope.getBlock(absl::MakeSpan(output));
REQUIRE(output == expected);
}
TEST_CASE("[LinearEnvelope] 3 events, overlapping")
{
sfz::LinearEnvelope<float> envelope;
envelope.registerEvent(2, 1.0f);
envelope.registerEvent(6, 2.0f);
envelope.registerEvent(6, 3.0f);
std::array<float, 8> output;
std::array<float, 8> expected { 0.5f, 1.0f, 1.5f, 2.0f, 2.5f, 3.0f, 3.0f, 3.0f };
envelope.getBlock(absl::MakeSpan(output));
sfz::EventVector events {
{0, 0.0f},
{2, 1.0f},
{6, 2.0f}
};
std::array<float, 9> output;
std::array<float, 9> expected { 0.0f, 0.5f, 1.0f, 1.25f, 1.5f, 1.75f, 2.0f, 2.0f, 2.0f };
linearEnvelope(events, absl::MakeSpan(output), idModifier);
REQUIRE(output == expected);
}
TEST_CASE("[LinearEnvelope] 3 events, out of block")
{
// sfz::LinearEnvelope<float> envelope;
// envelope.registerEvent(2, 1.0f);
// envelope.registerEvent(6, 2.0f);
// envelope.registerEvent(10, 3.0f);
// std::array<float, 8> output;
// std::array<float, 8> expected { 0.5f, 1.0f, 1.25f, 1.5f, 1.75f, 2.0f, 3.0f, 3.0f }; // TODO: this one is a bit strange
// envelope.getBlock(absl::MakeSpan(output));
// REQUIRE(output == expected);
}
TEST_CASE("[LinearEnvelope] 3 events, out of block, with another block call")
{
sfz::LinearEnvelope<float> envelope;
envelope.registerEvent(2, 1.0f);
envelope.registerEvent(6, 2.0f);
envelope.registerEvent(10, 3.0f);
std::array<float, 8> output;
std::array<float, 8> expected { 3.0f, 3.0f, 3.0f, 3.0f, 3.0f, 3.0f, 3.0f, 3.0f };
envelope.getBlock(absl::MakeSpan(output));
envelope.getBlock(absl::MakeSpan(output));
REQUIRE(output == expected);
}
TEST_CASE("[LinearEnvelope] 2 events, with another block call")
{
sfz::LinearEnvelope<float> envelope;
envelope.registerEvent(2, 1.0f);
envelope.registerEvent(6, 2.0f);
std::array<float, 8> output;
std::array<float, 8> expected { 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f };
envelope.getBlock(absl::MakeSpan(output));
envelope.getBlock(absl::MakeSpan(output));
sfz::EventVector events {
{0, 0.0f},
{2, 1.0f},
{6, 2.0f},
{10, 3.0f}
};
std::array<float, 9> output;
std::array<float, 9> expected { 0.0f, 0.5f, 1.0f, 1.25f, 1.5f, 1.75f, 2.0f, 2.5f, 3.0f };
linearEnvelope(events, absl::MakeSpan(output), idModifier);
REQUIRE(output == expected);
}
TEST_CASE("[LinearEnvelope] 2 events, function")
{
sfz::LinearEnvelope<float> envelope;
envelope.setFunction([](float x) { return 2 * x; });
envelope.registerEvent(2, 1.0f);
envelope.registerEvent(6, 2.0f);
std::array<float, 8> output;
std::array<float, 8> expected { 1.0f, 2.0f, 2.5f, 3.0f, 3.5f, 4.0f, 4.0f, 4.0f };
envelope.getBlock(absl::MakeSpan(output));
sfz::EventVector events {
{0, 0.0f},
{2, 1.0f},
{6, 2.0f}
};
std::array<float, 9> output;
std::array<float, 9> expected { 0.0f, 1.0f, 2.0f, 2.5f, 3.0f, 3.5f, 4.0f, 4.0f, 4.0f };
linearEnvelope(events, absl::MakeSpan(output), twiceModifier);
REQUIRE(output == expected);
}
TEST_CASE("[LinearEnvelope] Get quantized")
{
sfz::LinearEnvelope<float> envelope;
envelope.registerEvent(2, 1.0f);
envelope.registerEvent(6, 2.0f);
sfz::EventVector events {
{0, 0.0f},
{2, 1.0f},
{6, 2.0f}
};
std::array<float, 8> output;
std::array<float, 8> expected { 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 2.0f, 2.0f, 2.0f };
envelope.getQuantizedBlock(absl::MakeSpan(output), 1.0f);
std::array<float, 8> expected { 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 2.0f, 2.0f };
linearEnvelope(events, absl::MakeSpan(output), idModifier, 1.0f);
REQUIRE(output == expected);
}
TEST_CASE("[LinearEnvelope] Get quantized with unquantized targets")
{
sfz::LinearEnvelope<float> envelope;
envelope.registerEvent(2, 1.1f);
envelope.registerEvent(6, 1.9f);
sfz::EventVector events {
{0, 0.0f},
{2, 1.1f},
{6, 1.9f}
};
std::array<float, 8> output;
std::array<float, 8> expected { 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 2.0f, 2.0f, 2.0f };
envelope.getQuantizedBlock(absl::MakeSpan(output), 1.0f);
std::array<float, 8> expected { 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 2.0f, 2.0f };
linearEnvelope(events, absl::MakeSpan(output), idModifier, 1.0f);
REQUIRE(output == expected);
}
TEST_CASE("[LinearEnvelope] Get quantized with 2 steps")
{
sfz::LinearEnvelope<float> envelope;
envelope.registerEvent(2, 1.0f);
envelope.registerEvent(6, 3.0f);
sfz::EventVector events {
{0, 0.0f},
{2, 1.0f},
{6, 3.0f}
};
std::array<float, 8> output;
std::array<float, 8> expected { 0.0f, 1.0f, 1.0f, 2.0f, 2.0f, 3.0f, 3.0f, 3.0f };
envelope.getQuantizedBlock(absl::MakeSpan(output), 1.0f);
std::array<float, 8> expected { 0.0f, 0.0f, 1.0f, 1.0f, 2.0f, 2.0f, 3.0f, 3.0f };
linearEnvelope(events, absl::MakeSpan(output), idModifier, 1.0f);
REQUIRE(output == expected);
}
TEST_CASE("[LinearEnvelope] Get quantized with 2 steps and an unquantized out of block step")
{
sfz::LinearEnvelope<float> envelope;
envelope.registerEvent(2, 1.0f);
envelope.registerEvent(6, 3.0f);
envelope.registerEvent(10, 4.2f);
sfz::EventVector events {
{0, 0.0f},
{2, 1.0f},
{6, 3.0f},
{10, 4.2f},
};
std::array<float, 8> output;
std::array<float, 8> expected { 0.0f, 1.0f, 1.0f, 2.0f, 2.0f, 3.0f, 4.0f, 4.0f };
std::array<float, 8> expected2 { 4.0f, 4.0f, 4.0f,4.0f, 4.0f, 4.0f, 4.0f, 4.0f };
envelope.getQuantizedBlock(absl::MakeSpan(output), 1.0f);
std::array<float, 8> expected { 0.0f, 0.0f, 1.0f, 1.0f, 2.0f, 2.0f, 3.0f, 4.0f };
linearEnvelope(events, absl::MakeSpan(output), idModifier, 1.0f);
REQUIRE(output == expected);
envelope.getQuantizedBlock(absl::MakeSpan(output), 1.0f);
REQUIRE(output == expected2);
}
TEST_CASE("[LinearEnvelope] Going down quantized with 2 steps")
{
sfz::LinearEnvelope<float> envelope;
envelope.reset(3.0f);
envelope.registerEvent(2, 2.0f);
envelope.registerEvent(6, 0.0f);
sfz::EventVector events {
{0, 3.0f},
{2, 2.0f},
{6, 0.0f}
};
std::array<float, 8> output;
std::array<float, 8> expected { 3.0f, 2.0f, 2.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f };
envelope.getQuantizedBlock(absl::MakeSpan(output), 1.0f);
REQUIRE(output == expected);
}
TEST_CASE("[LinearEnvelope] Get quantized with 2 steps and starting unquantized")
{
sfz::LinearEnvelope<float> envelope;
envelope.reset(0.1f);
envelope.registerEvent(3, 1.0f);
envelope.registerEvent(7, 3.0f);
std::array<float, 8> output;
std::array<float, 8> expected { 0.1f, 0.1f, 1.0f, 1.0f, 2.0f, 2.0f, 3.0f, 3.0f };
envelope.getQuantizedBlock(absl::MakeSpan(output), 1.0f);
REQUIRE(output == expected);
}
TEST_CASE("[LinearEnvelope] Going down quantized with 2 steps and starting unquantized")
{
sfz::LinearEnvelope<float> envelope;
envelope.reset(3.6f);
envelope.registerEvent(4, 1.0f);
envelope.registerEvent(7, 0.0);
std::array<float, 8> output;
std::array<float, 8> expected { 3.6f, 3.0f, 2.0f, 2.0f, 1.0f, 1.0f, 0.0f, 0.0f };
envelope.getQuantizedBlock(absl::MakeSpan(output), 1.0f);
REQUIRE(output == expected);
}
TEST_CASE("[LinearEnvelope] Get quantized with unclean events")
{
sfz::LinearEnvelope<float> envelope;
envelope.registerEvent(2, 1.2f);
envelope.registerEvent(6, 2.5f);
std::array<float, 8> output;
std::array<float, 8> expected { 0.0f, 1.0f, 1.0f, 2.0f, 2.0f, 3.0f, 3.0f, 3.0f };
envelope.getQuantizedBlock(absl::MakeSpan(output), 1.0f);
REQUIRE(output == expected);
}
TEST_CASE("[LinearEnvelope] Get quantized 3 events, one out of block")
{
sfz::LinearEnvelope<float> envelope;
envelope.registerEvent(2, 1.0f);
envelope.registerEvent(6, 2.0f);
envelope.registerEvent(10, 3.0f);
std::array<float, 8> output;
std::array<float, 8> expected { 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 2.0f, 3.0f, 3.0f };
std::array<float, 8> expected2 { 3.0f, 3.0f, 3.0f, 3.0f, 3.0f, 3.0f, 3.0f, 3.0f };
envelope.getQuantizedBlock(absl::MakeSpan(output), 1.0f);
REQUIRE(output == expected);
envelope.getQuantizedBlock(absl::MakeSpan(output), 1.0f);
REQUIRE(output == expected2);
}
//
TEST_CASE("[MultiplicativeEnvelope] Basic state")
{
sfz::MultiplicativeEnvelope<float> envelope;
std::array<float, 5> output;
std::array<float, 5> expected { 1.0f, 1.0f, 1.0f, 1.0f, 1.0f };
envelope.getBlock(absl::MakeSpan(output));
std::array<float, 8> expected { 3.0f, 3.0f, 2.0f, 2.0f, 1.0f, 1.0f, 0.0f, 0.0f };
linearEnvelope(events, absl::MakeSpan(output), idModifier, 1.0f);
REQUIRE(output == expected);
}
TEST_CASE("[MultiplicativeEnvelope] Basic event")
{
sfz::MultiplicativeEnvelope<float> envelope;
envelope.registerEvent(4, 2.0f);
sfz::EventVector events {
{0, 1.0f},
{4, 2.0f}
};
std::array<float, 8> output;
std::array<float, 8> expected { 1.1892f, 1.4142f, 1.68176f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f };
envelope.getBlock(absl::MakeSpan(output));
std::array<float, 8> expected { 1.0f, 1.1892f, 1.4142f, 1.68176f, 2.0f, 2.0f, 2.0f, 2.0f };
multiplicativeEnvelope(events, absl::MakeSpan(output), idModifier);
REQUIRE(approxEqual<float>(output, expected));
}
TEST_CASE("[MultiplicativeEnvelope] 2 events")
{
sfz::MultiplicativeEnvelope<float> envelope;
envelope.registerEvent(4, 2.0f);
envelope.registerEvent(5, 4.0f);
sfz::EventVector events {
{0, 1.0f},
{4, 2.0f},
{5, 4.0f}
};
std::array<float, 8> output;
std::array<float, 8> expected { 1.1892f, 1.4142f, 1.68176f, 2.0f, 4.0f, 4.0f, 4.0f, 4.0f };
envelope.getBlock(absl::MakeSpan(output));
std::array<float, 8> expected { 1.0f, 1.1892f, 1.4142f, 1.68176f, 2.0f, 4.0f, 4.0f, 4.0f};
multiplicativeEnvelope(events, absl::MakeSpan(output), idModifier);
REQUIRE(approxEqual<float>(output, expected));
}
TEST_CASE("[MultiplicativeEnvelope] 2 events, far")
{
sfz::MultiplicativeEnvelope<float> envelope;
envelope.registerEvent(2, 2.0f);
envelope.registerEvent(6, 4.0f);
sfz::EventVector events {
{0, 1.0f},
{2, 2.0f},
{6, 4.0f}
};
std::array<float, 8> output;
std::array<float, 8> expected { 1.4142f, 2.0f, 2.37841f, 2.82843f, 3.36358f, 4.0f, 4.0f, 4.0f };
envelope.getBlock(absl::MakeSpan(output));
std::array<float, 8> expected { 1.0f, 1.4142f, 2.0f, 2.37841f, 2.82843f, 3.36358f, 4.0f, 4.0f};
multiplicativeEnvelope(events, absl::MakeSpan(output), idModifier);
REQUIRE(approxEqual<float>(output, expected));
}
TEST_CASE("[MultiplicativeEnvelope] Get quantized with 2 steps")
{
sfz::MultiplicativeEnvelope<float> envelope;
envelope.registerEvent(2, 2.0f);
envelope.registerEvent(6, 4.0f);
sfz::EventVector events {
{0, 1.0f},
{2, 2.0f},
{6, 4.0f}
};
std::array<float, 8> output;
std::array<float, 8> expected { 1.0f, 2.0f, 2.0f, 2.0f, 2.0f, 4.0f, 4.0f, 4.0f };
envelope.getQuantizedBlock(absl::MakeSpan(output), 2.0f);
std::array<float, 8> expected { 1.0f, 1.0f, 2.0f, 2.0f, 2.0f, 2.0f, 4.0f, 4.0f};
multiplicativeEnvelope(events, absl::MakeSpan(output), idModifier, 2.0f);
REQUIRE(output == expected);
}
TEST_CASE("[MultiplicativeEnvelope] Get quantized with an unquantized out of range step")
{
sfz::MultiplicativeEnvelope<float> envelope;
envelope.registerEvent(2, 2.0f);
envelope.registerEvent(6, 4.0f);
envelope.registerEvent(10, 8.2f);
sfz::EventVector events {
{0, 1.0f},
{2, 2.0f},
{6, 4.0f},
{10, 8.2f}
};
std::array<float, 8> output;
std::array<float, 8> expected { 1.0f, 2.0f, 2.0f, 2.0f, 2.0f, 4.0f, 8.0f, 8.0f };
std::array<float, 8> expected2 { 8.0f, 8.0f, 8.0f, 8.0f, 8.0f, 8.0f, 8.0f, 8.0f };
envelope.getQuantizedBlock(absl::MakeSpan(output), 2.0f);
std::array<float, 8> expected { 1.0f, 1.0f, 2.0f, 2.0f, 2.0f, 2.0f, 4.0f, 8.0f };
multiplicativeEnvelope(events, absl::MakeSpan(output), idModifier, 2.0f);
REQUIRE(output == expected);
envelope.getQuantizedBlock(absl::MakeSpan(output), 2.0f);
REQUIRE(output == expected2);
}
TEST_CASE("[MultiplicativeEnvelope] Going down quantized with 2 steps")
{
sfz::MultiplicativeEnvelope<float> envelope;
envelope.reset(4.0f);
envelope.registerEvent(2, 2.0f);
envelope.registerEvent(6, 0.5f);
sfz::EventVector events {
{0, 4.0f},
{2, 2.0f},
{6, 0.5f}
};
std::array<float, 8> output;
std::array<float, 8> expected { 4.0f, 2.0f, 2.0f, 1.0f, 1.0f, 0.5f, 0.5f, 0.5f };
envelope.getQuantizedBlock(absl::MakeSpan(output), 2.0f);
std::array<float, 8> expected { 4.0f, 4.0f, 2.0f, 2.0f, 1.0f, 1.0f, 0.5f, 0.5f };
multiplicativeEnvelope(events, absl::MakeSpan(output), idModifier, 2.0f);
REQUIRE(output == expected);
}
TEST_CASE("[MultiplicativeEnvelope] Get quantized with unclean events")
{
sfz::MultiplicativeEnvelope<float> envelope;
envelope.registerEvent(2, 1.2f);
envelope.registerEvent(6, 2.5f);
sfz::EventVector events {
{0, 1.0f},
{2, 1.2f},
{6, 2.5f}
};
std::array<float, 8> output;
std::array<float, 8> expected { 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 2.0f, 2.0f, 2.0f };
envelope.getQuantizedBlock(absl::MakeSpan(output), 2.0f);
std::array<float, 8> expected { 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 2.0f, 2.0f };
multiplicativeEnvelope(events, absl::MakeSpan(output), idModifier, 2.0f);
REQUIRE(output == expected);
}
TEST_CASE("[MultiplicativeEnvelope] Get quantized with 2 steps and starting unquantized")
{
sfz::MultiplicativeEnvelope<float> envelope;
envelope.reset(0.9f);
envelope.registerEvent(3, 1.0f);
envelope.registerEvent(7, 4.0f);
std::array<float, 8> output;
std::array<float, 8> expected { 0.9f, 0.9f, 1.0f, 1.0f, 2.0f, 2.0f, 4.0f, 4.0f };
envelope.getQuantizedBlock(absl::MakeSpan(output), 2.0f);
REQUIRE(output == expected);
}
TEST_CASE("[MultiplicativeEnvelope] Going down quantized with 2 steps and starting unquantized")
{
sfz::MultiplicativeEnvelope<float> envelope;
envelope.reset(4.6f);
envelope.registerEvent(4, 1.0f);
envelope.registerEvent(7, 0.25f);
std::array<float, 8> output;
std::array<float, 8> expected { 4.6f, 2.0f, 1.0f, 1.0f, 0.5f, 0.5f, 0.25f, 0.25f };
envelope.getQuantizedBlock(absl::MakeSpan(output), 2.0f);
REQUIRE(output == expected);
}
TEST_CASE("[MultiplicativeEnvelope] Pitch envelope basic function")
{
sfz::Buffer<float> output { 256 };
sfz::MultiplicativeEnvelope<float> envelope;
envelope.setFunction([](float pitchValue){
const auto normalizedBend = sfz::normalizeBend(pitchValue);
const auto bendInCents = normalizedBend * 200.0f;
return sfz::centsFactor(bendInCents);
});
envelope.reset(0.0f);
envelope.getBlock(absl::MakeSpan(output));
REQUIRE(output[255] == 1.0_a);
envelope.registerEvent(252, -6020.0f);
envelope.getBlock(absl::MakeSpan(output));
REQUIRE(output[255] == Approx(0.9168).epsilon(0.01));
}