BogaudioModules

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

commit b4808db9fd141ff66a5dc1edb4089985e19666f7
parent 71b217f2c7f46a299291cdac848b6635ce673606
Author: Matt Demanett <matt@demanett.net>
Date:   Mon, 15 Jul 2019 00:58:18 -0400

Refactoring: simplify TriggerOnLoad* and DisableOutputLimit*; factor modules that have a "select on clock" behavior in similar way.

Diffstat:
Msrc/AddrSeq.cpp | 32+++++---------------------------
Msrc/AddrSeq.hpp | 4++--
Msrc/DADSRH.cpp | 9+--------
Msrc/DADSRH.hpp | 123++++++++++++++++++++++++++++++++++++++++---------------------------------------
Msrc/DADSRHPlus.cpp | 9+--------
Msrc/DADSRHPlus.hpp | 122++++++++++++++++++++++++++++++++++++++++----------------------------------------
Msrc/DGate.cpp | 9+--------
Msrc/DGate.hpp | 4+++-
Msrc/EightOne.cpp | 42+-----------------------------------------
Msrc/EightOne.hpp | 6++----
Msrc/Manual.cpp | 8++++----
Msrc/Manual.hpp | 4+++-
Msrc/Offset.cpp | 3++-
Msrc/Offset.hpp | 3++-
Msrc/OneEight.cpp | 42+-----------------------------------------
Msrc/OneEight.hpp | 6++----
Msrc/Shaper.cpp | 9+--------
Msrc/Shaper.hpp | 95+++++++++++++++++++++++++++++++++++++++----------------------------------------
Msrc/ShaperPlus.cpp | 9+--------
Msrc/ShaperPlus.hpp | 95+++++++++++++++++++++++++++++++++++++++----------------------------------------
Msrc/Sums.cpp | 3++-
Msrc/Sums.hpp | 3++-
Msrc/VCM.cpp | 3++-
Msrc/VCM.hpp | 3++-
Msrc/bogaudio.hpp | 1-
Msrc/disable_output_limit.hpp | 8--------
Asrc/select_on_clock.cpp | 17+++++++++++++++++
Asrc/select_on_clock.hpp | 43+++++++++++++++++++++++++++++++++++++++++++
Msrc/trigger_on_load.hpp | 13+++++++++----
29 files changed, 326 insertions(+), 402 deletions(-)

diff --git a/src/AddrSeq.cpp b/src/AddrSeq.cpp @@ -1,7 +1,6 @@ #include "AddrSeq.hpp" -#define SELECT_ON_CLOCK "select_on_clock" #define RANGE_OFFSET "range_offset" #define RANGE_SCALE "range_scale" @@ -39,18 +38,14 @@ void AddrSeq::onSampleRateChange() { } json_t* AddrSeq::dataToJson() { - json_t* root = json_object(); - json_object_set_new(root, SELECT_ON_CLOCK, json_boolean(_selectOnClock)); + json_t* root = SelectOnClockModule::dataToJson(); json_object_set_new(root, RANGE_OFFSET, json_real(_rangeOffset)); json_object_set_new(root, RANGE_SCALE, json_real(_rangeScale)); return root; } void AddrSeq::dataFromJson(json_t* root) { - json_t* s = json_object_get(root, SELECT_ON_CLOCK); - if (s) { - _selectOnClock = json_is_true(s); - } + SelectOnClockModule::dataFromJson(root); json_t* ro = json_object_get(root, RANGE_OFFSET); if (ro) { @@ -94,23 +89,6 @@ void AddrSeq::process(const ProcessArgs& args) { outputs[OUT_OUTPUT].setVoltage(out); } -struct SelectOnClockMenuItem : MenuItem { - AddrSeq* _module; - - SelectOnClockMenuItem(AddrSeq* module, const char* label) - : _module(module) - { - this->text = label; - } - - void onAction(const event::Action& e) override { - _module->_selectOnClock = !_module->_selectOnClock; - } - - void step() override { - rightText = _module->_selectOnClock ? "✔" : ""; - } -}; struct AddrSeqRangeMenuItem : MenuItem { AddrSeq* _module; @@ -134,7 +112,7 @@ struct AddrSeqRangeMenuItem : MenuItem { } }; -struct AddrSeqWidget : ModuleWidget { +struct AddrSeqWidget : SelectOnClockModuleWidget { static constexpr int hp = 6; AddrSeqWidget(AddrSeq* module) { @@ -217,11 +195,11 @@ struct AddrSeqWidget : ModuleWidget { } void appendContextMenu(Menu* menu) override { + SelectOnClockModuleWidget::appendContextMenu(menu); + AddrSeq* m = dynamic_cast<AddrSeq*>(module); assert(m); menu->addChild(new MenuLabel()); - menu->addChild(new SelectOnClockMenuItem(m, "Select on clock")); - menu->addChild(new MenuLabel()); menu->addChild(new AddrSeqRangeMenuItem(m, "Range: +/-10V", 0.0f, 10.0f)); menu->addChild(new AddrSeqRangeMenuItem(m, "Range: +/-5V", 0.0f, 5.0f)); menu->addChild(new AddrSeqRangeMenuItem(m, "Range: +/-3V", 0.0f, 3.0f)); diff --git a/src/AddrSeq.hpp b/src/AddrSeq.hpp @@ -1,6 +1,7 @@ #pragma once #include "bogaudio.hpp" +#include "select_on_clock.hpp" #include "dsp/signal.hpp" using namespace bogaudio::dsp; @@ -9,7 +10,7 @@ extern Model* modelAddrSeq; namespace bogaudio { -struct AddrSeq : Module { +struct AddrSeq : SelectOnClockModule { enum ParamsIds { STEPS_PARAM, DIRECTION_PARAM, @@ -53,7 +54,6 @@ struct AddrSeq : Module { Trigger _reset; bogaudio::dsp::Timer _timer; int _step; - bool _selectOnClock = false; int _select = 0; float _rangeOffset = 0.0f; float _rangeScale = 10.0f; diff --git a/src/DADSRH.cpp b/src/DADSRH.cpp @@ -1,7 +1,7 @@ #include "DADSRH.hpp" -struct DADSRHWidget : ModuleWidget { +struct DADSRHWidget : TriggerOnLoadModuleWidget { static constexpr int hp = 10; DADSRHWidget(DADSRH* module) { @@ -94,13 +94,6 @@ struct DADSRHWidget : ModuleWidget { addChild(createLight<TinyLight<GreenLight>>(releaseShape2LightPosition, module, DADSRH::RELEASE_SHAPE2_LIGHT)); addChild(createLight<TinyLight<GreenLight>>(releaseShape3LightPosition, module, DADSRH::RELEASE_SHAPE3_LIGHT)); } - - void appendContextMenu(Menu* menu) override { - DADSRH* dadsrh = dynamic_cast<DADSRH*>(module); - assert(dadsrh); - menu->addChild(new MenuLabel()); - menu->addChild(new TriggerOnLoadMenuItem(dadsrh, "Resume loop on load")); - } }; Model* modelDADSRH = bogaudio::createModel<DADSRH, DADSRHWidget>("Bogaudio-DADSRH", "DADSR(H)", "advanced envelope", "Envelope generator"); diff --git a/src/DADSRH.hpp b/src/DADSRH.hpp @@ -1,6 +1,7 @@ #pragma once #include "bogaudio.hpp" +#include "trigger_on_load.hpp" #include "dadsrh_core.hpp" extern Model* modelDADSRH; @@ -56,65 +57,10 @@ struct DADSRH : TriggerOnLoadModule { NUM_LIGHTS }; - DADSRHCore _core; + DADSRHCore* _core; - DADSRH() : TriggerOnLoadModule( - NUM_PARAMS, - NUM_INPUTS, - NUM_OUTPUTS, - NUM_LIGHTS - ) - , _core( - params[DELAY_PARAM], - params[ATTACK_PARAM], - params[DECAY_PARAM], - params[SUSTAIN_PARAM], - params[RELEASE_PARAM], - params[HOLD_PARAM], - params[ATTACK_SHAPE_PARAM], - params[DECAY_SHAPE_PARAM], - params[RELEASE_SHAPE_PARAM], - params[TRIGGER_PARAM], - params[MODE_PARAM], - params[LOOP_PARAM], - params[SPEED_PARAM], - params[RETRIGGER_PARAM], - - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - inputs[TRIGGER_INPUT], - - NULL, - NULL, - NULL, - NULL, - NULL, - outputs[ENV_OUTPUT], - outputs[INV_OUTPUT], - outputs[TRIGGER_OUTPUT], - - lights[DELAY_LIGHT], - lights[ATTACK_LIGHT], - lights[DECAY_LIGHT], - lights[SUSTAIN_LIGHT], - lights[RELEASE_LIGHT], - lights[ATTACK_SHAPE1_LIGHT], - lights[ATTACK_SHAPE2_LIGHT], - lights[ATTACK_SHAPE3_LIGHT], - lights[DECAY_SHAPE1_LIGHT], - lights[DECAY_SHAPE2_LIGHT], - lights[DECAY_SHAPE3_LIGHT], - lights[RELEASE_SHAPE1_LIGHT], - lights[RELEASE_SHAPE2_LIGHT], - lights[RELEASE_SHAPE3_LIGHT], - - _triggerOnLoad, - _shouldTriggerOnLoad - ) { + DADSRH() { + config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); configParam<EnvelopeSegmentParamQuantity>(DELAY_PARAM, 0.0f, 1.0f, 0.0f, "Delay", " s"); configParam<EnvelopeSegmentParamQuantity>(ATTACK_PARAM, 0.0f, 1.0f, 0.14142f, "Attack", " s"); configParam<EnvelopeSegmentParamQuantity>(DECAY_PARAM, 0.0f, 1.0f, 0.31623f, "Decay", " s"); @@ -130,19 +76,74 @@ struct DADSRH : TriggerOnLoadModule { configParam(SPEED_PARAM, 0.0f, 1.0f, 1.0f, "Speed"); configParam(RETRIGGER_PARAM, 0.0f, 1.0f, 1.0f, "Retrigger"); + _core = new DADSRHCore( + params[DELAY_PARAM], + params[ATTACK_PARAM], + params[DECAY_PARAM], + params[SUSTAIN_PARAM], + params[RELEASE_PARAM], + params[HOLD_PARAM], + params[ATTACK_SHAPE_PARAM], + params[DECAY_SHAPE_PARAM], + params[RELEASE_SHAPE_PARAM], + params[TRIGGER_PARAM], + params[MODE_PARAM], + params[LOOP_PARAM], + params[SPEED_PARAM], + params[RETRIGGER_PARAM], + + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + inputs[TRIGGER_INPUT], + + NULL, + NULL, + NULL, + NULL, + NULL, + outputs[ENV_OUTPUT], + outputs[INV_OUTPUT], + outputs[TRIGGER_OUTPUT], + + lights[DELAY_LIGHT], + lights[ATTACK_LIGHT], + lights[DECAY_LIGHT], + lights[SUSTAIN_LIGHT], + lights[RELEASE_LIGHT], + lights[ATTACK_SHAPE1_LIGHT], + lights[ATTACK_SHAPE2_LIGHT], + lights[ATTACK_SHAPE3_LIGHT], + lights[DECAY_SHAPE1_LIGHT], + lights[DECAY_SHAPE2_LIGHT], + lights[DECAY_SHAPE3_LIGHT], + lights[RELEASE_SHAPE1_LIGHT], + lights[RELEASE_SHAPE2_LIGHT], + lights[RELEASE_SHAPE3_LIGHT], + + _triggerOnLoad, + _shouldTriggerOnLoad + ); + onReset(); } + virtual ~DADSRH() { + delete _core; + } void onReset() override { - _core.reset(); + _core->reset(); } void process(const ProcessArgs& args) override { - _core.step(); + _core->step(); } bool shouldTriggerOnNextLoad() override { - return _core._stage != _core.STOPPED_STAGE; + return _core->_stage != _core->STOPPED_STAGE; } }; diff --git a/src/DADSRHPlus.cpp b/src/DADSRHPlus.cpp @@ -1,7 +1,7 @@ #include "DADSRHPlus.hpp" -struct DADSRHPlusWidget : ModuleWidget { +struct DADSRHPlusWidget : TriggerOnLoadModuleWidget { static constexpr int hp = 15; DADSRHPlusWidget(DADSRHPlus* module) { @@ -116,13 +116,6 @@ struct DADSRHPlusWidget : ModuleWidget { addChild(createLight<TinyLight<GreenLight>>(releaseShape2LightPosition, module, DADSRHPlus::RELEASE_SHAPE2_LIGHT)); addChild(createLight<TinyLight<GreenLight>>(releaseShape3LightPosition, module, DADSRHPlus::RELEASE_SHAPE3_LIGHT)); } - - void appendContextMenu(Menu* menu) override { - DADSRHPlus* dadsrhPlus = dynamic_cast<DADSRHPlus*>(module); - assert(dadsrhPlus); - menu->addChild(new MenuLabel()); - menu->addChild(new TriggerOnLoadMenuItem(dadsrhPlus, "Resume loop on load")); - } }; Model* modelDADSRHPlus = bogaudio::createModel<DADSRHPlus, DADSRHPlusWidget>("Bogaudio-DADSRHPlus", "DADSR(H)+", "advanced envelope", "Envelope generator"); diff --git a/src/DADSRHPlus.hpp b/src/DADSRHPlus.hpp @@ -1,6 +1,7 @@ #pragma once #include "bogaudio.hpp" +#include "trigger_on_load.hpp" #include "dadsrh_core.hpp" extern Model* modelDADSRHPlus; @@ -67,65 +68,10 @@ struct DADSRHPlus : TriggerOnLoadModule { NUM_LIGHTS }; - DADSRHCore _core; + DADSRHCore* _core; - DADSRHPlus() : TriggerOnLoadModule( - NUM_PARAMS, - NUM_INPUTS, - NUM_OUTPUTS, - NUM_LIGHTS - ) - , _core( - params[DELAY_PARAM], - params[ATTACK_PARAM], - params[DECAY_PARAM], - params[SUSTAIN_PARAM], - params[RELEASE_PARAM], - params[HOLD_PARAM], - params[ATTACK_SHAPE_PARAM], - params[DECAY_SHAPE_PARAM], - params[RELEASE_SHAPE_PARAM], - params[TRIGGER_PARAM], - params[MODE_PARAM], - params[LOOP_PARAM], - params[SPEED_PARAM], - params[RETRIGGER_PARAM], - - &inputs[DELAY_INPUT], - &inputs[ATTACK_INPUT], - &inputs[DECAY_INPUT], - &inputs[SUSTAIN_INPUT], - &inputs[RELEASE_INPUT], - &inputs[HOLD_INPUT], - inputs[TRIGGER_INPUT], - - &outputs[DELAY_OUTPUT], - &outputs[ATTACK_OUTPUT], - &outputs[DECAY_OUTPUT], - &outputs[SUSTAIN_OUTPUT], - &outputs[RELEASE_OUTPUT], - outputs[ENV_OUTPUT], - outputs[INV_OUTPUT], - outputs[TRIGGER_OUTPUT], - - lights[DELAY_LIGHT], - lights[ATTACK_LIGHT], - lights[DECAY_LIGHT], - lights[SUSTAIN_LIGHT], - lights[RELEASE_LIGHT], - lights[ATTACK_SHAPE1_LIGHT], - lights[ATTACK_SHAPE2_LIGHT], - lights[ATTACK_SHAPE3_LIGHT], - lights[DECAY_SHAPE1_LIGHT], - lights[DECAY_SHAPE2_LIGHT], - lights[DECAY_SHAPE3_LIGHT], - lights[RELEASE_SHAPE1_LIGHT], - lights[RELEASE_SHAPE2_LIGHT], - lights[RELEASE_SHAPE3_LIGHT], - - _triggerOnLoad, - _shouldTriggerOnLoad - ) { + DADSRHPlus() { + config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); configParam<EnvelopeSegmentParamQuantity>(DELAY_PARAM, 0.0f, 1.0f, 0.0f, "Delay", " s"); configParam<EnvelopeSegmentParamQuantity>(ATTACK_PARAM, 0.0f, 1.0f, 0.14142f, "Attack", " s"); configParam<EnvelopeSegmentParamQuantity>(DECAY_PARAM, 0.0f, 1.0f, 0.31623f, "Decay", " s"); @@ -141,19 +87,73 @@ struct DADSRHPlus : TriggerOnLoadModule { configParam(SPEED_PARAM, 0.0f, 1.0f, 1.0f, "Speed"); configParam(RETRIGGER_PARAM, 0.0f, 1.0f, 1.0f, "Retrigger"); + _core = new DADSRHCore( + params[DELAY_PARAM], + params[ATTACK_PARAM], + params[DECAY_PARAM], + params[SUSTAIN_PARAM], + params[RELEASE_PARAM], + params[HOLD_PARAM], + params[ATTACK_SHAPE_PARAM], + params[DECAY_SHAPE_PARAM], + params[RELEASE_SHAPE_PARAM], + params[TRIGGER_PARAM], + params[MODE_PARAM], + params[LOOP_PARAM], + params[SPEED_PARAM], + params[RETRIGGER_PARAM], + + &inputs[DELAY_INPUT], + &inputs[ATTACK_INPUT], + &inputs[DECAY_INPUT], + &inputs[SUSTAIN_INPUT], + &inputs[RELEASE_INPUT], + &inputs[HOLD_INPUT], + inputs[TRIGGER_INPUT], + + &outputs[DELAY_OUTPUT], + &outputs[ATTACK_OUTPUT], + &outputs[DECAY_OUTPUT], + &outputs[SUSTAIN_OUTPUT], + &outputs[RELEASE_OUTPUT], + outputs[ENV_OUTPUT], + outputs[INV_OUTPUT], + outputs[TRIGGER_OUTPUT], + + lights[DELAY_LIGHT], + lights[ATTACK_LIGHT], + lights[DECAY_LIGHT], + lights[SUSTAIN_LIGHT], + lights[RELEASE_LIGHT], + lights[ATTACK_SHAPE1_LIGHT], + lights[ATTACK_SHAPE2_LIGHT], + lights[ATTACK_SHAPE3_LIGHT], + lights[DECAY_SHAPE1_LIGHT], + lights[DECAY_SHAPE2_LIGHT], + lights[DECAY_SHAPE3_LIGHT], + lights[RELEASE_SHAPE1_LIGHT], + lights[RELEASE_SHAPE2_LIGHT], + lights[RELEASE_SHAPE3_LIGHT], + + _triggerOnLoad, + _shouldTriggerOnLoad + ); onReset(); } + virtual ~DADSRHPlus() { + delete _core; + } void onReset() override { - _core.reset(); + _core->reset(); } void process(const ProcessArgs& args) override { - _core.step(); + _core->step(); } bool shouldTriggerOnNextLoad() override { - return _core._stage != _core.STOPPED_STAGE; + return _core->_stage != _core->STOPPED_STAGE; } }; diff --git a/src/DGate.cpp b/src/DGate.cpp @@ -69,7 +69,7 @@ bool DGate::stepStage(Param& knob) { return _stageProgress > t; } -struct DGateWidget : ModuleWidget { +struct DGateWidget : TriggerOnLoadModuleWidget { static constexpr int hp = 3; DGateWidget(DGate* module) { @@ -114,13 +114,6 @@ struct DGateWidget : ModuleWidget { addChild(createLight<TinyLight<GreenLight>>(delayLightPosition, module, DGate::DELAY_LIGHT)); addChild(createLight<TinyLight<GreenLight>>(gateLightPosition, module, DGate::GATE_LIGHT)); } - - void appendContextMenu(Menu* menu) override { - DGate* dgate = dynamic_cast<DGate*>(module); - assert(dgate); - menu->addChild(new MenuLabel()); - menu->addChild(new TriggerOnLoadMenuItem(dgate, "Resume loop on load")); - } }; Model* modelDGate = bogaudio::createModel<DGate, DGateWidget>("Bogaudio-DGate", "DGate", "trigger-to-gate with delay", "Utility"); diff --git a/src/DGate.hpp b/src/DGate.hpp @@ -1,6 +1,7 @@ #pragma once #include "bogaudio.hpp" +#include "trigger_on_load.hpp" extern Model* modelDGate; @@ -44,7 +45,8 @@ struct DGate : TriggerOnLoadModule { Stage _stage; float _stageProgress; - DGate() : TriggerOnLoadModule(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) { + DGate() { + config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); configParam<EnvelopeSegmentParamQuantity>(DELAY_PARAM, 0.0f, 1.0f, 0.0f, "Delay", " s"); configParam<EnvelopeSegmentParamQuantity>(GATE_PARAM, 0.0f, 1.0f, 0.31623f, "Gate", " s"); configParam(LOOP_PARAM, 0.0f, 1.0f, 1.0f, "Loop"); diff --git a/src/EightOne.cpp b/src/EightOne.cpp @@ -1,8 +1,6 @@ #include "EightOne.hpp" -#define SELECT_ON_CLOCK "select_on_clock" - void EightOne::onReset() { _step = 0; _clock.reset(); @@ -13,19 +11,6 @@ void EightOne::onSampleRateChange() { _timer.setParams(APP->engine->getSampleRate(), 0.001f); } -json_t* EightOne::dataToJson() { - json_t* root = json_object(); - json_object_set_new(root, SELECT_ON_CLOCK, json_boolean(_selectOnClock)); - return root; -} - -void EightOne::dataFromJson(json_t* root) { - json_t* s = json_object_get(root, SELECT_ON_CLOCK); - if (s) { - _selectOnClock = json_is_true(s); - } -} - void EightOne::process(const ProcessArgs& args) { bool reset = _reset.process(inputs[RESET_INPUT].getVoltage()); if (reset) { @@ -55,25 +40,7 @@ void EightOne::process(const ProcessArgs& args) { outputs[OUT_OUTPUT].setVoltage(out); } -struct SelectOnClockMenuItem : MenuItem { - EightOne* _module; - - SelectOnClockMenuItem(EightOne* module, const char* label) - : _module(module) - { - this->text = label; - } - - void onAction(const event::Action& e) override { - _module->_selectOnClock = !_module->_selectOnClock; - } - - void step() override { - rightText = _module->_selectOnClock ? "✔" : ""; - } -}; - -struct EightOneWidget : ModuleWidget { +struct EightOneWidget : SelectOnClockModuleWidget { static constexpr int hp = 6; EightOneWidget(EightOne* module) { @@ -154,13 +121,6 @@ struct EightOneWidget : ModuleWidget { addChild(createLight<SmallLight<GreenLight>>(in7LightPosition, module, EightOne::IN7_LIGHT)); addChild(createLight<SmallLight<GreenLight>>(in8LightPosition, module, EightOne::IN8_LIGHT)); } - - void appendContextMenu(Menu* menu) override { - EightOne* m = dynamic_cast<EightOne*>(module); - assert(m); - menu->addChild(new MenuLabel()); - menu->addChild(new SelectOnClockMenuItem(m, "Select on clock")); - } }; Model* modelEightOne = bogaudio::createModel<EightOne, EightOneWidget>("Bogaudio-EightOne", "8:1", "demux & sequential switch", "Switch"); diff --git a/src/EightOne.hpp b/src/EightOne.hpp @@ -1,6 +1,7 @@ #pragma once #include "bogaudio.hpp" +#include "select_on_clock.hpp" #include "dsp/signal.hpp" using namespace bogaudio::dsp; @@ -9,7 +10,7 @@ extern Model* modelEightOne; namespace bogaudio { -struct EightOne : Module { +struct EightOne : SelectOnClockModule { enum ParamsIds { STEPS_PARAM, DIRECTION_PARAM, @@ -53,7 +54,6 @@ struct EightOne : Module { Trigger _reset; bogaudio::dsp::Timer _timer; int _step; - bool _selectOnClock = false; int _select = 0; EightOne() { @@ -68,8 +68,6 @@ struct EightOne : Module { void onReset() override; void onSampleRateChange() override; - json_t* dataToJson() override; - void dataFromJson(json_t* root) override; void process(const ProcessArgs& args) override; }; diff --git a/src/Manual.cpp b/src/Manual.cpp @@ -29,7 +29,7 @@ void Manual::process(const ProcessArgs& args) { _firstStep = false; } -struct ManualWidget : ModuleWidget { +struct ManualWidget : TriggerOnLoadModuleWidget { static constexpr int hp = 3; ManualWidget(Manual* module) { @@ -72,10 +72,10 @@ struct ManualWidget : ModuleWidget { } void appendContextMenu(Menu* menu) override { - Manual* manual = dynamic_cast<Manual*>(module); - assert(manual); + TriggerOnLoadModule* m = dynamic_cast<TriggerOnLoadModule*>(module); + assert(m); menu->addChild(new MenuLabel()); - menu->addChild(new TriggerOnLoadMenuItem(manual, "Trigger on load")); + menu->addChild(new TriggerOnLoadMenuItem(m, "Trigger on load")); } }; diff --git a/src/Manual.hpp b/src/Manual.hpp @@ -1,6 +1,7 @@ #pragma once #include "bogaudio.hpp" +#include "trigger_on_load.hpp" extern Model* modelManual; @@ -36,7 +37,8 @@ struct Manual : TriggerOnLoadModule { Trigger _trigger; rack::dsp::PulseGenerator _pulse; - Manual() : TriggerOnLoadModule(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) { + Manual() { + config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); configParam(TRIGGER_PARAM, 0.0f, 1.0f, 0.0f, "Trigger"); _triggerOnLoad = false; onReset(); diff --git a/src/Offset.cpp b/src/Offset.cpp @@ -27,7 +27,8 @@ float Offset::knobValue(const Param& knob, Input& cv) const { struct OffsetWidget : DisableOutputLimitModuleWidget { static constexpr int hp = 3; - OffsetWidget(Offset* module) : DisableOutputLimitModuleWidget(module) { + OffsetWidget(Offset* module) { + setModule(module); box.size = Vec(RACK_GRID_WIDTH * hp, RACK_GRID_HEIGHT); { diff --git a/src/Offset.hpp b/src/Offset.hpp @@ -26,7 +26,8 @@ struct Offset : DisableOutputLimitModule { NUM_OUTPUTS }; - Offset() : DisableOutputLimitModule(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS) { + Offset() { + config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS); configParam(OFFSET_PARAM, -1.0f, 1.0f, 0.0f, "Offset", " V", 0.0f, 5.0f); configParam(SCALE_PARAM, -1.0f, 1.0f, 0.316f, "Scale", "%", 0.0f, 100.0f); } diff --git a/src/OneEight.cpp b/src/OneEight.cpp @@ -1,8 +1,6 @@ #include "OneEight.hpp" -#define SELECT_ON_CLOCK "select_on_clock" - void OneEight::onReset() { _step = 0; _clock.reset(); @@ -13,19 +11,6 @@ void OneEight::onSampleRateChange() { _timer.setParams(APP->engine->getSampleRate(), 0.001f); } -json_t* OneEight::dataToJson() { - json_t* root = json_object(); - json_object_set_new(root, SELECT_ON_CLOCK, json_boolean(_selectOnClock)); - return root; -} - -void OneEight::dataFromJson(json_t* root) { - json_t* s = json_object_get(root, SELECT_ON_CLOCK); - if (s) { - _selectOnClock = json_is_true(s); - } -} - void OneEight::process(const ProcessArgs& args) { bool reset = _reset.process(inputs[RESET_INPUT].getVoltage()); if (reset) { @@ -54,25 +39,7 @@ void OneEight::process(const ProcessArgs& args) { } } -struct SelectOnClockMenuItem : MenuItem { - OneEight* _module; - - SelectOnClockMenuItem(OneEight* module, const char* label) - : _module(module) - { - this->text = label; - } - - void onAction(const event::Action& e) override { - _module->_selectOnClock = !_module->_selectOnClock; - } - - void step() override { - rightText = _module->_selectOnClock ? "✔" : ""; - } -}; - -struct OneEightWidget : ModuleWidget { +struct OneEightWidget : SelectOnClockModuleWidget { static constexpr int hp = 6; OneEightWidget(OneEight* module) { @@ -153,13 +120,6 @@ struct OneEightWidget : ModuleWidget { addChild(createLight<SmallLight<GreenLight>>(out7LightPosition, module, OneEight::OUT7_LIGHT)); addChild(createLight<SmallLight<GreenLight>>(out8LightPosition, module, OneEight::OUT8_LIGHT)); } - - void appendContextMenu(Menu* menu) override { - OneEight* m = dynamic_cast<OneEight*>(module); - assert(m); - menu->addChild(new MenuLabel()); - menu->addChild(new SelectOnClockMenuItem(m, "Select on clock")); - } }; Model* modelOneEight = bogaudio::createModel<OneEight, OneEightWidget>("Bogaudio-OneEight", "1:8", "mux & sequential switch", "Switch"); diff --git a/src/OneEight.hpp b/src/OneEight.hpp @@ -1,6 +1,7 @@ #pragma once #include "bogaudio.hpp" +#include "select_on_clock.hpp" #include "dsp/signal.hpp" using namespace bogaudio::dsp; @@ -9,7 +10,7 @@ extern Model* modelOneEight; namespace bogaudio { -struct OneEight : Module { +struct OneEight : SelectOnClockModule { enum ParamsIds { STEPS_PARAM, DIRECTION_PARAM, @@ -53,7 +54,6 @@ struct OneEight : Module { Trigger _reset; bogaudio::dsp::Timer _timer; int _step; - bool _selectOnClock = false; int _select = 0; OneEight() { @@ -68,8 +68,6 @@ struct OneEight : Module { void onReset() override; void onSampleRateChange() override; - json_t* dataToJson() override; - void dataFromJson(json_t* root) override; void process(const ProcessArgs& args) override; }; diff --git a/src/Shaper.cpp b/src/Shaper.cpp @@ -1,7 +1,7 @@ #include "Shaper.hpp" -struct ShaperWidget : ModuleWidget { +struct ShaperWidget : TriggerOnLoadModuleWidget { static constexpr int hp = 10; ShaperWidget(Shaper* module) { @@ -70,13 +70,6 @@ struct ShaperWidget : ModuleWidget { addChild(createLight<TinyLight<GreenLight>>(decayLightPosition, module, Shaper::DECAY_LIGHT)); addChild(createLight<TinyLight<GreenLight>>(offLightPosition, module, Shaper::OFF_LIGHT)); } - - void appendContextMenu(Menu* menu) override { - Shaper* shaper = dynamic_cast<Shaper*>(module); - assert(shaper); - menu->addChild(new MenuLabel()); - menu->addChild(new TriggerOnLoadMenuItem(shaper, "Resume loop on load")); - } }; Model* modelShaper = bogaudio::createModel<Shaper, ShaperWidget>("Bogaudio-Shaper", "Shaper", "envelope and amplifier", "Envelope generator", "VCA"); diff --git a/src/Shaper.hpp b/src/Shaper.hpp @@ -1,6 +1,7 @@ #pragma once #include "bogaudio.hpp" +#include "trigger_on_load.hpp" #include "shaper_core.hpp" extern Model* modelShaper; @@ -43,52 +44,10 @@ struct Shaper : TriggerOnLoadModule { NUM_LIGHTS }; - ShaperCore _core; + ShaperCore* _core; - Shaper() : TriggerOnLoadModule( - NUM_PARAMS, - NUM_INPUTS, - NUM_OUTPUTS, - NUM_LIGHTS - ) - , _core( - params[ATTACK_PARAM], - params[ON_PARAM], - params[DECAY_PARAM], - params[OFF_PARAM], - params[ENV_PARAM], - params[SIGNAL_PARAM], - params[TRIGGER_PARAM], - params[SPEED_PARAM], - params[LOOP_PARAM], - - inputs[SIGNAL_INPUT], - inputs[TRIGGER_INPUT], - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - - outputs[SIGNAL_OUTPUT], - outputs[ENV_OUTPUT], - outputs[INV_OUTPUT], - outputs[TRIGGER_OUTPUT], - NULL, - NULL, - NULL, - NULL, - - lights[ATTACK_LIGHT], - lights[ON_LIGHT], - lights[DECAY_LIGHT], - lights[OFF_LIGHT], - - _triggerOnLoad, - _shouldTriggerOnLoad - ) - { + Shaper() { + config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); configParam<EnvelopeSegmentParamQuantity>(ATTACK_PARAM, 0.0f, 1.0f, 0.14142f, "Attack", " s"); configParam<EnvelopeSegmentParamQuantity>(ON_PARAM, 0.0f, 1.0f, 0.31623f, "On", " s"); configParam<EnvelopeSegmentParamQuantity>(DECAY_PARAM, 0.0f, 1.0f, 0.31623f, "Decay", " s"); @@ -99,19 +58,59 @@ struct Shaper : TriggerOnLoadModule { configParam(SPEED_PARAM, 0.0f, 1.0f, 1.0f, "Speed"); configParam(LOOP_PARAM, 0.0f, 1.0f, 1.0f, "Loop"); + _core = new ShaperCore( + params[ATTACK_PARAM], + params[ON_PARAM], + params[DECAY_PARAM], + params[OFF_PARAM], + params[ENV_PARAM], + params[SIGNAL_PARAM], + params[TRIGGER_PARAM], + params[SPEED_PARAM], + params[LOOP_PARAM], + + inputs[SIGNAL_INPUT], + inputs[TRIGGER_INPUT], + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + + outputs[SIGNAL_OUTPUT], + outputs[ENV_OUTPUT], + outputs[INV_OUTPUT], + outputs[TRIGGER_OUTPUT], + NULL, + NULL, + NULL, + NULL, + + lights[ATTACK_LIGHT], + lights[ON_LIGHT], + lights[DECAY_LIGHT], + lights[OFF_LIGHT], + + _triggerOnLoad, + _shouldTriggerOnLoad + ); onReset(); } + virtual ~Shaper() { + delete _core; + } void onReset() override { - _core.reset(); + _core->reset(); } void process(const ProcessArgs& args) override { - _core.step(); + _core->step(); } bool shouldTriggerOnNextLoad() override { - return _core._stage != _core.STOPPED_STAGE; + return _core->_stage != _core->STOPPED_STAGE; } }; diff --git a/src/ShaperPlus.cpp b/src/ShaperPlus.cpp @@ -1,7 +1,7 @@ #include "ShaperPlus.hpp" -struct ShaperPlusWidget : ModuleWidget { +struct ShaperPlusWidget : TriggerOnLoadModuleWidget { static constexpr int hp = 15; ShaperPlusWidget(ShaperPlus* module) { @@ -92,13 +92,6 @@ struct ShaperPlusWidget : ModuleWidget { addChild(createLight<TinyLight<GreenLight>>(decayLightPosition, module, ShaperPlus::DECAY_LIGHT)); addChild(createLight<TinyLight<GreenLight>>(offLightPosition, module, ShaperPlus::OFF_LIGHT)); } - - void appendContextMenu(Menu* menu) override { - ShaperPlus* shaperPlus = dynamic_cast<ShaperPlus*>(module); - assert(shaperPlus); - menu->addChild(new MenuLabel()); - menu->addChild(new TriggerOnLoadMenuItem(shaperPlus, "Resume loop on load")); - } }; Model* modelShaperPlus = bogaudio::createModel<ShaperPlus, ShaperPlusWidget>("Bogaudio-ShaperPlus", "Shaper+", "envelope and amplifier", "Envelope generator", "VCA"); diff --git a/src/ShaperPlus.hpp b/src/ShaperPlus.hpp @@ -1,6 +1,7 @@ #pragma once #include "bogaudio.hpp" +#include "trigger_on_load.hpp" #include "shaper_core.hpp" extern Model* modelShaperPlus; @@ -50,52 +51,10 @@ struct ShaperPlus : TriggerOnLoadModule { NUM_LIGHTS }; - ShaperCore _core; + ShaperCore* _core; - ShaperPlus() : TriggerOnLoadModule( - NUM_PARAMS, - NUM_INPUTS, - NUM_OUTPUTS, - NUM_LIGHTS - ) - , _core( - params[ATTACK_PARAM], - params[ON_PARAM], - params[DECAY_PARAM], - params[OFF_PARAM], - params[ENV_PARAM], - params[SIGNAL_PARAM], - params[TRIGGER_PARAM], - params[SPEED_PARAM], - params[LOOP_PARAM], - - inputs[SIGNAL_INPUT], - inputs[TRIGGER_INPUT], - &inputs[ATTACK_INPUT], - &inputs[ON_INPUT], - &inputs[DECAY_INPUT], - &inputs[OFF_INPUT], - &inputs[ENV_INPUT], - &inputs[SIGNALCV_INPUT], - - outputs[SIGNAL_OUTPUT], - outputs[ENV_OUTPUT], - outputs[INV_OUTPUT], - outputs[TRIGGER_OUTPUT], - &outputs[ATTACK_OUTPUT], - &outputs[ON_OUTPUT], - &outputs[DECAY_OUTPUT], - &outputs[OFF_OUTPUT], - - lights[ATTACK_LIGHT], - lights[ON_LIGHT], - lights[DECAY_LIGHT], - lights[OFF_LIGHT], - - _triggerOnLoad, - _shouldTriggerOnLoad - ) - { + ShaperPlus() { + config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); configParam<EnvelopeSegmentParamQuantity>(ATTACK_PARAM, 0.0f, 1.0f, 0.14142f, "Attack", " s"); configParam<EnvelopeSegmentParamQuantity>(ON_PARAM, 0.0f, 1.0f, 0.31623f, "On", " s"); configParam<EnvelopeSegmentParamQuantity>(DECAY_PARAM, 0.0f, 1.0f, 0.31623f, "Decay", " s"); @@ -106,19 +65,59 @@ struct ShaperPlus : TriggerOnLoadModule { configParam(SPEED_PARAM, 0.0f, 1.0f, 1.0f, "Speed"); configParam(LOOP_PARAM, 0.0f, 1.0f, 1.0f, "Loop"); + _core = new ShaperCore( + params[ATTACK_PARAM], + params[ON_PARAM], + params[DECAY_PARAM], + params[OFF_PARAM], + params[ENV_PARAM], + params[SIGNAL_PARAM], + params[TRIGGER_PARAM], + params[SPEED_PARAM], + params[LOOP_PARAM], + + inputs[SIGNAL_INPUT], + inputs[TRIGGER_INPUT], + &inputs[ATTACK_INPUT], + &inputs[ON_INPUT], + &inputs[DECAY_INPUT], + &inputs[OFF_INPUT], + &inputs[ENV_INPUT], + &inputs[SIGNALCV_INPUT], + + outputs[SIGNAL_OUTPUT], + outputs[ENV_OUTPUT], + outputs[INV_OUTPUT], + outputs[TRIGGER_OUTPUT], + &outputs[ATTACK_OUTPUT], + &outputs[ON_OUTPUT], + &outputs[DECAY_OUTPUT], + &outputs[OFF_OUTPUT], + + lights[ATTACK_LIGHT], + lights[ON_LIGHT], + lights[DECAY_LIGHT], + lights[OFF_LIGHT], + + _triggerOnLoad, + _shouldTriggerOnLoad + ); onReset(); } + virtual ~ShaperPlus() { + delete _core; + } void onReset() override { - _core.reset(); + _core->reset(); } void process(const ProcessArgs& args) override { - _core.step(); + _core->step(); } bool shouldTriggerOnNextLoad() override { - return _core._stage != _core.STOPPED_STAGE; + return _core->_stage != _core->STOPPED_STAGE; } }; diff --git a/src/Sums.cpp b/src/Sums.cpp @@ -35,7 +35,8 @@ void Sums::process(const ProcessArgs& args) { struct SumsWidget : DisableOutputLimitModuleWidget { static constexpr int hp = 3; - SumsWidget(Sums* module) : DisableOutputLimitModuleWidget(module) { + SumsWidget(Sums* module) { + setModule(module); box.size = Vec(RACK_GRID_WIDTH * hp, RACK_GRID_HEIGHT); { diff --git a/src/Sums.hpp b/src/Sums.hpp @@ -32,7 +32,8 @@ struct Sums : DisableOutputLimitModule { NUM_LIGHTS }; - Sums() : DisableOutputLimitModule(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) { + Sums() { + config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); } void process(const ProcessArgs& args) override; diff --git a/src/VCM.cpp b/src/VCM.cpp @@ -45,7 +45,8 @@ float VCM::channelStep(Input& input, Param& knob, Input& cv, Amplifier& amplifie struct VCMWidget : DisableOutputLimitModuleWidget { static constexpr int hp = 10; - VCMWidget(VCM* module) : DisableOutputLimitModuleWidget(module) { + VCMWidget(VCM* module) { + setModule(module); box.size = Vec(RACK_GRID_WIDTH * hp, RACK_GRID_HEIGHT); { diff --git a/src/VCM.hpp b/src/VCM.hpp @@ -53,7 +53,8 @@ struct VCM : DisableOutputLimitModule { bool isLinear() override; }; - VCM() : DisableOutputLimitModule(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) { + VCM() { + config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); configParam<LevelParamQuantity>(LEVEL1_PARAM, 0.0f, 1.0f, 0.8f, "Level 1"); configParam<LevelParamQuantity>(LEVEL2_PARAM, 0.0f, 1.0f, 0.8f, "Level 2"); configParam<LevelParamQuantity>(LEVEL3_PARAM, 0.0f, 1.0f, 0.8f, "Level 3"); diff --git a/src/bogaudio.hpp b/src/bogaudio.hpp @@ -11,7 +11,6 @@ #include "param_quantities.hpp" #include "rack_overrides.hpp" -#include "trigger_on_load.hpp" #include "widgets.hpp" #include "utils.hpp" diff --git a/src/disable_output_limit.hpp b/src/disable_output_limit.hpp @@ -7,10 +7,6 @@ namespace bogaudio { struct DisableOutputLimitModule : Module { bool _disableOutputLimit = false; - DisableOutputLimitModule(int numParams, int numInputs, int numOutputs, int numLights = 0) { - config(numParams, numInputs, numOutputs, numLights); - } - json_t* dataToJson() override; void dataFromJson(json_t* root) override; }; @@ -34,10 +30,6 @@ struct DisableOutputLimitMenuItem : MenuItem { }; struct DisableOutputLimitModuleWidget : ModuleWidget { - DisableOutputLimitModuleWidget(Module* module) { - setModule(module); - } - void appendContextMenu(Menu* menu) override { DisableOutputLimitModule* dolm = dynamic_cast<DisableOutputLimitModule*>(module); assert(dolm); diff --git a/src/select_on_clock.cpp b/src/select_on_clock.cpp @@ -0,0 +1,17 @@ + +#include "select_on_clock.hpp" + +#define SELECT_ON_CLOCK "select_on_clock" + +json_t* SelectOnClockModule::dataToJson() { + json_t* root = json_object(); + json_object_set_new(root, SELECT_ON_CLOCK, json_boolean(_selectOnClock)); + return root; +} + +void SelectOnClockModule::dataFromJson(json_t* root) { + json_t* s = json_object_get(root, SELECT_ON_CLOCK); + if (s) { + _selectOnClock = json_is_true(s); + } +} diff --git a/src/select_on_clock.hpp b/src/select_on_clock.hpp @@ -0,0 +1,43 @@ +#pragma once + +#include "bogaudio.hpp" + +using namespace rack; + +namespace bogaudio { + +struct SelectOnClockModule : Module { + bool _selectOnClock = false; + + json_t* dataToJson() override; + void dataFromJson(json_t* root) override; +}; + +struct SelectOnClockMenuItem : MenuItem { + SelectOnClockModule* _module; + + SelectOnClockMenuItem(SelectOnClockModule* module, const char* label) + : _module(module) + { + this->text = label; + } + + void onAction(const event::Action& e) override { + _module->_selectOnClock = !_module->_selectOnClock; + } + + void step() override { + rightText = _module->_selectOnClock ? "✔" : ""; + } +}; + +struct SelectOnClockModuleWidget : ModuleWidget { + void appendContextMenu(Menu* menu) override { + SelectOnClockModule* m = dynamic_cast<SelectOnClockModule*>(module); + assert(m); + menu->addChild(new MenuLabel()); + menu->addChild(new SelectOnClockMenuItem(m, "Select on clock")); + } +}; + +} // namespace bogaudio diff --git a/src/trigger_on_load.hpp b/src/trigger_on_load.hpp @@ -10,10 +10,6 @@ struct TriggerOnLoadModule : Module { bool _triggerOnLoad = true; bool _shouldTriggerOnLoad = true; - TriggerOnLoadModule(int numParams, int numInputs, int numOutputs, int numLights) { - config(numParams, numInputs, numOutputs, numLights); - } - json_t* dataToJson() override; void dataFromJson(json_t* root) override; @@ -38,4 +34,13 @@ struct TriggerOnLoadMenuItem : MenuItem { } }; +struct TriggerOnLoadModuleWidget : ModuleWidget { + void appendContextMenu(Menu* menu) override { + TriggerOnLoadModule* m = dynamic_cast<TriggerOnLoadModule*>(module); + assert(m); + menu->addChild(new MenuLabel()); + menu->addChild(new TriggerOnLoadMenuItem(m, "Resume loop on load")); + } +}; + } // namespace bogaudio