From b1f1fc40423d013d1430325b064edfa8de278fea Mon Sep 17 00:00:00 2001 From: Jean Pierre Cimalando Date: Thu, 27 Aug 2020 09:12:42 +0200 Subject: [PATCH] Power follower using a fixed block size --- src/sfizz/Config.h | 1 + src/sfizz/PowerFollower.cpp | 49 ++++++++++++++++++++++++++++--------- src/sfizz/PowerFollower.h | 6 +++-- 3 files changed, 42 insertions(+), 14 deletions(-) diff --git a/src/sfizz/Config.h b/src/sfizz/Config.h index fc48aab5..67821b02 100644 --- a/src/sfizz/Config.h +++ b/src/sfizz/Config.h @@ -57,6 +57,7 @@ namespace config { constexpr Oversampling defaultOversamplingFactor { Oversampling::x1 }; constexpr float A440 { 440.0 }; constexpr size_t powerHistoryLength { 16 }; + constexpr size_t powerFollowerStep { 512 }; constexpr float powerFollowerAttackFactor { 100 }; constexpr float powerFollowerReleaseFactor { 10 }; constexpr uint16_t numCCs { 512 }; diff --git a/src/sfizz/PowerFollower.cpp b/src/sfizz/PowerFollower.cpp index 56ccb86e..06807c7a 100644 --- a/src/sfizz/PowerFollower.cpp +++ b/src/sfizz/PowerFollower.cpp @@ -42,26 +42,51 @@ void PowerFollower::process(AudioSpan buffer) noexcept if (numFrames == 0) return; - absl::Span tempBuffer(tempBuffer_.get(), numFrames); + /// + constexpr size_t step = config::powerFollowerStep; + float currentPower = currentPower_; + float currentSum = currentSum_; + size_t currentCount = currentCount_; - copy(buffer.getConstSpan(0), tempBuffer); - for (unsigned i = 1; i < buffer.getNumChannels(); ++i) - add(buffer.getConstSpan(i), tempBuffer); + const float attackFactor = static_cast(numFrames) * attackTrackingFactor_; + const float releaseFactor = static_cast(numFrames) * releaseTrackingFactor_; - const float meanPower = meanSquared(tempBuffer); + /// + size_t index = 0; + while (index < numFrames) { + size_t blockSize = std::min(step - currentCount, numFrames - index); + absl::Span tempBuffer(tempBuffer_.get(), blockSize); - const float attackFactor = static_cast(buffer.getNumFrames()) * attackTrackingFactor_; - const float releaseFactor = static_cast(buffer.getNumFrames()) * releaseTrackingFactor_; + copy(buffer.getConstSpan(0).subspan(index, blockSize), tempBuffer); + for (unsigned i = 1, n = buffer.getNumChannels(); i < n; ++i) + add(buffer.getConstSpan(i).subspan(index, blockSize), tempBuffer); - meanChannelPower_ = max( - meanChannelPower_ * (1 - attackFactor) + meanPower * attackFactor, - meanChannelPower_ * (1 - releaseFactor) + meanPower * releaseFactor - ); + currentSum += sumSquares(tempBuffer); + currentCount += blockSize; + + if (currentCount == step) { + const float meanPower = currentSum / step; + currentPower = max( + currentPower * (1 - attackFactor) + meanPower * attackFactor, + currentPower * (1 - releaseFactor) + meanPower * releaseFactor); + currentSum = 0; + currentCount = 0; + } + + index += blockSize; + } + + /// + currentPower_ = currentPower; + currentSum_ = currentSum; + currentCount_ = currentCount; } void PowerFollower::clear() noexcept { - meanChannelPower_ = 0; + currentPower_ = 0; + currentSum_ = 0; + currentCount_ = 0; } void PowerFollower::updateTrackingFactor() noexcept diff --git a/src/sfizz/PowerFollower.h b/src/sfizz/PowerFollower.h index 2deff3d5..1febd9f1 100644 --- a/src/sfizz/PowerFollower.h +++ b/src/sfizz/PowerFollower.h @@ -17,7 +17,7 @@ public: void setSamplesPerBlock(unsigned samplesPerBlock); void process(AudioSpan buffer) noexcept; void clear() noexcept; - float getAveragePower() const noexcept { return meanChannelPower_; } + float getAveragePower() const noexcept { return currentPower_; } private: void updateTrackingFactor() noexcept; @@ -31,7 +31,9 @@ private: float attackTrackingFactor_ {}; float releaseTrackingFactor_ {}; - float meanChannelPower_ {}; + float currentPower_ {}; + float currentSum_ = 0; + size_t currentCount_ = 0; }; } // namespace sfz