Refactor the processes in chunks
This commit is contained in:
parent
a337cf5a15
commit
eac0c0e804
2 changed files with 147 additions and 130 deletions
|
|
@ -240,10 +240,15 @@ void sfz::Voice::renderBlock(AudioSpan<float> buffer) noexcept
|
||||||
fillWithData(delayed_buffer);
|
fillWithData(delayed_buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (region->isStereo)
|
if (region->isStereo) {
|
||||||
processStereo(buffer);
|
ampStageStereo(buffer);
|
||||||
else
|
panStageStereo(buffer);
|
||||||
processMono(buffer);
|
filterStageStereo(buffer);
|
||||||
|
} else {
|
||||||
|
ampStageMono(buffer);
|
||||||
|
filterStageMono(buffer);
|
||||||
|
panStageMono(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
if (!egEnvelope.isSmoothing())
|
if (!egEnvelope.isSmoothing())
|
||||||
reset();
|
reset();
|
||||||
|
|
@ -252,11 +257,50 @@ void sfz::Voice::renderBlock(AudioSpan<float> buffer) noexcept
|
||||||
this->triggerDelay = absl::nullopt;
|
this->triggerDelay = absl::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sfz::Voice::processMono(AudioSpan<float> buffer) noexcept
|
void sfz::Voice::ampStageMono(AudioSpan<float> 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<float, float>, _1, _2, region->crossfadeCCCurve);
|
||||||
|
const auto xfoutBind = std::bind(crossfadeIn<float, float>, _1, _2, region->crossfadeCCCurve);
|
||||||
|
|
||||||
|
auto modulationSpan = resources.bufferPool.getBuffer(numSamples);
|
||||||
|
auto tempSpan = resources.bufferPool.getBuffer(numSamples);
|
||||||
|
if (!modulationSpan || !tempSpan)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Amplitude envelope
|
||||||
|
fill<float>(*modulationSpan, baseGain);
|
||||||
|
resources.midiState.multiplicativeModifiers(region->amplitudeCC, *modulationSpan, *tempSpan);
|
||||||
|
DBG("Final gain: " << modulationSpan->back());
|
||||||
|
applyGain<float>(*modulationSpan, leftBuffer);
|
||||||
|
|
||||||
|
// Crossfade envelopes
|
||||||
|
// crossfadeEnvelope.getBlock(modulationSpan);
|
||||||
|
fill<float>(*modulationSpan, 1.0f);
|
||||||
|
resources.midiState.multiplicativeModifiers(region->crossfadeCCInRange, *modulationSpan, *tempSpan, xfinBind);
|
||||||
|
resources.midiState.multiplicativeModifiers(region->crossfadeCCOutRange, *modulationSpan, *tempSpan, xfoutBind);
|
||||||
|
DBG("XF: " << modulationSpan->back());
|
||||||
|
applyGain<float>(*modulationSpan, leftBuffer);
|
||||||
|
|
||||||
|
// Volume envelope
|
||||||
|
volumeEnvelope.getBlock(*modulationSpan);
|
||||||
|
applyGain<float>(*modulationSpan, leftBuffer);
|
||||||
|
|
||||||
|
// AmpEG envelope
|
||||||
|
egEnvelope.getBlock(*modulationSpan);
|
||||||
|
applyGain<float>(*modulationSpan, leftBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sfz::Voice::ampStageStereo(AudioSpan<float> buffer) noexcept
|
||||||
|
{
|
||||||
|
ScopedTiming logger { amplitudeDuration };
|
||||||
|
|
||||||
const auto numSamples = buffer.getNumFrames();
|
const auto numSamples = buffer.getNumFrames();
|
||||||
auto leftBuffer = buffer.getSpan(0);
|
|
||||||
auto rightBuffer = buffer.getSpan(1);
|
|
||||||
|
|
||||||
auto modulationSpan = resources.bufferPool.getBuffer(numSamples);
|
auto modulationSpan = resources.bufferPool.getBuffer(numSamples);
|
||||||
auto tempSpan = resources.bufferPool.getBuffer(numSamples);
|
auto tempSpan = resources.bufferPool.getBuffer(numSamples);
|
||||||
|
|
@ -267,132 +311,111 @@ void sfz::Voice::processMono(AudioSpan<float> buffer) noexcept
|
||||||
const auto xfinBind = std::bind(crossfadeIn<float, float>, _1, _2, region->crossfadeCCCurve);
|
const auto xfinBind = std::bind(crossfadeIn<float, float>, _1, _2, region->crossfadeCCCurve);
|
||||||
const auto xfoutBind = std::bind(crossfadeIn<float, float>, _1, _2, region->crossfadeCCCurve);
|
const auto xfoutBind = std::bind(crossfadeIn<float, float>, _1, _2, region->crossfadeCCCurve);
|
||||||
|
|
||||||
{ // Amplitude processing
|
// Amplitude envelope
|
||||||
ScopedTiming logger { amplitudeDuration };
|
fill<float>(*modulationSpan, baseGain);
|
||||||
|
resources.midiState.multiplicativeModifiers(region->amplitudeCC, *modulationSpan, *tempSpan);
|
||||||
|
buffer.applyGain(*modulationSpan);
|
||||||
|
|
||||||
// Amplitude envelope
|
// Crossfade envelopes
|
||||||
fill<float>(*modulationSpan, baseGain);
|
fill<float>(*modulationSpan, 1.0f);
|
||||||
resources.midiState.multiplicativeModifiers(region->amplitudeCC, *modulationSpan, *tempSpan);
|
resources.midiState.multiplicativeModifiers(region->crossfadeCCInRange, *modulationSpan, *tempSpan, xfinBind);
|
||||||
DBG("Final gain: " << modulationSpan->back());
|
resources.midiState.multiplicativeModifiers(region->crossfadeCCOutRange, *modulationSpan, *tempSpan, xfoutBind);
|
||||||
applyGain<float>(modulationSpan, leftBuffer);
|
buffer.applyGain(*modulationSpan);
|
||||||
|
|
||||||
// Crossfade envelopes
|
// Volume envelope
|
||||||
// crossfadeEnvelope.getBlock(modulationSpan);
|
volumeEnvelope.getBlock(*modulationSpan);
|
||||||
fill<float>(*modulationSpan, 1.0f);
|
buffer.applyGain(*modulationSpan);
|
||||||
resources.midiState.multiplicativeModifiers(region->crossfadeCCInRange, *modulationSpan, *tempSpan, xfinBind);
|
|
||||||
resources.midiState.multiplicativeModifiers(region->crossfadeCCOutRange, *modulationSpan, *tempSpan, xfoutBind);
|
|
||||||
DBG("XF: " << modulationSpan->back());
|
|
||||||
applyGain<float>(modulationSpan, leftBuffer);
|
|
||||||
|
|
||||||
// Volume envelope
|
// AmpEG envelope
|
||||||
volumeEnvelope.getBlock(*modulationSpan);
|
egEnvelope.getBlock(*modulationSpan);
|
||||||
applyGain<float>(*modulationSpan, leftBuffer);
|
buffer.applyGain(*modulationSpan);
|
||||||
|
}
|
||||||
|
|
||||||
// AmpEG envelope
|
void sfz::Voice::panStageMono(AudioSpan<float> buffer) noexcept
|
||||||
egEnvelope.getBlock(*modulationSpan);
|
{
|
||||||
applyGain<float>(*modulationSpan, leftBuffer);
|
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<float>(leftBuffer, rightBuffer);
|
||||||
|
|
||||||
|
// Apply panning
|
||||||
|
fill<float>(*modulationSpan, region->pan);
|
||||||
|
resources.midiState.additiveModifiers(region->panCC, *modulationSpan, *tempSpan);
|
||||||
|
DBG("Pan: " << modulationSpan->back());
|
||||||
|
pan<float>(*modulationSpan, leftBuffer, rightBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sfz::Voice::panStageStereo(AudioSpan<float> 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<float>(*modulationSpan, region->pan);
|
||||||
|
resources.midiState.additiveModifiers(region->panCC, *modulationSpan, *tempSpan);
|
||||||
|
pan<float>(*modulationSpan, leftBuffer, rightBuffer);
|
||||||
|
|
||||||
|
// Apply the width/position process
|
||||||
|
// widthModulation(*modulationSpan);
|
||||||
|
fill<float>(*modulationSpan, region->width);
|
||||||
|
resources.midiState.additiveModifiers(region->widthCC, *modulationSpan, *tempSpan);
|
||||||
|
width<float>(*modulationSpan, leftBuffer, rightBuffer);
|
||||||
|
|
||||||
|
// positionModulation(*modulationSpan);
|
||||||
|
fill<float>(*modulationSpan, region->position);
|
||||||
|
resources.midiState.additiveModifiers(region->positionCC, *modulationSpan, *tempSpan);
|
||||||
|
pan<float>(*modulationSpan, leftBuffer, rightBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sfz::Voice::filterStageMono(AudioSpan<float> 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
|
for (auto& eq: equalizers) {
|
||||||
ScopedTiming logger { filterDuration };
|
eq->process(inputChannel, outputChannel, numSamples);
|
||||||
|
|
||||||
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<float>(leftBuffer, rightBuffer);
|
|
||||||
|
|
||||||
// Apply panning
|
|
||||||
fill<float>(*modulationSpan, region->pan);
|
|
||||||
resources.midiState.additiveModifiers(region->panCC, *modulationSpan, *tempSpan);
|
|
||||||
DBG("Pan: " << modulationSpan->back());
|
|
||||||
pan<float>(*modulationSpan, leftBuffer, rightBuffer);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void sfz::Voice::processStereo(AudioSpan<float> buffer) noexcept
|
void sfz::Voice::filterStageStereo(AudioSpan<float> buffer) noexcept
|
||||||
{
|
{
|
||||||
|
ScopedTiming logger { filterDuration };
|
||||||
const auto numSamples = buffer.getNumFrames();
|
const auto numSamples = buffer.getNumFrames();
|
||||||
auto leftBuffer = buffer.getSpan(0);
|
const auto leftBuffer = buffer.getSpan(0);
|
||||||
auto rightBuffer = buffer.getSpan(1);
|
const auto rightBuffer = buffer.getSpan(1);
|
||||||
|
|
||||||
auto modulationSpan = resources.bufferPool.getBuffer(numSamples);
|
const float* inputChannels[2] { leftBuffer.data(), rightBuffer.data() };
|
||||||
auto tempSpan = resources.bufferPool.getBuffer(numSamples);
|
float* outputChannels[2] { leftBuffer.data(), rightBuffer.data() };
|
||||||
if (!modulationSpan || !tempSpan)
|
|
||||||
return;
|
|
||||||
|
|
||||||
using namespace std::placeholders;
|
for (auto& filter: filters) {
|
||||||
const auto xfinBind = std::bind(crossfadeIn<float, float>, _1, _2, region->crossfadeCCCurve);
|
filter->process(inputChannels, outputChannels, numSamples);
|
||||||
const auto xfoutBind = std::bind(crossfadeIn<float, float>, _1, _2, region->crossfadeCCCurve);
|
|
||||||
|
|
||||||
{ // Amplitude processing
|
|
||||||
ScopedTiming logger { amplitudeDuration };
|
|
||||||
|
|
||||||
// Amplitude envelope
|
|
||||||
fill<float>(*modulationSpan, baseGain);
|
|
||||||
resources.midiState.multiplicativeModifiers(region->amplitudeCC, *modulationSpan, *tempSpan);
|
|
||||||
buffer.applyGain(*modulationSpan);
|
|
||||||
|
|
||||||
// Crossfade envelopes
|
|
||||||
fill<float>(*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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
{ // Panning and stereo processing
|
for (auto& eq: equalizers) {
|
||||||
ScopedTiming logger { panningDuration };
|
eq->process(inputChannels, outputChannels, numSamples);
|
||||||
|
|
||||||
// Apply panning
|
|
||||||
// panningModulation(*modulationSpan);
|
|
||||||
fill<float>(*modulationSpan, region->pan);
|
|
||||||
resources.midiState.additiveModifiers(region->panCC, *modulationSpan, *tempSpan);
|
|
||||||
pan<float>(*modulationSpan, leftBuffer, rightBuffer);
|
|
||||||
|
|
||||||
// Apply the width/position process
|
|
||||||
// widthModulation(*modulationSpan);
|
|
||||||
fill<float>(*modulationSpan, region->width);
|
|
||||||
resources.midiState.additiveModifiers(region->widthCC, *modulationSpan, *tempSpan);
|
|
||||||
width<float>(*modulationSpan, leftBuffer, rightBuffer);
|
|
||||||
|
|
||||||
// positionModulation(*modulationSpan);
|
|
||||||
fill<float>(*modulationSpan, region->position);
|
|
||||||
resources.midiState.additiveModifiers(region->positionCC, *modulationSpan, *tempSpan);
|
|
||||||
pan<float>(*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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -238,18 +238,12 @@ private:
|
||||||
* @param buffer
|
* @param buffer
|
||||||
*/
|
*/
|
||||||
void fillWithGenerator(AudioSpan<float> buffer) noexcept;
|
void fillWithGenerator(AudioSpan<float> buffer) noexcept;
|
||||||
/**
|
void ampStageMono(AudioSpan<float> buffer) noexcept;
|
||||||
* @brief The function processing a mono sample source
|
void ampStageStereo(AudioSpan<float> buffer) noexcept;
|
||||||
*
|
void panStageMono(AudioSpan<float> buffer) noexcept;
|
||||||
* @param buffer
|
void panStageStereo(AudioSpan<float> buffer) noexcept;
|
||||||
*/
|
void filterStageMono(AudioSpan<float> buffer) noexcept;
|
||||||
void processMono(AudioSpan<float> buffer) noexcept;
|
void filterStageStereo(AudioSpan<float> buffer) noexcept;
|
||||||
/**
|
|
||||||
* @brief The function processing a stereo sample source
|
|
||||||
*
|
|
||||||
* @param buffer
|
|
||||||
*/
|
|
||||||
void processStereo(AudioSpan<float> buffer) noexcept;
|
|
||||||
|
|
||||||
Region* region { nullptr };
|
Region* region { nullptr };
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue