BogaudioModules

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

commit 5bc26b963ac09c366a5203d616988f935524ec79
parent 5a0995c9bfba3872a850492241c4c1f2d2062123
Author: Matt Demanett <matt@demanett.net>
Date:   Tue, 24 Jul 2018 00:41:01 -0400

CMP: (window) comparator.

Diffstat:
Ares-src/Cmp-src.svg | 215+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ares/Cmp.svg | 0
Asrc/Cmp.cpp | 216+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/Cmp.hpp | 70++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/bogaudio.cpp | 4++++
5 files changed, 505 insertions(+), 0 deletions(-)

diff --git a/res-src/Cmp-src.svg b/res-src/Cmp-src.svg @@ -0,0 +1,215 @@ +<svg + version="1.1" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + width="90" + height="380" + viewBox="0 0 90 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" viewBox="0 0 45px 45px"> + <g transform="translate(22.5 22.5)"> + <polyline points="-5,0 5,0" stroke-width="1" stroke="#00f" /> + <polyline points="0,-5 0,5" stroke-width="1" stroke="#00f" /> + <circle cx="0" cy="0" r="14" 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-offset" viewBox="0 0 45px 45px"> + <g transform="translate(22.5 22.5)"> + <text font-size="5.0pt" transform="rotate(-240) translate(21 0) rotate(240) translate(-5 2.2)">-10</text> + + <polyline points="0,0 2.5,0" stroke-width="0.3" stroke="#333" transform="rotate(-225) translate(17 0)" /> + <polyline points="0,0 2.5,0" stroke-width="0.3" stroke="#333" transform="rotate(-210) translate(17 0)" /> + <polyline points="0,0 2.5,0" stroke-width="0.3" stroke="#333" transform="rotate(-195) translate(17 0)" /> + <polyline points="0,0 2.5,0" stroke-width="0.3" stroke="#333" transform="rotate(-180) translate(17 0)" /> + + <polyline points="0,0 3.5,0" stroke-width="1" stroke="#333" transform="rotate(-165) translate(17 0)" /> + + <polyline points="0,0 2.5,0" stroke-width="0.3" stroke="#333" transform="rotate(-150) translate(17 0)" /> + <polyline points="0,0 2.5,0" stroke-width="0.3" stroke="#333" transform="rotate(-135) translate(17 0)" /> + <polyline points="0,0 2.5,0" stroke-width="0.3" stroke="#333" transform="rotate(-120) translate(17 0)" /> + <polyline points="0,0 2.5,0" stroke-width="0.3" stroke="#333" transform="rotate(-105) translate(17 0)" /> + + <text font-size="5.0pt" transform="rotate(-90) translate(19 0) rotate(90) translate(-1.9 2.2)">0</text> + + <polyline points="0,0 2.5,0" stroke-width="0.3" stroke="#333" transform="rotate(-75) translate(17 0)" /> + <polyline points="0,0 2.5,0" stroke-width="0.3" stroke="#333" transform="rotate(-60) translate(17 0)" /> + <polyline points="0,0 2.5,0" stroke-width="0.3" stroke="#333" transform="rotate(-45) translate(17 0)" /> + <polyline points="0,0 2.5,0" stroke-width="0.3" stroke="#333" transform="rotate(-30) translate(17 0)" /> + + <polyline points="0,0 3.5,0" stroke-width="1" stroke="#333" transform="rotate(-15) translate(17 0)" /> + + <polyline points="0,0 2.5,0" stroke-width="0.3" stroke="#333" transform="rotate(0) translate(17 0)" /> + <polyline points="0,0 2.5,0" stroke-width="0.3" stroke="#333" transform="rotate(15) translate(17 0)" /> + <polyline points="0,0 2.5,0" stroke-width="0.3" stroke="#333" transform="rotate(30) translate(17 0)" /> + <polyline points="0,0 2.5,0" stroke-width="0.3" stroke="#333" transform="rotate(45) translate(17 0)" /> + + <text font-size="5.0pt" transform="rotate(60) translate(21 0) rotate(-60) translate(-4 2.2)">10</text> + </g> + </symbol> + + <symbol id="knobguide-window" viewBox="0 0 45px 45px"> + <g transform="translate(22.5 22.5)"> + <text font-size="5.0pt" transform="rotate(-240) translate(20 0) rotate(240) translate(-1.9 2.2)">0</text> + + <polyline points="0,0 2.5,0" stroke-width="0.3" stroke="#333" transform="rotate(-210) translate(17 0)" /> + <polyline points="0,0 2.5,0" stroke-width="0.3" stroke="#333" transform="rotate(-180) translate(17 0)" /> + <polyline points="0,0 2.5,0" stroke-width="0.3" stroke="#333" transform="rotate(-150) translate(17 0)" /> + <polyline points="0,0 2.5,0" stroke-width="0.3" stroke="#333" transform="rotate(-120) translate(17 0)" /> + + <polyline points="0,0 3.5,0" stroke-width="1" stroke="#333" transform="rotate(-90) translate(17 0)" /> + + <polyline points="0,0 2.5,0" stroke-width="0.3" stroke="#333" transform="rotate(-60) translate(17 0)" /> + <polyline points="0,0 2.5,0" stroke-width="0.3" stroke="#333" transform="rotate(-30) translate(17 0)" /> + <polyline points="0,0 2.5,0" stroke-width="0.3" stroke="#333" transform="rotate(0) translate(17 0)" /> + <polyline points="0,0 2.5,0" stroke-width="0.3" stroke="#333" transform="rotate(30) translate(17 0)" /> + + <text font-size="5.0pt" transform="rotate(60) translate(20 0) rotate(-60) translate(-4 2.2)">10</text> + </g> + </symbol> + + <symbol id="knobguide-lag" viewBox="0 0 45px 45px"> + <g transform="translate(22.5 22.5)"> + <text font-size="5.0pt" transform="rotate(-240) translate(20 0) rotate(240) translate(-1.9 2.2)">0</text> + <polyline points="0,0 2.5,0" stroke-width="0.3" stroke="#333" transform="rotate(-210) translate(17 0)" /> + <text font-size="5.0pt" transform="rotate(-145.13) translate(20.5 0) rotate(145.13) translate(-4.7 2.2)">0.1</text> + <polyline points="0,0 2.5,0" stroke-width="0.3" stroke="#333" transform="rotate(-105.84) translate(17 0)" /> + <polyline points="0,0 2.5,0" stroke-width="0.3" stroke="#333" transform="rotate(-75.86) translate(17 0)" /> + <polyline points="0,0 2.5,0" stroke-width="0.3" stroke="#333" transform="rotate(-50.26) translate(17 0)" /> + <polyline points="0,0 3.5,0" stroke-width="1" stroke="#333" transform="rotate(-27.87) translate(17 0)" /> + <polyline points="0,0 2.5,0" stroke-width="0.3" stroke="#333" transform="rotate(-7.62) translate(17 0)" /> + <polyline points="0,0 2.5,0" stroke-width="0.3" stroke="#333" transform="rotate(11) translate(17 0)" /> + <polyline points="0,0 2.5,0" stroke-width="0.3" stroke="#333" transform="rotate(28.33) translate(17 0)" /> + <polyline points="0,0 2.5,0" stroke-width="0.3" stroke="#333" transform="rotate(44.6) translate(17 0)" /> + <text font-size="5.0pt" transform="rotate(60) translate(20 0) rotate(-60) translate(-1.8 2.2)">1</text> + </g> + </symbol> + + <symbol id="knobguide-voltage" viewBox="0 0 90px 45px"> + <!-- <rect width="90" height="45" fill="#f003" transform="translate(0 0)" /> --> + <g transform="translate(8 22.5)"> + <text font-size="5.0pt" transform="rotate(-22.5) translate(14 0) rotate(22.5) translate(-1 2.6)">0-10V</text> + <polyline points="0,0 2,0" stroke-width="1" stroke="#333" transform="rotate(-22.5) translate(9.5 0)" /> + <text font-size="5.0pt" transform="rotate(22.5) translate(14 0) rotate(-22.5) translate(-1 2.0)">+/-5V</text> + <polyline points="0,0 2,0" stroke-width="1" stroke="#333" transform="rotate(22.5) translate(9.5 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 89,1 89,379 1,379 1,1" stroke="#e4e4e4" stroke-width="0.5" fill="none" /> + <polyline points="0.5,0.5 89.5,0.5 89.5,379.5 0.5,379.5 0.5,0.5" stroke="#ebebeb" stroke-width="0.8" fill="none" /> + <polyline points="0,0 90,0 90,380 0,380 0,0" stroke="#f2f2f2" stroke-width="1" fill="none" /> + + <text class="title" x="45" y="17" font-size="9pt" letter-spacing="3px">CMP</text> + <g transform="translate(5.5 374)"> + <text class="brand" font-size="6.5pt" letter-spacing="2px">BOGAUDIO</text> + <rect width="1.5" height="2" fill="#ddd" transform="translate(21 -4)" /> + </g> + + <!-- <rect width="90" height="12" fill="#0f0" transform="translate(0 122)" /> --> + <!-- <rect width="90" height="12" fill="#0f0" transform="translate(0 228)" /> --> + <!-- <rect width="90" height="12" fill="#0f0" transform="translate(0 267)" /> --> + + <g transform="translate(0 35)"> + <text font-size="6pt" letter-spacing="1px" transform="translate(20 0)">A</text> + <use id="A_PARAM" xlink:href="#knob" transform="translate(0 3)" /> + <use xlink:href="#knobguide-offset" transform="translate(0 3)" /> + <g transform="translate(5.5 49)"> + <rect width="34" height="38" rx="5" fill="#fafafa" /> + <use id="A_INPUT" xlink:href="#input" transform="translate(5 3)" /> + <text font-size="5pt" letter-spacing="2px" transform="translate(13 35)">IN</text> + </g> + </g> + + <g transform="translate(45 35)"> + <text font-size="6pt" letter-spacing="1px" transform="translate(20 0)">B</text> + <use id="B_PARAM" xlink:href="#knob" transform="translate(0 3)" /> + <use xlink:href="#knobguide-offset" transform="translate(0 3)" /> + <g transform="translate(5.5 49)"> + <rect width="34" height="38" rx="5" fill="#fafafa" /> + <use id="B_INPUT" xlink:href="#input" transform="translate(5 3)" /> + <text font-size="5pt" letter-spacing="2px" transform="translate(13 35)">IN</text> + </g> + </g> + + <g transform="translate(0 140)"> + <text font-size="6pt" letter-spacing="1px" transform="translate(3.5 0)">WINDOW</text> + <use id="WINDOW_PARAM" xlink:href="#knob" transform="translate(0 3)" /> + <use xlink:href="#knobguide-window" transform="translate(0 3)" /> + <g transform="translate(5.5 49)"> + <rect width="34" height="38" rx="5" fill="#fafafa" /> + <use id="WINDOW_INPUT" xlink:href="#input" transform="translate(5 3)" /> + <text font-size="5pt" letter-spacing="2px" transform="translate(11 35)">CV</text> + </g> + </g> + + <g transform="translate(45 140)"> + <text font-size="6pt" letter-spacing="1px" transform="translate(14 0)">LAG</text> + <use id="LAG_PARAM" xlink:href="#knob" transform="translate(0 3)" /> + <use xlink:href="#knobguide-lag" transform="translate(0 3)" /> + <g transform="translate(5.5 49)"> + <rect width="34" height="38" rx="5" fill="#fafafa" /> + <use id="LAG_INPUT" xlink:href="#input" transform="translate(5 3)" /> + <text font-size="5pt" letter-spacing="2px" transform="translate(11 35)">CV</text> + </g> + </g> + + <g transform="translate(25 239)"> + <!-- <rect width="40" height="32" fill="#0f03" transform="translate(0 0)" /> --> + <text font-size="6pt" letter-spacing="1px" transform="translate(1.5 7)">OUTPUT</text> + <use id="OUTPUT_PARAM" xlink:href="#knob-smallest" transform="translate(0.5 12)" /> + <use xlink:href="#knobguide-voltage" transform="translate(0.5 -2.5)" /> + </g> + + <g transform="translate(11 279)"> + <rect width="68" height="77" rx="5" fill="#bbb" /> + <use id="GREATER_OUTPUT" xlink:href="#output" transform="translate(5 4)" /> + <text font-size="8pt" letter-spacing="2px" style="font-weight: normal" transform="translate(15 36.5)">&gt;</text> + <use id="LESS_OUTPUT" xlink:href="#output" transform="translate(39 4)" /> + <text font-size="8pt" letter-spacing="2px" style="font-weight: normal" transform="translate(48 36.5)">&lt;</text> + <use id="EQUAL_OUTPUT" xlink:href="#output" transform="translate(5 40)" /> + <text font-size="5pt" letter-spacing="2px" transform="translate(12 72)">EQ</text> + <use id="NOT_EQUAL_OUTPUT" xlink:href="#output" transform="translate(39 40)" /> + <text font-size="5pt" letter-spacing="2px" transform="translate(42 72)">NOT</text> + </g> +</svg> diff --git a/res/Cmp.svg b/res/Cmp.svg Binary files differ. diff --git a/src/Cmp.cpp b/src/Cmp.cpp @@ -0,0 +1,216 @@ + +#include "Cmp.hpp" + +void Cmp::onReset() { + _thresholdState = LOW; + _windowState = LOW; +} + +void Cmp::step() { + if (!( + outputs[GREATER_OUTPUT].active || + outputs[LESS_OUTPUT].active || + outputs[EQUAL_OUTPUT].active || + outputs[NOT_EQUAL_OUTPUT].active + )) { + return; + } + + float a = params[A_PARAM].value * 10.0f; + if (inputs[A_INPUT].active) { + a = clamp(a + inputs[A_INPUT].value, -12.0f, 12.0f); + } + + float b = params[B_PARAM].value * 10.0f; + if (inputs[B_INPUT].active) { + b = clamp(b + inputs[B_INPUT].value, -12.0f, 12.0f); + } + + float window = params[WINDOW_PARAM].value; + if (inputs[WINDOW_INPUT].active) { + window *= clamp(inputs[WINDOW_INPUT].value / 10.0f, 0.0f, 1.0f); + } + window *= 10.0f; + + float high = 10.0f; + float low = 0.0f; + if (params[OUTPUT_PARAM].value > 0.5f) { + high = 5.0f; + low = -5.0f; + } + + int lag = -1; + stepChannel( + a >= b, + high, + low, + _thresholdState, + _thresholdLag, + lag, + outputs[GREATER_OUTPUT], + outputs[LESS_OUTPUT] + ); + stepChannel( + abs(a - b) <= window, + high, + low, + _windowState, + _windowLag, + lag, + outputs[EQUAL_OUTPUT], + outputs[NOT_EQUAL_OUTPUT] + ); +} + +void Cmp::stepChannel( + bool high, + float highValue, + float lowValue, + State& state, + int& channelLag, + int& lag, + Output& highOutput, + Output& lowOutput +) { + switch (state) { + case LOW: { + if (high) { + if (lag < 0) { + lag = lagInSamples(); + } + if (lag < 1) { + state = HIGH; + } + else { + state = LAG_HIGH; + channelLag = lag; + } + } + break; + } + case HIGH: { + if (!high) { + if (lag < 0) { + lag = lagInSamples(); + } + if (lag < 1) { + state = LOW; + } + else { + state = LAG_LOW; + channelLag = lag; + } + } + break; + } + case LAG_LOW: { + if (!high) { + --channelLag; + if(channelLag == 0) { + state = LOW; + } + } + else { + state = HIGH; + } + break; + } + case LAG_HIGH: { + if (high) { + --channelLag; + if(channelLag == 0) { + state = HIGH; + } + } + else { + state = LOW; + } + break; + } + }; + + switch (state) { + case LOW: + case LAG_HIGH: { + highOutput.value = lowValue; + lowOutput.value = highValue; + break; + } + case HIGH: + case LAG_LOW: { + highOutput.value = highValue; + lowOutput.value = lowValue; + break; + } + } +} + +int Cmp::lagInSamples() { + float lag = params[LAG_PARAM].value; + if (inputs[LAG_INPUT].active) { + lag *= clamp(inputs[LAG_INPUT].value / 10.0f, 0.0f, 1.0f); + } + return lag * lag * engineGetSampleRate(); +} + +struct CmpWidget : ModuleWidget { + static constexpr int hp = 6; + + CmpWidget(Cmp* 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/Cmp.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 aParamPosition = Vec(8.0, 46.0); + auto bParamPosition = Vec(53.0, 46.0); + auto windowParamPosition = Vec(8.0, 151.0); + auto lagParamPosition = Vec(53.0, 151.0); + auto outputParamPosition = Vec(25.5, 251.0); + + auto aInputPosition = Vec(10.5, 87.0); + auto bInputPosition = Vec(55.5, 87.0); + auto windowInputPosition = Vec(10.5, 192.0); + auto lagInputPosition = Vec(55.5, 192.0); + + auto greaterOutputPosition = Vec(16.0, 283.0); + auto lessOutputPosition = Vec(50.0, 283.0); + auto equalOutputPosition = Vec(16.0, 319.0); + auto notEqualOutputPosition = Vec(50.0, 319.0); + // end generated by svg_widgets.rb + + addParam(ParamWidget::create<Knob29>(aParamPosition, module, Cmp::A_PARAM, -1.0, 1.0, 0.0)); + addParam(ParamWidget::create<Knob29>(bParamPosition, module, Cmp::B_PARAM, -1.0, 1.0, 0.0)); + addParam(ParamWidget::create<Knob29>(windowParamPosition, module, Cmp::WINDOW_PARAM, 0.0, 1.0, 0.5)); + addParam(ParamWidget::create<Knob29>(lagParamPosition, module, Cmp::LAG_PARAM, 0.0, 1.0, 0.1)); + { + auto w = ParamWidget::create<Knob16>(outputParamPosition, module, Cmp::OUTPUT_PARAM, 0.0, 1.0, 0.0); + auto k = dynamic_cast<SVGKnob*>(w); + k->snap = true; + k->minAngle = 3.0f * (M_PI / 8.0f); + k->maxAngle = 5.0f * (M_PI / 8.0f); + k->speed = 3.0; + addParam(w); + } + + addInput(Port::create<Port24>(aInputPosition, Port::INPUT, module, Cmp::A_INPUT)); + addInput(Port::create<Port24>(bInputPosition, Port::INPUT, module, Cmp::B_INPUT)); + addInput(Port::create<Port24>(windowInputPosition, Port::INPUT, module, Cmp::WINDOW_INPUT)); + addInput(Port::create<Port24>(lagInputPosition, Port::INPUT, module, Cmp::LAG_INPUT)); + + addOutput(Port::create<Port24>(greaterOutputPosition, Port::OUTPUT, module, Cmp::GREATER_OUTPUT)); + addOutput(Port::create<Port24>(lessOutputPosition, Port::OUTPUT, module, Cmp::LESS_OUTPUT)); + addOutput(Port::create<Port24>(equalOutputPosition, Port::OUTPUT, module, Cmp::EQUAL_OUTPUT)); + addOutput(Port::create<Port24>(notEqualOutputPosition, Port::OUTPUT, module, Cmp::NOT_EQUAL_OUTPUT)); + } +}; + +Model* modelCmp = createModel<Cmp, CmpWidget>("Bogaudio-Cmp", "CMP", "comparator", LOGIC_TAG); diff --git a/src/Cmp.hpp b/src/Cmp.hpp @@ -0,0 +1,70 @@ +#pragma once + +#include "bogaudio.hpp" + +extern Model* modelCmp; + +namespace bogaudio { + +struct Cmp : Module { + enum ParamsIds { + A_PARAM, + B_PARAM, + WINDOW_PARAM, + LAG_PARAM, + OUTPUT_PARAM, + NUM_PARAMS + }; + + enum InputsIds { + A_INPUT, + B_INPUT, + WINDOW_INPUT, + LAG_INPUT, + NUM_INPUTS + }; + + enum OutputsIds { + GREATER_OUTPUT, + LESS_OUTPUT, + EQUAL_OUTPUT, + NOT_EQUAL_OUTPUT, + NUM_OUTPUTS + }; + + enum LightsIds { + NUM_LIGHTS + }; + + enum State { + LOW, + HIGH, + LAG_LOW, + LAG_HIGH + }; + + State _thresholdState; + int _thresholdLag = 0; + State _windowState; + int _windowLag = 0; + + Cmp() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) { + onReset(); + } + + void onReset() override; + void step() override; + void stepChannel( + bool high, + float highValue, + float lowValue, + State& state, + int& channelLag, + int& lag, + Output& highOutput, + Output& lowOutput + ); + int lagInSamples(); +}; + +} // namespace bogaudio diff --git a/src/bogaudio.cpp b/src/bogaudio.cpp @@ -7,6 +7,7 @@ #include "AMRM.hpp" #include "Analyzer.hpp" #include "Bool.hpp" +#include "Cmp.hpp" #include "CVD.hpp" #include "DADSRH.hpp" #include "DADSRHPlus.hpp" @@ -100,6 +101,9 @@ void init(rack::Plugin *p) { p->addModel(modelReftone); p->addModel(modelBool); +#ifdef EXPERIMENTAL + p->addModel(modelCmp); +#endif p->addModel(modelCVD); p->addModel(modelFlipFlop); p->addModel(modelManual);