BogaudioModules

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

commit 45451f4e8d03a2bfbc5c6d1a7f69938e736a605a
parent 44d51ceb3f63fadb92b6541b0fa8b731e0b31076
Author: Matt Demanett <matt@demanett.net>
Date:   Fri,  9 Nov 2018 02:09:22 -0500

Slew module. #20

Diffstat:
Ares-src/Slew-src.svg | 156+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ares/Slew.svg | 0
Asrc/Slew.cpp | 105+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/Slew.hpp | 54++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/bogaudio.cpp | 4++++
5 files changed, 319 insertions(+), 0 deletions(-)

diff --git a/res-src/Slew-src.svg b/res-src/Slew-src.svg @@ -0,0 +1,156 @@ +<svg + version="1.1" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + width="45" + height="380" + viewBox="0 0 45 380" +> + <style> + text { + fill: #333; + font-family: 'Roboto', sans-serif; + font-weight: bold; + } + text.title { + font-family: 'Comfortaa', sans-serif; + font-weight: normal; + } + text.brand { + font-family: 'Audiowide', sans-serif; + font-weight: bold; + } + </style> + + <defs> + <symbol id="knob-medium" viewBox="0 0 26px 26px"> + <g transform="translate(13 13)"> + <polyline points="-3,0 3,0" stroke-width="1" stroke="#00f" /> + <polyline points="0,-3 0,3" stroke-width="1" stroke="#00f" /> + <circle cx="0" cy="0" r="12.5" stroke-width="1" stroke="#00f" fill="none" /> + </g> + </symbol> + + <symbol id="knob-smallest" viewBox="0 0 16px 16px"> + <g transform="translate(8 8)"> + <polyline points="-3,0 3,0" stroke-width="1" stroke="#00f" /> + <polyline points="0,-3 0,3" stroke-width="1" stroke="#00f" /> + <circle r="7.5" stroke-width="1" stroke="#00f" fill="none" /> + </g> + </symbol> + + <symbol id="knobguide-time" 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(-1.9 2.2)">0</text> + <polyline points="0,0 1.5,0" stroke-width="0.3" stroke="#333" transform="rotate(-172.92) translate(15 0)" /> + <text font-size="5.0pt" transform="rotate(-145.13) translate(17 0) rotate(145.13) translate(-2.5 2.2)">1</text> + <polyline points="0,0 2.5,0" stroke-width="0.3" stroke="#333" transform="rotate(-75.68) translate(15 0)" /> + <text font-size="5.0pt" transform="rotate(-27.87) translate(17 0) rotate(27.87) translate(-2 2.2)">5</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)">10</text> + </g> + </symbol> + + <symbol id="knobguide-rise-shape" viewBox="0 0 45px 45px"> + <g transform="translate(20 20)"> + <polyline points="0,0 2.5,0" stroke-width="0.3" stroke="#333" transform="rotate(-52.5) translate(10 0)" /> + <polyline points="0,0 2.5,0" stroke-width="0.3" stroke="#333" transform="rotate(-15) translate(10 0)" /> + <polyline points="0,0 2.5,0" stroke-width="0.3" stroke="#333" transform="rotate(22.5) translate(10 0)" /> + + <polyline points="0,0 2.5,0" stroke-width="0.3" stroke="#333" transform="rotate(-127.5) translate(10 0)" /> + <polyline points="0,0 2.5,0" stroke-width="0.3" stroke="#333" transform="rotate(-165) translate(10 0)" /> + <polyline points="0,0 2.5,0" stroke-width="0.3" stroke="#333" transform="rotate(-202.5) translate(10 0)" /> + + <path d="M -3.5 0 Q 0 3.5, 3.5 0" stroke="#333" stroke-width="1" fill="none" transform="rotate(60) translate(13 0) rotate(-60) translate(2 0) rotate(-45) translate(0 0)" /> + <polyline points="-3.5,0 3.5,0" stroke="#333" stroke-width="1" fill="none" transform="rotate(-90) translate(13 0) rotate(90) rotate(-45) translate(0 0)" /> + <path d="M -3.5 0 Q 0 3.5, 3.5 0" stroke="#333" stroke-width="1" fill="none" transform="rotate(-240) translate(13 0) rotate(240) translate(-2 0) rotate(135) translate(0 0)" /> + </g> + </symbol> + + <symbol id="knobguide-fall-shape" viewBox="0 0 45px 45px"> + <g transform="translate(20 20)"> + <polyline points="0,0 2.5,0" stroke-width="0.3" stroke="#333" transform="rotate(-52.5) translate(10 0)" /> + <polyline points="0,0 2.5,0" stroke-width="0.3" stroke="#333" transform="rotate(-15) translate(10 0)" /> + <polyline points="0,0 2.5,0" stroke-width="0.3" stroke="#333" transform="rotate(22.5) translate(10 0)" /> + + <polyline points="0,0 2.5,0" stroke-width="0.3" stroke="#333" transform="rotate(-127.5) translate(10 0)" /> + <polyline points="0,0 2.5,0" stroke-width="0.3" stroke="#333" transform="rotate(-165) translate(10 0)" /> + <polyline points="0,0 2.5,0" stroke-width="0.3" stroke="#333" transform="rotate(-202.5) translate(10 0)" /> + + <path d="M -3.5 0 Q 0 3.5, 3.5 0" stroke="#333" stroke-width="1" fill="none" transform="rotate(60) translate(13 0) rotate(-60) translate(2 0) rotate(-135) translate(0 0)" /> + <polyline points="-3.5,0 3.5,0" stroke="#333" stroke-width="1" fill="none" transform="rotate(-90) translate(13 0) rotate(90) rotate(45) translate(0 0)" /> + <path d="M -3.5 0 Q 0 3.5, 3.5 0" stroke="#333" stroke-width="1" fill="none" transform="rotate(-240) translate(13 0) rotate(240) translate(-2 0) rotate(45) translate(0 0)" /> + </g> + </symbol> + + <symbol id="input" viewBox="0 0 24px 24px"> + <g transform="translate(12 12)"> + <circle cx="0" cy="0" r="5" stroke-width="1" stroke="#0f0" fill="#0f0" /> + <circle cx="0" cy="0" r="10.5" stroke-width="3" stroke="#0f0" fill="none" /> + </g> + </symbol> + + <symbol id="output" viewBox="0 0 24px 24px"> + <g transform="translate(12 12)"> + <circle cx="0" cy="0" r="5" stroke-width="1" stroke="#f00" fill="#f00" /> + <circle cx="0" cy="0" r="10.5" stroke-width="3" stroke="#f00" fill="none" /> + </g> + </symbol> + </defs> + + <rect width="100%" height="100%" fill="#ddd" /> + <polyline points="1,1 44,1 44,379 1,379 1,1" stroke="#e4e4e4" stroke-width="0.5" fill="none" /> + <polyline points="0.5,0.5 44.5,0.5 44.5,379.5 0.5,379.5 0.5,0.5" stroke="#ebebeb" stroke-width="0.8" fill="none" /> + <polyline points="0,0 45,0 45,380 0,380 0,0" stroke="#f2f2f2" stroke-width="1" fill="none" /> + + <!-- <polyline points="0,0 0,300" stroke="#0f0" stroke-width="1" fill="none" transform="translate(22.5 0)" /> --> + + <g transform="rotate(-90) translate(-376 13)"> + <text class="title" font-size="7pt" letter-spacing="2.5px">SLEW</text> + <g transform="translate(0 12)"> + <text class="brand" font-size="7pt" letter-spacing="2px">BGA</text> + <rect width="3.0" height="3" fill="#ddd" transform="translate(11.5 -5)" /> + </g> + </g> + + <g transform="translate(0 25)"> + <text font-size="6pt" letter-spacing="2.0px" transform="translate(11 0)">RISE</text> + <use id="RISE_PARAM" xlink:href="#knob-medium" transform="translate(9.5 9)" /> + <use xlink:href="#knobguide-time" transform="translate(0 -1)" /> + <use id="RISE_SHAPE_PARAM" xlink:href="#knob-smallest" transform="translate(14.5 51)" /> + <use xlink:href="#knobguide-rise-shape" transform="translate(2.5 39)" /> + <g transform="translate(7.5 77)"> + <rect width="30" height="30" rx="5" fill="#fafafa" /> + <use id="RISE_INPUT" xlink:href="#input" transform="translate(3 3)" /> + <!-- <text font-size="5pt" letter-spacing="2px" transform="translate(11 35)">CV</text> --> + </g> + </g> + + <g transform="translate(0 146)"> + <text font-size="6pt" letter-spacing="2.0px" transform="translate(11 0)">FALL</text> + <use id="FALL_PARAM" xlink:href="#knob-medium" transform="translate(9.5 9)" /> + <use xlink:href="#knobguide-time" transform="translate(0 -1)" /> + <use id="FALL_SHAPE_PARAM" xlink:href="#knob-smallest" transform="translate(14.5 51)" /> + <use xlink:href="#knobguide-fall-shape" transform="translate(2.5 39)" /> + <g transform="translate(7.5 77)"> + <rect width="30" height="30" rx="5" fill="#fafafa" /> + <use id="FALL_INPUT" xlink:href="#input" transform="translate(3 3)" /> + <!-- <text font-size="5pt" letter-spacing="2px" transform="translate(11 35)">CV</text> --> + </g> + </g> + + <g transform="translate(0 260)"> + <g transform="translate(5.5 0)"> + <rect width="34" height="10" fill="#fafafa" transform="translate(0 28)" /> + <rect width="34" height="35" rx="5" fill="#fafafa" /> + <use id="IN_INPUT" xlink:href="#input" transform="translate(5 3)" /> + <text font-size="5pt" letter-spacing="2px" transform="translate(12.5 35)">IN</text> + </g> + <g transform="translate(5.5 41)"> + <rect width="34" height="10" fill="#bbb" transform="translate(0 -3)" /> + <rect width="34" height="35" rx="5" fill="#bbb" /> + <use id="OUT_OUTPUT" xlink:href="#output" transform="translate(5 0)" /> + <text font-size="5pt" letter-spacing="2px" transform="translate(8.3 32)">OUT</text> + </g> + </g> +</svg> diff --git a/res/Slew.svg b/res/Slew.svg Binary files differ. diff --git a/src/Slew.cpp b/src/Slew.cpp @@ -0,0 +1,105 @@ + +#include "Slew.hpp" + +void Slew::onReset() { + _modulationStep = modulationSteps; +} + +void Slew::step() { + if (!(inputs[IN_INPUT].active && outputs[OUT_OUTPUT].active)) { + return; + } + + ++_modulationStep; + if (_modulationStep >= modulationSteps) { + _modulationStep = 0; + + float riseTime = time(params[RISE_PARAM], inputs[RISE_INPUT]); + float riseShape = shape(params[RISE_SHAPE_PARAM]); + float fallTime = time(params[FALL_PARAM], inputs[FALL_INPUT]); + float fallShape = shape(params[FALL_SHAPE_PARAM]); + + _rise.setParams(engineGetSampleRate(), riseTime, riseShape); + _fall.setParams(engineGetSampleRate(), fallTime, fallShape); + } + + float sample = inputs[IN_INPUT].value; + if (sample > _last) { + if (!_rising) { + _rising = true; + _rise._last = _last; + } + outputs[OUT_OUTPUT].value = _last = _rise.next(sample); + } + else { + if (_rising) { + _rising = false; + _fall._last = _last; + } + outputs[OUT_OUTPUT].value = _last = _fall.next(sample); + } +} + +float Slew::time(Param& param, Input& input) { + float time = param.value; + if (input.active) { + time *= clamp(input.value / 10.0f, 0.0f, 1.0f); + } + return time * time * 10000.0f; +} + +float Slew::shape(Param& param) { + float shape = param.value; + if (shape < 0.0) { + shape = 1.0f + shape; + shape = _rise.minShape + shape * (1.0f - _rise.minShape); + } + else { + shape += 1.0f; + } + return shape; +} + +struct SlewWidget : ModuleWidget { + static constexpr int hp = 3; + + SlewWidget(Slew* module) : ModuleWidget(module) { + box.size = Vec(RACK_GRID_WIDTH * hp, RACK_GRID_HEIGHT); + + { + SVGPanel *panel = new SVGPanel(); + panel->box.size = box.size; + panel->setBackground(SVG::load(assetPlugin(plugin, "res/Slew.svg"))); + addChild(panel); + } + + addChild(Widget::create<ScrewSilver>(Vec(0, 0))); + addChild(Widget::create<ScrewSilver>(Vec(box.size.x - 15, 365))); + + // generated by svg_widgets.rb + auto riseParamPosition = Vec(9.5, 34.0); + auto riseShapeParamPosition = Vec(14.5, 76.0); + auto fallParamPosition = Vec(9.5, 155.0); + auto fallShapeParamPosition = Vec(14.5, 197.0); + + auto riseInputPosition = Vec(10.5, 105.0); + auto fallInputPosition = Vec(10.5, 226.0); + auto inInputPosition = Vec(10.5, 263.0); + + auto outOutputPosition = Vec(10.5, 301.0); + // end generated by svg_widgets.rb + + addParam(ParamWidget::create<Knob26>(riseParamPosition, module, Slew::RISE_PARAM, 0.0, 1.0, 0.316)); + addParam(ParamWidget::create<Knob16>(riseShapeParamPosition, module, Slew::RISE_SHAPE_PARAM, -1.0, 1.0, 0.0)); + addParam(ParamWidget::create<Knob26>(fallParamPosition, module, Slew::FALL_PARAM, 0.0, 1.0, 0.316)); + addParam(ParamWidget::create<Knob16>(fallShapeParamPosition, module, Slew::FALL_SHAPE_PARAM, -1.0, 1.0, 0.0)); + + addInput(Port::create<Port24>(riseInputPosition, Port::INPUT, module, Slew::RISE_INPUT)); + addInput(Port::create<Port24>(fallInputPosition, Port::INPUT, module, Slew::FALL_INPUT)); + addInput(Port::create<Port24>(inInputPosition, Port::INPUT, module, Slew::IN_INPUT)); + + addOutput(Port::create<Port24>(outOutputPosition, Port::OUTPUT, module, Slew::OUT_OUTPUT)); + } +}; + +Model* modelSlew = createModel<Slew, SlewWidget>("Bogaudio-Slew", "Slew", "slew/lag/glide", SLEW_LIMITER_TAG); diff --git a/src/Slew.hpp b/src/Slew.hpp @@ -0,0 +1,54 @@ +#pragma once + +#include "bogaudio.hpp" +#include "dsp/signal.hpp" + +using namespace bogaudio::dsp; + +extern Model* modelSlew; + +namespace bogaudio { + +struct Slew : Module { + enum ParamsIds { + RISE_PARAM, + RISE_SHAPE_PARAM, + FALL_PARAM, + FALL_SHAPE_PARAM, + NUM_PARAMS + }; + + enum InputsIds { + RISE_INPUT, + FALL_INPUT, + IN_INPUT, + NUM_INPUTS + }; + + enum OutputsIds { + OUT_OUTPUT, + NUM_OUTPUTS + }; + + enum LightsIds { + NUM_LIGHTS + }; + + const int modulationSteps = 100; + int _modulationStep = 0; + bool _rising = true; + float _last = 0.0f; + ShapedSlewLimiter _rise; + ShapedSlewLimiter _fall; + + Slew() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) { + onReset(); + } + + void onReset() override; + void step() override; + float time(Param& param, Input& input); + float shape(Param& param); +}; + +} // namespace bogaudio diff --git a/src/bogaudio.cpp b/src/bogaudio.cpp @@ -36,6 +36,7 @@ #include "SampleHold.hpp" #include "Shaper.hpp" #include "ShaperPlus.hpp" +#include "Slew.hpp" #include "Stack.hpp" #include "Sums.hpp" #include "Switch.hpp" @@ -112,6 +113,9 @@ void init(rack::Plugin *p) { p->addModel(modelNoise); p->addModel(modelOffset); p->addModel(modelSampleHold); +#ifdef EXPERIMENTAL + p->addModel(modelSlew); +#endif p->addModel(modelSums); p->addModel(modelSwitch);