From eac0c0e804054f4916cc979f314c08a6a37d1a4c Mon Sep 17 00:00:00 2001 From: Paul Ferrand Date: Mon, 30 Mar 2020 19:13:35 +0200 Subject: [PATCH] Refactor the processes in chunks --- src/sfizz/Voice.cpp | 259 ++++++++++++++++++++++++-------------------- src/sfizz/Voice.h | 18 +-- 2 files changed, 147 insertions(+), 130 deletions(-) diff --git a/src/sfizz/Voice.cpp b/src/sfizz/Voice.cpp index 8b401bf8..6444aecf 100644 --- a/src/sfizz/Voice.cpp +++ b/src/sfizz/Voice.cpp @@ -240,10 +240,15 @@ void sfz::Voice::renderBlock(AudioSpan buffer) noexcept fillWithData(delayed_buffer); } - if (region->isStereo) - processStereo(buffer); - else - processMono(buffer); + if (region->isStereo) { + ampStageStereo(buffer); + panStageStereo(buffer); + filterStageStereo(buffer); + } else { + ampStageMono(buffer); + filterStageMono(buffer); + panStageMono(buffer); + } if (!egEnvelope.isSmoothing()) reset(); @@ -252,11 +257,50 @@ void sfz::Voice::renderBlock(AudioSpan buffer) noexcept this->triggerDelay = absl::nullopt; } -void sfz::Voice::processMono(AudioSpan buffer) noexcept +void sfz::Voice::ampStageMono(AudioSpan buffer) noexcept { + ScopedTiming logger { amplitudeDuration }; + + const auto numSamples = buffer.getNumFrames(); + const auto leftBuffer = buffer.getSpan(0); + + using namespace std::placeholders; + const auto xfinBind = std::bind(crossfadeIn, _1, _2, region->crossfadeCCCurve); + const auto xfoutBind = std::bind(crossfadeIn, _1, _2, region->crossfadeCCCurve); + + auto modulationSpan = resources.bufferPool.getBuffer(numSamples); + auto tempSpan = resources.bufferPool.getBuffer(numSamples); + if (!modulationSpan || !tempSpan) + return; + + // Amplitude envelope + fill(*modulationSpan, baseGain); + resources.midiState.multiplicativeModifiers(region->amplitudeCC, *modulationSpan, *tempSpan); + DBG("Final gain: " << modulationSpan->back()); + applyGain(*modulationSpan, leftBuffer); + + // Crossfade envelopes + // crossfadeEnvelope.getBlock(modulationSpan); + fill(*modulationSpan, 1.0f); + resources.midiState.multiplicativeModifiers(region->crossfadeCCInRange, *modulationSpan, *tempSpan, xfinBind); + resources.midiState.multiplicativeModifiers(region->crossfadeCCOutRange, *modulationSpan, *tempSpan, xfoutBind); + DBG("XF: " << modulationSpan->back()); + applyGain(*modulationSpan, leftBuffer); + + // Volume envelope + volumeEnvelope.getBlock(*modulationSpan); + applyGain(*modulationSpan, leftBuffer); + + // AmpEG envelope + egEnvelope.getBlock(*modulationSpan); + applyGain(*modulationSpan, leftBuffer); +} + +void sfz::Voice::ampStageStereo(AudioSpan buffer) noexcept +{ + ScopedTiming logger { amplitudeDuration }; + const auto numSamples = buffer.getNumFrames(); - auto leftBuffer = buffer.getSpan(0); - auto rightBuffer = buffer.getSpan(1); auto modulationSpan = resources.bufferPool.getBuffer(numSamples); auto tempSpan = resources.bufferPool.getBuffer(numSamples); @@ -267,132 +311,111 @@ void sfz::Voice::processMono(AudioSpan buffer) noexcept const auto xfinBind = std::bind(crossfadeIn, _1, _2, region->crossfadeCCCurve); const auto xfoutBind = std::bind(crossfadeIn, _1, _2, region->crossfadeCCCurve); - { // Amplitude processing - ScopedTiming logger { amplitudeDuration }; + // Amplitude envelope + fill(*modulationSpan, baseGain); + resources.midiState.multiplicativeModifiers(region->amplitudeCC, *modulationSpan, *tempSpan); + buffer.applyGain(*modulationSpan); - // Amplitude envelope - fill(*modulationSpan, baseGain); - resources.midiState.multiplicativeModifiers(region->amplitudeCC, *modulationSpan, *tempSpan); - DBG("Final gain: " << modulationSpan->back()); - applyGain(modulationSpan, leftBuffer); + // Crossfade envelopes + fill(*modulationSpan, 1.0f); + resources.midiState.multiplicativeModifiers(region->crossfadeCCInRange, *modulationSpan, *tempSpan, xfinBind); + resources.midiState.multiplicativeModifiers(region->crossfadeCCOutRange, *modulationSpan, *tempSpan, xfoutBind); + buffer.applyGain(*modulationSpan); - // Crossfade envelopes - // crossfadeEnvelope.getBlock(modulationSpan); - fill(*modulationSpan, 1.0f); - resources.midiState.multiplicativeModifiers(region->crossfadeCCInRange, *modulationSpan, *tempSpan, xfinBind); - resources.midiState.multiplicativeModifiers(region->crossfadeCCOutRange, *modulationSpan, *tempSpan, xfoutBind); - DBG("XF: " << modulationSpan->back()); - applyGain(modulationSpan, leftBuffer); + // Volume envelope + volumeEnvelope.getBlock(*modulationSpan); + buffer.applyGain(*modulationSpan); - // Volume envelope - volumeEnvelope.getBlock(*modulationSpan); - applyGain(*modulationSpan, leftBuffer); + // AmpEG envelope + egEnvelope.getBlock(*modulationSpan); + buffer.applyGain(*modulationSpan); +} - // AmpEG envelope - egEnvelope.getBlock(*modulationSpan); - applyGain(*modulationSpan, leftBuffer); +void sfz::Voice::panStageMono(AudioSpan buffer) noexcept +{ + ScopedTiming logger { panningDuration }; + + const auto numSamples = buffer.getNumFrames(); + const auto leftBuffer = buffer.getSpan(0); + const auto rightBuffer = buffer.getSpan(1); + + auto modulationSpan = resources.bufferPool.getBuffer(numSamples); + auto tempSpan = resources.bufferPool.getBuffer(numSamples); + if (!modulationSpan || !tempSpan) + return; + + // Prepare for stereo output + copy(leftBuffer, rightBuffer); + + // Apply panning + fill(*modulationSpan, region->pan); + resources.midiState.additiveModifiers(region->panCC, *modulationSpan, *tempSpan); + DBG("Pan: " << modulationSpan->back()); + pan(*modulationSpan, leftBuffer, rightBuffer); +} + +void sfz::Voice::panStageStereo(AudioSpan buffer) noexcept +{ + ScopedTiming logger { panningDuration }; + const auto numSamples = buffer.getNumFrames(); + const auto leftBuffer = buffer.getSpan(0); + const auto rightBuffer = buffer.getSpan(1); + + auto modulationSpan = resources.bufferPool.getBuffer(numSamples); + auto tempSpan = resources.bufferPool.getBuffer(numSamples); + if (!modulationSpan || !tempSpan) + return; + + // Apply panning + // panningModulation(*modulationSpan); + fill(*modulationSpan, region->pan); + resources.midiState.additiveModifiers(region->panCC, *modulationSpan, *tempSpan); + pan(*modulationSpan, leftBuffer, rightBuffer); + + // Apply the width/position process + // widthModulation(*modulationSpan); + fill(*modulationSpan, region->width); + resources.midiState.additiveModifiers(region->widthCC, *modulationSpan, *tempSpan); + width(*modulationSpan, leftBuffer, rightBuffer); + + // positionModulation(*modulationSpan); + fill(*modulationSpan, region->position); + resources.midiState.additiveModifiers(region->positionCC, *modulationSpan, *tempSpan); + pan(*modulationSpan, leftBuffer, rightBuffer); +} + +void sfz::Voice::filterStageMono(AudioSpan buffer) noexcept +{ + ScopedTiming logger { filterDuration }; + const auto numSamples = buffer.getNumFrames(); + const auto leftBuffer = buffer.getSpan(0); + const float* inputChannel[1] { leftBuffer.data() }; + float* outputChannel[1] { leftBuffer.data() }; + for (auto& filter: filters) { + filter->process(inputChannel, outputChannel, numSamples); } - { // Filtering and EQ - ScopedTiming logger { filterDuration }; - - const float* inputChannel[1] { leftBuffer.data() }; - float* outputChannel[1] { leftBuffer.data() }; - for (auto& filter: filters) { - filter->process(inputChannel, outputChannel, numSamples); - } - - for (auto& eq: equalizers) { - eq->process(inputChannel, outputChannel, numSamples); - } - } - - { // Panning and stereo processing - ScopedTiming logger { panningDuration }; - - // Prepare for stereo output - copy(leftBuffer, rightBuffer); - - // Apply panning - fill(*modulationSpan, region->pan); - resources.midiState.additiveModifiers(region->panCC, *modulationSpan, *tempSpan); - DBG("Pan: " << modulationSpan->back()); - pan(*modulationSpan, leftBuffer, rightBuffer); + for (auto& eq: equalizers) { + eq->process(inputChannel, outputChannel, numSamples); } } -void sfz::Voice::processStereo(AudioSpan buffer) noexcept +void sfz::Voice::filterStageStereo(AudioSpan buffer) noexcept { + ScopedTiming logger { filterDuration }; const auto numSamples = buffer.getNumFrames(); - auto leftBuffer = buffer.getSpan(0); - auto rightBuffer = buffer.getSpan(1); + const auto leftBuffer = buffer.getSpan(0); + const auto rightBuffer = buffer.getSpan(1); - auto modulationSpan = resources.bufferPool.getBuffer(numSamples); - auto tempSpan = resources.bufferPool.getBuffer(numSamples); - if (!modulationSpan || !tempSpan) - return; + const float* inputChannels[2] { leftBuffer.data(), rightBuffer.data() }; + float* outputChannels[2] { leftBuffer.data(), rightBuffer.data() }; - using namespace std::placeholders; - const auto xfinBind = std::bind(crossfadeIn, _1, _2, region->crossfadeCCCurve); - const auto xfoutBind = std::bind(crossfadeIn, _1, _2, region->crossfadeCCCurve); - - { // Amplitude processing - ScopedTiming logger { amplitudeDuration }; - - // Amplitude envelope - fill(*modulationSpan, baseGain); - resources.midiState.multiplicativeModifiers(region->amplitudeCC, *modulationSpan, *tempSpan); - buffer.applyGain(*modulationSpan); - - // Crossfade envelopes - fill(*modulationSpan, 1.0f); - resources.midiState.multiplicativeModifiers(region->crossfadeCCInRange, *modulationSpan, *tempSpan, xfinBind); - resources.midiState.multiplicativeModifiers(region->crossfadeCCOutRange, *modulationSpan, *tempSpan, xfoutBind); - buffer.applyGain(*modulationSpan); - - // Volume envelope - volumeEnvelope.getBlock(*modulationSpan); - buffer.applyGain(*modulationSpan); - - // AmpEG envelope - egEnvelope.getBlock(*modulationSpan); - buffer.applyGain(*modulationSpan); + for (auto& filter: filters) { + filter->process(inputChannels, outputChannels, numSamples); } - { // Panning and stereo processing - ScopedTiming logger { panningDuration }; - - // Apply panning - // panningModulation(*modulationSpan); - fill(*modulationSpan, region->pan); - resources.midiState.additiveModifiers(region->panCC, *modulationSpan, *tempSpan); - pan(*modulationSpan, leftBuffer, rightBuffer); - - // Apply the width/position process - // widthModulation(*modulationSpan); - fill(*modulationSpan, region->width); - resources.midiState.additiveModifiers(region->widthCC, *modulationSpan, *tempSpan); - width(*modulationSpan, leftBuffer, rightBuffer); - - // positionModulation(*modulationSpan); - fill(*modulationSpan, region->position); - resources.midiState.additiveModifiers(region->positionCC, *modulationSpan, *tempSpan); - pan(*modulationSpan, leftBuffer, rightBuffer); - } - - { // Filtering and EQ - ScopedTiming logger { filterDuration }; - - const float* inputChannels[2] { leftBuffer.data(), rightBuffer.data() }; - float* outputChannels[2] { leftBuffer.data(), rightBuffer.data() }; - - for (auto& filter: filters) { - filter->process(inputChannels, outputChannels, numSamples); - } - - for (auto& eq: equalizers) { - eq->process(inputChannels, outputChannels, numSamples); - } + for (auto& eq: equalizers) { + eq->process(inputChannels, outputChannels, numSamples); } } diff --git a/src/sfizz/Voice.h b/src/sfizz/Voice.h index e8154546..d65a228a 100644 --- a/src/sfizz/Voice.h +++ b/src/sfizz/Voice.h @@ -238,18 +238,12 @@ private: * @param buffer */ void fillWithGenerator(AudioSpan buffer) noexcept; - /** - * @brief The function processing a mono sample source - * - * @param buffer - */ - void processMono(AudioSpan buffer) noexcept; - /** - * @brief The function processing a stereo sample source - * - * @param buffer - */ - void processStereo(AudioSpan buffer) noexcept; + void ampStageMono(AudioSpan buffer) noexcept; + void ampStageStereo(AudioSpan buffer) noexcept; + void panStageMono(AudioSpan buffer) noexcept; + void panStageStereo(AudioSpan buffer) noexcept; + void filterStageMono(AudioSpan buffer) noexcept; + void filterStageStereo(AudioSpan buffer) noexcept; Region* region { nullptr };