BogaudioModules

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

commit e756e94ffbd6d6e98d39d93e0f359be0ecacb0c8
parent 2c2648fc4d778416cc5e89010f37b8830a0b11bd
Author: Matt Demanett <matt@demanett.net>
Date:   Sun, 16 Sep 2018 23:26:48 -0400

PRESSOR: revise panel, add noise gate mode.

Diffstat:
MMakefile | 2+-
Mbenchmarks/signal_benchmark.cpp | 10++++++++++
Mres-src/Pressor-src.svg | 116+++++++++++++++++++++++++++++++++++++------------------------------------------
Mres/Pressor.svg | 0
Msrc/Pressor.cpp | 49++++++++++++++++++++++++++-----------------------
Msrc/Pressor.hpp | 8+++++---
Msrc/dsp/signal.cpp | 34++++++++++++++++++++++++++++++++++
Msrc/dsp/signal.hpp | 5+++++
8 files changed, 136 insertions(+), 88 deletions(-)

diff --git a/Makefile b/Makefile @@ -50,7 +50,7 @@ plot: $(PLOT_OBJECTS) plotrun: plot ./plot plotrungp: plot - ./plot > plot.tmp && gnuplot -e "set yrange [0:20]; plot 'plot.tmp' using 1:2 with lines" + ./plot > plot.tmp && gnuplot -e "set yrange [-80:80]; plot 'plot.tmp' using 1:2 with lines" plot_clean: rm -f plot $(PLOT_OBJECTS) diff --git a/benchmarks/signal_benchmark.cpp b/benchmarks/signal_benchmark.cpp @@ -228,3 +228,13 @@ static void BM_CompressorSoftKnee(benchmark::State& state) { } } BENCHMARK(BM_CompressorSoftKnee); + +static void BM_NoiseGateSoftKnee(benchmark::State& state) { + int i = 0; + NoiseGate ng; + for (auto _ : state) { + i = ++i % 15; + benchmark::DoNotOptimize(ng.compressionDb(0.0f - (float)(i * 3), 0.0f, 2.0f, true)); + } +} +BENCHMARK(BM_NoiseGateSoftKnee); diff --git a/res-src/Pressor-src.svg b/res-src/Pressor-src.svg @@ -79,7 +79,7 @@ <text font-size="5.0pt" transform="rotate(-27.87) translate(17 0) rotate(27.87) translate(-2.2 2.2)">250</text> <polyline points="0,0 2.5,0" stroke-width="0.3" stroke="#333" transform="rotate(19.81) translate(15 0)" /> <text font-size="5.0pt" transform="rotate(60) translate(18 0) rotate(-60) translate(-1.9 2.2)">500</text> - <text font-size="5.0pt" transform="rotate(90) translate(22 0) rotate(-90) translate(-4.8 2.2)">ms</text> + <text font-size="5.0pt" transform="rotate(90) translate(22 0) rotate(-90) translate(-4.4 2.2)">MS</text> </g> </symbol> @@ -92,7 +92,7 @@ <text font-size="5.0pt" transform="rotate(-27.87) translate(17 0) rotate(27.87) translate(-2.2 2.2)">1</text> <polyline points="0,0 2.5,0" stroke-width="0.3" stroke="#333" transform="rotate(19.81) translate(15 0)" /> <text font-size="5.0pt" transform="rotate(60) translate(18 0) rotate(-60) translate(-1.9 2.2)">2</text> - <text font-size="5.0pt" transform="rotate(90) translate(22 0) rotate(-90) translate(-1.8 2.2)">s</text> + <text font-size="5.0pt" transform="rotate(90) translate(22 0) rotate(-90) translate(-2 2.2)">S</text> </g> </symbol> @@ -126,22 +126,6 @@ </g> </symbol> - <symbol id="knobguide-outputmix" viewBox="0 0 45px 45px"> - <g transform="translate(22.5 22.5)"> - <text font-size="5.0pt" transform="rotate(-240) translate(18 0) rotate(240) translate(-2.2 2.2)">D</text> - <polyline points="0,0 2.5,0" stroke-width="0.3" stroke="#333" transform="rotate(-210) translate(15 0)" /> - <polyline points="0,0 2.5,0" stroke-width="0.3" stroke="#333" transform="rotate(-180) translate(15 0)" /> - <polyline points="0,0 2.5,0" stroke-width="0.3" stroke="#333" transform="rotate(-150) translate(15 0)" /> - <polyline points="0,0 2.5,0" stroke-width="0.3" stroke="#333" transform="rotate(-120) translate(15 0)" /> - <polyline points="0,0 3.5,0" stroke-width="1" stroke="#333" transform="rotate(-90) translate(15 0)" /> - <polyline points="0,0 2.5,0" stroke-width="0.3" stroke="#333" transform="rotate(-60) translate(15 0)" /> - <polyline points="0,0 2.5,0" stroke-width="0.3" stroke="#333" transform="rotate(-30) translate(15 0)" /> - <polyline points="0,0 2.5,0" stroke-width="0.3" stroke="#333" transform="rotate(0) translate(15 0)" /> - <polyline points="0,0 2.5,0" stroke-width="0.3" stroke="#333" transform="rotate(30) translate(15 0)" /> - <text font-size="5.0pt" transform="rotate(60) translate(18 0) rotate(-60) translate(-2.9 2.5)">W</text> - </g> - </symbol> - <symbol id="knobguide-detectormix" viewBox="0 0 45px 45px"> <g transform="translate(22.5 22.5)"> <text font-size="5.0pt" transform="rotate(-240) translate(18 0) rotate(240) translate(-4.2 2.2)">IN</text> @@ -282,16 +266,19 @@ <g transform="translate(13 53)"> <!-- <polyline points="0,19 268,19" stroke="#0f0" stroke-width="1" fill="none" /> --> - <!-- <polyline points="40,-20 40,50" stroke="#0f0" stroke-width="1" fill="none" /> --> - <text font-size="8pt" letter-spacing="1.5px" transform="translate(4 55) rotate(270)">THRESHOLD</text> + <!-- <polyline points="42,-20 42,250" stroke="#0f0" stroke-width="1" fill="none" /> --> + <!-- <polyline points="0,0 270,0" stroke="#0f0" stroke-width="1" fill="none" transform="translate(0 -1)" /> --> + <!-- <polyline points="0,0 270,0" stroke="#0f0" stroke-width="1" fill="none" transform="translate(0 19)" /> --> + <!-- <polyline points="0,0 270,0" stroke="#0f0" stroke-width="1" fill="none" transform="translate(0 39)" /> --> + <text font-size="8pt" letter-spacing="1.5px" transform="translate(4 56.5) rotate(270)">THRESHOLD</text> <use id="THRESHOLD_PARAM" xlink:href="#knob" transform="translate(23 0)" /> <use xlink:href="#knobguide-threshold" transform="translate(7 -16)" /> </g> <g transform="translate(102 53)"> <!-- <polyline points="0,19 68,19" stroke="#0f0" stroke-width="1" fill="none" /> --> - <!-- <polyline points="40,-20 40,50" stroke="#0f0" stroke-width="1" fill="none" /> --> - <text font-size="8pt" letter-spacing="2px" transform="translate(4 40) rotate(270)">RATIO</text> + <!-- <polyline points="42,-20 42,250" stroke="#0f0" stroke-width="1" fill="none" /> --> + <text font-size="8pt" letter-spacing="2px" transform="translate(4 38.5) rotate(270)">RATIO</text> <use id="RATIO_PARAM" xlink:href="#knob" transform="translate(23 0)" /> <use xlink:href="#knobguide-ratio" transform="translate(7 -16)" /> </g> @@ -303,61 +290,68 @@ </g> <g transform="translate(10 141)"> - <g transform="translate(-1 0)"> + <g transform="translate(13 0)"> <!-- <rect width="51" height="10" fill="#f003" transform="translate(8 -15)" /> --> <!-- <polyline points="0,0 0,380" stroke="#0f0" stroke-width="1" fill="none" transform="translate(29 -100)" /> --> - <!-- <polyline points="0,13 270,13" stroke="#0f0" stroke-width="1" fill="none" /> --> - <text font-size="8pt" letter-spacing="2px" transform="translate(8 35) rotate(270)">ATTACK</text> + <!-- <polyline points="0,0 270,0" stroke="#0f0" stroke-width="1" fill="none" transform="translate(0 -7)" /> --> + <!-- <polyline points="0,0 270,0" stroke="#0f0" stroke-width="1" fill="none" transform="translate(0 13)" /> --> + <!-- <polyline points="0,0 270,0" stroke="#0f0" stroke-width="1" fill="none" transform="translate(0 33)" /> --> + <text font-size="8pt" letter-spacing="2px" transform="translate(6 38.5) rotate(270)">ATTACK</text> <use id="ATTACK_PARAM" xlink:href="#knob-medium" transform="translate(19 0)" /> </g> - <use xlink:href="#knobguide-attack" transform="translate(8.5 -9.5)" /> - <g transform="translate(58 0)"> + <use xlink:href="#knobguide-attack" transform="translate(21.5 -9.5)" /> + <g transform="translate(102 0)"> <!-- <rect width="51" height="10" fill="#f003" transform="translate(8 -15)" /> --> <!-- <polyline points="0,0 0,380" stroke="#0f0" stroke-width="1" fill="none" transform="translate(29 -100)" /> --> - <text font-size="8pt" letter-spacing="2px" transform="translate(8 40) rotate(270)">RELEASE</text> + <text font-size="8pt" letter-spacing="2px" transform="translate(6 42) rotate(270)">RELEASE</text> <use id="RELEASE_PARAM" xlink:href="#knob-medium" transform="translate(19 0)" /> </g> - <use xlink:href="#knobguide-release" transform="translate(67.5 -9.5)" /> - <g transform="translate(117 0)"> - <!-- <rect widtq2h="51" height="10" fill="#f003" transform="translate(8 -15)" /> --> - <!-- <polyline points="0,0 0,380" stroke="#0f0" stroke-width="1" fill="none" transform="translate(29 -100)" /> --> - <text font-size="8pt" letter-spacing="2px" transform="translate(8 43) rotate(270)">OUT GAIN</text> - <use id="OUTPUT_GAIN_PARAM" xlink:href="#knob-medium" transform="translate(19 0)" /> - </g> - <use xlink:href="#knobguide-outputgain" transform="translate(126.5 -9.5)" /> - <g transform="translate(189 0)"> - <!-- <rect width="5" height="24" fill="#0f0" transform="translate(-14 2)" /> --> - <text font-size="5pt" letter-spacing="1.5px" transform="translate(-8 30) rotate(270)">DETECT</text> - <text font-size="5pt" letter-spacing="2px" transform="translate(-2 -1)">RMS</text> - <use id="DECTECTOR_MODE_PARAM" xlink:href="#switch" transform="translate(0 2)" /> - <text font-size="5pt" letter-spacing="2px" transform="translate(-4 34)">PEAK</text> - </g> + <use xlink:href="#knobguide-release" transform="translate(111.5 -9.5)" /> </g> <g transform="translate(10 213)"> <g transform="translate(-1 0)"> - <!-- <rect width="51" height="10" fill="#f003" transform="translate(8 -15)" /> --> + <!-- <rect width="47" height="10" fill="#f003" transform="translate(8 -15)" /> --> <!-- <polyline points="0,0 0,380" stroke="#0f0" stroke-width="1" fill="none" transform="translate(29 -100)" /> --> - <!-- <polyline points="0,13 270,13" stroke="#0f0" stroke-width="1" fill="none" /> --> - <text font-size="8pt" letter-spacing="2px" transform="translate(8 38) rotate(270)">IN GAIN</text> + <!-- <polyline points="0,0 270,0" stroke="#0f0" stroke-width="1" fill="none" transform="translate(0 -7)" /> --> + <!-- <polyline points="0,0 270,0" stroke="#0f0" stroke-width="1" fill="none" transform="translate(0 13)" /> --> + <!-- <polyline points="0,0 270,0" stroke="#0f0" stroke-width="1" fill="none" transform="translate(0 33)" /> --> + <text font-size="8pt" letter-spacing="2px" transform="translate(8 38.5) rotate(270)">IN GAIN</text> <use id="INPUT_GAIN_PARAM" xlink:href="#knob-medium" transform="translate(19 0)" /> </g> <use xlink:href="#knobguide-inputgain" transform="translate(8.5 -9.5)" /> - <g transform="translate(58 0)"> - <!-- <rect width="51" height="10" fill="#f003" transform="translate(8 -15)" /> --> + <g transform="translate(60 0)"> + <!-- <rect width="47" height="10" fill="#f003" transform="translate(8 -15)" /> --> <!-- <polyline points="0,0 0,380" stroke="#0f0" stroke-width="1" fill="none" transform="translate(29 -100)" /> --> - <text font-size="8pt" letter-spacing="2px" transform="translate(8 37) rotate(270)">IN/SIDE</text> - <use id="DETECTOR_MIX_PARAM" xlink:href="#knob-medium" transform="translate(19 0)" /> + <text font-size="8pt" letter-spacing="2px" transform="translate(8 44.5) rotate(270)">OUT GAIN</text> + <use id="OUTPUT_GAIN_PARAM" xlink:href="#knob-medium" transform="translate(19 0)" /> </g> - <use xlink:href="#knobguide-detectormix" transform="translate(67.5 -9.5)" /> - <g transform="translate(117 0)"> - <!-- <rect width="51" height="10" fill="#f003" transform="translate(8 -15)" /> --> + <use xlink:href="#knobguide-outputgain" transform="translate(69.5 -9.5)" /> + <g transform="translate(121 0)"> + <!-- <rect width="47" height="10" fill="#f003" transform="translate(8 -15)" /> --> <!-- <polyline points="0,0 0,380" stroke="#0f0" stroke-width="1" fill="none" transform="translate(29 -100)" /> --> - <text font-size="8pt" letter-spacing="2px" transform="translate(8 40) rotate(270)">DRY/WET</text> - <use id="OUTPUT_MIX_PARAM" xlink:href="#knob-medium" transform="translate(19 0)" /> + <text font-size="8pt" letter-spacing="2px" transform="translate(8 38) rotate(270)">IN/SIDE</text> + <use id="DETECTOR_MIX_PARAM" xlink:href="#knob-medium" transform="translate(19 0)" /> + </g> + <use xlink:href="#knobguide-detectormix" transform="translate(130.5 -9.5)" /> + </g> + + <g transform="translate(199 128)"> + <g transform="translate(0 0)"> + <!-- <rect width="5" height="24" fill="#0f0" transform="translate(-14 2)" /> --> + <text font-size="5pt" letter-spacing="1.5px" transform="translate(-8 25.5) rotate(270)">MODE</text> + <text font-size="5pt" letter-spacing="2px" transform="translate(-5 -1)">COMP</text> + <use id="MODE_PARAM" xlink:href="#switch" transform="translate(0 2)" /> + <text font-size="5pt" letter-spacing="2px" transform="translate(-4 34)">GATE</text> </g> - <use xlink:href="#knobguide-outputmix" transform="translate(126.5 -9.5)" /> - <g transform="translate(189 0)"> + <g transform="translate(0 49)"> + <!-- <rect width="5" height="24" fill="#0f0" transform="translate(-14 2)" /> --> + <text font-size="5pt" letter-spacing="1.5px" transform="translate(-8 30) rotate(270)">DETECT</text> + <text font-size="5pt" letter-spacing="2px" transform="translate(-2 -1)">RMS</text> + <use id="DECTECTOR_MODE_PARAM" xlink:href="#switch" transform="translate(0 2)" /> + <text font-size="5pt" letter-spacing="2px" transform="translate(-4 34)">PEAK</text> + </g> + <g transform="translate(0 98)"> <!-- <rect width="5" height="24" fill="#0f0" transform="translate(-14 2)" /> --> <text font-size="5pt" letter-spacing="2px" transform="translate(-8 25.5) rotate(270)">KNEE</text> <text font-size="5pt" letter-spacing="2px" transform="translate(-4 -1)">SOFT</text> @@ -414,12 +408,12 @@ <text font-size="6pt" letter-spacing="2px" transform="translate(5.4 40)">REL</text> </g> <g transform="translate(105 0)"> - <use id="OUTPUT_GAIN_INPUT" xlink:href="#input" transform="translate(3 5)" /> - <text font-size="6pt" letter-spacing="1px" transform="translate(5.3 40)">OGN</text> + <use id="INPUT_GAIN_INPUT" xlink:href="#input" transform="translate(3 5)" /> + <text font-size="6pt" letter-spacing="1px" transform="translate(5.3 40)">IGN</text> </g> <g transform="translate(139 0)"> - <use id="OUTPUT_MIX_INPUT" xlink:href="#input" transform="translate(3 5)" /> - <text font-size="6pt" letter-spacing="2px" transform="translate(5 40)">D/W</text> + <use id="OUTPUT_GAIN_INPUT" xlink:href="#input" transform="translate(3 5)" /> + <text font-size="6pt" letter-spacing="1px" transform="translate(5.3 40)">OGN</text> </g> <g transform="translate(173 0)"> <use id="RIGHT_OUTPUT" xlink:href="#output" transform="translate(3 5)" /> diff --git a/res/Pressor.svg b/res/Pressor.svg Binary files differ. diff --git a/src/Pressor.cpp b/src/Pressor.cpp @@ -62,7 +62,11 @@ void Pressor::step() { release *= release; _releaseSL.setParams(sampleRate, release * 2000.0f); - float inGain = params[INPUT_GAIN_PARAM].value * 12.0f; + float inGain = params[INPUT_GAIN_PARAM].value; + if (inputs[INPUT_GAIN_INPUT].active) { + inGain = clamp(inGain + inputs[INPUT_GAIN_INPUT].value / 5.0f, -1.0f, 1.0f); + } + inGain *= 12.0f; if (_inGain != inGain) { _inGain = inGain; _inLevel = decibelsToAmplitude(_inGain); @@ -80,14 +84,8 @@ void Pressor::step() { _detectorMix.setParams(params[DETECTOR_MIX_PARAM].value, 0.0f, true); - float outputMix = params[OUTPUT_MIX_PARAM].value; - if (inputs[OUTPUT_MIX_INPUT].active) { - outputMix *= clamp(inputs[OUTPUT_MIX_INPUT].value / 5.0f, -1.0f, 1.0f); - } - _outputMix.setParams(outputMix, 0.0f, true); - + _compressorMode = params[MODE_PARAM].value > 0.5f; _rmsDetector = params[DECTECTOR_MODE_PARAM].value > 0.5f; - _softKnee = params[KNEE_PARAM].value > 0.97f; } @@ -112,14 +110,19 @@ void Pressor::step() { _lastEnv = env; float detectorDb = amplitudeToDecibels(env / 5.0f); - _compressionDb = _compressor.compressionDb(detectorDb, _thresholdDb, _ratio, _softKnee); - float compression = decibelsToAmplitude(-_compressionDb); + if (_compressorMode) { + _compressionDb = _compressor.compressionDb(detectorDb, _thresholdDb, _ratio, _softKnee); + } + else { + _compressionDb = _noiseGate.compressionDb(detectorDb, _thresholdDb, _ratio, _softKnee); + } + _amplifier.setLevel(-_compressionDb); outputs[ENVELOPE_OUTPUT].value = env; if (outputs[LEFT_OUTPUT].active) { - outputs[LEFT_OUTPUT].value = _saturator.next(_outputMix.next(leftInput, leftInput * compression * _outLevel)); + outputs[LEFT_OUTPUT].value = _saturator.next(_amplifier.next(leftInput) * _outLevel); } if (outputs[RIGHT_OUTPUT].active) { - outputs[RIGHT_OUTPUT].value = _saturator.next(_outputMix.next(rightInput, rightInput * compression * _outLevel)); + outputs[RIGHT_OUTPUT].value = _saturator.next(_amplifier.next(rightInput) * _outLevel); } } @@ -189,14 +192,14 @@ struct PressorWidget : ModuleWidget { // generated by svg_widgets.rb auto thresholdParamPosition = Vec(36.0, 53.0); auto ratioParamPosition = Vec(125.0, 53.0); - auto attackParamPosition = Vec(28.0, 141.0); - auto releaseParamPosition = Vec(87.0, 141.0); - auto outputGainParamPosition = Vec(146.0, 141.0); - auto dectectorModeParamPosition = Vec(198.5, 142.5); + auto attackParamPosition = Vec(42.0, 141.0); + auto releaseParamPosition = Vec(131.0, 141.0); auto inputGainParamPosition = Vec(28.0, 213.0); - auto detectorMixParamPosition = Vec(87.0, 213.0); - auto outputMixParamPosition = Vec(146.0, 213.0); - auto kneeParamPosition = Vec(198.5, 214.5); + auto outputGainParamPosition = Vec(89.0, 213.0); + auto detectorMixParamPosition = Vec(150.0, 213.0); + auto modeParamPosition = Vec(198.5, 129.5); + auto dectectorModeParamPosition = Vec(198.5, 178.5); + auto kneeParamPosition = Vec(198.5, 227.5); auto leftInputPosition = Vec(16.0, 274.0); auto sidechainInputPosition = Vec(50.0, 274.0); @@ -205,8 +208,8 @@ struct PressorWidget : ModuleWidget { auto rightInputPosition = Vec(16.0, 318.0); auto attackInputPosition = Vec(50.0, 318.0); auto releaseInputPosition = Vec(84.0, 318.0); - auto outputGainInputPosition = Vec(118.0, 318.0); - auto outputMixInputPosition = Vec(152.0, 318.0); + auto inputGainInputPosition = Vec(118.0, 318.0); + auto outputGainInputPosition = Vec(152.0, 318.0); auto envelopeOutputPosition = Vec(152.0, 274.0); auto leftOutputPosition = Vec(186.0, 274.0); @@ -218,9 +221,9 @@ struct PressorWidget : ModuleWidget { addParam(ParamWidget::create<Knob26>(attackParamPosition, module, Pressor::ATTACK_PARAM, 0.0, 1.0, 0.316)); addParam(ParamWidget::create<Knob26>(releaseParamPosition, module, Pressor::RELEASE_PARAM, 0.0, 1.0, 0.316)); addParam(ParamWidget::create<Knob26>(outputGainParamPosition, module, Pressor::OUTPUT_GAIN_PARAM, 0.0, 1.0, 0.0)); - addParam(ParamWidget::create<Knob26>(outputMixParamPosition, module, Pressor::OUTPUT_MIX_PARAM, -1.0, 1.0, 1.0)); addParam(ParamWidget::create<Knob26>(inputGainParamPosition, module, Pressor::INPUT_GAIN_PARAM, -1.0, 1.0, 0.0)); addParam(ParamWidget::create<Knob26>(detectorMixParamPosition, module, Pressor::DETECTOR_MIX_PARAM, -1.0, 1.0, 0.0)); + addParam(ParamWidget::create<SliderSwitch2State14>(modeParamPosition, module, Pressor::MODE_PARAM, 0.0, 1.0, 1.0)); addParam(ParamWidget::create<SliderSwitch2State14>(dectectorModeParamPosition, module, Pressor::DECTECTOR_MODE_PARAM, 0.0, 1.0, 1.0)); addParam(ParamWidget::create<SliderSwitch2State14>(kneeParamPosition, module, Pressor::KNEE_PARAM, 0.95, 1.0, 1.0)); @@ -231,8 +234,8 @@ struct PressorWidget : ModuleWidget { addInput(Port::create<Port24>(rightInputPosition, Port::INPUT, module, Pressor::RIGHT_INPUT)); addInput(Port::create<Port24>(attackInputPosition, Port::INPUT, module, Pressor::ATTACK_INPUT)); addInput(Port::create<Port24>(releaseInputPosition, Port::INPUT, module, Pressor::RELEASE_INPUT)); + addInput(Port::create<Port24>(inputGainInputPosition, Port::INPUT, module, Pressor::INPUT_GAIN_INPUT)); addInput(Port::create<Port24>(outputGainInputPosition, Port::INPUT, module, Pressor::OUTPUT_GAIN_INPUT)); - addInput(Port::create<Port24>(outputMixInputPosition, Port::INPUT, module, Pressor::OUTPUT_MIX_INPUT)); addOutput(Port::create<Port24>(envelopeOutputPosition, Port::OUTPUT, module, Pressor::ENVELOPE_OUTPUT)); addOutput(Port::create<Port24>(leftOutputPosition, Port::OUTPUT, module, Pressor::LEFT_OUTPUT)); diff --git a/src/Pressor.hpp b/src/Pressor.hpp @@ -16,9 +16,9 @@ struct Pressor : Module { ATTACK_PARAM, RELEASE_PARAM, OUTPUT_GAIN_PARAM, - OUTPUT_MIX_PARAM, INPUT_GAIN_PARAM, DETECTOR_MIX_PARAM, + MODE_PARAM, DECTECTOR_MODE_PARAM, KNEE_PARAM, NUM_PARAMS @@ -32,8 +32,8 @@ struct Pressor : Module { RIGHT_INPUT, ATTACK_INPUT, RELEASE_INPUT, + INPUT_GAIN_INPUT, OUTPUT_GAIN_INPUT, - OUTPUT_MIX_INPUT, NUM_INPUTS }; @@ -57,6 +57,7 @@ struct Pressor : Module { float _inLevel = 0.0f; float _outGain = -1.0f; float _outLevel = 0.0f; + bool _compressorMode = true; bool _rmsDetector = true; bool _softKnee = true; float _lastEnv = 0.0f; @@ -65,9 +66,10 @@ struct Pressor : Module { SlewLimiter _attackSL; SlewLimiter _releaseSL; CrossFader _detectorMix; - CrossFader _outputMix; RootMeanSquare _detectorRMS; Compressor _compressor; + NoiseGate _noiseGate; + Amplifier _amplifier; Saturator _saturator; Pressor() diff --git a/src/dsp/signal.cpp b/src/dsp/signal.cpp @@ -460,3 +460,37 @@ float Compressor::compressionDb(float detectorDb, float thresholdDb, float ratio compressionDb -= compressionDb / ratio; return compressionDb; } + + +const float NoiseGate::maxEffectiveRatio = Compressor::maxEffectiveRatio; + +float NoiseGate::compressionDb(float detectorDb, float thresholdDb, float ratio, bool softKnee) { + const float softKneeDb = 6.0f; + + if (softKnee) { + // FIXME: this acheives nothing. + float range = thresholdDb - Amplifier::minDecibels; + float ix = thresholdDb + softKneeDb; + float iy = 0; + if (detectorDb >= ix) { + return 0.0f; + } + float ox = thresholdDb - range / ratio; + if (detectorDb <= ox) { + return -Amplifier::minDecibels; + } + const float oy = Amplifier::minDecibels; + float t = (detectorDb - ox) / (ix - ox); + float px = t * (ix - thresholdDb) + thresholdDb; + float py = t * (iy - thresholdDb) + thresholdDb; + float s = (py - oy) / (px - ox); + return -(oy + s * (detectorDb - ox)); + } + + if (detectorDb >= thresholdDb) { + return 0.0f; + } + float differenceDb = thresholdDb - detectorDb; + float compressionDb = differenceDb * ratio - differenceDb; + return std::min(compressionDb, -Amplifier::minDecibels); +} diff --git a/src/dsp/signal.hpp b/src/dsp/signal.hpp @@ -233,5 +233,10 @@ struct Compressor { float compressionDb(float detectorDb, float thresholdDb, float ratio, bool softKnee); }; +struct NoiseGate { + static const float maxEffectiveRatio; + float compressionDb(float detectorDb, float thresholdDb, float ratio, bool softKnee); +}; + } // namespace dsp } // namespace bogaudio