Smooth the crossfades

This commit is contained in:
Paul Ferrand 2020-07-05 15:25:57 +02:00
parent f874ad3db5
commit 4ee4bbe9c1
3 changed files with 49 additions and 17 deletions

View file

@ -41,6 +41,7 @@ namespace config {
constexpr int numVoices { 64 };
constexpr unsigned maxVoices { 256 };
constexpr unsigned smoothingSteps { 512 };
constexpr uint8_t xfadeSmoothing { 5 };
constexpr uint8_t gainSmoothing { 0 };
constexpr unsigned powerTableSizeExponent { 11 };
constexpr int maxFilePromises { maxVoices };

View file

@ -25,6 +25,7 @@ sfz::Voice::Voice(int voiceNumber, sfz::Resources& resources)
osc.init(sampleRate);
gainSmoother.setSmoothing(config::gainSmoothing, sampleRate);
xfadeSmoother.setSmoothing(config::xfadeSmoothing, sampleRate);
for (auto & filter : channelEnvelopeFilters)
filter.setGain(vaGain(config::filteredEnvelopeCutoff, sampleRate));
@ -245,6 +246,7 @@ void sfz::Voice::setSampleRate(float sampleRate) noexcept
{
this->sampleRate = sampleRate;
gainSmoother.setSmoothing(config::gainSmoothing, sampleRate);
xfadeSmoother.setSmoothing(config::xfadeSmoothing, sampleRate);
for (auto & filter : channelEnvelopeFilters)
filter.setGain(vaGain(config::filteredEnvelopeCutoff, sampleRate));
@ -308,11 +310,45 @@ void sfz::Voice::renderBlock(AudioSpan<float> buffer) noexcept
#endif
}
void sfz::Voice::amplitudeEnvelope(absl::Span<float> modulationSpan) noexcept
void sfz::Voice::applyCrossfades(absl::Span<float> modulationSpan) noexcept
{
const auto numSamples = modulationSpan.size();
const auto xfCurve = region->crossfadeCCCurve;
auto tempSpan = resources.bufferPool.getBuffer(numSamples);
if (!tempSpan)
return;
bool smoothOutput = false;
for (const auto& mod : region->crossfadeCCInRange) {
const auto events = resources.midiState.getCCEvents(mod.cc);
smoothOutput |= (events.size() > 1);
linearEnvelope(events, *tempSpan, [&](float x) {
return crossfadeIn(mod.data, x, xfCurve);
});
applyGain<float>(*tempSpan, modulationSpan);
}
for (const auto& mod : region->crossfadeCCOutRange) {
const auto events = resources.midiState.getCCEvents(mod.cc);
smoothOutput |= (events.size() > 1);
linearEnvelope(events, *tempSpan, [&](float x) {
return crossfadeOut(mod.data, x, xfCurve);
});
applyGain<float>(*tempSpan, modulationSpan);
}
if (smoothOutput) {
xfadeSmoother.reset(modulationSpan.front());
xfadeSmoother.process(modulationSpan, modulationSpan);
}
}
void sfz::Voice::amplitudeEnvelope(absl::Span<float> modulationSpan) noexcept
{
const auto numSamples = modulationSpan.size();
auto tempSpan = resources.bufferPool.getBuffer(numSamples);
if (!tempSpan)
return;
@ -328,22 +364,6 @@ void sfz::Voice::amplitudeEnvelope(absl::Span<float> modulationSpan) noexcept
applyGain<float>(*tempSpan, modulationSpan);
});
// Crossfade envelopes
for (const auto& mod : region->crossfadeCCInRange) {
const auto events = resources.midiState.getCCEvents(mod.cc);
linearEnvelope(events, *tempSpan, [&](float x) {
return crossfadeIn(mod.data, x, xfCurve);
});
applyGain<float>(*tempSpan, modulationSpan);
}
for (const auto& mod : region->crossfadeCCOutRange) {
const auto events = resources.midiState.getCCEvents(mod.cc);
linearEnvelope(events, *tempSpan, [&](float x) {
return crossfadeOut(mod.data, x, xfCurve);
});
applyGain<float>(*tempSpan, modulationSpan);
}
// Volume envelope
applyGain1<float>(db2mag(baseVolumedB), modulationSpan);
forEachWithSmoother(Mod::volume, [&](const CCData<Modifier>& mod, Smoother& smoother) {
@ -370,6 +390,7 @@ void sfz::Voice::ampStageMono(AudioSpan<float> buffer) noexcept
return;
amplitudeEnvelope(*modulationSpan);
applyCrossfades(*modulationSpan);
applyGain<float>(*modulationSpan, leftBuffer);
}
@ -383,6 +404,7 @@ void sfz::Voice::ampStageStereo(AudioSpan<float> buffer) noexcept
return;
amplitudeEnvelope(*modulationSpan);
applyCrossfades(*modulationSpan);
buffer.applyGain(*modulationSpan);
}

View file

@ -340,6 +340,14 @@ private:
* @param modulationSpan
*/
void amplitudeEnvelope(absl::Span<float> modulationSpan) noexcept;
/**
* @brief Apply the crossfade envelope to a span.
*
* @param modulationSpan
*/
void applyCrossfades(absl::Span<float> modulationSpan) noexcept;
/**
* @brief Amplitude stage for a mono source
*
@ -473,6 +481,7 @@ private:
ModifierArray<std::vector<Smoother>> modifierSmoothers;
Smoother gainSmoother;
Smoother bendSmoother;
Smoother xfadeSmoother;
void resetSmoothers() noexcept;
std::array<OnePoleFilter<float>, 2> channelEnvelopeFilters;