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 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 };

View file

@ -42,26 +42,51 @@ void PowerFollower::process(AudioSpan<float> buffer) noexcept
if (numFrames == 0)
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);
for (unsigned i = 1; i < buffer.getNumChannels(); ++i)
add(buffer.getConstSpan(i), tempBuffer);
const float attackFactor = static_cast<float>(numFrames) * attackTrackingFactor_;
const float releaseFactor = static_cast<float>(numFrames) * releaseTrackingFactor_;
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_;
const float releaseFactor = static_cast<float>(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<float>(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

View file

@ -17,7 +17,7 @@ public:
void setSamplesPerBlock(unsigned samplesPerBlock);
void process(AudioSpan<float> 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