From 97702e43081c0a2fdfea3bce0ad4b91a0bb25422 Mon Sep 17 00:00:00 2001 From: Jean Pierre Cimalando Date: Mon, 27 Jul 2020 19:14:30 +0200 Subject: [PATCH] Advance the generator when not used --- src/sfizz/Synth.cpp | 8 +++++-- src/sfizz/modulations/ModGenerator.h | 14 ++++++++++++ src/sfizz/modulations/ModMatrix.cpp | 33 ++++++++++++++++++++++++++++ src/sfizz/modulations/ModMatrix.h | 12 ++++++++++ 4 files changed, 65 insertions(+), 2 deletions(-) diff --git a/src/sfizz/Synth.cpp b/src/sfizz/Synth.cpp index cb1ba8c4..cba7e139 100644 --- a/src/sfizz/Synth.cpp +++ b/src/sfizz/Synth.cpp @@ -723,6 +723,7 @@ void sfz::Synth::renderBlock(AudioSpan buffer) noexcept } ModMatrix& mm = resources.modMatrix; + mm.beginCycle(numFrames); activeVoices = 0; { // Main render block @@ -731,8 +732,6 @@ void sfz::Synth::renderBlock(AudioSpan buffer) noexcept tempMixSpan->fill(0.0f); resources.filePool.cleanupPromises(); - mm.beginCycle(numFrames); - // Ramp out whatever is in the buffer at this point; should only be killed voice data linearRamp(*rampSpan, 1.0f, -1.0f / static_cast(numFrames)); for (size_t i = 0, n = effectBuses.size(); i < n; ++i) { @@ -754,6 +753,8 @@ void sfz::Synth::renderBlock(AudioSpan buffer) noexcept callbackBreakdown.filters += voice->getLastFilterDuration(); callbackBreakdown.panning += voice->getLastPanningDuration(); + mm.endVoice(); + if (voice->toBeCleanedUp()) voice->reset(); } @@ -781,6 +782,9 @@ void sfz::Synth::renderBlock(AudioSpan buffer) noexcept // Apply the master volume buffer.applyGain(db2mag(volume)); + // Perform any remaining modulators + mm.endCycle(); + { // Clear events and advance midi time ScopedTiming logger { dispatchDuration, ScopedTiming::Operation::addToDuration }; resources.midiState.advanceTime(buffer.getNumFrames()); diff --git a/src/sfizz/modulations/ModGenerator.h b/src/sfizz/modulations/ModGenerator.h index c146593d..457460c3 100644 --- a/src/sfizz/modulations/ModGenerator.h +++ b/src/sfizz/modulations/ModGenerator.h @@ -47,6 +47,20 @@ public: * @param buffer output buffer */ virtual void generate(const ModKey& sourceKey, NumericId voiceNum, absl::Span buffer) = 0; + + /** + * @brief Advance the generator by a number of frames + * This is called instead of `generate` in case the output is discarded. + * It can be overriden with a faster implementation if wanted. + * + * @param sourceKey source key + * @param voiceNum voice number if the generator is per-voice, otherwise undefined + * @param buffer writable spare buffer, contents will be discarded + */ + virtual void generateDiscarded(const ModKey& sourceKey, NumericId voiceNum, absl::Span buffer) + { + generate(sourceKey, voiceNum, buffer); + } }; } // namespace sfz diff --git a/src/sfizz/modulations/ModMatrix.cpp b/src/sfizz/modulations/ModMatrix.cpp index dd1bd4c3..9dd94893 100644 --- a/src/sfizz/modulations/ModMatrix.cpp +++ b/src/sfizz/modulations/ModMatrix.cpp @@ -224,6 +224,22 @@ void ModMatrix::beginCycle(unsigned numFrames) target.bufferReady = false; } +void ModMatrix::endCycle() +{ + Impl& impl = *impl_; + const uint32_t numFrames = impl.numFrames_; + + for (Impl::Source &source : impl.sources_) { + if (!source.bufferReady) { + int flags = source.key.flags(); + if (flags & kModIsPerCycle) { + absl::Span buffer(source.buffer.data(), numFrames); + source.gen->generateDiscarded(source.key, {}, buffer); + } + } + } +} + void ModMatrix::beginVoice(NumericId voiceId) { Impl& impl = *impl_; @@ -242,6 +258,23 @@ void ModMatrix::beginVoice(NumericId voiceId) } } +void ModMatrix::endVoice() +{ + Impl& impl = *impl_; + const uint32_t numFrames = impl.numFrames_; + const NumericId voiceId = impl.voiceId_; + + for (Impl::Source &source : impl.sources_) { + if (!source.bufferReady) { + int flags = source.key.flags(); + if (flags & kModIsPerVoice) { + absl::Span buffer(source.buffer.data(), numFrames); + source.gen->generateDiscarded(source.key, voiceId, buffer); + } + } + } +} + float* ModMatrix::getModulation(TargetId targetId) { if (!validTarget(targetId)) diff --git a/src/sfizz/modulations/ModMatrix.h b/src/sfizz/modulations/ModMatrix.h index 34edb802..e3381930 100644 --- a/src/sfizz/modulations/ModMatrix.h +++ b/src/sfizz/modulations/ModMatrix.h @@ -113,6 +113,12 @@ public: */ void beginCycle(unsigned numFrames); + /** + * @brief End modulation processing for the entire cycle. + * This performs a dummy run of any unused modulations. + */ + void endCycle(); + /** * @brief Start modulation processing for a given voice. * This clears all the buffers which are per-voice. @@ -121,6 +127,12 @@ public: */ void beginVoice(NumericId voiceId); + /** + * @brief End modulation processing for a given voice. + * This performs a dummy run of any unused modulations which are per-cycle. + */ + void endVoice(); + /** * @brief Get the modulation buffer for the given target. * If the target does not exist, the result is null.