BogaudioModules

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

commit c8da607e9cf326c20a7c2639535f48c4361a5a30
parent 8ebc14df5044e2320340912fc9a86115bb49f7cf
Author: Matt Demanett <matt@demanett.net>
Date:   Wed, 24 Jun 2020 22:03:54 -0400

Reorganize code for modules with expanders.

Diffstat:
Msrc/Mix4.cpp | 210-------------------------------------------------------------------------------
Msrc/Mix4.hpp | 125+------------------------------------------------------------------------------
Asrc/Mix4_shared.hpp | 14++++++++++++++
Asrc/Mix4x.cpp | 211+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/Mix4x.hpp | 124+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/Mix8.cpp | 282-------------------------------------------------------------------------------
Msrc/Mix8.hpp | 193+------------------------------------------------------------------------------
Asrc/Mix8_shared.hpp | 14++++++++++++++
Asrc/Mix8x.cpp | 283+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/Mix8x.hpp | 191+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/Pgmr.cpp | 212-------------------------------------------------------------------------------
Msrc/Pgmr.hpp | 184+------------------------------------------------------------------------------
Asrc/PgmrX.cpp | 137+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/PgmrX.hpp | 99+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/Pgmr_shared.cpp | 79+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/Pgmr_shared.hpp | 97+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/bogaudio.cpp | 3+++
17 files changed, 1255 insertions(+), 1203 deletions(-)

diff --git a/src/Mix4.cpp b/src/Mix4.cpp @@ -265,213 +265,3 @@ struct Mix4Widget : ModuleWidget { }; Model* modelMix4 = bogaudio::createModel<Mix4, Mix4Widget>("Bogaudio-Mix4", "MIX4", "4-channel mixer and panner", "Mixer", "Panning"); - - -void Mix4x::sampleRateChange() { - float sr = APP->engine->getSampleRate(); - for (int i = 0; i < 4; ++i) { - _channels[i]->setSampleRate(sr); - } - _returnASL.setParams(sr, MixerChannel::levelSlewTimeMS, MixerChannel::maxDecibels - MixerChannel::minDecibels); - _returnBSL.setParams(sr, MixerChannel::levelSlewTimeMS, MixerChannel::maxDecibels - MixerChannel::minDecibels); -} - -void Mix4x::modulate() { - for (int i = 0; i < 4; ++i) { - _channels[i]->modulate(); - } -} - -void Mix4x::processAll(const ProcessArgs& args) { - if (!baseConnected()) { - outputs[SEND_A_OUTPUT].setVoltage(0.0f); - outputs[SEND_B_OUTPUT].setVoltage(0.0f); - return; - } - - Mix4ExpanderMessage* from = fromBase(); - Mix4ExpanderMessage* to = toBase(); - float sendA = 0.0f; - float sendB = 0.0f; - bool sendAActive = outputs[SEND_A_OUTPUT].isConnected(); - bool sendBActive = outputs[SEND_B_OUTPUT].isConnected(); - for (int i = 0; i < 4; ++i) { - if (from->active[i]) { - _channels[i]->next(from->preFader[i], from->postFader[i], sendAActive, sendBActive); - to->postEQ[i] = _channels[i]->postEQ; - sendA += _channels[i]->sendA; - sendB += _channels[i]->sendB; - } - else { - to->postEQ[i] = from->preFader[i]; - } - } - outputs[SEND_A_OUTPUT].setVoltage(_saturatorA.next(sendA)); - outputs[SEND_B_OUTPUT].setVoltage(_saturatorA.next(sendB)); - - bool lAActive = inputs[L_A_INPUT].isConnected(); - bool rAActive = inputs[R_A_INPUT].isConnected(); - if (lAActive || rAActive) { - float levelA = clamp(params[LEVEL_A_PARAM].getValue(), 0.0f, 1.0f); - if (inputs[LEVEL_A_INPUT].isConnected()) { - levelA *= clamp(inputs[LEVEL_A_INPUT].getVoltage() / 10.0f, 0.0f, 1.0f); - } - levelA = 1.0f - levelA; - levelA *= Amplifier::minDecibels; - _returnAAmp.setLevel(_returnASL.next(levelA)); - if (lAActive) { - to->returnA[0] = _returnAAmp.next(inputs[L_A_INPUT].getVoltage()); - } - else { - to->returnA[0] = 0.0f; - } - if (rAActive) { - to->returnA[1] = _returnAAmp.next(inputs[R_A_INPUT].getVoltage()); - } - else { - to->returnA[1] = to->returnA[0]; - } - } - - bool lBActive = inputs[L_B_INPUT].isConnected(); - bool rBActive = inputs[R_B_INPUT].isConnected(); - if (lBActive || rBActive) { - float levelB = clamp(params[LEVEL_B_PARAM].getValue(), 0.0f, 1.0f); - levelB = 1.0f - levelB; - levelB *= Amplifier::minDecibels; - _returnBAmp.setLevel(_returnBSL.next(levelB)); - if (lBActive) { - to->returnB[0] = _returnBAmp.next(inputs[L_B_INPUT].getVoltage()); - } - else { - to->returnB[0] = 0.0f; - } - if (rBActive) { - to->returnB[1] = _returnBAmp.next(inputs[R_B_INPUT].getVoltage()); - } - else { - to->returnB[1] = to->returnB[0]; - } - } -} - -struct Mix4xWidget : ModuleWidget { - static constexpr int hp = 15; - - Mix4xWidget(Mix4x* 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/Mix4x.svg"))); - addChild(panel); - } - - addChild(createWidget<ScrewSilver>(Vec(15, 0))); - addChild(createWidget<ScrewSilver>(Vec(box.size.x - 30, 0))); - addChild(createWidget<ScrewSilver>(Vec(15, 365))); - addChild(createWidget<ScrewSilver>(Vec(box.size.x - 30, 365))); - - // generated by svg_widgets.rb - auto low1ParamPosition = Vec(18.5, 43.0); - auto mid1ParamPosition = Vec(18.5, 89.0); - auto high1ParamPosition = Vec(18.5, 135.0); - auto a1ParamPosition = Vec(18.5, 180.0); - auto preA1ParamPosition = Vec(30.0, 208.0); - auto b1ParamPosition = Vec(18.5, 236.0); - auto preB1ParamPosition = Vec(30.0, 264.0); - auto low2ParamPosition = Vec(61.5, 43.0); - auto mid2ParamPosition = Vec(61.5, 89.0); - auto high2ParamPosition = Vec(61.5, 135.0); - auto a2ParamPosition = Vec(61.5, 180.0); - auto preA2ParamPosition = Vec(73.0, 208.0); - auto b2ParamPosition = Vec(61.5, 236.0); - auto preB2ParamPosition = Vec(73.0, 264.0); - auto low3ParamPosition = Vec(104.5, 43.0); - auto mid3ParamPosition = Vec(104.5, 89.0); - auto high3ParamPosition = Vec(104.5, 135.0); - auto a3ParamPosition = Vec(104.5, 180.0); - auto preA3ParamPosition = Vec(116.0, 208.0); - auto b3ParamPosition = Vec(104.5, 236.0); - auto preB3ParamPosition = Vec(116.0, 264.0); - auto low4ParamPosition = Vec(147.5, 43.0); - auto mid4ParamPosition = Vec(147.5, 89.0); - auto high4ParamPosition = Vec(147.5, 135.0); - auto a4ParamPosition = Vec(147.5, 180.0); - auto preA4ParamPosition = Vec(159.0, 208.0); - auto b4ParamPosition = Vec(147.5, 236.0); - auto preB4ParamPosition = Vec(159.0, 264.0); - auto levelAParamPosition = Vec(190.5, 138.0); - auto levelBParamPosition = Vec(190.5, 328.0); - - auto a1InputPosition = Vec(14.5, 290.0); - auto b1InputPosition = Vec(14.5, 325.0); - auto a2InputPosition = Vec(57.5, 290.0); - auto b2InputPosition = Vec(57.5, 325.0); - auto a3InputPosition = Vec(100.5, 290.0); - auto b3InputPosition = Vec(100.5, 325.0); - auto a4InputPosition = Vec(143.5, 290.0); - auto b4InputPosition = Vec(143.5, 325.0); - auto lAInputPosition = Vec(186.5, 62.0); - auto rAInputPosition = Vec(186.5, 97.0); - auto levelAInputPosition = Vec(186.5, 170.0); - auto lBInputPosition = Vec(186.5, 252.0); - auto rBInputPosition = Vec(186.5, 287.0); - - auto sendAOutputPosition = Vec(186.5, 24.0); - auto sendBOutputPosition = Vec(186.5, 214.0); - // end generated by svg_widgets.rb - - addParam(createParam<Knob16>(low1ParamPosition, module, Mix4x::LOW1_PARAM)); - addParam(createParam<Knob16>(mid1ParamPosition, module, Mix4x::MID1_PARAM)); - addParam(createParam<Knob16>(high1ParamPosition, module, Mix4x::HIGH1_PARAM)); - addParam(createParam<Knob16>(a1ParamPosition, module, Mix4x::A1_PARAM)); - addParam(createParam<IndicatorButtonGreen9>(preA1ParamPosition, module, Mix4x::PRE_A1_PARAM)); - addParam(createParam<Knob16>(b1ParamPosition, module, Mix4x::B1_PARAM)); - addParam(createParam<IndicatorButtonGreen9>(preB1ParamPosition, module, Mix4x::PRE_B1_PARAM)); - addParam(createParam<Knob16>(low2ParamPosition, module, Mix4x::LOW2_PARAM)); - addParam(createParam<Knob16>(mid2ParamPosition, module, Mix4x::MID2_PARAM)); - addParam(createParam<Knob16>(high2ParamPosition, module, Mix4x::HIGH2_PARAM)); - addParam(createParam<Knob16>(a2ParamPosition, module, Mix4x::A2_PARAM)); - addParam(createParam<IndicatorButtonGreen9>(preA2ParamPosition, module, Mix4x::PRE_A2_PARAM)); - addParam(createParam<Knob16>(b2ParamPosition, module, Mix4x::B2_PARAM)); - addParam(createParam<IndicatorButtonGreen9>(preB2ParamPosition, module, Mix4x::PRE_B2_PARAM)); - addParam(createParam<Knob16>(low3ParamPosition, module, Mix4x::LOW3_PARAM)); - addParam(createParam<Knob16>(mid3ParamPosition, module, Mix4x::MID3_PARAM)); - addParam(createParam<Knob16>(high3ParamPosition, module, Mix4x::HIGH3_PARAM)); - addParam(createParam<Knob16>(a3ParamPosition, module, Mix4x::A3_PARAM)); - addParam(createParam<IndicatorButtonGreen9>(preA3ParamPosition, module, Mix4x::PRE_A3_PARAM)); - addParam(createParam<Knob16>(b3ParamPosition, module, Mix4x::B3_PARAM)); - addParam(createParam<IndicatorButtonGreen9>(preB3ParamPosition, module, Mix4x::PRE_B3_PARAM)); - addParam(createParam<Knob16>(low4ParamPosition, module, Mix4x::LOW4_PARAM)); - addParam(createParam<Knob16>(mid4ParamPosition, module, Mix4x::MID4_PARAM)); - addParam(createParam<Knob16>(high4ParamPosition, module, Mix4x::HIGH4_PARAM)); - addParam(createParam<Knob16>(a4ParamPosition, module, Mix4x::A4_PARAM)); - addParam(createParam<IndicatorButtonGreen9>(preA4ParamPosition, module, Mix4x::PRE_A4_PARAM)); - addParam(createParam<Knob16>(b4ParamPosition, module, Mix4x::B4_PARAM)); - addParam(createParam<IndicatorButtonGreen9>(preB4ParamPosition, module, Mix4x::PRE_B4_PARAM)); - addParam(createParam<Knob16>(levelAParamPosition, module, Mix4x::LEVEL_A_PARAM)); - addParam(createParam<Knob16>(levelBParamPosition, module, Mix4x::LEVEL_B_PARAM)); - - addInput(createInput<Port24>(a1InputPosition, module, Mix4x::A1_INPUT)); - addInput(createInput<Port24>(b1InputPosition, module, Mix4x::B1_INPUT)); - addInput(createInput<Port24>(a2InputPosition, module, Mix4x::A2_INPUT)); - addInput(createInput<Port24>(b2InputPosition, module, Mix4x::B2_INPUT)); - addInput(createInput<Port24>(a3InputPosition, module, Mix4x::A3_INPUT)); - addInput(createInput<Port24>(b3InputPosition, module, Mix4x::B3_INPUT)); - addInput(createInput<Port24>(a4InputPosition, module, Mix4x::A4_INPUT)); - addInput(createInput<Port24>(b4InputPosition, module, Mix4x::B4_INPUT)); - addInput(createInput<Port24>(lAInputPosition, module, Mix4x::L_A_INPUT)); - addInput(createInput<Port24>(rAInputPosition, module, Mix4x::R_A_INPUT)); - addInput(createInput<Port24>(levelAInputPosition, module, Mix4x::LEVEL_A_INPUT)); - addInput(createInput<Port24>(lBInputPosition, module, Mix4x::L_B_INPUT)); - addInput(createInput<Port24>(rBInputPosition, module, Mix4x::R_B_INPUT)); - - addOutput(createOutput<Port24>(sendAOutputPosition, module, Mix4x::SEND_A_OUTPUT)); - addOutput(createOutput<Port24>(sendBOutputPosition, module, Mix4x::SEND_B_OUTPUT)); - } -}; - -Model* modelMix4x = createModel<Mix4x, Mix4xWidget>("Bogaudio-Mix4x", "MIX4X", "Expander for MIX4, adds EQs and sends", "Mixer", "Expander"); diff --git a/src/Mix4.hpp b/src/Mix4.hpp @@ -1,20 +1,11 @@ #pragma once -#include "bogaudio.hpp" -#include "mixer_expander.hpp" -#include "dsp/signal.hpp" +#include "Mix4_shared.hpp" using namespace bogaudio::dsp; -extern Model* modelMix4; -extern Model* modelMix4x; - namespace bogaudio { -struct Mix4x; - -typedef MixerExpanderMessage<4> Mix4ExpanderMessage; - struct Mix4 : ExpandableModule<Mix4ExpanderMessage, BGModule> { enum ParamsIds { LEVEL1_PARAM, @@ -109,118 +100,4 @@ struct Mix4 : ExpandableModule<Mix4ExpanderMessage, BGModule> { void processAll(const ProcessArgs& args) override; }; -struct Mix4x : ExpanderModule<Mix4ExpanderMessage, BGModule> { - enum ParamsIds { - LOW1_PARAM, - MID1_PARAM, - HIGH1_PARAM, - A1_PARAM, - PRE_A1_PARAM, - B1_PARAM, - PRE_B1_PARAM, - LOW2_PARAM, - MID2_PARAM, - HIGH2_PARAM, - A2_PARAM, - PRE_A2_PARAM, - B2_PARAM, - PRE_B2_PARAM, - LOW3_PARAM, - MID3_PARAM, - HIGH3_PARAM, - A3_PARAM, - PRE_A3_PARAM, - B3_PARAM, - PRE_B3_PARAM, - LOW4_PARAM, - MID4_PARAM, - HIGH4_PARAM, - A4_PARAM, - PRE_A4_PARAM, - B4_PARAM, - PRE_B4_PARAM, - LEVEL_A_PARAM, - LEVEL_B_PARAM, - NUM_PARAMS - }; - - enum InputsIds { - A1_INPUT, - B1_INPUT, - A2_INPUT, - B2_INPUT, - A3_INPUT, - B3_INPUT, - A4_INPUT, - B4_INPUT, - L_A_INPUT, - R_A_INPUT, - LEVEL_A_INPUT, - L_B_INPUT, - R_B_INPUT, - NUM_INPUTS - }; - - enum OutputsIds { - SEND_A_OUTPUT, - SEND_B_OUTPUT, - NUM_OUTPUTS - }; - - MixerExpanderChannel* _channels[4] {}; - Saturator _saturatorA, _saturatorB; - Amplifier _returnAAmp, _returnBAmp; - bogaudio::dsp::SlewLimiter _returnASL, _returnBSL; - - Mix4x() { - config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS); - configParam<EQParamQuantity>(LOW1_PARAM, -1.0f, 1.0f, 0.0f, "Channel 1 low", " dB"); - configParam<EQParamQuantity>(MID1_PARAM, -1.0f, 1.0f, 0.0f, "Channel 1 mid", " dB"); - configParam<EQParamQuantity>(HIGH1_PARAM, -1.0f, 1.0f, 0.0f, "Channel 1 high", " dB"); - configParam<AmplifierParamQuantity>(A1_PARAM, 0.0f, 1.0f, 0.0f, "Channel 1 A send"); - configParam(PRE_A1_PARAM, 0.0f, 1.0f, 0.0f, "Channel 1 A send pre/post"); - configParam<AmplifierParamQuantity>(B1_PARAM, 0.0f, 1.0f, 0.0f, "Channel 1 B send"); - configParam(PRE_B1_PARAM, 0.0f, 1.0f, 0.0f, "Channel 1 B send pre/post"); - configParam<EQParamQuantity>(LOW2_PARAM, -1.0f, 1.0f, 0.0f, "Channel 2 low", " dB"); - configParam<EQParamQuantity>(MID2_PARAM, -1.0f, 1.0f, 0.0f, "Channel 2 mid", " dB"); - configParam<EQParamQuantity>(HIGH2_PARAM, -1.0f, 1.0f, 0.0f, "Channel 2 high", " dB"); - configParam<AmplifierParamQuantity>(A2_PARAM, 0.0f, 1.0f, 0.0f, "Channel 2 A send"); - configParam(PRE_A2_PARAM, 0.0f, 1.0f, 0.0f, "Channel 2 A send pre/post"); - configParam<AmplifierParamQuantity>(B2_PARAM, 0.0f, 1.0f, 0.0f, "Channel 2 B send"); - configParam(PRE_B2_PARAM, 0.0f, 1.0f, 0.0f, "Channel 2 B send pre/post"); - configParam<EQParamQuantity>(LOW3_PARAM, -1.0f, 1.0f, 0.0f, "Channel 3 low", " dB"); - configParam<EQParamQuantity>(MID3_PARAM, -1.0f, 1.0f, 0.0f, "Channel 3 mid", " dB"); - configParam<EQParamQuantity>(HIGH3_PARAM, -1.0f, 1.0f, 0.0f, "Channel 3 high", " dB"); - configParam<AmplifierParamQuantity>(A3_PARAM, 0.0f, 1.0f, 0.0f, "Channel 3 A send"); - configParam(PRE_A3_PARAM, 0.0f, 1.0f, 0.0f, "Channel 3 A send pre/post"); - configParam<AmplifierParamQuantity>(B3_PARAM, 0.0f, 1.0f, 0.0f, "Channel 3 B send"); - configParam(PRE_B3_PARAM, 0.0f, 1.0f, 0.0f, "Channel 3 B send pre/post"); - configParam<EQParamQuantity>(LOW4_PARAM, -1.0f, 1.0f, 0.0f, "Channel 4 low", " dB"); - configParam<EQParamQuantity>(MID4_PARAM, -1.0f, 1.0f, 0.0f, "Channel 4 mid", " dB"); - configParam<EQParamQuantity>(HIGH4_PARAM, -1.0f, 1.0f, 0.0f, "Channel 4 high", " dB"); - configParam<AmplifierParamQuantity>(A4_PARAM, 0.0f, 1.0f, 0.0f, "Channel 4 A send"); - configParam(PRE_A4_PARAM, 0.0f, 1.0f, 0.0f, "Channel 4 A send pre/post"); - configParam<AmplifierParamQuantity>(B4_PARAM, 0.0f, 1.0f, 0.0f, "Channel 4 B send"); - configParam(PRE_B4_PARAM, 0.0f, 1.0f, 0.0f, "Channel 4 B send pre/post"); - configParam<AmplifierParamQuantity>(LEVEL_A_PARAM, 0.0f, 1.0f, 0.8f, "A return level"); - configParam<AmplifierParamQuantity>(LEVEL_B_PARAM, 0.0f, 1.0f, 0.8f, "B return level"); - - _channels[0] = new MixerExpanderChannel(params[LOW1_PARAM], params[MID1_PARAM], params[HIGH1_PARAM], params[A1_PARAM], params[B1_PARAM], params[PRE_A1_PARAM], params[PRE_B1_PARAM], inputs[A1_INPUT], inputs[B1_INPUT]); - _channels[1] = new MixerExpanderChannel(params[LOW2_PARAM], params[MID2_PARAM], params[HIGH2_PARAM], params[A2_PARAM], params[B2_PARAM], params[PRE_A2_PARAM], params[PRE_B2_PARAM], inputs[A2_INPUT], inputs[B2_INPUT]); - _channels[2] = new MixerExpanderChannel(params[LOW3_PARAM], params[MID3_PARAM], params[HIGH3_PARAM], params[A3_PARAM], params[B3_PARAM], params[PRE_A3_PARAM], params[PRE_B3_PARAM], inputs[A3_INPUT], inputs[B3_INPUT]); - _channels[3] = new MixerExpanderChannel(params[LOW4_PARAM], params[MID4_PARAM], params[HIGH4_PARAM], params[A4_PARAM], params[B4_PARAM], params[PRE_A4_PARAM], params[PRE_B4_PARAM], inputs[A4_INPUT], inputs[B4_INPUT]); - - setBaseModel(modelMix4); - } - virtual ~Mix4x() { - for (int i = 0; i < 4; ++i) { - delete _channels[i]; - } - } - - void sampleRateChange() override; - void modulate() override; - void processAll(const ProcessArgs& args) override; -}; - } // namespace bogaudio diff --git a/src/Mix4_shared.hpp b/src/Mix4_shared.hpp @@ -0,0 +1,14 @@ +#pragma once + +#include "bogaudio.hpp" +#include "mixer_expander.hpp" +#include "dsp/signal.hpp" + +extern Model* modelMix4; +extern Model* modelMix4x; + +namespace bogaudio { + +typedef MixerExpanderMessage<4> Mix4ExpanderMessage; + +} // namespace bogaudio diff --git a/src/Mix4x.cpp b/src/Mix4x.cpp @@ -0,0 +1,211 @@ + +#include "Mix4x.hpp" + +void Mix4x::sampleRateChange() { + float sr = APP->engine->getSampleRate(); + for (int i = 0; i < 4; ++i) { + _channels[i]->setSampleRate(sr); + } + _returnASL.setParams(sr, MixerChannel::levelSlewTimeMS, MixerChannel::maxDecibels - MixerChannel::minDecibels); + _returnBSL.setParams(sr, MixerChannel::levelSlewTimeMS, MixerChannel::maxDecibels - MixerChannel::minDecibels); +} + +void Mix4x::modulate() { + for (int i = 0; i < 4; ++i) { + _channels[i]->modulate(); + } +} + +void Mix4x::processAll(const ProcessArgs& args) { + if (!baseConnected()) { + outputs[SEND_A_OUTPUT].setVoltage(0.0f); + outputs[SEND_B_OUTPUT].setVoltage(0.0f); + return; + } + + Mix4ExpanderMessage* from = fromBase(); + Mix4ExpanderMessage* to = toBase(); + float sendA = 0.0f; + float sendB = 0.0f; + bool sendAActive = outputs[SEND_A_OUTPUT].isConnected(); + bool sendBActive = outputs[SEND_B_OUTPUT].isConnected(); + for (int i = 0; i < 4; ++i) { + if (from->active[i]) { + _channels[i]->next(from->preFader[i], from->postFader[i], sendAActive, sendBActive); + to->postEQ[i] = _channels[i]->postEQ; + sendA += _channels[i]->sendA; + sendB += _channels[i]->sendB; + } + else { + to->postEQ[i] = from->preFader[i]; + } + } + outputs[SEND_A_OUTPUT].setVoltage(_saturatorA.next(sendA)); + outputs[SEND_B_OUTPUT].setVoltage(_saturatorA.next(sendB)); + + bool lAActive = inputs[L_A_INPUT].isConnected(); + bool rAActive = inputs[R_A_INPUT].isConnected(); + if (lAActive || rAActive) { + float levelA = clamp(params[LEVEL_A_PARAM].getValue(), 0.0f, 1.0f); + if (inputs[LEVEL_A_INPUT].isConnected()) { + levelA *= clamp(inputs[LEVEL_A_INPUT].getVoltage() / 10.0f, 0.0f, 1.0f); + } + levelA = 1.0f - levelA; + levelA *= Amplifier::minDecibels; + _returnAAmp.setLevel(_returnASL.next(levelA)); + if (lAActive) { + to->returnA[0] = _returnAAmp.next(inputs[L_A_INPUT].getVoltage()); + } + else { + to->returnA[0] = 0.0f; + } + if (rAActive) { + to->returnA[1] = _returnAAmp.next(inputs[R_A_INPUT].getVoltage()); + } + else { + to->returnA[1] = to->returnA[0]; + } + } + + bool lBActive = inputs[L_B_INPUT].isConnected(); + bool rBActive = inputs[R_B_INPUT].isConnected(); + if (lBActive || rBActive) { + float levelB = clamp(params[LEVEL_B_PARAM].getValue(), 0.0f, 1.0f); + levelB = 1.0f - levelB; + levelB *= Amplifier::minDecibels; + _returnBAmp.setLevel(_returnBSL.next(levelB)); + if (lBActive) { + to->returnB[0] = _returnBAmp.next(inputs[L_B_INPUT].getVoltage()); + } + else { + to->returnB[0] = 0.0f; + } + if (rBActive) { + to->returnB[1] = _returnBAmp.next(inputs[R_B_INPUT].getVoltage()); + } + else { + to->returnB[1] = to->returnB[0]; + } + } +} + +struct Mix4xWidget : ModuleWidget { + static constexpr int hp = 15; + + Mix4xWidget(Mix4x* 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/Mix4x.svg"))); + addChild(panel); + } + + addChild(createWidget<ScrewSilver>(Vec(15, 0))); + addChild(createWidget<ScrewSilver>(Vec(box.size.x - 30, 0))); + addChild(createWidget<ScrewSilver>(Vec(15, 365))); + addChild(createWidget<ScrewSilver>(Vec(box.size.x - 30, 365))); + + // generated by svg_widgets.rb + auto low1ParamPosition = Vec(18.5, 43.0); + auto mid1ParamPosition = Vec(18.5, 89.0); + auto high1ParamPosition = Vec(18.5, 135.0); + auto a1ParamPosition = Vec(18.5, 180.0); + auto preA1ParamPosition = Vec(30.0, 208.0); + auto b1ParamPosition = Vec(18.5, 236.0); + auto preB1ParamPosition = Vec(30.0, 264.0); + auto low2ParamPosition = Vec(61.5, 43.0); + auto mid2ParamPosition = Vec(61.5, 89.0); + auto high2ParamPosition = Vec(61.5, 135.0); + auto a2ParamPosition = Vec(61.5, 180.0); + auto preA2ParamPosition = Vec(73.0, 208.0); + auto b2ParamPosition = Vec(61.5, 236.0); + auto preB2ParamPosition = Vec(73.0, 264.0); + auto low3ParamPosition = Vec(104.5, 43.0); + auto mid3ParamPosition = Vec(104.5, 89.0); + auto high3ParamPosition = Vec(104.5, 135.0); + auto a3ParamPosition = Vec(104.5, 180.0); + auto preA3ParamPosition = Vec(116.0, 208.0); + auto b3ParamPosition = Vec(104.5, 236.0); + auto preB3ParamPosition = Vec(116.0, 264.0); + auto low4ParamPosition = Vec(147.5, 43.0); + auto mid4ParamPosition = Vec(147.5, 89.0); + auto high4ParamPosition = Vec(147.5, 135.0); + auto a4ParamPosition = Vec(147.5, 180.0); + auto preA4ParamPosition = Vec(159.0, 208.0); + auto b4ParamPosition = Vec(147.5, 236.0); + auto preB4ParamPosition = Vec(159.0, 264.0); + auto levelAParamPosition = Vec(190.5, 138.0); + auto levelBParamPosition = Vec(190.5, 328.0); + + auto a1InputPosition = Vec(14.5, 290.0); + auto b1InputPosition = Vec(14.5, 325.0); + auto a2InputPosition = Vec(57.5, 290.0); + auto b2InputPosition = Vec(57.5, 325.0); + auto a3InputPosition = Vec(100.5, 290.0); + auto b3InputPosition = Vec(100.5, 325.0); + auto a4InputPosition = Vec(143.5, 290.0); + auto b4InputPosition = Vec(143.5, 325.0); + auto lAInputPosition = Vec(186.5, 62.0); + auto rAInputPosition = Vec(186.5, 97.0); + auto levelAInputPosition = Vec(186.5, 170.0); + auto lBInputPosition = Vec(186.5, 252.0); + auto rBInputPosition = Vec(186.5, 287.0); + + auto sendAOutputPosition = Vec(186.5, 24.0); + auto sendBOutputPosition = Vec(186.5, 214.0); + // end generated by svg_widgets.rb + + addParam(createParam<Knob16>(low1ParamPosition, module, Mix4x::LOW1_PARAM)); + addParam(createParam<Knob16>(mid1ParamPosition, module, Mix4x::MID1_PARAM)); + addParam(createParam<Knob16>(high1ParamPosition, module, Mix4x::HIGH1_PARAM)); + addParam(createParam<Knob16>(a1ParamPosition, module, Mix4x::A1_PARAM)); + addParam(createParam<IndicatorButtonGreen9>(preA1ParamPosition, module, Mix4x::PRE_A1_PARAM)); + addParam(createParam<Knob16>(b1ParamPosition, module, Mix4x::B1_PARAM)); + addParam(createParam<IndicatorButtonGreen9>(preB1ParamPosition, module, Mix4x::PRE_B1_PARAM)); + addParam(createParam<Knob16>(low2ParamPosition, module, Mix4x::LOW2_PARAM)); + addParam(createParam<Knob16>(mid2ParamPosition, module, Mix4x::MID2_PARAM)); + addParam(createParam<Knob16>(high2ParamPosition, module, Mix4x::HIGH2_PARAM)); + addParam(createParam<Knob16>(a2ParamPosition, module, Mix4x::A2_PARAM)); + addParam(createParam<IndicatorButtonGreen9>(preA2ParamPosition, module, Mix4x::PRE_A2_PARAM)); + addParam(createParam<Knob16>(b2ParamPosition, module, Mix4x::B2_PARAM)); + addParam(createParam<IndicatorButtonGreen9>(preB2ParamPosition, module, Mix4x::PRE_B2_PARAM)); + addParam(createParam<Knob16>(low3ParamPosition, module, Mix4x::LOW3_PARAM)); + addParam(createParam<Knob16>(mid3ParamPosition, module, Mix4x::MID3_PARAM)); + addParam(createParam<Knob16>(high3ParamPosition, module, Mix4x::HIGH3_PARAM)); + addParam(createParam<Knob16>(a3ParamPosition, module, Mix4x::A3_PARAM)); + addParam(createParam<IndicatorButtonGreen9>(preA3ParamPosition, module, Mix4x::PRE_A3_PARAM)); + addParam(createParam<Knob16>(b3ParamPosition, module, Mix4x::B3_PARAM)); + addParam(createParam<IndicatorButtonGreen9>(preB3ParamPosition, module, Mix4x::PRE_B3_PARAM)); + addParam(createParam<Knob16>(low4ParamPosition, module, Mix4x::LOW4_PARAM)); + addParam(createParam<Knob16>(mid4ParamPosition, module, Mix4x::MID4_PARAM)); + addParam(createParam<Knob16>(high4ParamPosition, module, Mix4x::HIGH4_PARAM)); + addParam(createParam<Knob16>(a4ParamPosition, module, Mix4x::A4_PARAM)); + addParam(createParam<IndicatorButtonGreen9>(preA4ParamPosition, module, Mix4x::PRE_A4_PARAM)); + addParam(createParam<Knob16>(b4ParamPosition, module, Mix4x::B4_PARAM)); + addParam(createParam<IndicatorButtonGreen9>(preB4ParamPosition, module, Mix4x::PRE_B4_PARAM)); + addParam(createParam<Knob16>(levelAParamPosition, module, Mix4x::LEVEL_A_PARAM)); + addParam(createParam<Knob16>(levelBParamPosition, module, Mix4x::LEVEL_B_PARAM)); + + addInput(createInput<Port24>(a1InputPosition, module, Mix4x::A1_INPUT)); + addInput(createInput<Port24>(b1InputPosition, module, Mix4x::B1_INPUT)); + addInput(createInput<Port24>(a2InputPosition, module, Mix4x::A2_INPUT)); + addInput(createInput<Port24>(b2InputPosition, module, Mix4x::B2_INPUT)); + addInput(createInput<Port24>(a3InputPosition, module, Mix4x::A3_INPUT)); + addInput(createInput<Port24>(b3InputPosition, module, Mix4x::B3_INPUT)); + addInput(createInput<Port24>(a4InputPosition, module, Mix4x::A4_INPUT)); + addInput(createInput<Port24>(b4InputPosition, module, Mix4x::B4_INPUT)); + addInput(createInput<Port24>(lAInputPosition, module, Mix4x::L_A_INPUT)); + addInput(createInput<Port24>(rAInputPosition, module, Mix4x::R_A_INPUT)); + addInput(createInput<Port24>(levelAInputPosition, module, Mix4x::LEVEL_A_INPUT)); + addInput(createInput<Port24>(lBInputPosition, module, Mix4x::L_B_INPUT)); + addInput(createInput<Port24>(rBInputPosition, module, Mix4x::R_B_INPUT)); + + addOutput(createOutput<Port24>(sendAOutputPosition, module, Mix4x::SEND_A_OUTPUT)); + addOutput(createOutput<Port24>(sendBOutputPosition, module, Mix4x::SEND_B_OUTPUT)); + } +}; + +Model* modelMix4x = createModel<Mix4x, Mix4xWidget>("Bogaudio-Mix4x", "MIX4X", "Expander for MIX4, adds EQs and sends", "Mixer", "Expander"); diff --git a/src/Mix4x.hpp b/src/Mix4x.hpp @@ -0,0 +1,124 @@ +#pragma once + +#include "bogaudio.hpp" +#include "Mix4_shared.hpp" + +using namespace bogaudio::dsp; + +namespace bogaudio { + +struct Mix4x : ExpanderModule<Mix4ExpanderMessage, BGModule> { + enum ParamsIds { + LOW1_PARAM, + MID1_PARAM, + HIGH1_PARAM, + A1_PARAM, + PRE_A1_PARAM, + B1_PARAM, + PRE_B1_PARAM, + LOW2_PARAM, + MID2_PARAM, + HIGH2_PARAM, + A2_PARAM, + PRE_A2_PARAM, + B2_PARAM, + PRE_B2_PARAM, + LOW3_PARAM, + MID3_PARAM, + HIGH3_PARAM, + A3_PARAM, + PRE_A3_PARAM, + B3_PARAM, + PRE_B3_PARAM, + LOW4_PARAM, + MID4_PARAM, + HIGH4_PARAM, + A4_PARAM, + PRE_A4_PARAM, + B4_PARAM, + PRE_B4_PARAM, + LEVEL_A_PARAM, + LEVEL_B_PARAM, + NUM_PARAMS + }; + + enum InputsIds { + A1_INPUT, + B1_INPUT, + A2_INPUT, + B2_INPUT, + A3_INPUT, + B3_INPUT, + A4_INPUT, + B4_INPUT, + L_A_INPUT, + R_A_INPUT, + LEVEL_A_INPUT, + L_B_INPUT, + R_B_INPUT, + NUM_INPUTS + }; + + enum OutputsIds { + SEND_A_OUTPUT, + SEND_B_OUTPUT, + NUM_OUTPUTS + }; + + MixerExpanderChannel* _channels[4] {}; + Saturator _saturatorA, _saturatorB; + Amplifier _returnAAmp, _returnBAmp; + bogaudio::dsp::SlewLimiter _returnASL, _returnBSL; + + Mix4x() { + config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS); + configParam<EQParamQuantity>(LOW1_PARAM, -1.0f, 1.0f, 0.0f, "Channel 1 low", " dB"); + configParam<EQParamQuantity>(MID1_PARAM, -1.0f, 1.0f, 0.0f, "Channel 1 mid", " dB"); + configParam<EQParamQuantity>(HIGH1_PARAM, -1.0f, 1.0f, 0.0f, "Channel 1 high", " dB"); + configParam<AmplifierParamQuantity>(A1_PARAM, 0.0f, 1.0f, 0.0f, "Channel 1 A send"); + configParam(PRE_A1_PARAM, 0.0f, 1.0f, 0.0f, "Channel 1 A send pre/post"); + configParam<AmplifierParamQuantity>(B1_PARAM, 0.0f, 1.0f, 0.0f, "Channel 1 B send"); + configParam(PRE_B1_PARAM, 0.0f, 1.0f, 0.0f, "Channel 1 B send pre/post"); + configParam<EQParamQuantity>(LOW2_PARAM, -1.0f, 1.0f, 0.0f, "Channel 2 low", " dB"); + configParam<EQParamQuantity>(MID2_PARAM, -1.0f, 1.0f, 0.0f, "Channel 2 mid", " dB"); + configParam<EQParamQuantity>(HIGH2_PARAM, -1.0f, 1.0f, 0.0f, "Channel 2 high", " dB"); + configParam<AmplifierParamQuantity>(A2_PARAM, 0.0f, 1.0f, 0.0f, "Channel 2 A send"); + configParam(PRE_A2_PARAM, 0.0f, 1.0f, 0.0f, "Channel 2 A send pre/post"); + configParam<AmplifierParamQuantity>(B2_PARAM, 0.0f, 1.0f, 0.0f, "Channel 2 B send"); + configParam(PRE_B2_PARAM, 0.0f, 1.0f, 0.0f, "Channel 2 B send pre/post"); + configParam<EQParamQuantity>(LOW3_PARAM, -1.0f, 1.0f, 0.0f, "Channel 3 low", " dB"); + configParam<EQParamQuantity>(MID3_PARAM, -1.0f, 1.0f, 0.0f, "Channel 3 mid", " dB"); + configParam<EQParamQuantity>(HIGH3_PARAM, -1.0f, 1.0f, 0.0f, "Channel 3 high", " dB"); + configParam<AmplifierParamQuantity>(A3_PARAM, 0.0f, 1.0f, 0.0f, "Channel 3 A send"); + configParam(PRE_A3_PARAM, 0.0f, 1.0f, 0.0f, "Channel 3 A send pre/post"); + configParam<AmplifierParamQuantity>(B3_PARAM, 0.0f, 1.0f, 0.0f, "Channel 3 B send"); + configParam(PRE_B3_PARAM, 0.0f, 1.0f, 0.0f, "Channel 3 B send pre/post"); + configParam<EQParamQuantity>(LOW4_PARAM, -1.0f, 1.0f, 0.0f, "Channel 4 low", " dB"); + configParam<EQParamQuantity>(MID4_PARAM, -1.0f, 1.0f, 0.0f, "Channel 4 mid", " dB"); + configParam<EQParamQuantity>(HIGH4_PARAM, -1.0f, 1.0f, 0.0f, "Channel 4 high", " dB"); + configParam<AmplifierParamQuantity>(A4_PARAM, 0.0f, 1.0f, 0.0f, "Channel 4 A send"); + configParam(PRE_A4_PARAM, 0.0f, 1.0f, 0.0f, "Channel 4 A send pre/post"); + configParam<AmplifierParamQuantity>(B4_PARAM, 0.0f, 1.0f, 0.0f, "Channel 4 B send"); + configParam(PRE_B4_PARAM, 0.0f, 1.0f, 0.0f, "Channel 4 B send pre/post"); + configParam<AmplifierParamQuantity>(LEVEL_A_PARAM, 0.0f, 1.0f, 0.8f, "A return level"); + configParam<AmplifierParamQuantity>(LEVEL_B_PARAM, 0.0f, 1.0f, 0.8f, "B return level"); + + _channels[0] = new MixerExpanderChannel(params[LOW1_PARAM], params[MID1_PARAM], params[HIGH1_PARAM], params[A1_PARAM], params[B1_PARAM], params[PRE_A1_PARAM], params[PRE_B1_PARAM], inputs[A1_INPUT], inputs[B1_INPUT]); + _channels[1] = new MixerExpanderChannel(params[LOW2_PARAM], params[MID2_PARAM], params[HIGH2_PARAM], params[A2_PARAM], params[B2_PARAM], params[PRE_A2_PARAM], params[PRE_B2_PARAM], inputs[A2_INPUT], inputs[B2_INPUT]); + _channels[2] = new MixerExpanderChannel(params[LOW3_PARAM], params[MID3_PARAM], params[HIGH3_PARAM], params[A3_PARAM], params[B3_PARAM], params[PRE_A3_PARAM], params[PRE_B3_PARAM], inputs[A3_INPUT], inputs[B3_INPUT]); + _channels[3] = new MixerExpanderChannel(params[LOW4_PARAM], params[MID4_PARAM], params[HIGH4_PARAM], params[A4_PARAM], params[B4_PARAM], params[PRE_A4_PARAM], params[PRE_B4_PARAM], inputs[A4_INPUT], inputs[B4_INPUT]); + + setBaseModel(modelMix4); + } + virtual ~Mix4x() { + for (int i = 0; i < 4; ++i) { + delete _channels[i]; + } + } + + void sampleRateChange() override; + void modulate() override; + void processAll(const ProcessArgs& args) override; +}; + +} // namespace bogaudio diff --git a/src/Mix8.cpp b/src/Mix8.cpp @@ -319,285 +319,3 @@ struct Mix8Widget : ModuleWidget { }; Model* modelMix8 = bogaudio::createModel<Mix8, Mix8Widget>("Bogaudio-Mix8", "MIX8", "8-channel mixer and panner", "Mixer", "Panning"); - - -void Mix8x::sampleRateChange() { - float sr = APP->engine->getSampleRate(); - for (int i = 0; i < 8; ++i) { - _channels[i]->setSampleRate(sr); - } - _returnASL.setParams(sr, MixerChannel::levelSlewTimeMS, MixerChannel::maxDecibels - MixerChannel::minDecibels); - _returnBSL.setParams(sr, MixerChannel::levelSlewTimeMS, MixerChannel::maxDecibels - MixerChannel::minDecibels); -} - -void Mix8x::modulate() { - for (int i = 0; i < 8; ++i) { - _channels[i]->modulate(); - } -} - -void Mix8x::processAll(const ProcessArgs& args) { - if (!baseConnected()) { - outputs[SEND_A_OUTPUT].setVoltage(0.0f); - outputs[SEND_B_OUTPUT].setVoltage(0.0f); - return; - } - - Mix8ExpanderMessage* from = fromBase(); - Mix8ExpanderMessage* to = toBase(); - float sendA = 0.0f; - float sendB = 0.0f; - bool sendAActive = outputs[SEND_A_OUTPUT].isConnected(); - bool sendBActive = outputs[SEND_B_OUTPUT].isConnected(); - for (int i = 0; i < 8; ++i) { - if (from->active[i]) { - _channels[i]->next(from->preFader[i], from->postFader[i], sendAActive, sendBActive); - to->postEQ[i] = _channels[i]->postEQ; - sendA += _channels[i]->sendA; - sendB += _channels[i]->sendB; - } - else { - to->postEQ[i] = from->preFader[i]; - } - } - outputs[SEND_A_OUTPUT].setVoltage(_saturatorA.next(sendA)); - outputs[SEND_B_OUTPUT].setVoltage(_saturatorA.next(sendB)); - - bool lAActive = inputs[L_A_INPUT].isConnected(); - bool rAActive = inputs[R_A_INPUT].isConnected(); - if (lAActive || rAActive) { - float levelA = clamp(params[LEVEL_A_PARAM].getValue(), 0.0f, 1.0f); - if (inputs[LEVEL_A_INPUT].isConnected()) { - levelA *= clamp(inputs[LEVEL_A_INPUT].getVoltage() / 10.0f, 0.0f, 1.0f); - } - levelA = 1.0f - levelA; - levelA *= Amplifier::minDecibels; - _returnAAmp.setLevel(_returnASL.next(levelA)); - if (lAActive) { - to->returnA[0] = _returnAAmp.next(inputs[L_A_INPUT].getVoltage()); - } - else { - to->returnA[0] = 0.0f; - } - if (rAActive) { - to->returnA[1] = _returnAAmp.next(inputs[R_A_INPUT].getVoltage()); - } - else { - to->returnA[1] = to->returnA[0]; - } - } - - bool lBActive = inputs[L_B_INPUT].isConnected(); - bool rBActive = inputs[R_B_INPUT].isConnected(); - if (lBActive || rBActive) { - float levelB = clamp(params[LEVEL_B_PARAM].getValue(), 0.0f, 1.0f); - levelB = 1.0f - levelB; - levelB *= Amplifier::minDecibels; - _returnBAmp.setLevel(_returnBSL.next(levelB)); - if (lBActive) { - to->returnB[0] = _returnBAmp.next(inputs[L_B_INPUT].getVoltage()); - } - else { - to->returnB[0] = 0.0f; - } - if (rBActive) { - to->returnB[1] = _returnBAmp.next(inputs[R_B_INPUT].getVoltage()); - } - else { - to->returnB[1] = to->returnB[0]; - } - } -} - -struct Mix8xWidget : ModuleWidget { - static constexpr int hp = 27; - - Mix8xWidget(Mix8x* 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/Mix8x.svg"))); - addChild(panel); - } - - addChild(createWidget<ScrewSilver>(Vec(15, 0))); - addChild(createWidget<ScrewSilver>(Vec(box.size.x - 30, 0))); - addChild(createWidget<ScrewSilver>(Vec(15, 365))); - addChild(createWidget<ScrewSilver>(Vec(box.size.x - 30, 365))); - - // generated by svg_widgets.rb - auto low1ParamPosition = Vec(18.5, 43.0); - auto mid1ParamPosition = Vec(18.5, 89.0); - auto high1ParamPosition = Vec(18.5, 135.0); - auto a1ParamPosition = Vec(18.5, 180.0); - auto preA1ParamPosition = Vec(30.0, 208.0); - auto b1ParamPosition = Vec(18.5, 236.0); - auto preB1ParamPosition = Vec(30.0, 264.0); - auto low2ParamPosition = Vec(62.5, 43.0); - auto mid2ParamPosition = Vec(62.5, 89.0); - auto high2ParamPosition = Vec(62.5, 135.0); - auto a2ParamPosition = Vec(62.5, 180.0); - auto preA2ParamPosition = Vec(74.0, 208.0); - auto b2ParamPosition = Vec(62.5, 236.0); - auto preB2ParamPosition = Vec(74.0, 264.0); - auto low3ParamPosition = Vec(106.5, 43.0); - auto mid3ParamPosition = Vec(106.5, 89.0); - auto high3ParamPosition = Vec(106.5, 135.0); - auto a3ParamPosition = Vec(106.5, 180.0); - auto preA3ParamPosition = Vec(118.0, 208.0); - auto b3ParamPosition = Vec(106.5, 236.0); - auto preB3ParamPosition = Vec(118.0, 264.0); - auto low4ParamPosition = Vec(150.5, 43.0); - auto mid4ParamPosition = Vec(150.5, 89.0); - auto high4ParamPosition = Vec(150.5, 135.0); - auto a4ParamPosition = Vec(150.5, 180.0); - auto preA4ParamPosition = Vec(162.0, 208.0); - auto b4ParamPosition = Vec(150.5, 236.0); - auto preB4ParamPosition = Vec(162.0, 264.0); - auto low5ParamPosition = Vec(194.5, 43.0); - auto mid5ParamPosition = Vec(194.5, 89.0); - auto high5ParamPosition = Vec(194.5, 135.0); - auto a5ParamPosition = Vec(194.5, 180.0); - auto preA5ParamPosition = Vec(206.0, 208.0); - auto b5ParamPosition = Vec(194.5, 236.0); - auto preB5ParamPosition = Vec(206.0, 264.0); - auto low6ParamPosition = Vec(238.5, 43.0); - auto mid6ParamPosition = Vec(238.5, 89.0); - auto high6ParamPosition = Vec(238.5, 135.0); - auto a6ParamPosition = Vec(238.5, 180.0); - auto preA6ParamPosition = Vec(250.0, 208.0); - auto b6ParamPosition = Vec(238.5, 236.0); - auto preB6ParamPosition = Vec(250.0, 264.0); - auto low7ParamPosition = Vec(282.5, 43.0); - auto mid7ParamPosition = Vec(282.5, 89.0); - auto high7ParamPosition = Vec(282.5, 135.0); - auto a7ParamPosition = Vec(282.5, 180.0); - auto preA7ParamPosition = Vec(294.0, 208.0); - auto b7ParamPosition = Vec(282.5, 236.0); - auto preB7ParamPosition = Vec(294.0, 264.0); - auto low8ParamPosition = Vec(326.5, 43.0); - auto mid8ParamPosition = Vec(326.5, 89.0); - auto high8ParamPosition = Vec(326.5, 135.0); - auto a8ParamPosition = Vec(326.5, 180.0); - auto preA8ParamPosition = Vec(338.0, 208.0); - auto b8ParamPosition = Vec(326.5, 236.0); - auto preB8ParamPosition = Vec(338.0, 264.0); - auto levelAParamPosition = Vec(370.5, 138.0); - auto levelBParamPosition = Vec(370.5, 328.0); - - auto a1InputPosition = Vec(14.5, 290.0); - auto b1InputPosition = Vec(14.5, 325.0); - auto a2InputPosition = Vec(58.5, 290.0); - auto b2InputPosition = Vec(58.5, 325.0); - auto a3InputPosition = Vec(102.5, 290.0); - auto b3InputPosition = Vec(102.5, 325.0); - auto a4InputPosition = Vec(146.5, 290.0); - auto b4InputPosition = Vec(146.5, 325.0); - auto a5InputPosition = Vec(190.5, 290.0); - auto b5InputPosition = Vec(190.5, 325.0); - auto a6InputPosition = Vec(234.5, 290.0); - auto b6InputPosition = Vec(234.5, 325.0); - auto a7InputPosition = Vec(278.5, 290.0); - auto b7InputPosition = Vec(278.5, 325.0); - auto a8InputPosition = Vec(322.5, 290.0); - auto b8InputPosition = Vec(322.5, 325.0); - auto lAInputPosition = Vec(366.5, 62.0); - auto rAInputPosition = Vec(366.5, 97.0); - auto levelAInputPosition = Vec(366.5, 170.0); - auto lBInputPosition = Vec(366.5, 252.0); - auto rBInputPosition = Vec(366.5, 287.0); - - auto sendAOutputPosition = Vec(366.5, 24.0); - auto sendBOutputPosition = Vec(366.5, 214.0); - // end generated by svg_widgets.rb - - addParam(createParam<Knob16>(low1ParamPosition, module, Mix8x::LOW1_PARAM)); - addParam(createParam<Knob16>(mid1ParamPosition, module, Mix8x::MID1_PARAM)); - addParam(createParam<Knob16>(high1ParamPosition, module, Mix8x::HIGH1_PARAM)); - addParam(createParam<Knob16>(a1ParamPosition, module, Mix8x::A1_PARAM)); - addParam(createParam<IndicatorButtonGreen9>(preA1ParamPosition, module, Mix8x::PRE_A1_PARAM)); - addParam(createParam<Knob16>(b1ParamPosition, module, Mix8x::B1_PARAM)); - addParam(createParam<IndicatorButtonGreen9>(preB1ParamPosition, module, Mix8x::PRE_B1_PARAM)); - addParam(createParam<Knob16>(low2ParamPosition, module, Mix8x::LOW2_PARAM)); - addParam(createParam<Knob16>(mid2ParamPosition, module, Mix8x::MID2_PARAM)); - addParam(createParam<Knob16>(high2ParamPosition, module, Mix8x::HIGH2_PARAM)); - addParam(createParam<Knob16>(a2ParamPosition, module, Mix8x::A2_PARAM)); - addParam(createParam<IndicatorButtonGreen9>(preA2ParamPosition, module, Mix8x::PRE_A2_PARAM)); - addParam(createParam<Knob16>(b2ParamPosition, module, Mix8x::B2_PARAM)); - addParam(createParam<IndicatorButtonGreen9>(preB2ParamPosition, module, Mix8x::PRE_B2_PARAM)); - addParam(createParam<Knob16>(low3ParamPosition, module, Mix8x::LOW3_PARAM)); - addParam(createParam<Knob16>(mid3ParamPosition, module, Mix8x::MID3_PARAM)); - addParam(createParam<Knob16>(high3ParamPosition, module, Mix8x::HIGH3_PARAM)); - addParam(createParam<Knob16>(a3ParamPosition, module, Mix8x::A3_PARAM)); - addParam(createParam<IndicatorButtonGreen9>(preA3ParamPosition, module, Mix8x::PRE_A3_PARAM)); - addParam(createParam<Knob16>(b3ParamPosition, module, Mix8x::B3_PARAM)); - addParam(createParam<IndicatorButtonGreen9>(preB3ParamPosition, module, Mix8x::PRE_B3_PARAM)); - addParam(createParam<Knob16>(low4ParamPosition, module, Mix8x::LOW4_PARAM)); - addParam(createParam<Knob16>(mid4ParamPosition, module, Mix8x::MID4_PARAM)); - addParam(createParam<Knob16>(high4ParamPosition, module, Mix8x::HIGH4_PARAM)); - addParam(createParam<Knob16>(a4ParamPosition, module, Mix8x::A4_PARAM)); - addParam(createParam<IndicatorButtonGreen9>(preA4ParamPosition, module, Mix8x::PRE_A4_PARAM)); - addParam(createParam<Knob16>(b4ParamPosition, module, Mix8x::B4_PARAM)); - addParam(createParam<IndicatorButtonGreen9>(preB4ParamPosition, module, Mix8x::PRE_B4_PARAM)); - addParam(createParam<Knob16>(low5ParamPosition, module, Mix8x::LOW5_PARAM)); - addParam(createParam<Knob16>(mid5ParamPosition, module, Mix8x::MID5_PARAM)); - addParam(createParam<Knob16>(high5ParamPosition, module, Mix8x::HIGH5_PARAM)); - addParam(createParam<Knob16>(a5ParamPosition, module, Mix8x::A5_PARAM)); - addParam(createParam<IndicatorButtonGreen9>(preA5ParamPosition, module, Mix8x::PRE_A5_PARAM)); - addParam(createParam<Knob16>(b5ParamPosition, module, Mix8x::B5_PARAM)); - addParam(createParam<IndicatorButtonGreen9>(preB5ParamPosition, module, Mix8x::PRE_B5_PARAM)); - addParam(createParam<Knob16>(low6ParamPosition, module, Mix8x::LOW6_PARAM)); - addParam(createParam<Knob16>(mid6ParamPosition, module, Mix8x::MID6_PARAM)); - addParam(createParam<Knob16>(high6ParamPosition, module, Mix8x::HIGH6_PARAM)); - addParam(createParam<Knob16>(a6ParamPosition, module, Mix8x::A6_PARAM)); - addParam(createParam<IndicatorButtonGreen9>(preA6ParamPosition, module, Mix8x::PRE_A6_PARAM)); - addParam(createParam<Knob16>(b6ParamPosition, module, Mix8x::B6_PARAM)); - addParam(createParam<IndicatorButtonGreen9>(preB6ParamPosition, module, Mix8x::PRE_B6_PARAM)); - addParam(createParam<Knob16>(low7ParamPosition, module, Mix8x::LOW7_PARAM)); - addParam(createParam<Knob16>(mid7ParamPosition, module, Mix8x::MID7_PARAM)); - addParam(createParam<Knob16>(high7ParamPosition, module, Mix8x::HIGH7_PARAM)); - addParam(createParam<Knob16>(a7ParamPosition, module, Mix8x::A7_PARAM)); - addParam(createParam<IndicatorButtonGreen9>(preA7ParamPosition, module, Mix8x::PRE_A7_PARAM)); - addParam(createParam<Knob16>(b7ParamPosition, module, Mix8x::B7_PARAM)); - addParam(createParam<IndicatorButtonGreen9>(preB7ParamPosition, module, Mix8x::PRE_B7_PARAM)); - addParam(createParam<Knob16>(low8ParamPosition, module, Mix8x::LOW8_PARAM)); - addParam(createParam<Knob16>(mid8ParamPosition, module, Mix8x::MID8_PARAM)); - addParam(createParam<Knob16>(high8ParamPosition, module, Mix8x::HIGH8_PARAM)); - addParam(createParam<Knob16>(a8ParamPosition, module, Mix8x::A8_PARAM)); - addParam(createParam<IndicatorButtonGreen9>(preA8ParamPosition, module, Mix8x::PRE_A8_PARAM)); - addParam(createParam<Knob16>(b8ParamPosition, module, Mix8x::B8_PARAM)); - addParam(createParam<IndicatorButtonGreen9>(preB8ParamPosition, module, Mix8x::PRE_B8_PARAM)); - addParam(createParam<Knob16>(levelAParamPosition, module, Mix8x::LEVEL_A_PARAM)); - addParam(createParam<Knob16>(levelBParamPosition, module, Mix8x::LEVEL_B_PARAM)); - - addInput(createInput<Port24>(a1InputPosition, module, Mix8x::A1_INPUT)); - addInput(createInput<Port24>(b1InputPosition, module, Mix8x::B1_INPUT)); - addInput(createInput<Port24>(a2InputPosition, module, Mix8x::A2_INPUT)); - addInput(createInput<Port24>(b2InputPosition, module, Mix8x::B2_INPUT)); - addInput(createInput<Port24>(a3InputPosition, module, Mix8x::A3_INPUT)); - addInput(createInput<Port24>(b3InputPosition, module, Mix8x::B3_INPUT)); - addInput(createInput<Port24>(a4InputPosition, module, Mix8x::A4_INPUT)); - addInput(createInput<Port24>(b4InputPosition, module, Mix8x::B4_INPUT)); - addInput(createInput<Port24>(a5InputPosition, module, Mix8x::A5_INPUT)); - addInput(createInput<Port24>(b5InputPosition, module, Mix8x::B5_INPUT)); - addInput(createInput<Port24>(a6InputPosition, module, Mix8x::A6_INPUT)); - addInput(createInput<Port24>(b6InputPosition, module, Mix8x::B6_INPUT)); - addInput(createInput<Port24>(a7InputPosition, module, Mix8x::A7_INPUT)); - addInput(createInput<Port24>(b7InputPosition, module, Mix8x::B7_INPUT)); - addInput(createInput<Port24>(a8InputPosition, module, Mix8x::A8_INPUT)); - addInput(createInput<Port24>(b8InputPosition, module, Mix8x::B8_INPUT)); - addInput(createInput<Port24>(lAInputPosition, module, Mix8x::L_A_INPUT)); - addInput(createInput<Port24>(rAInputPosition, module, Mix8x::R_A_INPUT)); - addInput(createInput<Port24>(levelAInputPosition, module, Mix8x::LEVEL_A_INPUT)); - addInput(createInput<Port24>(lBInputPosition, module, Mix8x::L_B_INPUT)); - addInput(createInput<Port24>(rBInputPosition, module, Mix8x::R_B_INPUT)); - - addOutput(createOutput<Port24>(sendAOutputPosition, module, Mix8x::SEND_A_OUTPUT)); - addOutput(createOutput<Port24>(sendBOutputPosition, module, Mix8x::SEND_B_OUTPUT)); - } -}; - -Model* modelMix8x = createModel<Mix8x, Mix8xWidget>("Bogaudio-Mix8x", "MIX8X", "Expander for MIX8, adds EQs and sends", "Mixer", "Expander"); diff --git a/src/Mix8.hpp b/src/Mix8.hpp @@ -1,20 +1,11 @@ #pragma once -#include "bogaudio.hpp" -#include "mixer_expander.hpp" -#include "dsp/signal.hpp" +#include "Mix8_shared.hpp" using namespace bogaudio::dsp; -extern Model* modelMix8; -extern Model* modelMix8x; - namespace bogaudio { -struct Mix8x; - -typedef MixerExpanderMessage<8> Mix8ExpanderMessage; - struct Mix8 : ExpandableModule<Mix8ExpanderMessage, BGModule> { enum ParamsIds { LEVEL1_PARAM, @@ -149,186 +140,4 @@ struct Mix8 : ExpandableModule<Mix8ExpanderMessage, BGModule> { void processAll(const ProcessArgs& args) override; }; -struct Mix8x : ExpanderModule<Mix8ExpanderMessage, BGModule> { - enum ParamsIds { - LOW1_PARAM, - MID1_PARAM, - HIGH1_PARAM, - A1_PARAM, - PRE_A1_PARAM, - B1_PARAM, - PRE_B1_PARAM, - LOW2_PARAM, - MID2_PARAM, - HIGH2_PARAM, - A2_PARAM, - PRE_A2_PARAM, - B2_PARAM, - PRE_B2_PARAM, - LOW3_PARAM, - MID3_PARAM, - HIGH3_PARAM, - A3_PARAM, - PRE_A3_PARAM, - B3_PARAM, - PRE_B3_PARAM, - LOW4_PARAM, - MID4_PARAM, - HIGH4_PARAM, - A4_PARAM, - PRE_A4_PARAM, - B4_PARAM, - PRE_B4_PARAM, - LOW5_PARAM, - MID5_PARAM, - HIGH5_PARAM, - A5_PARAM, - PRE_A5_PARAM, - B5_PARAM, - PRE_B5_PARAM, - LOW6_PARAM, - MID6_PARAM, - HIGH6_PARAM, - A6_PARAM, - PRE_A6_PARAM, - B6_PARAM, - PRE_B6_PARAM, - LOW7_PARAM, - MID7_PARAM, - HIGH7_PARAM, - A7_PARAM, - PRE_A7_PARAM, - B7_PARAM, - PRE_B7_PARAM, - LOW8_PARAM, - MID8_PARAM, - HIGH8_PARAM, - A8_PARAM, - PRE_A8_PARAM, - B8_PARAM, - PRE_B8_PARAM, - LEVEL_A_PARAM, - LEVEL_B_PARAM, - NUM_PARAMS - }; - - enum InputsIds { - A1_INPUT, - B1_INPUT, - A2_INPUT, - B2_INPUT, - A3_INPUT, - B3_INPUT, - A4_INPUT, - B4_INPUT, - A5_INPUT, - B5_INPUT, - A6_INPUT, - B6_INPUT, - A7_INPUT, - B7_INPUT, - A8_INPUT, - B8_INPUT, - L_A_INPUT, - R_A_INPUT, - LEVEL_A_INPUT, - L_B_INPUT, - R_B_INPUT, - NUM_INPUTS - }; - - enum OutputsIds { - SEND_A_OUTPUT, - SEND_B_OUTPUT, - NUM_OUTPUTS - }; - - MixerExpanderChannel* _channels[8] {}; - Saturator _saturatorA, _saturatorB; - Amplifier _returnAAmp, _returnBAmp; - bogaudio::dsp::SlewLimiter _returnASL, _returnBSL; - - Mix8x() { - config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS); - configParam<EQParamQuantity>(LOW1_PARAM, -1.0f, 1.0f, 0.0f, "Channel 1 low", " dB"); - configParam<EQParamQuantity>(MID1_PARAM, -1.0f, 1.0f, 0.0f, "Channel 1 mid", " dB"); - configParam<EQParamQuantity>(HIGH1_PARAM, -1.0f, 1.0f, 0.0f, "Channel 1 high", " dB"); - configParam<AmplifierParamQuantity>(A1_PARAM, 0.0f, 1.0f, 0.0f, "Channel 1 A send"); - configParam(PRE_A1_PARAM, 0.0f, 1.0f, 0.0f, "Channel 1 A send pre/post"); - configParam<AmplifierParamQuantity>(B1_PARAM, 0.0f, 1.0f, 0.0f, "Channel 1 B send"); - configParam(PRE_B1_PARAM, 0.0f, 1.0f, 0.0f, "Channel 1 B send pre/post"); - configParam<EQParamQuantity>(LOW2_PARAM, -1.0f, 1.0f, 0.0f, "Channel 2 low", " dB"); - configParam<EQParamQuantity>(MID2_PARAM, -1.0f, 1.0f, 0.0f, "Channel 2 mid", " dB"); - configParam<EQParamQuantity>(HIGH2_PARAM, -1.0f, 1.0f, 0.0f, "Channel 2 high", " dB"); - configParam<AmplifierParamQuantity>(A2_PARAM, 0.0f, 1.0f, 0.0f, "Channel 2 A send"); - configParam(PRE_A2_PARAM, 0.0f, 1.0f, 0.0f, "Channel 2 A send pre/post"); - configParam<AmplifierParamQuantity>(B2_PARAM, 0.0f, 1.0f, 0.0f, "Channel 2 B send"); - configParam(PRE_B2_PARAM, 0.0f, 1.0f, 0.0f, "Channel 2 B send pre/post"); - configParam<EQParamQuantity>(LOW3_PARAM, -1.0f, 1.0f, 0.0f, "Channel 3 low", " dB"); - configParam<EQParamQuantity>(MID3_PARAM, -1.0f, 1.0f, 0.0f, "Channel 3 mid", " dB"); - configParam<EQParamQuantity>(HIGH3_PARAM, -1.0f, 1.0f, 0.0f, "Channel 3 high", " dB"); - configParam<AmplifierParamQuantity>(A3_PARAM, 0.0f, 1.0f, 0.0f, "Channel 3 A send"); - configParam(PRE_A3_PARAM, 0.0f, 1.0f, 0.0f, "Channel 3 A send pre/post"); - configParam<AmplifierParamQuantity>(B3_PARAM, 0.0f, 1.0f, 0.0f, "Channel 3 B send"); - configParam(PRE_B3_PARAM, 0.0f, 1.0f, 0.0f, "Channel 3 B send pre/post"); - configParam<EQParamQuantity>(LOW4_PARAM, -1.0f, 1.0f, 0.0f, "Channel 4 low", " dB"); - configParam<EQParamQuantity>(MID4_PARAM, -1.0f, 1.0f, 0.0f, "Channel 4 mid", " dB"); - configParam<EQParamQuantity>(HIGH4_PARAM, -1.0f, 1.0f, 0.0f, "Channel 4 high", " dB"); - configParam<AmplifierParamQuantity>(A4_PARAM, 0.0f, 1.0f, 0.0f, "Channel 4 A send"); - configParam(PRE_A4_PARAM, 0.0f, 1.0f, 0.0f, "Channel 4 A send pre/post"); - configParam<AmplifierParamQuantity>(B4_PARAM, 0.0f, 1.0f, 0.0f, "Channel 4 B send"); - configParam(PRE_B4_PARAM, 0.0f, 1.0f, 0.0f, "Channel 4 B send pre/post"); - configParam<EQParamQuantity>(LOW5_PARAM, -1.0f, 1.0f, 0.0f, "Channel 5 low", " dB"); - configParam<EQParamQuantity>(MID5_PARAM, -1.0f, 1.0f, 0.0f, "Channel 5 mid", " dB"); - configParam<EQParamQuantity>(HIGH5_PARAM, -1.0f, 1.0f, 0.0f, "Channel 5 high", " dB"); - configParam<AmplifierParamQuantity>(A5_PARAM, 0.0f, 1.0f, 0.0f, "Channel 5 A send"); - configParam(PRE_A5_PARAM, 0.0f, 1.0f, 0.0f, "Channel 5 A send pre/post"); - configParam<AmplifierParamQuantity>(B5_PARAM, 0.0f, 1.0f, 0.0f, "Channel 5 B send"); - configParam(PRE_B5_PARAM, 0.0f, 1.0f, 0.0f, "Channel 5 B send pre/post"); - configParam<EQParamQuantity>(LOW6_PARAM, -1.0f, 1.0f, 0.0f, "Channel 6 low", " dB"); - configParam<EQParamQuantity>(MID6_PARAM, -1.0f, 1.0f, 0.0f, "Channel 6 mid", " dB"); - configParam<EQParamQuantity>(HIGH6_PARAM, -1.0f, 1.0f, 0.0f, "Channel 6 high", " dB"); - configParam<AmplifierParamQuantity>(A6_PARAM, 0.0f, 1.0f, 0.0f, "Channel 6 A send"); - configParam(PRE_A6_PARAM, 0.0f, 1.0f, 0.0f, "Channel 6 A send pre/post"); - configParam<AmplifierParamQuantity>(B6_PARAM, 0.0f, 1.0f, 0.0f, "Channel 6 B send"); - configParam(PRE_B6_PARAM, 0.0f, 1.0f, 0.0f, "Channel 6 B send pre/post"); - configParam<EQParamQuantity>(LOW7_PARAM, -1.0f, 1.0f, 0.0f, "Channel 7 low", " dB"); - configParam<EQParamQuantity>(MID7_PARAM, -1.0f, 1.0f, 0.0f, "Channel 7 mid", " dB"); - configParam<EQParamQuantity>(HIGH7_PARAM, -1.0f, 1.0f, 0.0f, "Channel 7 high", " dB"); - configParam<AmplifierParamQuantity>(A7_PARAM, 0.0f, 1.0f, 0.0f, "Channel 7 A send"); - configParam(PRE_A7_PARAM, 0.0f, 1.0f, 0.0f, "Channel 7 A send pre/post"); - configParam<AmplifierParamQuantity>(B7_PARAM, 0.0f, 1.0f, 0.0f, "Channel 7 B send"); - configParam(PRE_B7_PARAM, 0.0f, 1.0f, 0.0f, "Channel 7 B send pre/post"); - configParam<EQParamQuantity>(LOW8_PARAM, -1.0f, 1.0f, 0.0f, "Channel 8 low", " dB"); - configParam<EQParamQuantity>(MID8_PARAM, -1.0f, 1.0f, 0.0f, "Channel 8 mid", " dB"); - configParam<EQParamQuantity>(HIGH8_PARAM, -1.0f, 1.0f, 0.0f, "Channel 8 high", " dB"); - configParam<AmplifierParamQuantity>(A8_PARAM, 0.0f, 1.0f, 0.0f, "Channel 8 A send"); - configParam(PRE_A8_PARAM, 0.0f, 1.0f, 0.0f, "Channel 8 A send pre/post"); - configParam<AmplifierParamQuantity>(B8_PARAM, 0.0f, 1.0f, 0.0f, "Channel 8 B send"); - configParam(PRE_B8_PARAM, 0.0f, 1.0f, 0.0f, "Channel 8 B send pre/post"); - configParam<AmplifierParamQuantity>(LEVEL_A_PARAM, 0.0f, 1.0f, 0.8f, "A return level"); - configParam<AmplifierParamQuantity>(LEVEL_B_PARAM, 0.0f, 1.0f, 0.8f, "B return level"); - - _channels[0] = new MixerExpanderChannel(params[LOW1_PARAM], params[MID1_PARAM], params[HIGH1_PARAM], params[A1_PARAM], params[B1_PARAM], params[PRE_A1_PARAM], params[PRE_B1_PARAM], inputs[A1_INPUT], inputs[B1_INPUT]); - _channels[1] = new MixerExpanderChannel(params[LOW2_PARAM], params[MID2_PARAM], params[HIGH2_PARAM], params[A2_PARAM], params[B2_PARAM], params[PRE_A2_PARAM], params[PRE_B2_PARAM], inputs[A2_INPUT], inputs[B2_INPUT]); - _channels[2] = new MixerExpanderChannel(params[LOW3_PARAM], params[MID3_PARAM], params[HIGH3_PARAM], params[A3_PARAM], params[B3_PARAM], params[PRE_A3_PARAM], params[PRE_B3_PARAM], inputs[A3_INPUT], inputs[B3_INPUT]); - _channels[3] = new MixerExpanderChannel(params[LOW4_PARAM], params[MID4_PARAM], params[HIGH4_PARAM], params[A4_PARAM], params[B4_PARAM], params[PRE_A4_PARAM], params[PRE_B4_PARAM], inputs[A4_INPUT], inputs[B4_INPUT]); - _channels[4] = new MixerExpanderChannel(params[LOW5_PARAM], params[MID5_PARAM], params[HIGH5_PARAM], params[A5_PARAM], params[B5_PARAM], params[PRE_A5_PARAM], params[PRE_B5_PARAM], inputs[A5_INPUT], inputs[B5_INPUT]); - _channels[5] = new MixerExpanderChannel(params[LOW6_PARAM], params[MID6_PARAM], params[HIGH6_PARAM], params[A6_PARAM], params[B6_PARAM], params[PRE_A6_PARAM], params[PRE_B6_PARAM], inputs[A6_INPUT], inputs[B6_INPUT]); - _channels[6] = new MixerExpanderChannel(params[LOW7_PARAM], params[MID7_PARAM], params[HIGH7_PARAM], params[A7_PARAM], params[B7_PARAM], params[PRE_A7_PARAM], params[PRE_B7_PARAM], inputs[A7_INPUT], inputs[B7_INPUT]); - _channels[7] = new MixerExpanderChannel(params[LOW8_PARAM], params[MID8_PARAM], params[HIGH8_PARAM], params[A8_PARAM], params[B8_PARAM], params[PRE_A8_PARAM], params[PRE_B8_PARAM], inputs[A8_INPUT], inputs[B8_INPUT]); - - setBaseModel(modelMix8); - } - virtual ~Mix8x() { - for (int i = 0; i < 8; ++i) { - delete _channels[i]; - } - } - - void sampleRateChange() override; - void modulate() override; - void processAll(const ProcessArgs& args) override; -}; - } // namespace bogaudio diff --git a/src/Mix8_shared.hpp b/src/Mix8_shared.hpp @@ -0,0 +1,14 @@ +#pragma once + +#include "bogaudio.hpp" +#include "mixer_expander.hpp" +#include "dsp/signal.hpp" + +extern Model* modelMix8; +extern Model* modelMix8x; + +namespace bogaudio { + +typedef MixerExpanderMessage<8> Mix8ExpanderMessage; + +} // namespace bogaudio diff --git a/src/Mix8x.cpp b/src/Mix8x.cpp @@ -0,0 +1,283 @@ + +#include "Mix8x.hpp" + +void Mix8x::sampleRateChange() { + float sr = APP->engine->getSampleRate(); + for (int i = 0; i < 8; ++i) { + _channels[i]->setSampleRate(sr); + } + _returnASL.setParams(sr, MixerChannel::levelSlewTimeMS, MixerChannel::maxDecibels - MixerChannel::minDecibels); + _returnBSL.setParams(sr, MixerChannel::levelSlewTimeMS, MixerChannel::maxDecibels - MixerChannel::minDecibels); +} + +void Mix8x::modulate() { + for (int i = 0; i < 8; ++i) { + _channels[i]->modulate(); + } +} + +void Mix8x::processAll(const ProcessArgs& args) { + if (!baseConnected()) { + outputs[SEND_A_OUTPUT].setVoltage(0.0f); + outputs[SEND_B_OUTPUT].setVoltage(0.0f); + return; + } + + Mix8ExpanderMessage* from = fromBase(); + Mix8ExpanderMessage* to = toBase(); + float sendA = 0.0f; + float sendB = 0.0f; + bool sendAActive = outputs[SEND_A_OUTPUT].isConnected(); + bool sendBActive = outputs[SEND_B_OUTPUT].isConnected(); + for (int i = 0; i < 8; ++i) { + if (from->active[i]) { + _channels[i]->next(from->preFader[i], from->postFader[i], sendAActive, sendBActive); + to->postEQ[i] = _channels[i]->postEQ; + sendA += _channels[i]->sendA; + sendB += _channels[i]->sendB; + } + else { + to->postEQ[i] = from->preFader[i]; + } + } + outputs[SEND_A_OUTPUT].setVoltage(_saturatorA.next(sendA)); + outputs[SEND_B_OUTPUT].setVoltage(_saturatorA.next(sendB)); + + bool lAActive = inputs[L_A_INPUT].isConnected(); + bool rAActive = inputs[R_A_INPUT].isConnected(); + if (lAActive || rAActive) { + float levelA = clamp(params[LEVEL_A_PARAM].getValue(), 0.0f, 1.0f); + if (inputs[LEVEL_A_INPUT].isConnected()) { + levelA *= clamp(inputs[LEVEL_A_INPUT].getVoltage() / 10.0f, 0.0f, 1.0f); + } + levelA = 1.0f - levelA; + levelA *= Amplifier::minDecibels; + _returnAAmp.setLevel(_returnASL.next(levelA)); + if (lAActive) { + to->returnA[0] = _returnAAmp.next(inputs[L_A_INPUT].getVoltage()); + } + else { + to->returnA[0] = 0.0f; + } + if (rAActive) { + to->returnA[1] = _returnAAmp.next(inputs[R_A_INPUT].getVoltage()); + } + else { + to->returnA[1] = to->returnA[0]; + } + } + + bool lBActive = inputs[L_B_INPUT].isConnected(); + bool rBActive = inputs[R_B_INPUT].isConnected(); + if (lBActive || rBActive) { + float levelB = clamp(params[LEVEL_B_PARAM].getValue(), 0.0f, 1.0f); + levelB = 1.0f - levelB; + levelB *= Amplifier::minDecibels; + _returnBAmp.setLevel(_returnBSL.next(levelB)); + if (lBActive) { + to->returnB[0] = _returnBAmp.next(inputs[L_B_INPUT].getVoltage()); + } + else { + to->returnB[0] = 0.0f; + } + if (rBActive) { + to->returnB[1] = _returnBAmp.next(inputs[R_B_INPUT].getVoltage()); + } + else { + to->returnB[1] = to->returnB[0]; + } + } +} + +struct Mix8xWidget : ModuleWidget { + static constexpr int hp = 27; + + Mix8xWidget(Mix8x* 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/Mix8x.svg"))); + addChild(panel); + } + + addChild(createWidget<ScrewSilver>(Vec(15, 0))); + addChild(createWidget<ScrewSilver>(Vec(box.size.x - 30, 0))); + addChild(createWidget<ScrewSilver>(Vec(15, 365))); + addChild(createWidget<ScrewSilver>(Vec(box.size.x - 30, 365))); + + // generated by svg_widgets.rb + auto low1ParamPosition = Vec(18.5, 43.0); + auto mid1ParamPosition = Vec(18.5, 89.0); + auto high1ParamPosition = Vec(18.5, 135.0); + auto a1ParamPosition = Vec(18.5, 180.0); + auto preA1ParamPosition = Vec(30.0, 208.0); + auto b1ParamPosition = Vec(18.5, 236.0); + auto preB1ParamPosition = Vec(30.0, 264.0); + auto low2ParamPosition = Vec(62.5, 43.0); + auto mid2ParamPosition = Vec(62.5, 89.0); + auto high2ParamPosition = Vec(62.5, 135.0); + auto a2ParamPosition = Vec(62.5, 180.0); + auto preA2ParamPosition = Vec(74.0, 208.0); + auto b2ParamPosition = Vec(62.5, 236.0); + auto preB2ParamPosition = Vec(74.0, 264.0); + auto low3ParamPosition = Vec(106.5, 43.0); + auto mid3ParamPosition = Vec(106.5, 89.0); + auto high3ParamPosition = Vec(106.5, 135.0); + auto a3ParamPosition = Vec(106.5, 180.0); + auto preA3ParamPosition = Vec(118.0, 208.0); + auto b3ParamPosition = Vec(106.5, 236.0); + auto preB3ParamPosition = Vec(118.0, 264.0); + auto low4ParamPosition = Vec(150.5, 43.0); + auto mid4ParamPosition = Vec(150.5, 89.0); + auto high4ParamPosition = Vec(150.5, 135.0); + auto a4ParamPosition = Vec(150.5, 180.0); + auto preA4ParamPosition = Vec(162.0, 208.0); + auto b4ParamPosition = Vec(150.5, 236.0); + auto preB4ParamPosition = Vec(162.0, 264.0); + auto low5ParamPosition = Vec(194.5, 43.0); + auto mid5ParamPosition = Vec(194.5, 89.0); + auto high5ParamPosition = Vec(194.5, 135.0); + auto a5ParamPosition = Vec(194.5, 180.0); + auto preA5ParamPosition = Vec(206.0, 208.0); + auto b5ParamPosition = Vec(194.5, 236.0); + auto preB5ParamPosition = Vec(206.0, 264.0); + auto low6ParamPosition = Vec(238.5, 43.0); + auto mid6ParamPosition = Vec(238.5, 89.0); + auto high6ParamPosition = Vec(238.5, 135.0); + auto a6ParamPosition = Vec(238.5, 180.0); + auto preA6ParamPosition = Vec(250.0, 208.0); + auto b6ParamPosition = Vec(238.5, 236.0); + auto preB6ParamPosition = Vec(250.0, 264.0); + auto low7ParamPosition = Vec(282.5, 43.0); + auto mid7ParamPosition = Vec(282.5, 89.0); + auto high7ParamPosition = Vec(282.5, 135.0); + auto a7ParamPosition = Vec(282.5, 180.0); + auto preA7ParamPosition = Vec(294.0, 208.0); + auto b7ParamPosition = Vec(282.5, 236.0); + auto preB7ParamPosition = Vec(294.0, 264.0); + auto low8ParamPosition = Vec(326.5, 43.0); + auto mid8ParamPosition = Vec(326.5, 89.0); + auto high8ParamPosition = Vec(326.5, 135.0); + auto a8ParamPosition = Vec(326.5, 180.0); + auto preA8ParamPosition = Vec(338.0, 208.0); + auto b8ParamPosition = Vec(326.5, 236.0); + auto preB8ParamPosition = Vec(338.0, 264.0); + auto levelAParamPosition = Vec(370.5, 138.0); + auto levelBParamPosition = Vec(370.5, 328.0); + + auto a1InputPosition = Vec(14.5, 290.0); + auto b1InputPosition = Vec(14.5, 325.0); + auto a2InputPosition = Vec(58.5, 290.0); + auto b2InputPosition = Vec(58.5, 325.0); + auto a3InputPosition = Vec(102.5, 290.0); + auto b3InputPosition = Vec(102.5, 325.0); + auto a4InputPosition = Vec(146.5, 290.0); + auto b4InputPosition = Vec(146.5, 325.0); + auto a5InputPosition = Vec(190.5, 290.0); + auto b5InputPosition = Vec(190.5, 325.0); + auto a6InputPosition = Vec(234.5, 290.0); + auto b6InputPosition = Vec(234.5, 325.0); + auto a7InputPosition = Vec(278.5, 290.0); + auto b7InputPosition = Vec(278.5, 325.0); + auto a8InputPosition = Vec(322.5, 290.0); + auto b8InputPosition = Vec(322.5, 325.0); + auto lAInputPosition = Vec(366.5, 62.0); + auto rAInputPosition = Vec(366.5, 97.0); + auto levelAInputPosition = Vec(366.5, 170.0); + auto lBInputPosition = Vec(366.5, 252.0); + auto rBInputPosition = Vec(366.5, 287.0); + + auto sendAOutputPosition = Vec(366.5, 24.0); + auto sendBOutputPosition = Vec(366.5, 214.0); + // end generated by svg_widgets.rb + + addParam(createParam<Knob16>(low1ParamPosition, module, Mix8x::LOW1_PARAM)); + addParam(createParam<Knob16>(mid1ParamPosition, module, Mix8x::MID1_PARAM)); + addParam(createParam<Knob16>(high1ParamPosition, module, Mix8x::HIGH1_PARAM)); + addParam(createParam<Knob16>(a1ParamPosition, module, Mix8x::A1_PARAM)); + addParam(createParam<IndicatorButtonGreen9>(preA1ParamPosition, module, Mix8x::PRE_A1_PARAM)); + addParam(createParam<Knob16>(b1ParamPosition, module, Mix8x::B1_PARAM)); + addParam(createParam<IndicatorButtonGreen9>(preB1ParamPosition, module, Mix8x::PRE_B1_PARAM)); + addParam(createParam<Knob16>(low2ParamPosition, module, Mix8x::LOW2_PARAM)); + addParam(createParam<Knob16>(mid2ParamPosition, module, Mix8x::MID2_PARAM)); + addParam(createParam<Knob16>(high2ParamPosition, module, Mix8x::HIGH2_PARAM)); + addParam(createParam<Knob16>(a2ParamPosition, module, Mix8x::A2_PARAM)); + addParam(createParam<IndicatorButtonGreen9>(preA2ParamPosition, module, Mix8x::PRE_A2_PARAM)); + addParam(createParam<Knob16>(b2ParamPosition, module, Mix8x::B2_PARAM)); + addParam(createParam<IndicatorButtonGreen9>(preB2ParamPosition, module, Mix8x::PRE_B2_PARAM)); + addParam(createParam<Knob16>(low3ParamPosition, module, Mix8x::LOW3_PARAM)); + addParam(createParam<Knob16>(mid3ParamPosition, module, Mix8x::MID3_PARAM)); + addParam(createParam<Knob16>(high3ParamPosition, module, Mix8x::HIGH3_PARAM)); + addParam(createParam<Knob16>(a3ParamPosition, module, Mix8x::A3_PARAM)); + addParam(createParam<IndicatorButtonGreen9>(preA3ParamPosition, module, Mix8x::PRE_A3_PARAM)); + addParam(createParam<Knob16>(b3ParamPosition, module, Mix8x::B3_PARAM)); + addParam(createParam<IndicatorButtonGreen9>(preB3ParamPosition, module, Mix8x::PRE_B3_PARAM)); + addParam(createParam<Knob16>(low4ParamPosition, module, Mix8x::LOW4_PARAM)); + addParam(createParam<Knob16>(mid4ParamPosition, module, Mix8x::MID4_PARAM)); + addParam(createParam<Knob16>(high4ParamPosition, module, Mix8x::HIGH4_PARAM)); + addParam(createParam<Knob16>(a4ParamPosition, module, Mix8x::A4_PARAM)); + addParam(createParam<IndicatorButtonGreen9>(preA4ParamPosition, module, Mix8x::PRE_A4_PARAM)); + addParam(createParam<Knob16>(b4ParamPosition, module, Mix8x::B4_PARAM)); + addParam(createParam<IndicatorButtonGreen9>(preB4ParamPosition, module, Mix8x::PRE_B4_PARAM)); + addParam(createParam<Knob16>(low5ParamPosition, module, Mix8x::LOW5_PARAM)); + addParam(createParam<Knob16>(mid5ParamPosition, module, Mix8x::MID5_PARAM)); + addParam(createParam<Knob16>(high5ParamPosition, module, Mix8x::HIGH5_PARAM)); + addParam(createParam<Knob16>(a5ParamPosition, module, Mix8x::A5_PARAM)); + addParam(createParam<IndicatorButtonGreen9>(preA5ParamPosition, module, Mix8x::PRE_A5_PARAM)); + addParam(createParam<Knob16>(b5ParamPosition, module, Mix8x::B5_PARAM)); + addParam(createParam<IndicatorButtonGreen9>(preB5ParamPosition, module, Mix8x::PRE_B5_PARAM)); + addParam(createParam<Knob16>(low6ParamPosition, module, Mix8x::LOW6_PARAM)); + addParam(createParam<Knob16>(mid6ParamPosition, module, Mix8x::MID6_PARAM)); + addParam(createParam<Knob16>(high6ParamPosition, module, Mix8x::HIGH6_PARAM)); + addParam(createParam<Knob16>(a6ParamPosition, module, Mix8x::A6_PARAM)); + addParam(createParam<IndicatorButtonGreen9>(preA6ParamPosition, module, Mix8x::PRE_A6_PARAM)); + addParam(createParam<Knob16>(b6ParamPosition, module, Mix8x::B6_PARAM)); + addParam(createParam<IndicatorButtonGreen9>(preB6ParamPosition, module, Mix8x::PRE_B6_PARAM)); + addParam(createParam<Knob16>(low7ParamPosition, module, Mix8x::LOW7_PARAM)); + addParam(createParam<Knob16>(mid7ParamPosition, module, Mix8x::MID7_PARAM)); + addParam(createParam<Knob16>(high7ParamPosition, module, Mix8x::HIGH7_PARAM)); + addParam(createParam<Knob16>(a7ParamPosition, module, Mix8x::A7_PARAM)); + addParam(createParam<IndicatorButtonGreen9>(preA7ParamPosition, module, Mix8x::PRE_A7_PARAM)); + addParam(createParam<Knob16>(b7ParamPosition, module, Mix8x::B7_PARAM)); + addParam(createParam<IndicatorButtonGreen9>(preB7ParamPosition, module, Mix8x::PRE_B7_PARAM)); + addParam(createParam<Knob16>(low8ParamPosition, module, Mix8x::LOW8_PARAM)); + addParam(createParam<Knob16>(mid8ParamPosition, module, Mix8x::MID8_PARAM)); + addParam(createParam<Knob16>(high8ParamPosition, module, Mix8x::HIGH8_PARAM)); + addParam(createParam<Knob16>(a8ParamPosition, module, Mix8x::A8_PARAM)); + addParam(createParam<IndicatorButtonGreen9>(preA8ParamPosition, module, Mix8x::PRE_A8_PARAM)); + addParam(createParam<Knob16>(b8ParamPosition, module, Mix8x::B8_PARAM)); + addParam(createParam<IndicatorButtonGreen9>(preB8ParamPosition, module, Mix8x::PRE_B8_PARAM)); + addParam(createParam<Knob16>(levelAParamPosition, module, Mix8x::LEVEL_A_PARAM)); + addParam(createParam<Knob16>(levelBParamPosition, module, Mix8x::LEVEL_B_PARAM)); + + addInput(createInput<Port24>(a1InputPosition, module, Mix8x::A1_INPUT)); + addInput(createInput<Port24>(b1InputPosition, module, Mix8x::B1_INPUT)); + addInput(createInput<Port24>(a2InputPosition, module, Mix8x::A2_INPUT)); + addInput(createInput<Port24>(b2InputPosition, module, Mix8x::B2_INPUT)); + addInput(createInput<Port24>(a3InputPosition, module, Mix8x::A3_INPUT)); + addInput(createInput<Port24>(b3InputPosition, module, Mix8x::B3_INPUT)); + addInput(createInput<Port24>(a4InputPosition, module, Mix8x::A4_INPUT)); + addInput(createInput<Port24>(b4InputPosition, module, Mix8x::B4_INPUT)); + addInput(createInput<Port24>(a5InputPosition, module, Mix8x::A5_INPUT)); + addInput(createInput<Port24>(b5InputPosition, module, Mix8x::B5_INPUT)); + addInput(createInput<Port24>(a6InputPosition, module, Mix8x::A6_INPUT)); + addInput(createInput<Port24>(b6InputPosition, module, Mix8x::B6_INPUT)); + addInput(createInput<Port24>(a7InputPosition, module, Mix8x::A7_INPUT)); + addInput(createInput<Port24>(b7InputPosition, module, Mix8x::B7_INPUT)); + addInput(createInput<Port24>(a8InputPosition, module, Mix8x::A8_INPUT)); + addInput(createInput<Port24>(b8InputPosition, module, Mix8x::B8_INPUT)); + addInput(createInput<Port24>(lAInputPosition, module, Mix8x::L_A_INPUT)); + addInput(createInput<Port24>(rAInputPosition, module, Mix8x::R_A_INPUT)); + addInput(createInput<Port24>(levelAInputPosition, module, Mix8x::LEVEL_A_INPUT)); + addInput(createInput<Port24>(lBInputPosition, module, Mix8x::L_B_INPUT)); + addInput(createInput<Port24>(rBInputPosition, module, Mix8x::R_B_INPUT)); + + addOutput(createOutput<Port24>(sendAOutputPosition, module, Mix8x::SEND_A_OUTPUT)); + addOutput(createOutput<Port24>(sendBOutputPosition, module, Mix8x::SEND_B_OUTPUT)); + } +}; + +Model* modelMix8x = createModel<Mix8x, Mix8xWidget>("Bogaudio-Mix8x", "MIX8X", "Expander for MIX8, adds EQs and sends", "Mixer", "Expander"); diff --git a/src/Mix8x.hpp b/src/Mix8x.hpp @@ -0,0 +1,191 @@ +#pragma once + +#include "bogaudio.hpp" +#include "Mix8_shared.hpp" + +using namespace bogaudio::dsp; +namespace bogaudio { + +struct Mix8x : ExpanderModule<Mix8ExpanderMessage, BGModule> { + enum ParamsIds { + LOW1_PARAM, + MID1_PARAM, + HIGH1_PARAM, + A1_PARAM, + PRE_A1_PARAM, + B1_PARAM, + PRE_B1_PARAM, + LOW2_PARAM, + MID2_PARAM, + HIGH2_PARAM, + A2_PARAM, + PRE_A2_PARAM, + B2_PARAM, + PRE_B2_PARAM, + LOW3_PARAM, + MID3_PARAM, + HIGH3_PARAM, + A3_PARAM, + PRE_A3_PARAM, + B3_PARAM, + PRE_B3_PARAM, + LOW4_PARAM, + MID4_PARAM, + HIGH4_PARAM, + A4_PARAM, + PRE_A4_PARAM, + B4_PARAM, + PRE_B4_PARAM, + LOW5_PARAM, + MID5_PARAM, + HIGH5_PARAM, + A5_PARAM, + PRE_A5_PARAM, + B5_PARAM, + PRE_B5_PARAM, + LOW6_PARAM, + MID6_PARAM, + HIGH6_PARAM, + A6_PARAM, + PRE_A6_PARAM, + B6_PARAM, + PRE_B6_PARAM, + LOW7_PARAM, + MID7_PARAM, + HIGH7_PARAM, + A7_PARAM, + PRE_A7_PARAM, + B7_PARAM, + PRE_B7_PARAM, + LOW8_PARAM, + MID8_PARAM, + HIGH8_PARAM, + A8_PARAM, + PRE_A8_PARAM, + B8_PARAM, + PRE_B8_PARAM, + LEVEL_A_PARAM, + LEVEL_B_PARAM, + NUM_PARAMS + }; + + enum InputsIds { + A1_INPUT, + B1_INPUT, + A2_INPUT, + B2_INPUT, + A3_INPUT, + B3_INPUT, + A4_INPUT, + B4_INPUT, + A5_INPUT, + B5_INPUT, + A6_INPUT, + B6_INPUT, + A7_INPUT, + B7_INPUT, + A8_INPUT, + B8_INPUT, + L_A_INPUT, + R_A_INPUT, + LEVEL_A_INPUT, + L_B_INPUT, + R_B_INPUT, + NUM_INPUTS + }; + + enum OutputsIds { + SEND_A_OUTPUT, + SEND_B_OUTPUT, + NUM_OUTPUTS + }; + + MixerExpanderChannel* _channels[8] {}; + Saturator _saturatorA, _saturatorB; + Amplifier _returnAAmp, _returnBAmp; + bogaudio::dsp::SlewLimiter _returnASL, _returnBSL; + + Mix8x() { + config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS); + configParam<EQParamQuantity>(LOW1_PARAM, -1.0f, 1.0f, 0.0f, "Channel 1 low", " dB"); + configParam<EQParamQuantity>(MID1_PARAM, -1.0f, 1.0f, 0.0f, "Channel 1 mid", " dB"); + configParam<EQParamQuantity>(HIGH1_PARAM, -1.0f, 1.0f, 0.0f, "Channel 1 high", " dB"); + configParam<AmplifierParamQuantity>(A1_PARAM, 0.0f, 1.0f, 0.0f, "Channel 1 A send"); + configParam(PRE_A1_PARAM, 0.0f, 1.0f, 0.0f, "Channel 1 A send pre/post"); + configParam<AmplifierParamQuantity>(B1_PARAM, 0.0f, 1.0f, 0.0f, "Channel 1 B send"); + configParam(PRE_B1_PARAM, 0.0f, 1.0f, 0.0f, "Channel 1 B send pre/post"); + configParam<EQParamQuantity>(LOW2_PARAM, -1.0f, 1.0f, 0.0f, "Channel 2 low", " dB"); + configParam<EQParamQuantity>(MID2_PARAM, -1.0f, 1.0f, 0.0f, "Channel 2 mid", " dB"); + configParam<EQParamQuantity>(HIGH2_PARAM, -1.0f, 1.0f, 0.0f, "Channel 2 high", " dB"); + configParam<AmplifierParamQuantity>(A2_PARAM, 0.0f, 1.0f, 0.0f, "Channel 2 A send"); + configParam(PRE_A2_PARAM, 0.0f, 1.0f, 0.0f, "Channel 2 A send pre/post"); + configParam<AmplifierParamQuantity>(B2_PARAM, 0.0f, 1.0f, 0.0f, "Channel 2 B send"); + configParam(PRE_B2_PARAM, 0.0f, 1.0f, 0.0f, "Channel 2 B send pre/post"); + configParam<EQParamQuantity>(LOW3_PARAM, -1.0f, 1.0f, 0.0f, "Channel 3 low", " dB"); + configParam<EQParamQuantity>(MID3_PARAM, -1.0f, 1.0f, 0.0f, "Channel 3 mid", " dB"); + configParam<EQParamQuantity>(HIGH3_PARAM, -1.0f, 1.0f, 0.0f, "Channel 3 high", " dB"); + configParam<AmplifierParamQuantity>(A3_PARAM, 0.0f, 1.0f, 0.0f, "Channel 3 A send"); + configParam(PRE_A3_PARAM, 0.0f, 1.0f, 0.0f, "Channel 3 A send pre/post"); + configParam<AmplifierParamQuantity>(B3_PARAM, 0.0f, 1.0f, 0.0f, "Channel 3 B send"); + configParam(PRE_B3_PARAM, 0.0f, 1.0f, 0.0f, "Channel 3 B send pre/post"); + configParam<EQParamQuantity>(LOW4_PARAM, -1.0f, 1.0f, 0.0f, "Channel 4 low", " dB"); + configParam<EQParamQuantity>(MID4_PARAM, -1.0f, 1.0f, 0.0f, "Channel 4 mid", " dB"); + configParam<EQParamQuantity>(HIGH4_PARAM, -1.0f, 1.0f, 0.0f, "Channel 4 high", " dB"); + configParam<AmplifierParamQuantity>(A4_PARAM, 0.0f, 1.0f, 0.0f, "Channel 4 A send"); + configParam(PRE_A4_PARAM, 0.0f, 1.0f, 0.0f, "Channel 4 A send pre/post"); + configParam<AmplifierParamQuantity>(B4_PARAM, 0.0f, 1.0f, 0.0f, "Channel 4 B send"); + configParam(PRE_B4_PARAM, 0.0f, 1.0f, 0.0f, "Channel 4 B send pre/post"); + configParam<EQParamQuantity>(LOW5_PARAM, -1.0f, 1.0f, 0.0f, "Channel 5 low", " dB"); + configParam<EQParamQuantity>(MID5_PARAM, -1.0f, 1.0f, 0.0f, "Channel 5 mid", " dB"); + configParam<EQParamQuantity>(HIGH5_PARAM, -1.0f, 1.0f, 0.0f, "Channel 5 high", " dB"); + configParam<AmplifierParamQuantity>(A5_PARAM, 0.0f, 1.0f, 0.0f, "Channel 5 A send"); + configParam(PRE_A5_PARAM, 0.0f, 1.0f, 0.0f, "Channel 5 A send pre/post"); + configParam<AmplifierParamQuantity>(B5_PARAM, 0.0f, 1.0f, 0.0f, "Channel 5 B send"); + configParam(PRE_B5_PARAM, 0.0f, 1.0f, 0.0f, "Channel 5 B send pre/post"); + configParam<EQParamQuantity>(LOW6_PARAM, -1.0f, 1.0f, 0.0f, "Channel 6 low", " dB"); + configParam<EQParamQuantity>(MID6_PARAM, -1.0f, 1.0f, 0.0f, "Channel 6 mid", " dB"); + configParam<EQParamQuantity>(HIGH6_PARAM, -1.0f, 1.0f, 0.0f, "Channel 6 high", " dB"); + configParam<AmplifierParamQuantity>(A6_PARAM, 0.0f, 1.0f, 0.0f, "Channel 6 A send"); + configParam(PRE_A6_PARAM, 0.0f, 1.0f, 0.0f, "Channel 6 A send pre/post"); + configParam<AmplifierParamQuantity>(B6_PARAM, 0.0f, 1.0f, 0.0f, "Channel 6 B send"); + configParam(PRE_B6_PARAM, 0.0f, 1.0f, 0.0f, "Channel 6 B send pre/post"); + configParam<EQParamQuantity>(LOW7_PARAM, -1.0f, 1.0f, 0.0f, "Channel 7 low", " dB"); + configParam<EQParamQuantity>(MID7_PARAM, -1.0f, 1.0f, 0.0f, "Channel 7 mid", " dB"); + configParam<EQParamQuantity>(HIGH7_PARAM, -1.0f, 1.0f, 0.0f, "Channel 7 high", " dB"); + configParam<AmplifierParamQuantity>(A7_PARAM, 0.0f, 1.0f, 0.0f, "Channel 7 A send"); + configParam(PRE_A7_PARAM, 0.0f, 1.0f, 0.0f, "Channel 7 A send pre/post"); + configParam<AmplifierParamQuantity>(B7_PARAM, 0.0f, 1.0f, 0.0f, "Channel 7 B send"); + configParam(PRE_B7_PARAM, 0.0f, 1.0f, 0.0f, "Channel 7 B send pre/post"); + configParam<EQParamQuantity>(LOW8_PARAM, -1.0f, 1.0f, 0.0f, "Channel 8 low", " dB"); + configParam<EQParamQuantity>(MID8_PARAM, -1.0f, 1.0f, 0.0f, "Channel 8 mid", " dB"); + configParam<EQParamQuantity>(HIGH8_PARAM, -1.0f, 1.0f, 0.0f, "Channel 8 high", " dB"); + configParam<AmplifierParamQuantity>(A8_PARAM, 0.0f, 1.0f, 0.0f, "Channel 8 A send"); + configParam(PRE_A8_PARAM, 0.0f, 1.0f, 0.0f, "Channel 8 A send pre/post"); + configParam<AmplifierParamQuantity>(B8_PARAM, 0.0f, 1.0f, 0.0f, "Channel 8 B send"); + configParam(PRE_B8_PARAM, 0.0f, 1.0f, 0.0f, "Channel 8 B send pre/post"); + configParam<AmplifierParamQuantity>(LEVEL_A_PARAM, 0.0f, 1.0f, 0.8f, "A return level"); + configParam<AmplifierParamQuantity>(LEVEL_B_PARAM, 0.0f, 1.0f, 0.8f, "B return level"); + + _channels[0] = new MixerExpanderChannel(params[LOW1_PARAM], params[MID1_PARAM], params[HIGH1_PARAM], params[A1_PARAM], params[B1_PARAM], params[PRE_A1_PARAM], params[PRE_B1_PARAM], inputs[A1_INPUT], inputs[B1_INPUT]); + _channels[1] = new MixerExpanderChannel(params[LOW2_PARAM], params[MID2_PARAM], params[HIGH2_PARAM], params[A2_PARAM], params[B2_PARAM], params[PRE_A2_PARAM], params[PRE_B2_PARAM], inputs[A2_INPUT], inputs[B2_INPUT]); + _channels[2] = new MixerExpanderChannel(params[LOW3_PARAM], params[MID3_PARAM], params[HIGH3_PARAM], params[A3_PARAM], params[B3_PARAM], params[PRE_A3_PARAM], params[PRE_B3_PARAM], inputs[A3_INPUT], inputs[B3_INPUT]); + _channels[3] = new MixerExpanderChannel(params[LOW4_PARAM], params[MID4_PARAM], params[HIGH4_PARAM], params[A4_PARAM], params[B4_PARAM], params[PRE_A4_PARAM], params[PRE_B4_PARAM], inputs[A4_INPUT], inputs[B4_INPUT]); + _channels[4] = new MixerExpanderChannel(params[LOW5_PARAM], params[MID5_PARAM], params[HIGH5_PARAM], params[A5_PARAM], params[B5_PARAM], params[PRE_A5_PARAM], params[PRE_B5_PARAM], inputs[A5_INPUT], inputs[B5_INPUT]); + _channels[5] = new MixerExpanderChannel(params[LOW6_PARAM], params[MID6_PARAM], params[HIGH6_PARAM], params[A6_PARAM], params[B6_PARAM], params[PRE_A6_PARAM], params[PRE_B6_PARAM], inputs[A6_INPUT], inputs[B6_INPUT]); + _channels[6] = new MixerExpanderChannel(params[LOW7_PARAM], params[MID7_PARAM], params[HIGH7_PARAM], params[A7_PARAM], params[B7_PARAM], params[PRE_A7_PARAM], params[PRE_B7_PARAM], inputs[A7_INPUT], inputs[B7_INPUT]); + _channels[7] = new MixerExpanderChannel(params[LOW8_PARAM], params[MID8_PARAM], params[HIGH8_PARAM], params[A8_PARAM], params[B8_PARAM], params[PRE_A8_PARAM], params[PRE_B8_PARAM], inputs[A8_INPUT], inputs[B8_INPUT]); + + setBaseModel(modelMix8); + } + virtual ~Mix8x() { + for (int i = 0; i < 8; ++i) { + delete _channels[i]; + } + } + + void sampleRateChange() override; + void modulate() override; + void processAll(const ProcessArgs& args) override; +}; + +} // namespace bogaudio diff --git a/src/Pgmr.cpp b/src/Pgmr.cpp @@ -3,82 +3,6 @@ #define SELECT_TRIGGERS "SELECT_TRIGGERS" -void PgmrStep::reset() { - for (int c = 0; c < BGModule::maxChannels; ++c) { - triggers[c].reset(); - pulseGens[c].process(1000.0f); - } -} - - -PgmrRegistry::Base::Base(Pgmr& b) : module(b) { - std::copy(b._localSteps, b._localSteps + 4, std::back_inserter(steps)); -} - -int PgmrRegistry::registerBase(Pgmr& b) { - std::lock_guard<std::mutex> lock(_lock); - - int id = _nextID; - ++_nextID; - auto p = _bases.emplace(id, Base(b)); - b.setSteps(p.first->second.steps); - return id; -} - -void PgmrRegistry::deregisterBase(int id) { - std::lock_guard<std::mutex> lock(_lock); - _bases.erase(id); -} - -void PgmrRegistry::registerExpander(int baseID, int position, PgmrX& x) { - std::lock_guard<std::mutex> lock(_lock); - - assert(position > 0); - auto base = _bases.find(baseID); - if (base != _bases.end()) { - int i = 4 * position; - if (i < (int)base->second.steps.size()) { - assert(!base->second.steps[i]); - std::copy(x._localSteps, x._localSteps + 4, base->second.steps.begin() + i); - } - else { - base->second.steps.resize(i + 4, NULL); - std::copy(x._localSteps, x._localSteps + 4, base->second.steps.begin() + i); - } - for (auto i = base->second.steps.begin(), n = base->second.steps.end(); i != n; ++i) { - if (!*i) { - return; - } - } - base->second.module.setSteps(base->second.steps); - } -} - -void PgmrRegistry::deregisterExpander(int baseID, int position) { - std::lock_guard<std::mutex> lock(_lock); - - auto base = _bases.find(baseID); - if (base != _bases.end()) { - int n = 4 * position; - if (n < (int)base->second.steps.size()) { - int i = 0; - for (; i < n; ++i) { - if (!base->second.steps[i]) { - break; - } - } - base->second.steps.resize(i); - base->second.module.setSteps(base->second.steps); - } - } -} - -PgmrRegistry& PgmrRegistry::registry() { - static PgmrRegistry instance; - return instance; -} - - void Pgmr::reset() { std::lock_guard<SpinLock> lock(_stepsLock); @@ -332,139 +256,3 @@ struct PgmrWidget : AddressableSequenceBaseModuleWidget { }; Model* modelPgmr = createModel<Pgmr, PgmrWidget>("Bogaudio-Pgmr", "PGMR", "4-step programmer and sequencer", "Sequencer", "Polyphonic"); - - -void PgmrX::processAlways(const ProcessArgs& args) { - int position = 0; - int baseID = 0; - if (baseConnected()) { - PgmrExpanderMessage* bm = fromBase(); - baseID = bm->baseID; - position = bm->position; - _rangeOffset = bm->rangeOffset; - _rangeScale = bm->rangeScale; - } - - if (_registered && (position <= 0 || position != _position)) { - PgmrRegistry::registry().deregisterExpander(_baseID, _position); - _registered = false; - _baseID = 0; - _position = 0; - } - else if (!_registered && position > 0) { - _registered = true; - _baseID = baseID; - _position = position; - PgmrRegistry::registry().registerExpander(_baseID, _position, *this); - } - - if (_position < 1) { - for (int i = 0; i < 4; ++i) { - _localSteps[i]->selectedLight.value = 0.0f; - } - } - if (expanderConnected()) { - PgmrExpanderMessage* te = toExpander(); - te->baseID = _baseID; - te->position = _position > 0 ? _position + 1 : 0; - te->rangeOffset = _rangeOffset; - te->rangeScale = _rangeScale; - } -} - -struct PgmrXWidget : ModuleWidget { - static constexpr int hp = 12; - - PgmrXWidget(PgmrX* 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/PgmrX.svg"))); - addChild(panel); - } - - addChild(createWidget<ScrewSilver>(Vec(0, 0))); - addChild(createWidget<ScrewSilver>(Vec(box.size.x - 15, 0))); - addChild(createWidget<ScrewSilver>(Vec(0, 365))); - addChild(createWidget<ScrewSilver>(Vec(box.size.x - 15, 365))); - - // generated by svg_widgets.rb - auto cva1ParamPosition = Vec(9.5, 40.5); - auto cvb1ParamPosition = Vec(9.5, 94.5); - auto cvc1ParamPosition = Vec(9.5, 148.5); - auto cvd1ParamPosition = Vec(9.5, 202.5); - auto select1ParamPosition = Vec(13.5, 267.0); - auto cva2ParamPosition = Vec(54.5, 40.5); - auto cvb2ParamPosition = Vec(54.5, 94.5); - auto cvc2ParamPosition = Vec(54.5, 148.5); - auto cvd2ParamPosition = Vec(54.5, 202.5); - auto select2ParamPosition = Vec(58.5, 267.0); - auto cva3ParamPosition = Vec(99.5, 40.5); - auto cvb3ParamPosition = Vec(99.5, 94.5); - auto cvc3ParamPosition = Vec(99.5, 148.5); - auto cvd3ParamPosition = Vec(99.5, 202.5); - auto select3ParamPosition = Vec(103.5, 267.0); - auto cva4ParamPosition = Vec(144.5, 40.5); - auto cvb4ParamPosition = Vec(144.5, 94.5); - auto cvc4ParamPosition = Vec(144.5, 148.5); - auto cvd4ParamPosition = Vec(144.5, 202.5); - auto select4ParamPosition = Vec(148.5, 267.0); - - auto select1InputPosition = Vec(10.5, 290.0); - auto select2InputPosition = Vec(55.5, 290.0); - auto select3InputPosition = Vec(100.5, 290.0); - auto select4InputPosition = Vec(145.5, 290.0); - - auto select1OutputPosition = Vec(10.5, 330.0); - auto select2OutputPosition = Vec(55.5, 330.0); - auto select3OutputPosition = Vec(100.5, 330.0); - auto select4OutputPosition = Vec(145.5, 330.0); - - auto select1LightPosition = Vec(19.3, 255.0); - auto select2LightPosition = Vec(64.3, 255.0); - auto select3LightPosition = Vec(109.3, 255.0); - auto select4LightPosition = Vec(154.3, 255.0); - // end generated by svg_widgets.rb - - addParam(createParam<Knob26>(cva1ParamPosition, module, PgmrX::CVA1_PARAM)); - addParam(createParam<Knob26>(cvb1ParamPosition, module, PgmrX::CVB1_PARAM)); - addParam(createParam<Knob26>(cvc1ParamPosition, module, PgmrX::CVC1_PARAM)); - addParam(createParam<Knob26>(cvd1ParamPosition, module, PgmrX::CVD1_PARAM)); - addParam(createParam<Button18>(select1ParamPosition, module, PgmrX::SELECT1_PARAM)); - addParam(createParam<Knob26>(cva2ParamPosition, module, PgmrX::CVA2_PARAM)); - addParam(createParam<Knob26>(cvb2ParamPosition, module, PgmrX::CVB2_PARAM)); - addParam(createParam<Knob26>(cvc2ParamPosition, module, PgmrX::CVC2_PARAM)); - addParam(createParam<Knob26>(cvd2ParamPosition, module, PgmrX::CVD2_PARAM)); - addParam(createParam<Button18>(select2ParamPosition, module, PgmrX::SELECT2_PARAM)); - addParam(createParam<Knob26>(cva3ParamPosition, module, PgmrX::CVA3_PARAM)); - addParam(createParam<Knob26>(cvb3ParamPosition, module, PgmrX::CVB3_PARAM)); - addParam(createParam<Knob26>(cvc3ParamPosition, module, PgmrX::CVC3_PARAM)); - addParam(createParam<Knob26>(cvd3ParamPosition, module, PgmrX::CVD3_PARAM)); - addParam(createParam<Button18>(select3ParamPosition, module, PgmrX::SELECT3_PARAM)); - addParam(createParam<Knob26>(cva4ParamPosition, module, PgmrX::CVA4_PARAM)); - addParam(createParam<Knob26>(cvb4ParamPosition, module, PgmrX::CVB4_PARAM)); - addParam(createParam<Knob26>(cvc4ParamPosition, module, PgmrX::CVC4_PARAM)); - addParam(createParam<Knob26>(cvd4ParamPosition, module, PgmrX::CVD4_PARAM)); - addParam(createParam<Button18>(select4ParamPosition, module, PgmrX::SELECT4_PARAM)); - - addInput(createInput<Port24>(select1InputPosition, module, PgmrX::SELECT1_INPUT)); - addInput(createInput<Port24>(select2InputPosition, module, PgmrX::SELECT2_INPUT)); - addInput(createInput<Port24>(select3InputPosition, module, PgmrX::SELECT3_INPUT)); - addInput(createInput<Port24>(select4InputPosition, module, PgmrX::SELECT4_INPUT)); - - addOutput(createOutput<Port24>(select1OutputPosition, module, PgmrX::SELECT1_OUTPUT)); - addOutput(createOutput<Port24>(select2OutputPosition, module, PgmrX::SELECT2_OUTPUT)); - addOutput(createOutput<Port24>(select3OutputPosition, module, PgmrX::SELECT3_OUTPUT)); - addOutput(createOutput<Port24>(select4OutputPosition, module, PgmrX::SELECT4_OUTPUT)); - - addChild(createLight<SmallLight<GreenLight>>(select1LightPosition, module, PgmrX::SELECT1_LIGHT)); - addChild(createLight<SmallLight<GreenLight>>(select2LightPosition, module, PgmrX::SELECT2_LIGHT)); - addChild(createLight<SmallLight<GreenLight>>(select3LightPosition, module, PgmrX::SELECT3_LIGHT)); - addChild(createLight<SmallLight<GreenLight>>(select4LightPosition, module, PgmrX::SELECT4_LIGHT)); - } -}; - -Model* modelPgmrX = createModel<PgmrX, PgmrXWidget>("Bogaudio-PgmrX", "PGMRX", "4-step chainable expander for PGMR", "Sequencer", "Expander", "Polyphonic"); diff --git a/src/Pgmr.hpp b/src/Pgmr.hpp @@ -1,99 +1,9 @@ #pragma once -#include <mutex> -#include <unordered_map> - -#include "bogaudio.hpp" -#include "addressable_sequence.hpp" -#include "expanders.hpp" - -extern Model* modelPgmr; -extern Model* modelPgmrX; +#include "Pgmr_shared.hpp" namespace bogaudio { -struct PgmrExpanderMessage : ExpanderMessage { - int baseID = -1; - int position = -1; - float rangeOffset = 0.0f; - float rangeScale = 10.0f; -}; - -struct PgmrStep { - Param& aParam; - Param& bParam; - Param& cParam; - Param& dParam; - Light& selectedLight; - Param& selectParam; - Input& selectInput; - Output& selectedOutput; - - Trigger triggers[BGModule::maxChannels]; - rack::dsp::PulseGenerator pulseGens[BGModule::maxChannels]; - float lightSum = 0.0f; - - PgmrStep( - Param& aParam, - Param& bParam, - Param& cParam, - Param& dParam, - Light& selectedLight, - Param& selectParam, - Input& selectInput, - Output& selectedOutput - ) - : aParam(aParam) - , bParam(bParam) - , cParam(cParam) - , dParam(dParam) - , selectedLight(selectedLight) - , selectParam(selectParam) - , selectInput(selectInput) - , selectedOutput(selectedOutput) - { - } - - void reset(); -}; - -struct PgmrBase { - PgmrStep* _localSteps[4] {}; - - virtual ~PgmrBase() { - for (int i = 0; i < 4; ++i) { - if (_localSteps[i]) { - delete _localSteps[i]; - } - } - } -}; - -struct Pgmr; -struct PgmrX; - -struct PgmrRegistry { -private: - struct Base { - Pgmr& module; - std::vector<PgmrStep*> steps; - - Base(Pgmr& b); - }; - - std::mutex _lock; - int _nextID = 1; - std::unordered_map<int, Base> _bases; - -public: - int registerBase(Pgmr& b); - void deregisterBase(int id); - void registerExpander(int baseID, int position, PgmrX& x); - void deregisterExpander(int baseID, int position); - - static PgmrRegistry& registry(); -}; - struct Pgmr : ExpandableModule<PgmrExpanderMessage, OutputRangeAddressableSequenceModule>, PgmrBase { enum ParamsIds { DIRECTION_PARAM, @@ -208,96 +118,4 @@ struct Pgmr : ExpandableModule<PgmrExpanderMessage, OutputRangeAddressableSequen void setSteps(std::vector<PgmrStep*>& steps); }; -struct PgmrX : ExpanderModule<PgmrExpanderMessage, ExpandableModule<PgmrExpanderMessage, BGModule>>, PgmrBase, OutputRange { - enum ParamsIds { - CVA1_PARAM, - CVB1_PARAM, - CVC1_PARAM, - CVD1_PARAM, - SELECT1_PARAM, - CVA2_PARAM, - CVB2_PARAM, - CVC2_PARAM, - CVD2_PARAM, - SELECT2_PARAM, - CVA3_PARAM, - CVB3_PARAM, - CVC3_PARAM, - CVD3_PARAM, - SELECT3_PARAM, - CVA4_PARAM, - CVB4_PARAM, - CVC4_PARAM, - CVD4_PARAM, - SELECT4_PARAM, - NUM_PARAMS - }; - - enum InputsIds { - SELECT1_INPUT, - SELECT2_INPUT, - SELECT3_INPUT, - SELECT4_INPUT, - NUM_INPUTS - }; - - enum OutputsIds { - SELECT1_OUTPUT, - SELECT2_OUTPUT, - SELECT3_OUTPUT, - SELECT4_OUTPUT, - NUM_OUTPUTS - }; - - enum LightsIds { - SELECT1_LIGHT, - SELECT2_LIGHT, - SELECT3_LIGHT, - SELECT4_LIGHT, - NUM_LIGHTS - }; - - bool _registered = false; - int _baseID = -1; - int _position = -1; - - PgmrX() { - config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); - configParam<OutputRangeParamQuantity>(CVA1_PARAM, -1.0f, 1.0f, 0.0f, "Step 1A", " V"); - configParam<OutputRangeParamQuantity>(CVB1_PARAM, -1.0f, 1.0f, 0.0f, "Step 1B", " V"); - configParam<OutputRangeParamQuantity>(CVC1_PARAM, -1.0f, 1.0f, 0.0f, "Step 1C", " V"); - configParam<OutputRangeParamQuantity>(CVD1_PARAM, -1.0f, 1.0f, 0.0f, "Step 1D", " V"); - configParam(SELECT1_PARAM, 0.0f, 1.0f, 0.0f, "Select 1"); - configParam<OutputRangeParamQuantity>(CVA2_PARAM, -1.0f, 1.0f, 0.0f, "Step 2A", " V"); - configParam<OutputRangeParamQuantity>(CVB2_PARAM, -1.0f, 1.0f, 0.0f, "Step 2B", " V"); - configParam<OutputRangeParamQuantity>(CVC2_PARAM, -1.0f, 1.0f, 0.0f, "Step 2C", " V"); - configParam<OutputRangeParamQuantity>(CVD2_PARAM, -1.0f, 1.0f, 0.0f, "Step 2D", " V"); - configParam(SELECT2_PARAM, 0.0f, 1.0f, 0.0f, "Select 2"); - configParam<OutputRangeParamQuantity>(CVA3_PARAM, -1.0f, 1.0f, 0.0f, "Step 3A", " V"); - configParam<OutputRangeParamQuantity>(CVB3_PARAM, -1.0f, 1.0f, 0.0f, "Step 3B", " V"); - configParam<OutputRangeParamQuantity>(CVC3_PARAM, -1.0f, 1.0f, 0.0f, "Step 3C", " V"); - configParam<OutputRangeParamQuantity>(CVD3_PARAM, -1.0f, 1.0f, 0.0f, "Step 3D", " V"); - configParam(SELECT3_PARAM, 0.0f, 1.0f, 0.0f, "Select 3"); - configParam<OutputRangeParamQuantity>(CVA4_PARAM, -1.0f, 1.0f, 0.0f, "Step 4A", " V"); - configParam<OutputRangeParamQuantity>(CVB4_PARAM, -1.0f, 1.0f, 0.0f, "Step 4B", " V"); - configParam<OutputRangeParamQuantity>(CVC4_PARAM, -1.0f, 1.0f, 0.0f, "Step 4C", " V"); - configParam<OutputRangeParamQuantity>(CVD4_PARAM, -1.0f, 1.0f, 0.0f, "Step 4D", " V"); - configParam<OutputRangeParamQuantity>(SELECT4_PARAM, 0.0f, 1.0f, 0.0f, "Select 4"); - - _localSteps[0] = new PgmrStep(params[CVA1_PARAM], params[CVB1_PARAM], params[CVC1_PARAM], params[CVD1_PARAM], lights[SELECT1_LIGHT], params[SELECT1_PARAM], inputs[SELECT1_INPUT], outputs[SELECT1_OUTPUT]); - _localSteps[1] = new PgmrStep(params[CVA2_PARAM], params[CVB2_PARAM], params[CVC2_PARAM], params[CVD2_PARAM], lights[SELECT2_LIGHT], params[SELECT2_PARAM], inputs[SELECT2_INPUT], outputs[SELECT2_OUTPUT]); - _localSteps[2] = new PgmrStep(params[CVA3_PARAM], params[CVB3_PARAM], params[CVC3_PARAM], params[CVD3_PARAM], lights[SELECT3_LIGHT], params[SELECT3_PARAM], inputs[SELECT3_INPUT], outputs[SELECT3_OUTPUT]); - _localSteps[3] = new PgmrStep(params[CVA4_PARAM], params[CVB4_PARAM], params[CVC4_PARAM], params[CVD4_PARAM], lights[SELECT4_LIGHT], params[SELECT4_PARAM], inputs[SELECT4_INPUT], outputs[SELECT4_OUTPUT]); - - setBaseModel(modelPgmr); - setChainableModel(modelPgmrX); - setExpanderModel(modelPgmrX); - } - virtual ~PgmrX() { - PgmrRegistry::registry().deregisterExpander(_baseID, _position); - } - - void processAlways(const ProcessArgs& args) override; -}; - } // namespace bogaudio diff --git a/src/PgmrX.cpp b/src/PgmrX.cpp @@ -0,0 +1,137 @@ + +#include "PgmrX.hpp" + +void PgmrX::processAlways(const ProcessArgs& args) { + int position = 0; + int baseID = 0; + if (baseConnected()) { + PgmrExpanderMessage* bm = fromBase(); + baseID = bm->baseID; + position = bm->position; + _rangeOffset = bm->rangeOffset; + _rangeScale = bm->rangeScale; + } + + if (_registered && (position <= 0 || position != _position)) { + PgmrRegistry::registry().deregisterExpander(_baseID, _position); + _registered = false; + _baseID = 0; + _position = 0; + } + else if (!_registered && position > 0) { + _registered = true; + _baseID = baseID; + _position = position; + PgmrRegistry::registry().registerExpander(_baseID, _position, *this); + } + + if (_position < 1) { + for (int i = 0; i < 4; ++i) { + _localSteps[i]->selectedLight.value = 0.0f; + } + } + if (expanderConnected()) { + PgmrExpanderMessage* te = toExpander(); + te->baseID = _baseID; + te->position = _position > 0 ? _position + 1 : 0; + te->rangeOffset = _rangeOffset; + te->rangeScale = _rangeScale; + } +} + +struct PgmrXWidget : ModuleWidget { + static constexpr int hp = 12; + + PgmrXWidget(PgmrX* 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/PgmrX.svg"))); + addChild(panel); + } + + addChild(createWidget<ScrewSilver>(Vec(0, 0))); + addChild(createWidget<ScrewSilver>(Vec(box.size.x - 15, 0))); + addChild(createWidget<ScrewSilver>(Vec(0, 365))); + addChild(createWidget<ScrewSilver>(Vec(box.size.x - 15, 365))); + + // generated by svg_widgets.rb + auto cva1ParamPosition = Vec(9.5, 40.5); + auto cvb1ParamPosition = Vec(9.5, 94.5); + auto cvc1ParamPosition = Vec(9.5, 148.5); + auto cvd1ParamPosition = Vec(9.5, 202.5); + auto select1ParamPosition = Vec(13.5, 267.0); + auto cva2ParamPosition = Vec(54.5, 40.5); + auto cvb2ParamPosition = Vec(54.5, 94.5); + auto cvc2ParamPosition = Vec(54.5, 148.5); + auto cvd2ParamPosition = Vec(54.5, 202.5); + auto select2ParamPosition = Vec(58.5, 267.0); + auto cva3ParamPosition = Vec(99.5, 40.5); + auto cvb3ParamPosition = Vec(99.5, 94.5); + auto cvc3ParamPosition = Vec(99.5, 148.5); + auto cvd3ParamPosition = Vec(99.5, 202.5); + auto select3ParamPosition = Vec(103.5, 267.0); + auto cva4ParamPosition = Vec(144.5, 40.5); + auto cvb4ParamPosition = Vec(144.5, 94.5); + auto cvc4ParamPosition = Vec(144.5, 148.5); + auto cvd4ParamPosition = Vec(144.5, 202.5); + auto select4ParamPosition = Vec(148.5, 267.0); + + auto select1InputPosition = Vec(10.5, 290.0); + auto select2InputPosition = Vec(55.5, 290.0); + auto select3InputPosition = Vec(100.5, 290.0); + auto select4InputPosition = Vec(145.5, 290.0); + + auto select1OutputPosition = Vec(10.5, 330.0); + auto select2OutputPosition = Vec(55.5, 330.0); + auto select3OutputPosition = Vec(100.5, 330.0); + auto select4OutputPosition = Vec(145.5, 330.0); + + auto select1LightPosition = Vec(19.3, 255.0); + auto select2LightPosition = Vec(64.3, 255.0); + auto select3LightPosition = Vec(109.3, 255.0); + auto select4LightPosition = Vec(154.3, 255.0); + // end generated by svg_widgets.rb + + addParam(createParam<Knob26>(cva1ParamPosition, module, PgmrX::CVA1_PARAM)); + addParam(createParam<Knob26>(cvb1ParamPosition, module, PgmrX::CVB1_PARAM)); + addParam(createParam<Knob26>(cvc1ParamPosition, module, PgmrX::CVC1_PARAM)); + addParam(createParam<Knob26>(cvd1ParamPosition, module, PgmrX::CVD1_PARAM)); + addParam(createParam<Button18>(select1ParamPosition, module, PgmrX::SELECT1_PARAM)); + addParam(createParam<Knob26>(cva2ParamPosition, module, PgmrX::CVA2_PARAM)); + addParam(createParam<Knob26>(cvb2ParamPosition, module, PgmrX::CVB2_PARAM)); + addParam(createParam<Knob26>(cvc2ParamPosition, module, PgmrX::CVC2_PARAM)); + addParam(createParam<Knob26>(cvd2ParamPosition, module, PgmrX::CVD2_PARAM)); + addParam(createParam<Button18>(select2ParamPosition, module, PgmrX::SELECT2_PARAM)); + addParam(createParam<Knob26>(cva3ParamPosition, module, PgmrX::CVA3_PARAM)); + addParam(createParam<Knob26>(cvb3ParamPosition, module, PgmrX::CVB3_PARAM)); + addParam(createParam<Knob26>(cvc3ParamPosition, module, PgmrX::CVC3_PARAM)); + addParam(createParam<Knob26>(cvd3ParamPosition, module, PgmrX::CVD3_PARAM)); + addParam(createParam<Button18>(select3ParamPosition, module, PgmrX::SELECT3_PARAM)); + addParam(createParam<Knob26>(cva4ParamPosition, module, PgmrX::CVA4_PARAM)); + addParam(createParam<Knob26>(cvb4ParamPosition, module, PgmrX::CVB4_PARAM)); + addParam(createParam<Knob26>(cvc4ParamPosition, module, PgmrX::CVC4_PARAM)); + addParam(createParam<Knob26>(cvd4ParamPosition, module, PgmrX::CVD4_PARAM)); + addParam(createParam<Button18>(select4ParamPosition, module, PgmrX::SELECT4_PARAM)); + + addInput(createInput<Port24>(select1InputPosition, module, PgmrX::SELECT1_INPUT)); + addInput(createInput<Port24>(select2InputPosition, module, PgmrX::SELECT2_INPUT)); + addInput(createInput<Port24>(select3InputPosition, module, PgmrX::SELECT3_INPUT)); + addInput(createInput<Port24>(select4InputPosition, module, PgmrX::SELECT4_INPUT)); + + addOutput(createOutput<Port24>(select1OutputPosition, module, PgmrX::SELECT1_OUTPUT)); + addOutput(createOutput<Port24>(select2OutputPosition, module, PgmrX::SELECT2_OUTPUT)); + addOutput(createOutput<Port24>(select3OutputPosition, module, PgmrX::SELECT3_OUTPUT)); + addOutput(createOutput<Port24>(select4OutputPosition, module, PgmrX::SELECT4_OUTPUT)); + + addChild(createLight<SmallLight<GreenLight>>(select1LightPosition, module, PgmrX::SELECT1_LIGHT)); + addChild(createLight<SmallLight<GreenLight>>(select2LightPosition, module, PgmrX::SELECT2_LIGHT)); + addChild(createLight<SmallLight<GreenLight>>(select3LightPosition, module, PgmrX::SELECT3_LIGHT)); + addChild(createLight<SmallLight<GreenLight>>(select4LightPosition, module, PgmrX::SELECT4_LIGHT)); + } +}; + +Model* modelPgmrX = createModel<PgmrX, PgmrXWidget>("Bogaudio-PgmrX", "PGMRX", "4-step chainable expander for PGMR", "Sequencer", "Expander", "Polyphonic"); diff --git a/src/PgmrX.hpp b/src/PgmrX.hpp @@ -0,0 +1,99 @@ +#pragma once + +#include "Pgmr_shared.hpp" + +namespace bogaudio { + +struct PgmrX : ExpanderModule<PgmrExpanderMessage, ExpandableModule<PgmrExpanderMessage, BGModule>>, PgmrBase, OutputRange { + enum ParamsIds { + CVA1_PARAM, + CVB1_PARAM, + CVC1_PARAM, + CVD1_PARAM, + SELECT1_PARAM, + CVA2_PARAM, + CVB2_PARAM, + CVC2_PARAM, + CVD2_PARAM, + SELECT2_PARAM, + CVA3_PARAM, + CVB3_PARAM, + CVC3_PARAM, + CVD3_PARAM, + SELECT3_PARAM, + CVA4_PARAM, + CVB4_PARAM, + CVC4_PARAM, + CVD4_PARAM, + SELECT4_PARAM, + NUM_PARAMS + }; + + enum InputsIds { + SELECT1_INPUT, + SELECT2_INPUT, + SELECT3_INPUT, + SELECT4_INPUT, + NUM_INPUTS + }; + + enum OutputsIds { + SELECT1_OUTPUT, + SELECT2_OUTPUT, + SELECT3_OUTPUT, + SELECT4_OUTPUT, + NUM_OUTPUTS + }; + + enum LightsIds { + SELECT1_LIGHT, + SELECT2_LIGHT, + SELECT3_LIGHT, + SELECT4_LIGHT, + NUM_LIGHTS + }; + + bool _registered = false; + int _baseID = -1; + int _position = -1; + + PgmrX() { + config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); + configParam<OutputRangeParamQuantity>(CVA1_PARAM, -1.0f, 1.0f, 0.0f, "Step 1A", " V"); + configParam<OutputRangeParamQuantity>(CVB1_PARAM, -1.0f, 1.0f, 0.0f, "Step 1B", " V"); + configParam<OutputRangeParamQuantity>(CVC1_PARAM, -1.0f, 1.0f, 0.0f, "Step 1C", " V"); + configParam<OutputRangeParamQuantity>(CVD1_PARAM, -1.0f, 1.0f, 0.0f, "Step 1D", " V"); + configParam(SELECT1_PARAM, 0.0f, 1.0f, 0.0f, "Select 1"); + configParam<OutputRangeParamQuantity>(CVA2_PARAM, -1.0f, 1.0f, 0.0f, "Step 2A", " V"); + configParam<OutputRangeParamQuantity>(CVB2_PARAM, -1.0f, 1.0f, 0.0f, "Step 2B", " V"); + configParam<OutputRangeParamQuantity>(CVC2_PARAM, -1.0f, 1.0f, 0.0f, "Step 2C", " V"); + configParam<OutputRangeParamQuantity>(CVD2_PARAM, -1.0f, 1.0f, 0.0f, "Step 2D", " V"); + configParam(SELECT2_PARAM, 0.0f, 1.0f, 0.0f, "Select 2"); + configParam<OutputRangeParamQuantity>(CVA3_PARAM, -1.0f, 1.0f, 0.0f, "Step 3A", " V"); + configParam<OutputRangeParamQuantity>(CVB3_PARAM, -1.0f, 1.0f, 0.0f, "Step 3B", " V"); + configParam<OutputRangeParamQuantity>(CVC3_PARAM, -1.0f, 1.0f, 0.0f, "Step 3C", " V"); + configParam<OutputRangeParamQuantity>(CVD3_PARAM, -1.0f, 1.0f, 0.0f, "Step 3D", " V"); + configParam(SELECT3_PARAM, 0.0f, 1.0f, 0.0f, "Select 3"); + configParam<OutputRangeParamQuantity>(CVA4_PARAM, -1.0f, 1.0f, 0.0f, "Step 4A", " V"); + configParam<OutputRangeParamQuantity>(CVB4_PARAM, -1.0f, 1.0f, 0.0f, "Step 4B", " V"); + configParam<OutputRangeParamQuantity>(CVC4_PARAM, -1.0f, 1.0f, 0.0f, "Step 4C", " V"); + configParam<OutputRangeParamQuantity>(CVD4_PARAM, -1.0f, 1.0f, 0.0f, "Step 4D", " V"); + configParam<OutputRangeParamQuantity>(SELECT4_PARAM, 0.0f, 1.0f, 0.0f, "Select 4"); + + _localSteps[0] = new PgmrStep(params[CVA1_PARAM], params[CVB1_PARAM], params[CVC1_PARAM], params[CVD1_PARAM], lights[SELECT1_LIGHT], params[SELECT1_PARAM], inputs[SELECT1_INPUT], outputs[SELECT1_OUTPUT]); + _localSteps[1] = new PgmrStep(params[CVA2_PARAM], params[CVB2_PARAM], params[CVC2_PARAM], params[CVD2_PARAM], lights[SELECT2_LIGHT], params[SELECT2_PARAM], inputs[SELECT2_INPUT], outputs[SELECT2_OUTPUT]); + _localSteps[2] = new PgmrStep(params[CVA3_PARAM], params[CVB3_PARAM], params[CVC3_PARAM], params[CVD3_PARAM], lights[SELECT3_LIGHT], params[SELECT3_PARAM], inputs[SELECT3_INPUT], outputs[SELECT3_OUTPUT]); + _localSteps[3] = new PgmrStep(params[CVA4_PARAM], params[CVB4_PARAM], params[CVC4_PARAM], params[CVD4_PARAM], lights[SELECT4_LIGHT], params[SELECT4_PARAM], inputs[SELECT4_INPUT], outputs[SELECT4_OUTPUT]); + + setBaseModel(modelPgmr); + setChainableModel(modelPgmrX); + setExpanderModel(modelPgmrX); + } + virtual ~PgmrX() { + PgmrRegistry::registry().deregisterExpander(_baseID, _position); + } + + void processAlways(const ProcessArgs& args) override; +}; + +} // namespace bogaudio diff --git a/src/Pgmr_shared.cpp b/src/Pgmr_shared.cpp @@ -0,0 +1,79 @@ + +#include "Pgmr_shared.hpp" +#include "Pgmr.hpp" +#include "PgmrX.hpp" + +void PgmrStep::reset() { + for (int c = 0; c < BGModule::maxChannels; ++c) { + triggers[c].reset(); + pulseGens[c].process(1000.0f); + } +} + + +PgmrRegistry::Base::Base(Pgmr& b) : module(b) { + std::copy(b._localSteps, b._localSteps + 4, std::back_inserter(steps)); +} + +int PgmrRegistry::registerBase(Pgmr& b) { + std::lock_guard<std::mutex> lock(_lock); + + int id = _nextID; + ++_nextID; + auto p = _bases.emplace(id, Base(b)); + b.setSteps(p.first->second.steps); + return id; +} + +void PgmrRegistry::deregisterBase(int id) { + std::lock_guard<std::mutex> lock(_lock); + _bases.erase(id); +} + +void PgmrRegistry::registerExpander(int baseID, int position, PgmrX& x) { + std::lock_guard<std::mutex> lock(_lock); + + assert(position > 0); + auto base = _bases.find(baseID); + if (base != _bases.end()) { + int i = 4 * position; + if (i < (int)base->second.steps.size()) { + assert(!base->second.steps[i]); + std::copy(x._localSteps, x._localSteps + 4, base->second.steps.begin() + i); + } + else { + base->second.steps.resize(i + 4, NULL); + std::copy(x._localSteps, x._localSteps + 4, base->second.steps.begin() + i); + } + for (auto i = base->second.steps.begin(), n = base->second.steps.end(); i != n; ++i) { + if (!*i) { + return; + } + } + base->second.module.setSteps(base->second.steps); + } +} + +void PgmrRegistry::deregisterExpander(int baseID, int position) { + std::lock_guard<std::mutex> lock(_lock); + + auto base = _bases.find(baseID); + if (base != _bases.end()) { + int n = 4 * position; + if (n < (int)base->second.steps.size()) { + int i = 0; + for (; i < n; ++i) { + if (!base->second.steps[i]) { + break; + } + } + base->second.steps.resize(i); + base->second.module.setSteps(base->second.steps); + } + } +} + +PgmrRegistry& PgmrRegistry::registry() { + static PgmrRegistry instance; + return instance; +} diff --git a/src/Pgmr_shared.hpp b/src/Pgmr_shared.hpp @@ -0,0 +1,97 @@ +#pragma once + +#include <mutex> +#include <unordered_map> + +#include "bogaudio.hpp" +#include "addressable_sequence.hpp" +#include "expanders.hpp" + +extern Model* modelPgmr; +extern Model* modelPgmrX; + +namespace bogaudio { + +struct PgmrExpanderMessage : ExpanderMessage { + int baseID = -1; + int position = -1; + float rangeOffset = 0.0f; + float rangeScale = 10.0f; +}; + +struct PgmrStep { + Param& aParam; + Param& bParam; + Param& cParam; + Param& dParam; + Light& selectedLight; + Param& selectParam; + Input& selectInput; + Output& selectedOutput; + + Trigger triggers[BGModule::maxChannels]; + rack::dsp::PulseGenerator pulseGens[BGModule::maxChannels]; + float lightSum = 0.0f; + + PgmrStep( + Param& aParam, + Param& bParam, + Param& cParam, + Param& dParam, + Light& selectedLight, + Param& selectParam, + Input& selectInput, + Output& selectedOutput + ) + : aParam(aParam) + , bParam(bParam) + , cParam(cParam) + , dParam(dParam) + , selectedLight(selectedLight) + , selectParam(selectParam) + , selectInput(selectInput) + , selectedOutput(selectedOutput) + { + } + + void reset(); +}; + +struct PgmrBase { + PgmrStep* _localSteps[4] {}; + + virtual ~PgmrBase() { + for (int i = 0; i < 4; ++i) { + if (_localSteps[i]) { + delete _localSteps[i]; + } + } + } +}; + +struct Pgmr; +struct PgmrX; + +struct PgmrRegistry { +private: + struct Base { + Pgmr& module; + std::vector<PgmrStep*> steps; + + Base(Pgmr& b); + }; + + std::mutex _lock; + int _nextID = 1; + std::unordered_map<int, Base> _bases; + +public: + int registerBase(Pgmr& b); + void deregisterBase(int id); + void registerExpander(int baseID, int position, PgmrX& x); + void deregisterExpander(int baseID, int position); + + static PgmrRegistry& registry(); +}; + +} // namespace bogaudio diff --git a/src/bogaudio.cpp b/src/bogaudio.cpp @@ -44,7 +44,9 @@ #include "Mix1.hpp" #include "Mix2.hpp" #include "Mix4.hpp" +#include "Mix4x.hpp" #include "Mix8.hpp" +#include "Mix8x.hpp" #include "Mono.hpp" #include "Mult.hpp" #include "Mumix.hpp" @@ -58,6 +60,7 @@ #include "PEQ6.hpp" #include "PEQ14.hpp" #include "Pgmr.hpp" +#include "PgmrX.hpp" #include "PolyCon8.hpp" #include "PolyCon16.hpp" #include "PolyOff8.hpp"