From 03b9e19676dc4d5c25495c92a6117fe17c8c3f0e Mon Sep 17 00:00:00 2001 From: Jean Pierre Cimalando Date: Sun, 29 Mar 2020 20:17:49 +0200 Subject: [PATCH] Oversample the limiter by 2x --- src/sfizz/effects/Limiter.cpp | 25 ++++++++++++++++++++++--- src/sfizz/effects/Limiter.h | 5 +++++ src/sfizz/effects/dsp/limiter.dsp | 5 +++-- src/sfizz/effects/gen/limiter.cpp | 2 +- 4 files changed, 31 insertions(+), 6 deletions(-) diff --git a/src/sfizz/effects/Limiter.cpp b/src/sfizz/effects/Limiter.cpp index 577fcba5..70f317d8 100644 --- a/src/sfizz/effects/Limiter.cpp +++ b/src/sfizz/effects/Limiter.cpp @@ -12,9 +12,12 @@ #include "Limiter.h" #include "Opcode.h" -#include "gen/limiter.cpp" +#include "AudioSpan.h" #include "absl/memory/memory.h" +static constexpr int _oversampling = 2; +#include "gen/limiter.cpp" + namespace sfz { namespace fx { @@ -32,12 +35,20 @@ namespace fx { { _limiter->classInit(sampleRate); _limiter->instanceConstants(sampleRate); + + static constexpr double coefs2x[12] = { 0.036681502163648017, 0.13654762463195794, 0.27463175937945444, 0.42313861743656711, 0.56109869787919531, 0.67754004997416184, 0.76974183386322703, 0.83988962484963892, 0.89226081800387902, 0.9315419599631839, 0.96209454837808417, 0.98781637073289585 }; + + for (unsigned c = 0; c < EffectChannels; ++c) { + _downsampler2x[c].set_coefs(coefs2x); + _upsampler2x[c].set_coefs(coefs2x); + } + clear(); } void Limiter::setSamplesPerBlock(int samplesPerBlock) { - (void)samplesPerBlock; + _tempBuffer2x.resize(2 * samplesPerBlock); } void Limiter::clear() @@ -47,7 +58,15 @@ namespace fx { void Limiter::process(const float* const inputs[], float* const outputs[], unsigned nframes) { - _limiter->compute(nframes, inputs, outputs); + auto inOut2x = AudioSpan( _tempBuffer2x).first(2 * nframes); + + for (unsigned c = 0; c < EffectChannels; ++c) + _upsampler2x[c].process_block(inOut2x.getSpan(c).data(), inputs[c], nframes); + + _limiter->compute(2 * nframes, inOut2x, inOut2x); + + for (unsigned c = 0; c < EffectChannels; ++c) + _downsampler2x[c].process_block(outputs[c], inOut2x.getSpan(c).data(), nframes); } std::unique_ptr Limiter::makeInstance(absl::Span members) diff --git a/src/sfizz/effects/Limiter.h b/src/sfizz/effects/Limiter.h index 49cb264a..30737377 100644 --- a/src/sfizz/effects/Limiter.h +++ b/src/sfizz/effects/Limiter.h @@ -6,6 +6,8 @@ #pragma once #include "Effects.h" +#include "hiir/Downsampler2xFpu.h" +#include "hiir/Upsampler2xFpu.h" class faustLimiter; namespace sfz { @@ -47,6 +49,9 @@ namespace fx { private: std::unique_ptr _limiter; + AudioBuffer _tempBuffer2x { 2, 2 * config::defaultSamplesPerBlock }; + hiir::Downsampler2xFpu<12> _downsampler2x[EffectChannels]; + hiir::Upsampler2xFpu<12> _upsampler2x[EffectChannels]; }; } // namespace fx diff --git a/src/sfizz/effects/dsp/limiter.dsp b/src/sfizz/effects/dsp/limiter.dsp index e8ed03d9..cbb14b26 100644 --- a/src/sfizz/effects/dsp/limiter.dsp +++ b/src/sfizz/effects/dsp/limiter.dsp @@ -1,8 +1,9 @@ import("stdfaust.lib"); limiter(x) = gain*x with { - att = 0.0008; - rel = 0.5; + att = 0.0008 * over; + rel = 0.5 * over; + over = fconstant(int _oversampling, ); peak = x : an.amp_follower_ud(att, rel); gain = ba.if(peak>1.0, 1.0/peak, 1.0) : si.smooth(ba.tau2pole(0.5*att)); }; diff --git a/src/sfizz/effects/gen/limiter.cpp b/src/sfizz/effects/gen/limiter.cpp index 7a3d99db..420f6728 100644 --- a/src/sfizz/effects/gen/limiter.cpp +++ b/src/sfizz/effects/gen/limiter.cpp @@ -51,7 +51,7 @@ public: void instanceConstants(int sample_rate) { fSampleRate = sample_rate; - fConst0 = std::min(192000.0f, std::max(1.0f, float(fSampleRate))); + fConst0 = (std::min(192000.0f, std::max(1.0f, float(fSampleRate))) * float(_oversampling)); fConst1 = std::exp((0.0f - (2500.0f / fConst0))); fConst2 = (1.0f - fConst1); fConst3 = std::exp((0.0f - (1250.0f / fConst0)));