BogaudioModules

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

commit 0cf0b216506df09105bee226f5711be597e6a504
parent 29fac385bddb7ad93216729edbeb09c867d392f8
Author: Matt Demanett <matt@demanett.net>
Date:   Tue, 14 Apr 2020 00:26:30 -0400

Refactor/standardize output range options; add unipolar ranges to PGMR/X; add ranges to POLYCON. #106

Diffstat:
Msrc/AddrSeq.cpp | 27+--------------------------
Msrc/AddrSeq.hpp | 16++++++++--------
Msrc/Pgmr.cpp | 45++-------------------------------------------
Msrc/Pgmr.hpp | 75++++++++++++++++++++++++++++++++++-----------------------------------------
Msrc/PolyCon.cpp | 10+++++++++-
Msrc/PolyCon.hpp | 37+++++++++++++++++++------------------
Msrc/addressable_sequence.cpp | 48------------------------------------------------
Msrc/addressable_sequence.hpp | 14++------------
Asrc/output_range.cpp | 27+++++++++++++++++++++++++++
Asrc/output_range.hpp | 74++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
10 files changed, 176 insertions(+), 197 deletions(-)

diff --git a/src/AddrSeq.cpp b/src/AddrSeq.cpp @@ -115,34 +115,9 @@ struct AddrSeqWidget : AddressableSequenceModuleWidget { addChild(createLight<SmallLight<GreenLight>>(out8LightPosition, module, AddrSeq::OUT8_LIGHT)); } - struct RangeOptionMenuItem : OptionMenuItem { - RangeOptionMenuItem(AddrSeq* module, const char* label, float offset, float scale) - : OptionMenuItem( - label, - [=]() { return module->_rangeOffset == offset && module->_rangeScale == scale; }, - [=]() { - module->_rangeOffset = offset; - module->_rangeScale = scale; - } - ) - {} - }; - void appendContextMenu(Menu* menu) override { AddressableSequenceModuleWidget::appendContextMenu(menu); - - AddrSeq* m = dynamic_cast<AddrSeq*>(module); - assert(m); - OptionsMenuItem* mi = new OptionsMenuItem("Range"); - mi->addItem(RangeOptionMenuItem(m, "+/-10V", 0.0f, 10.0f)); - mi->addItem(RangeOptionMenuItem(m, "+/-5V", 0.0f, 5.0f)); - mi->addItem(RangeOptionMenuItem(m, "+/-3V", 0.0f, 3.0f)); - mi->addItem(RangeOptionMenuItem(m, "+/-1V", 0.0f, 1.0f)); - mi->addItem(RangeOptionMenuItem(m, "0V-10V", 1.0f, 5.0f)); - mi->addItem(RangeOptionMenuItem(m, "0V-5V", 1.0f, 2.5f)); - mi->addItem(RangeOptionMenuItem(m, "0V-3V", 1.0f, 1.5f)); - mi->addItem(RangeOptionMenuItem(m, "0V-1V", 1.0f, 0.5f)); - OptionsMenuItem::addToMenu(mi, menu); + OutputRangeOptionMenuItem::addOutputRangeOptionsToMenu(module, menu); } }; diff --git a/src/AddrSeq.hpp b/src/AddrSeq.hpp @@ -54,14 +54,14 @@ struct AddrSeq : OutputRangeAddressableSequenceModule { configParam(STEPS_PARAM, 1.0f, 8.0f, 8.0f, "Steps"); configParam(DIRECTION_PARAM, 0.0f, 1.0f, 1.0f, "Direction"); configParam(SELECT_PARAM, 0.0f, 7.0f, 0.0f, "Select step"); - configParam<OutputParamQuantity>(OUT1_PARAM, -1.0f, 1.0f, 0.0f, "Step 1", " V"); - configParam<OutputParamQuantity>(OUT2_PARAM, -1.0f, 1.0f, 0.0f, "Step 2", " V"); - configParam<OutputParamQuantity>(OUT3_PARAM, -1.0f, 1.0f, 0.0f, "Step 3", " V"); - configParam<OutputParamQuantity>(OUT4_PARAM, -1.0f, 1.0f, 0.0f, "Step 4", " V"); - configParam<OutputParamQuantity>(OUT5_PARAM, -1.0f, 1.0f, 0.0f, "Step 5", " V"); - configParam<OutputParamQuantity>(OUT6_PARAM, -1.0f, 1.0f, 0.0f, "Step 6", " V"); - configParam<OutputParamQuantity>(OUT7_PARAM, -1.0f, 1.0f, 0.0f, "Step 7", " V"); - configParam<OutputParamQuantity>(OUT8_PARAM, -1.0f, 1.0f, 0.0f, "Step 8", " V"); + configParam<OutputRangeParamQuantity>(OUT1_PARAM, -1.0f, 1.0f, 0.0f, "Step 1", " V"); + configParam<OutputRangeParamQuantity>(OUT2_PARAM, -1.0f, 1.0f, 0.0f, "Step 2", " V"); + configParam<OutputRangeParamQuantity>(OUT3_PARAM, -1.0f, 1.0f, 0.0f, "Step 3", " V"); + configParam<OutputRangeParamQuantity>(OUT4_PARAM, -1.0f, 1.0f, 0.0f, "Step 4", " V"); + configParam<OutputRangeParamQuantity>(OUT5_PARAM, -1.0f, 1.0f, 0.0f, "Step 5", " V"); + configParam<OutputRangeParamQuantity>(OUT6_PARAM, -1.0f, 1.0f, 0.0f, "Step 6", " V"); + configParam<OutputRangeParamQuantity>(OUT7_PARAM, -1.0f, 1.0f, 0.0f, "Step 7", " V"); + configParam<OutputRangeParamQuantity>(OUT8_PARAM, -1.0f, 1.0f, 0.0f, "Step 8", " V"); setInputIDs(CLOCK_INPUT, SELECT_INPUT); } diff --git a/src/Pgmr.cpp b/src/Pgmr.cpp @@ -317,64 +317,23 @@ struct PgmrWidget : AddressableSequenceBaseModuleWidget { addChild(createLight<SmallLight<GreenLight>>(select4LightPosition, module, Pgmr::SELECT4_LIGHT)); } - struct RangeOptionMenuItem : OptionMenuItem { - RangeOptionMenuItem(Pgmr* module, const char* label, float offset, float scale) - : OptionMenuItem( - label, - [=]() { return module->_rangeOffset == offset && module->_rangeScale == scale; }, - [=]() { - module->_rangeOffset = offset; - module->_rangeScale = scale; - } - ) - {} - }; - void appendContextMenu(Menu* menu) override { AddressableSequenceBaseModuleWidget::appendContextMenu(menu); auto m = dynamic_cast<Pgmr*>(module); assert(m); - OptionsMenuItem* mi = new OptionsMenuItem("Range"); - mi->addItem(RangeOptionMenuItem(m, "+/-10V", 0.0f, 10.0f)); - mi->addItem(RangeOptionMenuItem(m, "+/-5V", 0.0f, 5.0f)); - mi->addItem(RangeOptionMenuItem(m, "+/-3V", 0.0f, 3.0f)); - mi->addItem(RangeOptionMenuItem(m, "+/-1V", 0.0f, 1.0f)); - OptionsMenuItem::addToMenu(mi, menu); - OptionsMenuItem* so = new OptionsMenuItem("Output on selected step"); so->addItem(OptionMenuItem("Gate", [m]() { return !m->_selectTriggers; }, [m]() { m->_selectTriggers = false; })); so->addItem(OptionMenuItem("Trigger", [m]() { return m->_selectTriggers; }, [m]() { m->_selectTriggers = true; })); OptionsMenuItem::addToMenu(so, menu); + + OutputRangeOptionMenuItem::addOutputRangeOptionsToMenu(module, menu); } }; Model* modelPgmr = createModel<Pgmr, PgmrWidget>("Bogaudio-Pgmr", "PGMR", "4-step programmer and sequencer", "Sequencer", "Polyphonic"); -float PgmrX::OutputParamQuantity::getDisplayValue() { - float v = getValue(); - if (!module) { - return v; - } - - auto m = dynamic_cast<PgmrX*>(module); - v += m->_rangeOffset; - v *= m->_rangeScale; - return v; -} - -void PgmrX::OutputParamQuantity::setDisplayValue(float v) { - if (!module) { - return; - } - - auto m = dynamic_cast<PgmrX*>(module); - v /= m->_rangeScale; - v -= m->_rangeOffset; - setValue(v); -} - void PgmrX::processAlways(const ProcessArgs& args) { int position = 0; int baseID = 0; diff --git a/src/Pgmr.hpp b/src/Pgmr.hpp @@ -164,25 +164,25 @@ struct Pgmr : ExpandableModule<PgmrExpanderMessage, OutputRangeAddressableSequen config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); configParam(DIRECTION_PARAM, 0.0f, 1.0f, 1.0f, "Forward"); configParam(SELECT_ON_CLOCK_PARAM, 0.0f, 1.0f, 0.0f, "Select on clock"); - configParam<OutputParamQuantity>(CVA1_PARAM, -1.0f, 1.0f, 0.0f, "Step 1A", " V"); - configParam<OutputParamQuantity>(CVB1_PARAM, -1.0f, 1.0f, 0.0f, "Step 1B", " V"); - configParam<OutputParamQuantity>(CVC1_PARAM, -1.0f, 1.0f, 0.0f, "Step 1C", " V"); - configParam<OutputParamQuantity>(CVD1_PARAM, -1.0f, 1.0f, 0.0f, "Step 1D", " V"); + 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<OutputParamQuantity>(CVA2_PARAM, -1.0f, 1.0f, 0.0f, "Step 2A", " V"); - configParam<OutputParamQuantity>(CVB2_PARAM, -1.0f, 1.0f, 0.0f, "Step 2B", " V"); - configParam<OutputParamQuantity>(CVC2_PARAM, -1.0f, 1.0f, 0.0f, "Step 2C", " V"); - configParam<OutputParamQuantity>(CVD2_PARAM, -1.0f, 1.0f, 0.0f, "Step 2D", " V"); + 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<OutputParamQuantity>(CVA3_PARAM, -1.0f, 1.0f, 0.0f, "Step 3A", " V"); - configParam<OutputParamQuantity>(CVB3_PARAM, -1.0f, 1.0f, 0.0f, "Step 3B", " V"); - configParam<OutputParamQuantity>(CVC3_PARAM, -1.0f, 1.0f, 0.0f, "Step 3C", " V"); - configParam<OutputParamQuantity>(CVD3_PARAM, -1.0f, 1.0f, 0.0f, "Step 3D", " V"); + 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<OutputParamQuantity>(CVA4_PARAM, -1.0f, 1.0f, 0.0f, "Step 4A", " V"); - configParam<OutputParamQuantity>(CVB4_PARAM, -1.0f, 1.0f, 0.0f, "Step 4B", " V"); - configParam<OutputParamQuantity>(CVC4_PARAM, -1.0f, 1.0f, 0.0f, "Step 4C", " V"); - configParam<OutputParamQuantity>(CVD4_PARAM, -1.0f, 1.0f, 0.0f, "Step 4D", " V"); + 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(SELECT4_PARAM, 0.0f, 1.0f, 0.0f, "Select 4"); setInputIDs(CLOCK_INPUT, SELECT_INPUT); @@ -208,7 +208,7 @@ struct Pgmr : ExpandableModule<PgmrExpanderMessage, OutputRangeAddressableSequen void setSteps(std::vector<PgmrStep*>& steps); }; -struct PgmrX : ExpanderModule<PgmrExpanderMessage, ExpandableModule<PgmrExpanderMessage, BGModule>>, PgmrBase { +struct PgmrX : ExpanderModule<PgmrExpanderMessage, ExpandableModule<PgmrExpanderMessage, BGModule>>, PgmrBase, OutputRange { enum ParamsIds { CVA1_PARAM, CVB1_PARAM, @@ -257,39 +257,32 @@ struct PgmrX : ExpanderModule<PgmrExpanderMessage, ExpandableModule<PgmrExpander NUM_LIGHTS }; - struct OutputParamQuantity : ParamQuantity { - float getDisplayValue() override; - void setDisplayValue(float v) override; - }; - bool _registered = false; int _baseID = -1; int _position = -1; - float _rangeOffset = 0.0f; - float _rangeScale = 10.0f; PgmrX() { config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); - configParam<OutputParamQuantity>(CVA1_PARAM, -1.0f, 1.0f, 0.0f, "Step 1A", " V"); - configParam<OutputParamQuantity>(CVB1_PARAM, -1.0f, 1.0f, 0.0f, "Step 1B", " V"); - configParam<OutputParamQuantity>(CVC1_PARAM, -1.0f, 1.0f, 0.0f, "Step 1C", " V"); - configParam<OutputParamQuantity>(CVD1_PARAM, -1.0f, 1.0f, 0.0f, "Step 1D", " V"); + 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<OutputParamQuantity>(CVA2_PARAM, -1.0f, 1.0f, 0.0f, "Step 2A", " V"); - configParam<OutputParamQuantity>(CVB2_PARAM, -1.0f, 1.0f, 0.0f, "Step 2B", " V"); - configParam<OutputParamQuantity>(CVC2_PARAM, -1.0f, 1.0f, 0.0f, "Step 2C", " V"); - configParam<OutputParamQuantity>(CVD2_PARAM, -1.0f, 1.0f, 0.0f, "Step 2D", " V"); + 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<OutputParamQuantity>(CVA3_PARAM, -1.0f, 1.0f, 0.0f, "Step 3A", " V"); - configParam<OutputParamQuantity>(CVB3_PARAM, -1.0f, 1.0f, 0.0f, "Step 3B", " V"); - configParam<OutputParamQuantity>(CVC3_PARAM, -1.0f, 1.0f, 0.0f, "Step 3C", " V"); - configParam<OutputParamQuantity>(CVD3_PARAM, -1.0f, 1.0f, 0.0f, "Step 3D", " V"); + 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<OutputParamQuantity>(CVA4_PARAM, -1.0f, 1.0f, 0.0f, "Step 4A", " V"); - configParam<OutputParamQuantity>(CVB4_PARAM, -1.0f, 1.0f, 0.0f, "Step 4B", " V"); - configParam<OutputParamQuantity>(CVC4_PARAM, -1.0f, 1.0f, 0.0f, "Step 4C", " V"); - configParam<OutputParamQuantity>(CVD4_PARAM, -1.0f, 1.0f, 0.0f, "Step 4D", " V"); - configParam<OutputParamQuantity>(SELECT4_PARAM, 0.0f, 1.0f, 0.0f, "Select 4"); + 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]); diff --git a/src/PolyCon.cpp b/src/PolyCon.cpp @@ -9,7 +9,10 @@ void PolyCon::processAll(const ProcessArgs& args) { outputs[OUT_OUTPUT].setChannels(cn); for (int c = 0; c < cn; ++c) { - outputs[OUT_OUTPUT].setVoltage(clamp(params[CHANNEL1_PARAM + c].getValue(), -1.0f, 1.0f) * 10.0f, c); + float out = clamp(params[CHANNEL1_PARAM + c].getValue(), -1.0f, 1.0f); + out += _rangeOffset; + out *= _rangeScale; + outputs[OUT_OUTPUT].setVoltage(out, c); lights[CHANNEL1_LIGHT + c].value = 1.0f; } for (int c = cn; c < maxChannels; ++c) { @@ -119,6 +122,11 @@ struct PolyConWidget : ModuleWidget { addChild(createLight<TinyLight<GreenLight>>(channel15LightPosition, module, PolyCon::CHANNEL15_LIGHT)); addChild(createLight<TinyLight<GreenLight>>(channel16LightPosition, module, PolyCon::CHANNEL16_LIGHT)); } + + void appendContextMenu(Menu* menu) override { + menu->addChild(new MenuLabel()); + OutputRangeOptionMenuItem::addOutputRangeOptionsToMenu(module, menu); + } }; Model* modelPolyCon = createModel<PolyCon, PolyConWidget>("Bogaudio-PolyCon", "POLYCON", "Polyphonic per-channel constant voltages", "Utility", "Polyphonic"); diff --git a/src/PolyCon.hpp b/src/PolyCon.hpp @@ -1,12 +1,13 @@ #pragma once #include "bogaudio.hpp" +#include "output_range.hpp" extern Model* modelPolyCon; namespace bogaudio { -struct PolyCon : BGModule { +struct PolyCon : OutputRangeModule<BGModule> { enum ParamsIds { CHANNELS_PARAM, CHANNEL1_PARAM, @@ -60,23 +61,23 @@ struct PolyCon : BGModule { PolyCon() { config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); - configParam(CHANNELS_PARAM, 1.0f, 16.0f, 1.0f, "Polyphony channels"); - configParam(CHANNEL1_PARAM, -1.0f, 1.0f, 0.0f, "Channel 1", "V", 0.0f, 10.0f); - configParam(CHANNEL2_PARAM, -1.0f, 1.0f, 0.0f, "Channel 2", "V", 0.0f, 10.0f); - configParam(CHANNEL3_PARAM, -1.0f, 1.0f, 0.0f, "Channel 3", "V", 0.0f, 10.0f); - configParam(CHANNEL4_PARAM, -1.0f, 1.0f, 0.0f, "Channel 4", "V", 0.0f, 10.0f); - configParam(CHANNEL5_PARAM, -1.0f, 1.0f, 0.0f, "Channel 5", "V", 0.0f, 10.0f); - configParam(CHANNEL6_PARAM, -1.0f, 1.0f, 0.0f, "Channel 6", "V", 0.0f, 10.0f); - configParam(CHANNEL7_PARAM, -1.0f, 1.0f, 0.0f, "Channel 7", "V", 0.0f, 10.0f); - configParam(CHANNEL8_PARAM, -1.0f, 1.0f, 0.0f, "Channel 8", "V", 0.0f, 10.0f); - configParam(CHANNEL9_PARAM, -1.0f, 1.0f, 0.0f, "Channel 9", "V", 0.0f, 10.0f); - configParam(CHANNEL10_PARAM, -1.0f, 1.0f, 0.0f, "Channel 10", "V", 0.0f, 10.0f); - configParam(CHANNEL11_PARAM, -1.0f, 1.0f, 0.0f, "Channel 11", "V", 0.0f, 10.0f); - configParam(CHANNEL12_PARAM, -1.0f, 1.0f, 0.0f, "Channel 12", "V", 0.0f, 10.0f); - configParam(CHANNEL13_PARAM, -1.0f, 1.0f, 0.0f, "Channel 13", "V", 0.0f, 10.0f); - configParam(CHANNEL14_PARAM, -1.0f, 1.0f, 0.0f, "Channel 14", "V", 0.0f, 10.0f); - configParam(CHANNEL15_PARAM, -1.0f, 1.0f, 0.0f, "Channel 15", "V", 0.0f, 10.0f); - configParam(CHANNEL16_PARAM, -1.0f, 1.0f, 0.0f, "Channel 16", "V", 0.0f, 10.0f); + configParam<OutputRangeParamQuantity>(CHANNELS_PARAM, 1.0f, 16.0f, 1.0f, "Polyphony channels"); + configParam<OutputRangeParamQuantity>(CHANNEL1_PARAM, -1.0f, 1.0f, 0.0f, "Channel 1", "V", 0.0f, 10.0f); + configParam<OutputRangeParamQuantity>(CHANNEL2_PARAM, -1.0f, 1.0f, 0.0f, "Channel 2", "V", 0.0f, 10.0f); + configParam<OutputRangeParamQuantity>(CHANNEL3_PARAM, -1.0f, 1.0f, 0.0f, "Channel 3", "V", 0.0f, 10.0f); + configParam<OutputRangeParamQuantity>(CHANNEL4_PARAM, -1.0f, 1.0f, 0.0f, "Channel 4", "V", 0.0f, 10.0f); + configParam<OutputRangeParamQuantity>(CHANNEL5_PARAM, -1.0f, 1.0f, 0.0f, "Channel 5", "V", 0.0f, 10.0f); + configParam<OutputRangeParamQuantity>(CHANNEL6_PARAM, -1.0f, 1.0f, 0.0f, "Channel 6", "V", 0.0f, 10.0f); + configParam<OutputRangeParamQuantity>(CHANNEL7_PARAM, -1.0f, 1.0f, 0.0f, "Channel 7", "V", 0.0f, 10.0f); + configParam<OutputRangeParamQuantity>(CHANNEL8_PARAM, -1.0f, 1.0f, 0.0f, "Channel 8", "V", 0.0f, 10.0f); + configParam<OutputRangeParamQuantity>(CHANNEL9_PARAM, -1.0f, 1.0f, 0.0f, "Channel 9", "V", 0.0f, 10.0f); + configParam<OutputRangeParamQuantity>(CHANNEL10_PARAM, -1.0f, 1.0f, 0.0f, "Channel 10", "V", 0.0f, 10.0f); + configParam<OutputRangeParamQuantity>(CHANNEL11_PARAM, -1.0f, 1.0f, 0.0f, "Channel 11", "V", 0.0f, 10.0f); + configParam<OutputRangeParamQuantity>(CHANNEL12_PARAM, -1.0f, 1.0f, 0.0f, "Channel 12", "V", 0.0f, 10.0f); + configParam<OutputRangeParamQuantity>(CHANNEL13_PARAM, -1.0f, 1.0f, 0.0f, "Channel 13", "V", 0.0f, 10.0f); + configParam<OutputRangeParamQuantity>(CHANNEL14_PARAM, -1.0f, 1.0f, 0.0f, "Channel 14", "V", 0.0f, 10.0f); + configParam<OutputRangeParamQuantity>(CHANNEL15_PARAM, -1.0f, 1.0f, 0.0f, "Channel 15", "V", 0.0f, 10.0f); + configParam<OutputRangeParamQuantity>(CHANNEL16_PARAM, -1.0f, 1.0f, 0.0f, "Channel 16", "V", 0.0f, 10.0f); } void processAll(const ProcessArgs& args) override; diff --git a/src/addressable_sequence.cpp b/src/addressable_sequence.cpp @@ -120,51 +120,3 @@ int AddressableSequenceModule::nextStep( int AddressableSequenceModule::setStep(int c, int i, int n) { return _step[c] = i % n; } - - -float OutputRangeAddressableSequenceModule::OutputParamQuantity::getDisplayValue() { - float v = getValue(); - if (!module) { - return v; - } - - auto m = dynamic_cast<OutputRangeAddressableSequenceModule*>(module); - v += m->_rangeOffset; - v *= m->_rangeScale; - return v; -} - -void OutputRangeAddressableSequenceModule::OutputParamQuantity::setDisplayValue(float v) { - if (!module) { - return; - } - - auto m = dynamic_cast<OutputRangeAddressableSequenceModule*>(module); - v /= m->_rangeScale; - v -= m->_rangeOffset; - setValue(v); -} - -#define RANGE_OFFSET "range_offset" -#define RANGE_SCALE "range_scale" - -json_t* OutputRangeAddressableSequenceModule::dataToJson() { - json_t* root = AddressableSequenceModule::dataToJson(); - json_object_set_new(root, RANGE_OFFSET, json_real(_rangeOffset)); - json_object_set_new(root, RANGE_SCALE, json_real(_rangeScale)); - return root; -} - -void OutputRangeAddressableSequenceModule::dataFromJson(json_t* root) { - AddressableSequenceModule::dataFromJson(root); - - json_t* ro = json_object_get(root, RANGE_OFFSET); - if (ro) { - _rangeOffset = json_real_value(ro); - } - - json_t* rs = json_object_get(root, RANGE_SCALE); - if (rs) { - _rangeScale = json_real_value(rs); - } -} diff --git a/src/addressable_sequence.hpp b/src/addressable_sequence.hpp @@ -1,6 +1,7 @@ #pragma once #include "bogaudio.hpp" +#include "output_range.hpp" #include "dsp/signal.hpp" using namespace rack; @@ -71,17 +72,6 @@ struct AddressableSequenceModuleWidget : AddressableSequenceBaseModuleWidget { } }; -struct OutputRangeAddressableSequenceModule : AddressableSequenceModule { - float _rangeOffset = 0.0f; - float _rangeScale = 10.0f; - - struct OutputParamQuantity : ParamQuantity { - float getDisplayValue() override; - void setDisplayValue(float v) override; - }; - - json_t* dataToJson() override; - void dataFromJson(json_t* root) override; -}; +typedef OutputRangeModule<AddressableSequenceModule> OutputRangeAddressableSequenceModule; } // namespace bogaudio diff --git a/src/output_range.cpp b/src/output_range.cpp @@ -0,0 +1,27 @@ + +#include "output_range.hpp" + +using namespace bogaudio; + +float OutputRange::OutputRangeParamQuantity::getDisplayValue() { + float v = getValue(); + if (!module) { + return v; + } + + auto m = dynamic_cast<OutputRange*>(module); + v += m->_rangeOffset; + v *= m->_rangeScale; + return v; +} + +void OutputRange::OutputRangeParamQuantity::setDisplayValue(float v) { + if (!module) { + return; + } + + auto m = dynamic_cast<OutputRange*>(module); + v /= m->_rangeScale; + v -= m->_rangeOffset; + setValue(v); +} diff --git a/src/output_range.hpp b/src/output_range.hpp @@ -0,0 +1,74 @@ +#pragma once + +#include "bogaudio.hpp" + +using namespace rack; + +namespace bogaudio { + +struct OutputRange { + float _rangeOffset = 0.0f; + float _rangeScale = 10.0f; + + struct OutputRangeParamQuantity : ParamQuantity { + float getDisplayValue() override; + void setDisplayValue(float v) override; + }; +}; + +template<class BASE> +struct OutputRangeModule : BASE, OutputRange { + json_t* dataToJson() { + json_t* root = BASE::dataToJson(); + if (!root) { + root = json_object(); + } + json_object_set_new(root, "range_offset", json_real(_rangeOffset)); + json_object_set_new(root, "range_scale", json_real(_rangeScale)); + return root; + } + + void dataFromJson(json_t* root) { + BASE::dataFromJson(root); + + json_t* ro = json_object_get(root, "range_offset"); + if (ro) { + _rangeOffset = json_real_value(ro); + } + + json_t* rs = json_object_get(root, "range_scale"); + if (rs) { + _rangeScale = json_real_value(rs); + } + } +}; + +struct OutputRangeOptionMenuItem : OptionMenuItem { + OutputRangeOptionMenuItem(OutputRange* module, const char* label, float offset, float scale) + : OptionMenuItem( + label, + [=]() { return module->_rangeOffset == offset && module->_rangeScale == scale; }, + [=]() { + module->_rangeOffset = offset; + module->_rangeScale = scale; + } + ) + {} + + static void addOutputRangeOptionsToMenu(Module* module, Menu* menu) { + auto m = dynamic_cast<OutputRange*>(module); + assert(m); + OptionsMenuItem* mi = new OptionsMenuItem("Range"); + mi->addItem(OutputRangeOptionMenuItem(m, "+/-10V", 0.0f, 10.0f)); + mi->addItem(OutputRangeOptionMenuItem(m, "+/-5V", 0.0f, 5.0f)); + mi->addItem(OutputRangeOptionMenuItem(m, "+/-3V", 0.0f, 3.0f)); + mi->addItem(OutputRangeOptionMenuItem(m, "+/-1V", 0.0f, 1.0f)); + mi->addItem(OutputRangeOptionMenuItem(m, "0V-10V", 1.0f, 5.0f)); + mi->addItem(OutputRangeOptionMenuItem(m, "0V-5V", 1.0f, 2.5f)); + mi->addItem(OutputRangeOptionMenuItem(m, "0V-3V", 1.0f, 1.5f)); + mi->addItem(OutputRangeOptionMenuItem(m, "0V-1V", 1.0f, 0.5f)); + OptionsMenuItem::addToMenu(mi, menu); + } +}; + +} // namespace bogaudio