Smooth the crossfades
This commit is contained in:
parent
f874ad3db5
commit
4ee4bbe9c1
3 changed files with 49 additions and 17 deletions
|
|
@ -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 };
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue