BogaudioModules

BogaudioModules for VCV Rack
Log | Files | Refs | README | LICENSE

commit de4d71f50145de05dc07a86b3d05afb8e78602ae
parent 0869c830ff65f5243e0f7a9ef7f9a427d54083c9
Author: Matt Demanett <matt@demanett.net>
Date:   Thu,  7 Jun 2018 22:09:12 -0400

Work-in-progress limiter DSP.

Diffstat:
Msrc/Test2.cpp | 8++++++++
Msrc/Test2.hpp | 7++++++-
Msrc/dsp/oscillator.cpp | 12+++++++-----
Msrc/dsp/signal.cpp | 48++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/dsp/signal.hpp | 15+++++++++++++++
5 files changed, 84 insertions(+), 6 deletions(-)

diff --git a/src/Test2.cpp b/src/Test2.cpp @@ -85,6 +85,14 @@ void Test2::step() { _adsr.setShapes(attackShape, decayShape, decayShape); outputs[OUT_OUTPUT].value = _adsr.next() * 10.0f; } + +#elif LIMITER + float shape = params[PARAM1A_PARAM].value * 5.0f; + float knee = params[PARAM2A_PARAM].value * 10.0f; + float limit = params[PARAM2B_PARAM].value * 15.0f; + float scale = params[PARAM1B_PARAM].value * 2.0f + 1.0f; + _limiter.setParams(shape, knee, limit, scale); + outputs[OUT_OUTPUT].value = _limiter.next(inputs[IN_INPUT].value); #endif } diff --git a/src/Test2.hpp b/src/Test2.hpp @@ -6,7 +6,8 @@ extern Model* modelTest2; // #define COMPLEX_BIQUAD 1 // #define MULTIPOLE 1 -#define ADSR_ENVELOPE 1 +// #define ADSR_ENVELOPE 1 +#define LIMITER 1 #ifdef COMPLEX_BIQUAD #include "dsp/filter.hpp" @@ -14,6 +15,8 @@ extern Model* modelTest2; #include "dsp/filter.hpp" #elif ADSR_ENVELOPE #include "dsp/envelope.hpp" +#elif LIMITER +#include "dsp/signal.hpp" #elif #error what #endif @@ -62,6 +65,8 @@ struct Test2 : Module { #elif ADSR_ENVELOPE ADSR _adsr; SchmittTrigger _trigger; +#elif LIMITER + Limiter _limiter; #endif Test2() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) { diff --git a/src/dsp/oscillator.cpp b/src/dsp/oscillator.cpp @@ -103,11 +103,13 @@ void SaturatingSawOscillator::setSaturation(float saturation) { if (_saturation != saturation) { assert(saturation >= 0.0f); _saturation = saturation; - if (_saturation < 1.0f) { - _saturationNormalization = 1.0f / tanhf(_saturation * M_PI); - } - else { - _saturationNormalization = 1.0f; + if (_saturation >= 0.1f) { + if (_saturation < 1.0f) { + _saturationNormalization = 1.0f / tanhf(_saturation * M_PI); + } + else { + _saturationNormalization = 1.0f; + } } } } diff --git a/src/dsp/signal.cpp b/src/dsp/signal.cpp @@ -361,3 +361,51 @@ float DelayLine::next(float sample) { int DelayLine::delaySamples() { return std::max((_time * _maxTimeMS / 1000.0f) * _sampleRate, 1.0f); } + + +void Limiter::setParams(float shape, float knee, float limit, float scale) { + assert(shape >= 0.0f); + assert(knee >= 0.0f); + assert(limit >= 0.0f); + assert(scale >= 1.0f); + _shape = shape; + _knee = knee; + _limit = std::max(knee, limit); + _scale = scale; + + if (_shape >= 0.1f) { + if (_shape < 1.0f) { + _normalization = 1.0f / tanhf(_shape * M_PI); + } + else { + _normalization = 1.0f; + } + } +} + +float Limiter::next(float sample) { + float out = abs(sample); + if (out > _knee) { + out -= _knee; + out /= _scale; + if (_shape >= 0.1f) { + // out /= _limit - _knee; + // out = _tanhf.value(out * _shape * M_PI) * _normalization; + // out *= _limit - _knee; + float x = out / (_limit - _knee); + x = _tanhf.value(x * _shape * M_PI) * _normalization; + x = std::min(x, 1.0f); + x *= _limit - _knee; + out = std::min(abs(sample) - _knee, x); + } + else { + out = std::min(out, _limit - _knee); + } + out += _knee; + } + + if (sample < 0.0f) { + return -out; + } + return out; +} diff --git a/src/dsp/signal.hpp b/src/dsp/signal.hpp @@ -2,6 +2,7 @@ #include <math.h> +#include "math.hpp" #include "table.hpp" namespace bogaudio { @@ -205,5 +206,19 @@ struct DelayLine { int delaySamples(); }; +struct Limiter { + float _shape; + float _knee; + float _limit; + float _scale; + float _normalization; + FastTanhf _tanhf; + + Limiter() {} + + void setParams(float shape = 1.0f, float knee = 5.0f, float limit = 10.0f, float scale = 2.0f); + float next(float sample); +}; + } // namespace dsp } // namespace bogaudio