Power follower using a fixed block size

This commit is contained in:
Jean Pierre Cimalando 2020-08-27 09:12:42 +02:00
parent 732222b8d3
commit b1f1fc4042
3 changed files with 42 additions and 14 deletions

View file

@ -57,6 +57,7 @@ namespace config {
constexpr Oversampling defaultOversamplingFactor { Oversampling::x1 }; constexpr Oversampling defaultOversamplingFactor { Oversampling::x1 };
constexpr float A440 { 440.0 }; constexpr float A440 { 440.0 };
constexpr size_t powerHistoryLength { 16 }; constexpr size_t powerHistoryLength { 16 };
constexpr size_t powerFollowerStep { 512 };
constexpr float powerFollowerAttackFactor { 100 }; constexpr float powerFollowerAttackFactor { 100 };
constexpr float powerFollowerReleaseFactor { 10 }; constexpr float powerFollowerReleaseFactor { 10 };
constexpr uint16_t numCCs { 512 }; constexpr uint16_t numCCs { 512 };

View file

@ -42,26 +42,51 @@ void PowerFollower::process(AudioSpan<float> buffer) noexcept
if (numFrames == 0) if (numFrames == 0)
return; return;
absl::Span<float> 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); const float attackFactor = static_cast<float>(numFrames) * attackTrackingFactor_;
for (unsigned i = 1; i < buffer.getNumChannels(); ++i) const float releaseFactor = static_cast<float>(numFrames) * releaseTrackingFactor_;
add(buffer.getConstSpan(i), tempBuffer);
const float meanPower = meanSquared<float>(tempBuffer); ///
size_t index = 0;
while (index < numFrames) {
size_t blockSize = std::min(step - currentCount, numFrames - index);
absl::Span<float> tempBuffer(tempBuffer_.get(), blockSize);
const float attackFactor = static_cast<float>(buffer.getNumFrames()) * attackTrackingFactor_; copy(buffer.getConstSpan(0).subspan(index, blockSize), tempBuffer);
const float releaseFactor = static_cast<float>(buffer.getNumFrames()) * releaseTrackingFactor_; for (unsigned i = 1, n = buffer.getNumChannels(); i < n; ++i)
add(buffer.getConstSpan(i).subspan(index, blockSize), tempBuffer);
meanChannelPower_ = max( currentSum += sumSquares<float>(tempBuffer);
meanChannelPower_ * (1 - attackFactor) + meanPower * attackFactor, currentCount += blockSize;
meanChannelPower_ * (1 - releaseFactor) + meanPower * releaseFactor
); 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 void PowerFollower::clear() noexcept
{ {
meanChannelPower_ = 0; currentPower_ = 0;
currentSum_ = 0;
currentCount_ = 0;
} }
void PowerFollower::updateTrackingFactor() noexcept void PowerFollower::updateTrackingFactor() noexcept

View file

@ -17,7 +17,7 @@ public:
void setSamplesPerBlock(unsigned samplesPerBlock); void setSamplesPerBlock(unsigned samplesPerBlock);
void process(AudioSpan<float> buffer) noexcept; void process(AudioSpan<float> buffer) noexcept;
void clear() noexcept; void clear() noexcept;
float getAveragePower() const noexcept { return meanChannelPower_; } float getAveragePower() const noexcept { return currentPower_; }
private: private:
void updateTrackingFactor() noexcept; void updateTrackingFactor() noexcept;
@ -31,7 +31,9 @@ private:
float attackTrackingFactor_ {}; float attackTrackingFactor_ {};
float releaseTrackingFactor_ {}; float releaseTrackingFactor_ {};
float meanChannelPower_ {}; float currentPower_ {};
float currentSum_ = 0;
size_t currentCount_ = 0;
}; };
} // namespace sfz } // namespace sfz