BogaudioModules

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

commit d4dfcf39958fa5533fe3040b12360abc857efb3a
parent 72ee64b9a5486aa8d96fa9f12dde51adced9f4da
Author: Matt Demanett <matt@demanett.net>
Date:   Thu, 12 Sep 2019 23:25:14 -0400

Poly: PRESSOR; and add add/remove engine callbacks to base module.

Diffstat:
Msrc/CVD.cpp | 22+++++++---------------
Msrc/CVD.hpp | 3++-
Msrc/Pressor.cpp | 127++++++++++++++++++++++++++++++++++++++++++++++++++-----------------------------
Msrc/Pressor.hpp | 52++++++++++++++++++++++++++++++----------------------
Msrc/module.cpp | 12++++++++++++
Msrc/module.hpp | 8++++++++
6 files changed, 140 insertions(+), 84 deletions(-)

diff --git a/src/CVD.cpp b/src/CVD.cpp @@ -13,21 +13,13 @@ int CVD::channels() { return inputs[IN_INPUT].getChannels(); } -void CVD::channelsChanged(int before, int after) { - if (before < after) { - while (before < after) { - _engines[before] = new Engine(); - _engines[before]->delay.setSampleRate(APP->engine->getSampleRate()); - ++before; - } - } - else { - while (after > before) { - delete _engines[after - 1]; - _engines[after - 1] = NULL; - ++after; - } - } +void CVD::addEngine(int c) { + _engines[c] = new Engine(); +} + +void CVD::removeEngine(int c) { + delete _engines[c]; + _engines[c] = NULL; } void CVD::modulateChannel(int c) { diff --git a/src/CVD.hpp b/src/CVD.hpp @@ -59,7 +59,8 @@ struct CVD : BGModule { void sampleRateChange() override; int channels() override; - void channelsChanged(int before, int after) override; + void addEngine(int c) override; + void removeEngine(int c) override; void modulateChannel(int c) override; void processChannel(const ProcessArgs& args, int c) override; }; diff --git a/src/Pressor.cpp b/src/Pressor.cpp @@ -2,7 +2,11 @@ #include "Pressor.hpp" void Pressor::sampleRateChange() { - _detectorRMS.setSampleRate(APP->engine->getSampleRate()); + for (int i = 0; i < maxChannels; ++i) { + if (_engines[i]) { + _engines[i]->detectorRMS.setSampleRate(APP->engine->getSampleRate()); + } + } } bool Pressor::active() { @@ -16,105 +20,136 @@ bool Pressor::active() { ); } +int Pressor::channels() { + return inputs[LEFT_INPUT].getChannels() + inputs[RIGHT_INPUT].getChannels(); +} + +void Pressor::addEngine(int c) { + _engines[c] = new Engine(); +} + +void Pressor::removeEngine(int c) { + delete _engines[c]; + _engines[c] = NULL; +} + void Pressor::modulate() { - _thresholdDb = params[THRESHOLD_PARAM].getValue(); + _compressorMode = params[MODE_PARAM].getValue() > 0.5f; + _rmsDetector = params[DECTECTOR_MODE_PARAM].getValue() > 0.5f; + _softKnee = params[KNEE_PARAM].getValue() > 0.5f; +} + +void Pressor::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(ratio, 1.5f); + ratio = 1.0f - ratio; + ratio *= M_PI; + ratio *= 0.25f; + ratio = tanf(ratio); + ratio = 1.0f / ratio; + _engines[c]->ratio = ratio; } float sampleRate = APP->engine->getSampleRate(); float attack = params[ATTACK_PARAM].getValue(); if (inputs[ATTACK_INPUT].isConnected()) { - attack *= clamp(inputs[ATTACK_INPUT].getVoltage() / 10.0f, 0.0f, 1.0f); + attack *= clamp(inputs[ATTACK_INPUT].getPolyVoltage(c) / 10.0f, 0.0f, 1.0f); } attack *= attack; - _attackSL.setParams(sampleRate, attack * 500.0f); + _engines[c]->attackSL.setParams(sampleRate, attack * 500.0f); float release = params[RELEASE_PARAM].getValue(); if (inputs[RELEASE_INPUT].isConnected()) { - release *= clamp(inputs[RELEASE_INPUT].getVoltage() / 10.0f, 0.0f, 1.0f); + release *= clamp(inputs[RELEASE_INPUT].getPolyVoltage(c) / 10.0f, 0.0f, 1.0f); } release *= release; - _releaseSL.setParams(sampleRate, release * 2000.0f); + _engines[c]->releaseSL.setParams(sampleRate, release * 2000.0f); float inGain = params[INPUT_GAIN_PARAM].getValue(); if (inputs[INPUT_GAIN_INPUT].isConnected()) { - inGain = clamp(inGain + inputs[INPUT_GAIN_INPUT].getVoltage() / 5.0f, -1.0f, 1.0f); + inGain = clamp(inGain + inputs[INPUT_GAIN_INPUT].getPolyVoltage(c) / 5.0f, -1.0f, 1.0f); } inGain *= 12.0f; - if (_inGain != inGain) { - _inGain = inGain; - _inLevel = decibelsToAmplitude(_inGain); + if (_engines[c]->inGain != inGain) { + _engines[c]->inGain = inGain; + _engines[c]->inLevel = decibelsToAmplitude(_engines[c]->inGain); } 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); } - _detectorMix.setParams(params[DETECTOR_MIX_PARAM].getValue(), 0.0f, true); - - _compressorMode = params[MODE_PARAM].getValue() > 0.5f; - _rmsDetector = params[DECTECTOR_MODE_PARAM].getValue() > 0.5f; - _softKnee = params[KNEE_PARAM].getValue() > 0.5f; + _engines[c]->detectorMix.setParams(params[DETECTOR_MIX_PARAM].getValue(), 0.0f, true); } -void Pressor::processChannel(const ProcessArgs& args, int _c) { - float leftInput = inputs[LEFT_INPUT].getVoltageSum() * _inLevel; - float rightInput = inputs[RIGHT_INPUT].getVoltageSum() * _inLevel; +void Pressor::processChannel(const ProcessArgs& args, int c) { + if (!_engines[c]) { + return; + } + + float leftInput = inputs[LEFT_INPUT].getPolyVoltage(c) * _engines[c]->inLevel; + float rightInput = inputs[RIGHT_INPUT].getPolyVoltage(c) * _engines[c]->inLevel; float env = leftInput + rightInput; if (inputs[SIDECHAIN_INPUT].isConnected()) { - env = _detectorMix.next(env, inputs[SIDECHAIN_INPUT].getVoltageSum()); + env = _engines[c]->detectorMix.next(env, inputs[SIDECHAIN_INPUT].getPolyVoltage(c)); } if (_rmsDetector) { - env = _detectorRMS.next(env); + env = _engines[c]->detectorRMS.next(env); } else { env = fabsf(env); } - if (env > _lastEnv) { - env = _attackSL.next(env, _lastEnv); + 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 = 0.0f; if (_compressorMode) { - _compressionDb = _compressor.compressionDb(detectorDb, _thresholdDb, _ratio, _softKnee); + compressionDb = _engines[c]->compressor.compressionDb(detectorDb, _engines[c]->thresholdDb, _engines[c]->ratio, _softKnee); } else { - _compressionDb = _noiseGate.compressionDb(detectorDb, _thresholdDb, _ratio, _softKnee); + compressionDb = _engines[c]->noiseGate.compressionDb(detectorDb, _engines[c]->thresholdDb, _engines[c]->ratio, _softKnee); + } + _engines[c]->amplifier.setLevel(-compressionDb); + if (c == 0) { + _compressionDb = compressionDb; + outputs[ENVELOPE_OUTPUT].setChannels(_channels); + outputs[LEFT_OUTPUT].setChannels(_channels); + outputs[RIGHT_OUTPUT].setChannels(_channels); } - _amplifier.setLevel(-_compressionDb); - outputs[ENVELOPE_OUTPUT].setVoltage(env); + outputs[ENVELOPE_OUTPUT].setVoltage(env, c); if (outputs[LEFT_OUTPUT].isConnected()) { - outputs[LEFT_OUTPUT].setVoltage(_saturator.next(_amplifier.next(leftInput) * _outLevel)); + 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].setVoltage(_engines[c]->saturator.next(_engines[c]->amplifier.next(rightInput) * _engines[c]->outLevel), c); } } diff --git a/src/Pressor.hpp b/src/Pressor.hpp @@ -48,31 +48,35 @@ struct Pressor : BGModule { NUM_LIGHTS }; - float _thresholdDb = 0.0f; - float _ratio = 0.0f; - float _ratioKnob = -1.0f; - float _inGain = -1.0f; - float _inLevel = 0.0f; - float _outGain = -1.0f; - float _outLevel = 0.0f; + struct Engine { + float thresholdDb = 0.0f; + float ratio = 0.0f; + float ratioKnob = -1.0f; + float inGain = -1.0f; + float inLevel = 0.0f; + float outGain = -1.0f; + float outLevel = 0.0f; + float lastEnv = 0.0f; + + bogaudio::dsp::SlewLimiter attackSL; + bogaudio::dsp::SlewLimiter releaseSL; + CrossFader detectorMix; + RootMeanSquare detectorRMS; + Compressor compressor; + NoiseGate noiseGate; + Amplifier amplifier; + Saturator saturator; + + Engine() : detectorRMS(1000.0f, 1.0f, 50.0f) {} + }; + + Engine* _engines[maxChannels] {}; + float _compressionDb = 0.0f; bool _compressorMode = true; bool _rmsDetector = true; bool _softKnee = true; - float _lastEnv = 0.0f; - float _compressionDb = 0.0f; - bogaudio::dsp::SlewLimiter _attackSL; - bogaudio::dsp::SlewLimiter _releaseSL; - CrossFader _detectorMix; - RootMeanSquare _detectorRMS; - Compressor _compressor; - NoiseGate _noiseGate; - Amplifier _amplifier; - Saturator _saturator; - - Pressor() - : _detectorRMS(1000.0f, 1.0f, 50.0f) - { + Pressor() { config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); configParam(THRESHOLD_PARAM, 0.0f, 1.0f, 0.8f, "Threshold", " dB", 0.0f, 30.0f, -24.0f); configParam<DynamicsRatioParamQuantity>(RATIO_PARAM, 0.0f, 1.0f, 0.55159f, "Ratio"); @@ -90,8 +94,12 @@ struct Pressor : 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/module.cpp b/src/module.cpp @@ -25,6 +25,18 @@ void BGModule::process(const ProcessArgs& args) { if (channelsBefore != channelsNow) { _channels = channelsNow; channelsChanged(channelsBefore, channelsNow); + if (channelsBefore < channelsNow) { + while (channelsBefore < channelsNow) { + addEngine(channelsBefore); + ++channelsBefore; + } + } + else { + while (channelsNow < channelsBefore) { + removeEngine(channelsBefore - 1); + --channelsBefore; + } + } } modulate(); diff --git a/src/module.hpp b/src/module.hpp @@ -16,6 +16,12 @@ struct BGModule : Module { BGModule(int modulationSteps = 100) : _modulationSteps(modulationSteps) { _steps = _modulationSteps; } + virtual ~BGModule() { + while (_channels >= 1) { + removeEngine(_channels - 1); + --_channels; + } + } void onReset() override final; void onSampleRateChange() override final; @@ -26,6 +32,8 @@ struct BGModule : Module { virtual bool active() { return true; } virtual int channels() { return 1; } virtual void channelsChanged(int before, int after) {} + virtual void addEngine(int c) {} + virtual void removeEngine(int c) {} virtual void modulate() {} virtual void modulateChannel(int c) {} virtual void always(const ProcessArgs& args) {}