BogaudioModules

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

commit bff5f32ab915e9b7bae84fa691ff50cecb8c949f
parent d4dfcf39958fa5533fe3040b12360abc857efb3a
Author: Matt Demanett <matt@demanett.net>
Date:   Thu, 12 Sep 2019 23:48:48 -0400

Poly: LMTR, NSGT.

Diffstat:
Msrc/Lmtr.cpp | 79++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------------
Msrc/Lmtr.hpp | 32++++++++++++++++++++------------
Msrc/Nsgt.cpp | 90+++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------------
Msrc/Nsgt.hpp | 30+++++++++++++++++++-----------
4 files changed, 153 insertions(+), 78 deletions(-)

diff --git a/src/Lmtr.cpp b/src/Lmtr.cpp @@ -3,56 +3,85 @@ void Lmtr::sampleRateChange() { float sampleRate = APP->engine->getSampleRate(); - _detector.setSampleRate(sampleRate); - _attackSL.setParams(sampleRate, 150.0f); - _releaseSL.setParams(sampleRate, 600.0f); + for (int i = 0; i < _channels; ++i) { + if (_engines[i]) { + _engines[i]->detector.setSampleRate(sampleRate); + _engines[i]->attackSL.setParams(sampleRate, 150.0f); + _engines[i]->releaseSL.setParams(sampleRate, 600.0f); + } + } } bool Lmtr::active() { return outputs[LEFT_OUTPUT].isConnected() || outputs[RIGHT_OUTPUT].isConnected(); } +int Lmtr::channels() { + return inputs[LEFT_INPUT].getChannels() + inputs[RIGHT_INPUT].getChannels(); +} + +void Lmtr::addEngine(int c) { + _engines[c] = new Engine(); +} + +void Lmtr::removeEngine(int c) { + delete _engines[c]; + _engines[c] = NULL; +} + void Lmtr::modulate() { - _thresholdDb = params[THRESHOLD_PARAM].getValue(); + _softKnee = params[KNEE_PARAM].getValue() > 0.5f; +} + +void Lmtr::modulateChannel(int c) { + if (!_engines[c]) { + return; + } + + _engines[c]->thresholdDb = params[THRESHOLD_PARAM].getValue(); if (inputs[THRESHOLD_INPUT].isConnected()) { - _thresholdDb *= clamp(inputs[THRESHOLD_INPUT].getVoltage() / 10.0f, 0.0f, 1.0f); + _engines[c]->thresholdDb *= clamp(inputs[THRESHOLD_INPUT].getPolyVoltage(c) / 10.0f, 0.0f, 1.0f); } - _thresholdDb *= 30.0f; - _thresholdDb -= 24.0f; + _engines[c]->thresholdDb *= 30.0f; + _engines[c]->thresholdDb -= 24.0f; float outGain = params[OUTPUT_GAIN_PARAM].getValue(); if (inputs[OUTPUT_GAIN_INPUT].isConnected()) { - outGain = clamp(outGain + inputs[OUTPUT_GAIN_INPUT].getVoltage() / 5.0f, 0.0f, 1.0f); + outGain = clamp(outGain + inputs[OUTPUT_GAIN_INPUT].getPolyVoltage(c) / 5.0f, 0.0f, 1.0f); } outGain *= 24.0f; - if (_outGain != outGain) { - _outGain = outGain; - _outLevel = decibelsToAmplitude(_outGain); + if (_engines[c]->outGain != outGain) { + _engines[c]->outGain = outGain; + _engines[c]->outLevel = decibelsToAmplitude(_engines[c]->outGain); } - - _softKnee = params[KNEE_PARAM].getValue() > 0.5f; } -void Lmtr::processChannel(const ProcessArgs& args, int _c) { - float leftInput = inputs[LEFT_INPUT].getVoltageSum(); - float rightInput = inputs[RIGHT_INPUT].getVoltageSum(); - float env = _detector.next(leftInput + rightInput); - if (env > _lastEnv) { - env = _attackSL.next(env, _lastEnv); +void Lmtr::processChannel(const ProcessArgs& args, int c) { + if (!_engines[c]) { + return; + } + + float leftInput = inputs[LEFT_INPUT].getPolyVoltage(c); + float rightInput = inputs[RIGHT_INPUT].getPolyVoltage(c); + float env = _engines[c]->detector.next(leftInput + rightInput); + if (env > _engines[c]->lastEnv) { + env = _engines[c]->attackSL.next(env, _engines[c]->lastEnv); } else { - env = _releaseSL.next(env, _lastEnv); + env = _engines[c]->releaseSL.next(env, _engines[c]->lastEnv); } - _lastEnv = env; + _engines[c]->lastEnv = env; float detectorDb = amplitudeToDecibels(env / 5.0f); - float compressionDb = _compressor.compressionDb(detectorDb, _thresholdDb, Compressor::maxEffectiveRatio, _softKnee); - _amplifier.setLevel(-compressionDb); + float compressionDb = _engines[c]->compressor.compressionDb(detectorDb, _engines[c]->thresholdDb, Compressor::maxEffectiveRatio, _softKnee); + _engines[c]->amplifier.setLevel(-compressionDb); if (outputs[LEFT_OUTPUT].isConnected()) { - outputs[LEFT_OUTPUT].setVoltage(_saturator.next(_amplifier.next(leftInput) * _outLevel)); + outputs[LEFT_OUTPUT].setChannels(_channels); + outputs[LEFT_OUTPUT].setVoltage(_engines[c]->saturator.next(_engines[c]->amplifier.next(leftInput) * _engines[c]->outLevel), c); } if (outputs[RIGHT_OUTPUT].isConnected()) { - outputs[RIGHT_OUTPUT].setVoltage(_saturator.next(_amplifier.next(rightInput) * _outLevel)); + outputs[RIGHT_OUTPUT].setChannels(_channels); + outputs[RIGHT_OUTPUT].setVoltage(_engines[c]->saturator.next(_engines[c]->amplifier.next(rightInput) * _engines[c]->outLevel), c); } } diff --git a/src/Lmtr.hpp b/src/Lmtr.hpp @@ -35,18 +35,22 @@ struct Lmtr : BGModule { NUM_LIGHTS }; - float _thresholdDb = 0.0f; - float _outGain = -1.0f; - float _outLevel = 0.0f; - bool _softKnee = true; - float _lastEnv = 0.0f; + struct Engine { + float thresholdDb = 0.0f; + float outGain = -1.0f; + float outLevel = 0.0f; + float lastEnv = 0.0f; + + bogaudio::dsp::SlewLimiter attackSL; + bogaudio::dsp::SlewLimiter releaseSL; + RootMeanSquare detector; + Compressor compressor; + Amplifier amplifier; + Saturator saturator; + }; - bogaudio::dsp::SlewLimiter _attackSL; - bogaudio::dsp::SlewLimiter _releaseSL; - RootMeanSquare _detector; - Compressor _compressor; - Amplifier _amplifier; - Saturator _saturator; + Engine* _engines[maxChannels] {}; + bool _softKnee = true; Lmtr() { config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); @@ -59,8 +63,12 @@ struct Lmtr : BGModule { void sampleRateChange() override; bool active() override; + int channels() override; + void addEngine(int c) override; + void removeEngine(int c) override; void modulate() override; - void processChannel(const ProcessArgs& args, int _c) override; + void modulateChannel(int c) override; + void processChannel(const ProcessArgs& args, int c) override; }; } // namespace bogaudio diff --git a/src/Nsgt.cpp b/src/Nsgt.cpp @@ -4,60 +4,90 @@ void Nsgt::sampleRateChange() { float sampleRate = APP->engine->getSampleRate(); - _detector.setSampleRate(sampleRate); - _attackSL.setParams(sampleRate, 150.0f); - _releaseSL.setParams(sampleRate, 600.0f); + for (int i = 0; i < _channels; ++i) { + if (_engines[i]) { + _engines[i]->detector.setSampleRate(sampleRate); + _engines[i]->attackSL.setParams(sampleRate, 150.0f); + _engines[i]->releaseSL.setParams(sampleRate, 600.0f); + } + } } bool Nsgt::active() { return outputs[LEFT_OUTPUT].isConnected() || outputs[RIGHT_OUTPUT].isConnected(); } +int Nsgt::channels() { + return inputs[LEFT_INPUT].getChannels() + inputs[RIGHT_INPUT].getChannels(); +} + +void Nsgt::addEngine(int c) { + _engines[c] = new Engine(); +} + +void Nsgt::removeEngine(int c) { + delete _engines[c]; + _engines[c] = NULL; +} + void Nsgt::modulate() { - _thresholdDb = params[THRESHOLD_PARAM].getValue(); + _softKnee = params[KNEE_PARAM].getValue() > 0.5f; +} + +void Nsgt::modulateChannel(int c) { + if (!_engines[c]) { + return; + } + + _engines[c]->thresholdDb = params[THRESHOLD_PARAM].getValue(); if (inputs[THRESHOLD_INPUT].isConnected()) { - _thresholdDb *= clamp(inputs[THRESHOLD_INPUT].getVoltage() / 10.0f, 0.0f, 1.0f); + _engines[c]->thresholdDb *= clamp(inputs[THRESHOLD_INPUT].getPolyVoltage(c) / 10.0f, 0.0f, 1.0f); } - _thresholdDb *= 30.0f; - _thresholdDb -= 24.0f; + _engines[c]->thresholdDb *= 30.0f; + _engines[c]->thresholdDb -= 24.0f; float ratio = params[RATIO_PARAM].getValue(); if (inputs[RATIO_INPUT].isConnected()) { - ratio *= clamp(inputs[RATIO_INPUT].getVoltage() / 10.0f, 0.0f, 1.0f); + ratio *= clamp(inputs[RATIO_INPUT].getPolyVoltage(c) / 10.0f, 0.0f, 1.0f); } - if (_ratioKnob != ratio) { - _ratioKnob = ratio; - _ratio = powf(_ratioKnob, 1.5f); - _ratio = 1.0f - _ratio; - _ratio *= M_PI; - _ratio *= 0.25f; - _ratio = tanf(_ratio); - _ratio = 1.0f / _ratio; + if (_engines[c]->ratioKnob != ratio) { + _engines[c]->ratioKnob = ratio; + ratio = powf(_engines[c]->ratioKnob, 1.5f); + ratio = 1.0f - ratio; + ratio *= M_PI; + ratio *= 0.25f; + ratio = tanf(ratio); + ratio = 1.0f / ratio; + _engines[c]->ratioKnob = ratio; } - - _softKnee = params[KNEE_PARAM].getValue() > 0.5f; } -void Nsgt::processChannel(const ProcessArgs& args, int _c) { - float leftInput = inputs[LEFT_INPUT].getVoltageSum(); - float rightInput = inputs[RIGHT_INPUT].getVoltageSum(); - float env = _detector.next(leftInput + rightInput); - if (env > _lastEnv) { - env = _attackSL.next(env, _lastEnv); +void Nsgt::processChannel(const ProcessArgs& args, int c) { + if (!_engines[c]) { + return; + } + + float leftInput = inputs[LEFT_INPUT].getPolyVoltage(c); + float rightInput = inputs[RIGHT_INPUT].getPolyVoltage(c); + float env = _engines[c]->detector.next(leftInput + rightInput); + if (env > _engines[c]->lastEnv) { + env = _engines[c]->attackSL.next(env, _engines[c]->lastEnv); } else { - env = _releaseSL.next(env, _lastEnv); + env = _engines[c]->releaseSL.next(env, _engines[c]->lastEnv); } - _lastEnv = env; + _engines[c]->lastEnv = env; float detectorDb = amplitudeToDecibels(env / 5.0f); - float compressionDb = _noiseGate.compressionDb(detectorDb, _thresholdDb, _ratio, _softKnee); - _amplifier.setLevel(-compressionDb); + float compressionDb = _engines[c]->noiseGate.compressionDb(detectorDb, _engines[c]->thresholdDb, _engines[c]->ratio, _softKnee); + _engines[c]->amplifier.setLevel(-compressionDb); if (outputs[LEFT_OUTPUT].isConnected()) { - outputs[LEFT_OUTPUT].setVoltage(_saturator.next(_amplifier.next(leftInput))); + outputs[LEFT_OUTPUT].setChannels(_channels); + outputs[LEFT_OUTPUT].setVoltage(_engines[c]->saturator.next(_engines[c]->amplifier.next(leftInput)), c); } if (outputs[RIGHT_OUTPUT].isConnected()) { - outputs[RIGHT_OUTPUT].setVoltage(_saturator.next(_amplifier.next(rightInput))); + outputs[RIGHT_OUTPUT].setChannels(_channels); + outputs[RIGHT_OUTPUT].setVoltage(_engines[c]->saturator.next(_engines[c]->amplifier.next(rightInput)), c); } } diff --git a/src/Nsgt.hpp b/src/Nsgt.hpp @@ -35,18 +35,22 @@ struct Nsgt : BGModule { NUM_LIGHTS }; - float _thresholdDb = 0.0f; - float _ratio = 0.0f; - float _ratioKnob = -1.0f; - bool _softKnee = true; - float _lastEnv = 0.0f; + struct Engine { + float thresholdDb = 0.0f; + float ratio = 0.0f; + float ratioKnob = -1.0f; + float lastEnv = 0.0f; + + bogaudio::dsp::SlewLimiter attackSL; + bogaudio::dsp::SlewLimiter releaseSL; + RootMeanSquare detector; + NoiseGate noiseGate; + Amplifier amplifier; + Saturator saturator; + }; - bogaudio::dsp::SlewLimiter _attackSL; - bogaudio::dsp::SlewLimiter _releaseSL; - RootMeanSquare _detector; - NoiseGate _noiseGate; - Amplifier _amplifier; - Saturator _saturator; + Engine* _engines[maxChannels] {}; + bool _softKnee = true; Nsgt() { config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); @@ -59,7 +63,11 @@ struct Nsgt : BGModule { void sampleRateChange() override; bool active() override; + int channels() override; + void addEngine(int c) override; + void removeEngine(int c) override; void modulate() override; + void modulateChannel(int c) override; void processChannel(const ProcessArgs& args, int _c) override; };