diff --git a/src/sfizz/Smoothers.cpp b/src/sfizz/Smoothers.cpp index c94d670a..59fcc5b9 100644 --- a/src/sfizz/Smoothers.cpp +++ b/src/sfizz/Smoothers.cpp @@ -25,26 +25,21 @@ void Smoother::reset(float value) filter.reset(value); } -void Smoother::process(absl::Span input, absl::Span output) +void Smoother::process(absl::Span input, absl::Span output, bool canShortcut) { CHECK_SPAN_SIZES(input, output); if (input.size() == 0) return; - const auto midValue = input[input.size() / 2]; - const bool shortcut = ( - input.front() == input.back() - && input.front() == midValue - && input.front() == current() - ); + if (canShortcut && std::abs(input.front() - current()) < config::virtuallyZero) { + if (input.data() != output.data()) + copy(input, output); - if (smoothing && !shortcut) { + filter.reset(input.back()); + } else if (smoothing) { filter.processLowpass(input, output); - } - else if (input.data() != output.data()) { + } else if (input.data() != output.data()) { copy(input, output); - } else { - // Nothing to do } } diff --git a/src/sfizz/Smoothers.h b/src/sfizz/Smoothers.h index e2dadb8b..598dd203 100644 --- a/src/sfizz/Smoothers.h +++ b/src/sfizz/Smoothers.h @@ -42,8 +42,11 @@ public: * * @param input * @param output + * @param canShortcut whether we can have a fast path if the filter is within + * a reasonable range around the first value of the input + * span. */ - void process(absl::Span input, absl::Span output); + void process(absl::Span input, absl::Span output, bool canShortcut = false); float current() const { return filter.current(); } private: diff --git a/src/sfizz/Voice.cpp b/src/sfizz/Voice.cpp index 293857b1..b2412cc8 100644 --- a/src/sfizz/Voice.cpp +++ b/src/sfizz/Voice.cpp @@ -342,10 +342,10 @@ void sfz::Voice::applyCrossfades(absl::Span modulationSpan) noexcept fill(*xfadeSpan, 1.0f); - bool smoothOutput = false; + bool canShortcut = true; for (const auto& mod : region->crossfadeCCInRange) { const auto events = resources.midiState.getCCEvents(mod.cc); - smoothOutput |= (events.size() > 1); + canShortcut &= (events.size() == 1); linearEnvelope(events, *tempSpan, [&](float x) { return crossfadeIn(mod.data, x, xfCurve); }); @@ -354,14 +354,14 @@ void sfz::Voice::applyCrossfades(absl::Span modulationSpan) noexcept for (const auto& mod : region->crossfadeCCOutRange) { const auto events = resources.midiState.getCCEvents(mod.cc); - smoothOutput |= (events.size() > 1); + canShortcut &= (events.size() == 1); linearEnvelope(events, *tempSpan, [&](float x) { return crossfadeOut(mod.data, x, xfCurve); }); applyGain(*tempSpan, *xfadeSpan); } - xfadeSmoother.process(*xfadeSpan, *xfadeSpan); + xfadeSmoother.process(*xfadeSpan, *xfadeSpan, canShortcut); applyGain(*xfadeSpan, modulationSpan); }