BogaudioModules

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

commit 450e09c25b0c9dba336df52153015dba4168ce32
parent 22df3b7e1afbe03176536209bd51905127c974f4
Author: Matt Demanett <matt@demanett.net>
Date:   Sun,  7 Jun 2020 01:49:47 -0400

MIX2: stereo MIX1.

Diffstat:
Mplugin.json | 12+++++++++++-
Ares-src/Mix2-src.svg | 138+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ares/Mix2.svg | 0
Msrc/Mix1.cpp | 2+-
Asrc/Mix2.cpp | 112+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/Mix2.hpp | 75+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/bogaudio.cpp | 2++
Msrc/widgets.cpp | 22+++++++++++++++++++---
Msrc/widgets.hpp | 8++++++--
9 files changed, 364 insertions(+), 7 deletions(-)

diff --git a/plugin.json b/plugin.json @@ -346,9 +346,19 @@ ] }, { + "slug": "Bogaudio-Mix2", + "name": "MIX2", + "description": "Stereo fader/amplifier with CV-controllable mute", + "manualUrl": "https://github.com/bogaudio/BogaudioModules/blob/master/README.md#mix2", + "tags": [ + "VCA", + "Polyphonic" + ] + }, + { "slug": "Bogaudio-Mix1", "name": "MIX1", - "description": "Fader/amplifier with CV controllable mute", + "description": "Fader/amplifier with CV-controllable mute", "manualUrl": "https://github.com/bogaudio/BogaudioModules/blob/master/README.md#mix1", "tags": [ "VCA", diff --git a/res-src/Mix2-src.svg b/res-src/Mix2-src.svg @@ -0,0 +1,138 @@ +<svg + version="1.1" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + width="75" + height="380" + viewBox="0 0 75 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="slider" viewBox="0 0 18px 151x"> + <rect width="18" height="151" fill="none" /> + <rect width="6" height="145" x="6" y="3" rx="2" stroke-width="1" stroke="#888" fill="#222" /> + <g transform="translate(0 40)"> + <rect width="18" height="13" rx="1.5" fill="#777" /> + <rect width="18" height="9" x="0" y="2" fill="#444" /> + <polyline points="0,6.5 18,6.5" stroke="#fafafa" stroke-width="1" fill="none" /> + <rect width="14" height="5" x="2" y="4" rx="1.0" fill="#ddd" transform="translate(0 0)" /> + </g> + </symbol> + + <symbol id="sliderguide-db" viewBox="0 0 20px 151px"> + <g transform="translate(0 6.5)"> + <polyline points="0,0 6.5,0" stroke="#333" fill="none" transform="translate(10.5 0)" /> + <polyline points="0,0 6.5,0" stroke="#333" fill="none" transform="translate(28 0)" /> + </g> + <g transform="translate(0 19.05)"> + <polyline points="0,0 6.5,0" stroke="#333" fill="none" transform="translate(10.5 0)" /> + <polyline points="0,0 6.5,0" stroke="#333" fill="none" transform="translate(28 0)" /> + <text font-size="6.0pt" transform="translate(7 0) rotate(0) translate(-2.5 2.6)">0</text> + </g> + <g transform="translate(0 32.86)"> + <polyline points="0,0 6.5,0" stroke="#333" fill="none" transform="translate(10.5 0)" /> + <polyline points="0,0 6.5,0" stroke="#333" fill="none" transform="translate(28 0)" /> + <text font-size="6.0pt" transform="translate(7 0) rotate(-90) translate(-4 2.2)">-6</text> + </g> + <g transform="translate(0 46.05)"> + <polyline points="0,0 6.5,0" stroke="#333" fill="none" transform="translate(10.5 0)" /> + <polyline points="0,0 6.5,0" stroke="#333" fill="none" transform="translate(28 0)" /> + <text font-size="6.0pt" transform="translate(7 0) rotate(-90) translate(-7 2.2)">-12</text> + </g> + <g transform="translate(0 72.41)"> + <polyline points="0,0 6.5,0" stroke="#333" fill="none" transform="translate(10.5 0)" /> + <polyline points="0,0 6.5,0" stroke="#333" fill="none" transform="translate(28 0)" /> + <text font-size="6.0pt" transform="translate(7 0) rotate(-90) translate(-7 2.2)">-24</text> + </g> + <g transform="translate(0 125.14)"> + <polyline points="0,0 6.5,0" stroke="#333" fill="none" transform="translate(10.5 0)" /> + <polyline points="0,0 6.5,0" stroke="#333" fill="none" transform="translate(28 0)" /> + <text font-size="6.0pt" transform="translate(7 0) rotate(-90) translate(-7 2.2)">-48</text> + </g> + <g transform="translate(0 151.5)"> + <!-- <polyline points="0,0 6.5,0" stroke="#333" fill="none" transform="translate(10.5 0)" /> --> + <text font-size="6.0pt" transform="translate(7 -10) rotate(-90) translate(-9 4)">dB</text> + </g> + </symbol> + + <symbol id="button" viewBox="0 0 20px 20px"> + <g transform="translate(10 10)"> + <circle cx="0" cy="0" r="8.8" stroke-width="1" stroke="#00f" fill="#f00" /> + </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 75,1 75,379 1,379 1,1" stroke="#e4e4e4" stroke-width="0.5" fill="none" /> + <polyline points="0.5,0.5 75.5,0.5 75.5,379.5 0.5,379.5 0.5,0.5" stroke="#ebebeb" stroke-width="0.8" fill="none" /> + <polyline points="0,0 75,0 75,380 0,380 0,0" stroke="#f2f2f2" stroke-width="1" fill="none" /> + + <text class="title" x="30" y="17" font-size="9pt" letter-spacing="3px">MIX2</text> + <g transform="translate(5.5 374)"> + <text class="brand" font-size="6.5pt" letter-spacing="2px">BGA</text> + <rect width="2" height="2" fill="#ddd" transform="translate(11.5 -4)" /> + </g> + + <g transform="translate(0 32)"> + <use xlink:href="#sliderguide-db" transform="translate(15 0)" /> + <use id="LEVEL_PARAM" xlink:href="#slider" transform="translate(28.5 0)" /> + </g> + + <g transform="translate(15 197)"> + <use id="MUTE_PARAM" xlink:href="#button" transform="translate(12.5 0)" /> + <text font-size="5pt" letter-spacing="2px" transform="translate(10 27)">MUTE</text> + </g> + + <g transform="translate(0 240)"> + <g transform="translate(5.5 0)"> + <rect width="64" height="10" fill="#fafafa" transform="translate(0 66)" /> + <rect width="64" height="73" rx="5" fill="#fafafa" /> + <!-- <use id="MUTE_PARAM" xlink:href="#button" transform="translate(7 2)" /> --> + <use id="LEVEL_INPUT" xlink:href="#input" transform="translate(5 4)" /> + <text font-size="5pt" letter-spacing="1.5px" transform="translate(4.5 36)">LEVEL</text> + <use id="MUTE_INPUT" xlink:href="#input" transform="translate(35 4)" /> + <text font-size="5pt" letter-spacing="1.5px" transform="translate(35.5 36)">MUTE</text> + <use id="L_INPUT" xlink:href="#input" transform="translate(5 40)" /> + <text font-size="5pt" letter-spacing="2px" transform="translate(15 72)">L</text> + <use id="R_INPUT" xlink:href="#input" transform="translate(35 40)" /> + <text font-size="5pt" letter-spacing="0.5px" transform="translate(39 72)">R (L)</text> + </g> + <g transform="translate(5.5 79)"> + <rect width="64" height="10" fill="#bbb" transform="translate(0 -3)" /> + <rect width="64" height="37" rx="5" fill="#bbb" /> + <use id="L_OUTPUT" xlink:href="#output" transform="translate(5 1)" /> + <text font-size="5pt" letter-spacing="2px" transform="translate(15 33)">L</text> + <use id="R_OUTPUT" xlink:href="#output" transform="translate(35 1)" /> + <text font-size="5pt" letter-spacing="2px" transform="translate(45 33)">R</text> + </g> + </g> +</svg> diff --git a/res/Mix2.svg b/res/Mix2.svg Binary files differ. diff --git a/src/Mix1.cpp b/src/Mix1.cpp @@ -93,4 +93,4 @@ struct Mix1Widget : ModuleWidget { } }; -Model* modelMix1 = bogaudio::createModel<Mix1, Mix1Widget>("Bogaudio-Mix1", "MIX1", "Fader/amplifier with CV controllable mute", "VCA", "Polyphonic"); +Model* modelMix1 = bogaudio::createModel<Mix1, Mix1Widget>("Bogaudio-Mix1", "MIX1", "Fader/amplifier with CV-controllable mute", "VCA", "Polyphonic"); diff --git a/src/Mix2.cpp b/src/Mix2.cpp @@ -0,0 +1,112 @@ + +#include "Mix2.hpp" + +void Mix2::sampleRateChange() { + float sr = APP->engine->getSampleRate(); + for (int c = 0; c < _channels; ++c) { + _engines[c]->left.setSampleRate(sr); + _engines[c]->right.setSampleRate(sr); + } +} + +bool Mix2::active() { + return outputs[L_OUTPUT].isConnected() || outputs[R_OUTPUT].isConnected(); +} + +int Mix2::channels() { + return inputs[L_INPUT].getChannels(); +} + +void Mix2::addChannel(int c) { + _engines[c] = new Engine( + params[LEVEL_PARAM], + params[MUTE_PARAM], + inputs[LEVEL_INPUT], + inputs[MUTE_INPUT] + ); +} + +void Mix2::removeChannel(int c) { + delete _engines[c]; + _engines[c] = NULL; +} + +void Mix2::processAlways(const ProcessArgs& args) { + _leftRmsSum = 0.0f; + _rightRmsSum = 0.0f; +} + +void Mix2::processChannel(const ProcessArgs& args, int c) { + Engine& e = *_engines[c]; + + float left = inputs[L_INPUT].getVoltage(c); + e.left.next(left, false, c); + _leftRmsSum += e.left.rms; + outputs[L_OUTPUT].setChannels(_channels); + outputs[L_OUTPUT].setVoltage(e.left.out, c); + + float right = left; + if (inputs[R_INPUT].isConnected()) { + right = inputs[R_INPUT].getVoltage(c); + } + e.right.next(right, false, c); + _rightRmsSum += e.right.rms; + outputs[R_OUTPUT].setChannels(_channels); + outputs[R_OUTPUT].setVoltage(e.right.out, c); +} + +void Mix2::postProcessAlways(const ProcessArgs& args) { + _leftRms = _leftRmsSum / (float)_channels; + _rightRms = _rightRmsSum / (float)_channels; +} + +struct Mix2Widget : ModuleWidget { + static constexpr int hp = 5; + + Mix2Widget(Mix2* module) { + setModule(module); + box.size = Vec(RACK_GRID_WIDTH * hp, RACK_GRID_HEIGHT); + + { + SvgPanel *panel = new SvgPanel(); + panel->box.size = box.size; + panel->setBackground(APP->window->loadSvg(asset::plugin(pluginInstance, "res/Mix2.svg"))); + addChild(panel); + } + + addChild(createWidget<ScrewSilver>(Vec(0, 0))); + addChild(createWidget<ScrewSilver>(Vec(box.size.x - 15, 365))); + + // generated by svg_widgets.rb + auto levelParamPosition = Vec(28.5, 32.0); + auto muteParamPosition = Vec(28.2, 197.7); + + auto levelInputPosition = Vec(10.5, 244.0); + auto muteInputPosition = Vec(40.5, 244.0); + auto lInputPosition = Vec(10.5, 280.0); + auto rInputPosition = Vec(40.5, 280.0); + + auto lOutputPosition = Vec(10.5, 320.0); + auto rOutputPosition = Vec(40.5, 320.0); + // end generated by svg_widgets.rb + + { + auto slider = createParam<VUSlider151>(levelParamPosition, module, Mix2::LEVEL_PARAM); + if (module) { + dynamic_cast<VUSlider*>(slider)->setVULevel(&module->_leftRms); + dynamic_cast<VUSlider*>(slider)->setStereoVULevel(&module->_rightRms); + } + addParam(slider); + } + addParam(createParam<MuteButton>(muteParamPosition, module, Mix2::MUTE_PARAM)); + + addInput(createInput<Port24>(levelInputPosition, module, Mix2::LEVEL_INPUT)); + addInput(createInput<Port24>(muteInputPosition, module, Mix2::MUTE_INPUT)); + addInput(createInput<Port24>(lInputPosition, module, Mix2::L_INPUT)); + addInput(createInput<Port24>(rInputPosition, module, Mix2::R_INPUT)); + + addOutput(createOutput<Port24>(lOutputPosition, module, Mix2::L_OUTPUT)); + addOutput(createOutput<Port24>(rOutputPosition, module, Mix2::R_OUTPUT)); } +}; + +Model* modelMix2 = createModel<Mix2, Mix2Widget>("Bogaudio-Mix2", "MIX2", "Stereo fader/amplifier with CV-controllable mute", "VCA", "Polyphonic"); diff --git a/src/Mix2.hpp b/src/Mix2.hpp @@ -0,0 +1,75 @@ +#pragma once + +#include "bogaudio.hpp" +#include "mixer.hpp" +#include "dsp/signal.hpp" + +using namespace bogaudio::dsp; + +extern Model* modelMix2; + +namespace bogaudio { + +struct Mix2 : BGModule { + enum ParamsIds { + LEVEL_PARAM, + MUTE_PARAM, + NUM_PARAMS + }; + + enum InputsIds { + LEVEL_INPUT, + MUTE_INPUT, + L_INPUT, + R_INPUT, + NUM_INPUTS + }; + + enum OutputsIds { + L_OUTPUT, + R_OUTPUT, + NUM_OUTPUTS + }; + + struct Engine { + MixerChannel left; + MixerChannel right; + + Engine( + Param& levelParam, + Param& muteParam, + Input& levelInput, + Input& muteInput + ) + : left(levelParam, muteParam, levelInput, 1000.0f, &muteInput) + , right(levelParam, muteParam, levelInput, 1000.0f, &muteInput) + { + float sr = APP->engine->getSampleRate(); + left.setSampleRate(sr); + right.setSampleRate(sr); + } + }; + + Engine* _engines[maxChannels] {}; + float _leftRmsSum = 0.0f; + float _leftRms = 0.0f; + float _rightRmsSum = 0.0f; + float _rightRms = 0.0f; + + Mix2() { + config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS); + configParam(LEVEL_PARAM, 0.0f, 1.0f, fabsf(MixerChannel::minDecibels) / (MixerChannel::maxDecibels - MixerChannel::minDecibels), "Level", "dB", 0.0f, MixerChannel::maxDecibels - MixerChannel::minDecibels, MixerChannel::minDecibels); + configParam(MUTE_PARAM, 0.0f, 1.0f, 0.0f, "Mute"); + } + + void sampleRateChange() override; + bool active() override; + int channels() override; + void addChannel(int c) override; + void removeChannel(int c) override; + void processAlways(const ProcessArgs& args) override; + void processChannel(const ProcessArgs& args, int c) override; + void postProcessAlways(const ProcessArgs& args) override; +}; + +} // namespace bogaudio diff --git a/src/bogaudio.cpp b/src/bogaudio.cpp @@ -41,6 +41,7 @@ #include "Matrix44.hpp" #include "Matrix88.hpp" #include "Mix1.hpp" +#include "Mix2.hpp" #include "Mix4.hpp" #include "Mix8.hpp" #include "Mono.hpp" @@ -136,6 +137,7 @@ void init(rack::Plugin *p) { p->addModel(modelMix8x); p->addModel(modelMix4); p->addModel(modelMix4x); + p->addModel(modelMix2); p->addModel(modelMix1); p->addModel(modelVCM); p->addModel(modelMute8); diff --git a/src/widgets.cpp b/src/widgets.cpp @@ -485,11 +485,27 @@ void VUSlider::draw(const DrawArgs& args) { nvgFill(args.vg); float db = _vuLevel ? *_vuLevel : 0.0f; + bool stereo = false; + float stereoDb = 0.0f; + if (_stereoVuLevel) { + stereo = true; + stereoDb = *_stereoVuLevel; + } if (db > 0.0f) { - db = amplitudeToDecibels(db); nvgBeginPath(args.vg); - nvgRoundedRect(args.vg, 2, 4, 14, 5, 1.0); - nvgFillColor(args.vg, decibelsToColor(db)); + if (stereo) { + nvgRoundedRect(args.vg, 2, 4, stereo ? 7 : 14, 5, 1.0); + } + else { + nvgRoundedRect(args.vg, 2, 4, 14, 5, 1.0); + } + nvgFillColor(args.vg, decibelsToColor(amplitudeToDecibels(db))); + nvgFill(args.vg); + } + if (stereo) { + nvgBeginPath(args.vg); + nvgRoundedRect(args.vg, 9, 4, 7, 5, 1.0); + nvgFillColor(args.vg, decibelsToColor(amplitudeToDecibels(stereoDb))); nvgFill(args.vg); } } diff --git a/src/widgets.hpp b/src/widgets.hpp @@ -160,13 +160,17 @@ NVGcolor decibelsToColor(float db); struct VUSlider : SliderKnob { const float slideHeight = 13.0f; float* _vuLevel = NULL; + float* _stereoVuLevel = NULL; VUSlider(float height = 183.0f) { box.size = Vec(18.0f, height); } - void setVULevel(float* vuLevel) { - _vuLevel = vuLevel; + inline void setVULevel(float* level) { + _vuLevel = level; + } + inline void setStereoVULevel(float* level) { + _stereoVuLevel = level; } void draw(const DrawArgs& args) override; };