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:
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;