From ab07b548fe02198557f6ae3c875dcefbf92fc044 Mon Sep 17 00:00:00 2001 From: Paul Ferrand Date: Tue, 10 Dec 2019 00:01:15 +0100 Subject: [PATCH] Added a way to get an envelope with quantized jumps --- src/sfizz/LinearEnvelope.cpp | 40 +++++++++++++++++++++++++++++++++++- src/sfizz/LinearEnvelope.h | 8 ++++++++ 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/src/sfizz/LinearEnvelope.cpp b/src/sfizz/LinearEnvelope.cpp index c9c04d44..3c9dc975 100644 --- a/src/sfizz/LinearEnvelope.cpp +++ b/src/sfizz/LinearEnvelope.cpp @@ -100,4 +100,42 @@ void LinearEnvelope::getBlock(absl::Span output) clear(); } -} \ No newline at end of file +template +void LinearEnvelope::getQuantizedBlock(absl::Span output, Type quantizationStep) +{ + absl::c_sort(events, [](const auto& lhs, const auto& rhs) { + return lhs.first < rhs.first; + }); + int index { 0 }; + + auto quantize = [quantizationStep](Type value) -> Type { + return static_cast(value / quantizationStep) * quantizationStep; + } + + currentValue = quantize(currentValue); + const auto outputSize = static_cast(output.size()); + for (auto& event : events) { + const auto length = min(event.first, outputSize) - index; + const auto newValue = quantize(event.second); + + if (length == 0) { + currentValue = newValue; + continue; + } + + const int numSteps = abs(newValue - currentValue) / quantizationStep; + const auto stepLength = static_cast(length / numSteps); + while (outputSize - index > stepLength) { + currentValue += currentValue <= newValue ? quantizationStep : -quantizationStep; + fill(output.subspan(index, stepLength), currentValue); + index += stepLength; + } + } + + if (index < outputSize) + fill(output.subspan(index), currentValue); + + clear(); +} + +} diff --git a/src/sfizz/LinearEnvelope.h b/src/sfizz/LinearEnvelope.h index d69562c3..545b6c56 100644 --- a/src/sfizz/LinearEnvelope.h +++ b/src/sfizz/LinearEnvelope.h @@ -99,6 +99,14 @@ public: * @param output */ void getBlock(absl::Span output); + /** + * @brief Get a block of interpolated values with a forced quantization. The + * values within the block will vary in quantization steps. + * + * @param output + * @param quantizationStep + */ + void getQuantizedBlock(absl::Span output, Type quantizationStep); private: std::function function { [](Type input) { return input; } }; static_assert(std::is_arithmetic::value, "Type should be arithmetic");