diff --git a/src/sfizz/Voice.cpp b/src/sfizz/Voice.cpp index e0799d86..293857b1 100644 --- a/src/sfizz/Voice.cpp +++ b/src/sfizz/Voice.cpp @@ -107,6 +107,7 @@ void sfz::Voice::startVoice(Region* region, int delay, int number, float value, if (triggerType != TriggerType::CC) baseGain *= region->getNoteGain(number, value); gainSmoother.reset(); + resetCrossfades(); // Check that we can handle the number of filters; filters should be cleared here ASSERT((filters.capacity() - filters.size()) >= region->filters.size()); @@ -310,15 +311,37 @@ void sfz::Voice::renderBlock(AudioSpan buffer) noexcept #endif } +void sfz::Voice::resetCrossfades() noexcept +{ + float xfadeValue { 1.0f }; + const auto xfCurve = region->crossfadeCCCurve; + + for (const auto& mod : region->crossfadeCCInRange) { + const auto value = resources.midiState.getCCValue(mod.cc); + xfadeValue *= crossfadeIn(mod.data, value, xfCurve); + } + + for (const auto& mod : region->crossfadeCCOutRange) { + const auto value = resources.midiState.getCCValue(mod.cc); + xfadeValue *= crossfadeOut(mod.data, value, xfCurve); + } + + xfadeSmoother.reset(xfadeValue); +} + void sfz::Voice::applyCrossfades(absl::Span modulationSpan) noexcept { const auto numSamples = modulationSpan.size(); const auto xfCurve = region->crossfadeCCCurve; auto tempSpan = resources.bufferPool.getBuffer(numSamples); - if (!tempSpan) + auto xfadeSpan = resources.bufferPool.getBuffer(numSamples); + + if (!tempSpan || !xfadeSpan) return; + fill(*xfadeSpan, 1.0f); + bool smoothOutput = false; for (const auto& mod : region->crossfadeCCInRange) { const auto events = resources.midiState.getCCEvents(mod.cc); @@ -326,7 +349,7 @@ void sfz::Voice::applyCrossfades(absl::Span modulationSpan) noexcept linearEnvelope(events, *tempSpan, [&](float x) { return crossfadeIn(mod.data, x, xfCurve); }); - applyGain(*tempSpan, modulationSpan); + applyGain(*tempSpan, *xfadeSpan); } for (const auto& mod : region->crossfadeCCOutRange) { @@ -335,13 +358,11 @@ void sfz::Voice::applyCrossfades(absl::Span modulationSpan) noexcept linearEnvelope(events, *tempSpan, [&](float x) { return crossfadeOut(mod.data, x, xfCurve); }); - applyGain(*tempSpan, modulationSpan); + applyGain(*tempSpan, *xfadeSpan); } - if (smoothOutput) { - xfadeSmoother.reset(modulationSpan.front()); - xfadeSmoother.process(modulationSpan, modulationSpan); - } + xfadeSmoother.process(*xfadeSpan, *xfadeSpan); + applyGain(*xfadeSpan, modulationSpan); } diff --git a/src/sfizz/Voice.h b/src/sfizz/Voice.h index 03c83337..74fa080c 100644 --- a/src/sfizz/Voice.h +++ b/src/sfizz/Voice.h @@ -347,6 +347,7 @@ private: * @param modulationSpan */ void applyCrossfades(absl::Span modulationSpan) noexcept; + void resetCrossfades() noexcept; /** * @brief Amplitude stage for a mono source