From a9980f163f03f8e306a4bdd957bd969652c9d493 Mon Sep 17 00:00:00 2001 From: Paul Ferrand Date: Thu, 7 May 2020 01:27:20 +0200 Subject: [PATCH] Changed the historical buffer to a smoothed envelope tracker --- src/sfizz/Config.h | 1 + src/sfizz/Voice.cpp | 44 +++++++++++++++++++++++++++++++++++++------- src/sfizz/Voice.h | 5 ++++- 3 files changed, 42 insertions(+), 8 deletions(-) diff --git a/src/sfizz/Config.h b/src/sfizz/Config.h index 8a1443ac..fadba005 100644 --- a/src/sfizz/Config.h +++ b/src/sfizz/Config.h @@ -54,6 +54,7 @@ namespace config { constexpr Oversampling defaultOversamplingFactor { Oversampling::x1 }; constexpr float A440 { 440.0 }; constexpr size_t powerHistoryLength { 16 }; + constexpr float filteredEnvelopeCutoff { 5 }; constexpr uint16_t numCCs { 512 }; constexpr int maxCurves { 256 }; constexpr int chunkSize { 1024 }; diff --git a/src/sfizz/Voice.cpp b/src/sfizz/Voice.cpp index 131c3670..992d97e7 100644 --- a/src/sfizz/Voice.cpp +++ b/src/sfizz/Voice.cpp @@ -21,6 +21,9 @@ sfz::Voice::Voice(sfz::Resources& resources) for (WavetableOscillator& osc : waveOscillators) osc.init(sampleRate); + + for (auto & filter : channelPowerFilters) + filter.setGain(vaGain(config::filteredEnvelopeCutoff, sampleRate)); } void sfz::Voice::startVoice(Region* region, int delay, int number, float value, sfz::Voice::TriggerType triggerType) noexcept @@ -192,6 +195,9 @@ void sfz::Voice::setSampleRate(float sampleRate) noexcept { this->sampleRate = sampleRate; + for (auto & filter : channelPowerFilters) + filter.setGain(vaGain(config::filteredEnvelopeCutoff, sampleRate)); + for (WavetableOscillator& osc : waveOscillators) osc.init(sampleRate); } @@ -207,11 +213,6 @@ void sfz::Voice::renderBlock(AudioSpan buffer) noexcept ASSERT(static_cast(buffer.getNumFrames()) <= samplesPerBlock); buffer.fill(0.0f); - if (state == State::idle || region == nullptr) { - powerHistory.push(0.0f); - return; - } - const auto delay = min(static_cast(initialDelay), buffer.getNumFrames()); auto delayed_buffer = buffer.subspan(delay); initialDelay -= static_cast(delay); @@ -237,7 +238,8 @@ void sfz::Voice::renderBlock(AudioSpan buffer) noexcept if (!egEnvelope.isSmoothing()) reset(); - powerHistory.push(buffer.meanSquared()); + updateChannelPowers(buffer); + this->triggerDelay = absl::nullopt; #if 0 ASSERT(!hasNanInf(buffer.getConstSpan(0))); @@ -629,13 +631,20 @@ void sfz::Voice::reset() noexcept sourcePosition = 0; floatPositionOffset = 0.0f; noteIsOff = false; + + for (auto& f : channelPowerFilters) + f.reset(); + + for (auto& p : channelPowers) + p = 0.0f; + filters.clear(); equalizers.clear(); } float sfz::Voice::getMeanSquaredAverage() const noexcept { - return powerHistory.getAverage(); + return max(channelPowers[0], channelPowers[1]); } bool sfz::Voice::releasedOrFree() const noexcept @@ -718,3 +727,24 @@ void sfz::Voice::setupOscillatorUnison() } #endif } + + +void sfz::Voice::updateChannelPowers(AudioSpan buffer) +{ + assert(channelPowers.size() == channelPowerFilters.size()); + assert(buffer.getNumFrames() <= channelPowerFilters.size()); + if (buffer.getNumFrames() == 0) + return; + + auto tempSpan = resources.bufferPool.getBuffer(buffer.getNumFrames()); + if (!tempSpan) + return; + + for (unsigned i = 0; i < channelPowers.size(); ++i) { + for (unsigned s = 0; s < buffer.getNumFrames(); ++s) + (*tempSpan)[s] = std::abs(buffer.getConstSpan(i)[s]); + + channelPowerFilters[i].processLowpass(*tempSpan, *tempSpan); + channelPowers[i] = tempSpan->back(); + } +} diff --git a/src/sfizz/Voice.h b/src/sfizz/Voice.h index 462cdfd7..a8d30cbf 100644 --- a/src/sfizz/Voice.h +++ b/src/sfizz/Voice.h @@ -13,6 +13,7 @@ #include "Resources.h" #include "AudioSpan.h" #include "LeakDetector.h" +#include "OnePoleFilter.h" #include "absl/types/span.h" #include #include @@ -245,6 +246,7 @@ private: * @brief Initialize frequency and gain coefficients for the oscillators. */ void setupOscillatorUnison(); + void updateChannelPowers(AudioSpan buffer); Region* region { nullptr }; @@ -299,7 +301,8 @@ private: std::normal_distribution noiseDist { 0, config::noiseVariance }; - HistoricalBuffer powerHistory { config::powerHistoryLength }; + std::array, 2> channelPowerFilters; + std::array channelPowers; LEAK_DETECTOR(Voice); };