BogaudioModules

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

commit ba02ea3a6395f0e672618c250a044750a48a6357
parent 9d400f2ea76bc9cb189fb2593bbd4c42596934ac
Author: Matt Demanett <matt@demanett.net>
Date:   Tue,  1 Oct 2019 00:17:18 -0400

Add option to invert output on ADSR and AD. #69

Diffstat:
Msrc/AD.cpp | 48+++++++++++++++++++++++++++++++++++++++++++++++-
Msrc/AD.hpp | 3+++
Msrc/ADSR.cpp | 48+++++++++++++++++++++++++++++++++++++++++++++++-
Msrc/ADSR.hpp | 3+++
4 files changed, 100 insertions(+), 2 deletions(-)

diff --git a/src/AD.cpp b/src/AD.cpp @@ -1,6 +1,8 @@ #include "AD.hpp" +#define INVERT "invert" + void AD::Engine::reset() { trigger.reset(); eocPulseGen.process(10.0); @@ -27,6 +29,19 @@ void AD::sampleRateChange() { } } +json_t* AD::dataToJson() { + json_t* root = json_object(); + json_object_set_new(root, INVERT, json_real(_invert)); + return root; +} + +void AD::dataFromJson(json_t* root) { + json_t* i = json_object_get(root, INVERT); + if (i) { + _invert = json_real_value(i); + } +} + bool AD::active() { return inputs[TRIGGER_INPUT].isConnected() || outputs[ENV_OUTPUT].isConnected() || outputs[EOC_OUTPUT].isConnected(); } @@ -79,7 +94,7 @@ void AD::processChannel(const ProcessArgs& args, int c) { } e.envelope.setGate(e.on); outputs[ENV_OUTPUT].setChannels(_channels); - outputs[ENV_OUTPUT].setVoltage(e.envelope.next() * 10.0f, c); + outputs[ENV_OUTPUT].setVoltage(e.envelope.next() * 10.0f * _invert, c); if (e.on && e.envelope.isStage(ADSR::SUSTAIN_STAGE)) { e.envelope.reset(); e.on = false; @@ -150,6 +165,37 @@ struct ADWidget : ModuleWidget { addChild(createLight<SmallLight<GreenLight>>(loopLightPosition, module, AD::LOOP_LIGHT)); addChild(createLight<SmallLight<GreenLight>>(linearLightPosition, module, AD::LINEAR_LIGHT)); } + + struct InvertMenuItem : MenuItem { + AD* _module; + + InvertMenuItem(AD* module, const char* label, int offset) + : _module(module) + { + this->text = label; + } + + void onAction(const event::Action& e) override { + if (_module->_invert < 0.0f) { + _module->_invert = 1.0f; + } + else { + _module->_invert = -1.0f; + } + } + + void step() override { + MenuItem::step(); + rightText = _module->_invert == -1.0f ? "✔" : ""; + } + }; + + void appendContextMenu(Menu* menu) override { + AD* m = dynamic_cast<AD*>(module); + assert(m); + menu->addChild(new MenuLabel()); + menu->addChild(new InvertMenuItem(m, "Invert output", -1)); + } }; Model* modelAD = bogaudio::createModel<AD, ADWidget>("Bogaudio-AD", "AD", "utility envelope", "Envelope generator"); diff --git a/src/AD.hpp b/src/AD.hpp @@ -63,6 +63,7 @@ struct AD : BGModule { bool _linearMode = false; int _attackLightSum; int _decayLightSum; + float _invert = 1.0f; AD() { config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); @@ -74,6 +75,8 @@ struct AD : BGModule { void reset() override; void sampleRateChange() override; + json_t* dataToJson() override; + void dataFromJson(json_t* root) override; bool active() override; int channels() override; void addEngine(int c) override; diff --git a/src/ADSR.cpp b/src/ADSR.cpp @@ -1,6 +1,8 @@ #include "ADSR.hpp" +#define INVERT "invert" + void ADSR::Engine::reset() { gateTrigger.reset(); envelope.reset(); @@ -22,6 +24,19 @@ void ADSR::sampleRateChange() { } } +json_t* ADSR::dataToJson() { + json_t* root = json_object(); + json_object_set_new(root, INVERT, json_real(_invert)); + return root; +} + +void ADSR::dataFromJson(json_t* root) { + json_t* i = json_object_get(root, INVERT); + if (i) { + _invert = json_real_value(i); + } +} + bool ADSR::active() { return inputs[GATE_INPUT].isConnected() || outputs[OUT_OUTPUT].isConnected(); } @@ -62,7 +77,7 @@ void ADSR::processChannel(const ProcessArgs& args, int c) { e.gateTrigger.process(inputs[GATE_INPUT].getVoltage(c)); e.envelope.setGate(e.gateTrigger.isHigh()); outputs[OUT_OUTPUT].setChannels(_channels); - outputs[OUT_OUTPUT].setVoltage(e.envelope.next() * 10.0f, c); + outputs[OUT_OUTPUT].setVoltage(e.envelope.next() * 10.0f * _invert, c); _attackLightSum += e.envelope.isStage(dsp::ADSR::ATTACK_STAGE); _decayLightSum += e.envelope.isStage(dsp::ADSR::DECAY_STAGE); @@ -128,6 +143,37 @@ struct ADSRWidget : ModuleWidget { addChild(createLight<TinyLight<GreenLight>>(releaseLightPosition, module, ADSR::RELEASE_LIGHT)); addChild(createLight<SmallLight<GreenLight>>(linearLightPosition, module, ADSR::LINEAR_LIGHT)); } + + struct InvertMenuItem : MenuItem { + ADSR* _module; + + InvertMenuItem(ADSR* module, const char* label, int offset) + : _module(module) + { + this->text = label; + } + + void onAction(const event::Action& e) override { + if (_module->_invert < 0.0f) { + _module->_invert = 1.0f; + } + else { + _module->_invert = -1.0f; + } + } + + void step() override { + MenuItem::step(); + rightText = _module->_invert == -1.0f ? "✔" : ""; + } + }; + + void appendContextMenu(Menu* menu) override { + ADSR* m = dynamic_cast<ADSR*>(module); + assert(m); + menu->addChild(new MenuLabel()); + menu->addChild(new InvertMenuItem(m, "Invert output", -1)); + } }; Model* modelADSR = bogaudio::createModel<ADSR, ADSRWidget>("Bogaudio-ADSR", "ADSR", "utility envelope", "Envelope generator"); diff --git a/src/ADSR.hpp b/src/ADSR.hpp @@ -55,6 +55,7 @@ struct ADSR : BGModule { int _decayLightSum; int _sustainLightSum; int _releaseLightSum; + float _invert = 1.0f; ADSR() { config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); @@ -67,6 +68,8 @@ struct ADSR : BGModule { void reset() override; void sampleRateChange() override; + json_t* dataToJson() override; + void dataFromJson(json_t* root) override; bool active() override; int channels() override; void addEngine(int c) override;