The process call in the smoother now takes an external canShortcut parameter

If the filter can shortcut, it will check that the first input of the span is within a reasonable range of the current value of the filter, and if so it resets it to this value and proceeds as if it were not smoothing
This commit is contained in:
Paul Ferrand 2020-07-07 11:17:53 +02:00
parent 18d4240e58
commit dda4a94a1b
3 changed files with 15 additions and 17 deletions

View file

@ -25,26 +25,21 @@ void Smoother::reset(float value)
filter.reset(value);
}
void Smoother::process(absl::Span<const float> input, absl::Span<float> output)
void Smoother::process(absl::Span<const float> input, absl::Span<float> 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<float>(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<float>(input, output);
} else {
// Nothing to do
}
}

View file

@ -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<const float> input, absl::Span<float> output);
void process(absl::Span<const float> input, absl::Span<float> output, bool canShortcut = false);
float current() const { return filter.current(); }
private:

View file

@ -342,10 +342,10 @@ void sfz::Voice::applyCrossfades(absl::Span<float> modulationSpan) noexcept
fill<float>(*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<float> 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<float>(*tempSpan, *xfadeSpan);
}
xfadeSmoother.process(*xfadeSpan, *xfadeSpan);
xfadeSmoother.process(*xfadeSpan, *xfadeSpan, canShortcut);
applyGain<float>(*xfadeSpan, modulationSpan);
}