BogaudioModules

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

commit 0b5dc72b3b7023b9301ac6d93b56969eea5d4e70
parent eeb52cc954fadb5bbfe4b24a9802835226d7af02
Author: Matt Demanett <matt@demanett.net>
Date:   Mon, 13 Apr 2020 18:42:04 -0400

ADDR-SEQ, 8:1, 1:8, PGMR: add option where negative triggers will step backwards.

Diffstat:
Msrc/addressable_sequence.cpp | 14++++++++++++--
Msrc/addressable_sequence.hpp | 4++++
Msrc/rack_overrides.hpp | 29+++++++++++++++++++++++++++++
3 files changed, 45 insertions(+), 2 deletions(-)

diff --git a/src/addressable_sequence.cpp b/src/addressable_sequence.cpp @@ -4,12 +4,14 @@ #define POLY_INPUT "poly_input" #define SELECT_ON_CLOCK "select_on_clock" #define TRIGGERED_SELECT "triggered_select" +#define REVERSE_ON_NEGATIVE_CLOCK "reverse_on_negative_clock" void AddressableSequenceModule::reset() { for (int i = 0; i < maxChannels; ++i) { _step[i] = 0; _select[i] = 0; _clock[i].reset(); + _negativeClock[i].reset(); _reset[i].reset(); _selectTrigger[i].reset(); } @@ -27,6 +29,7 @@ json_t* AddressableSequenceModule::dataToJson() { json_object_set_new(root, POLY_INPUT, json_integer(_polyInputID)); json_object_set_new(root, SELECT_ON_CLOCK, json_boolean(_selectOnClock)); json_object_set_new(root, TRIGGERED_SELECT, json_boolean(_triggeredSelect)); + json_object_set_new(root, REVERSE_ON_NEGATIVE_CLOCK, json_boolean(_reverseOnNegativeClock)); return root; } @@ -45,6 +48,11 @@ void AddressableSequenceModule::dataFromJson(json_t* root) { if (t) { _triggeredSelect = json_is_true(t); } + + json_t* r = json_object_get(root, REVERSE_ON_NEGATIVE_CLOCK); + if (r) { + _reverseOnNegativeClock = json_is_true(r); + } } int AddressableSequenceModule::channels() { @@ -72,14 +80,16 @@ int AddressableSequenceModule::nextStep( } } bool timer = _timer[c].next(); - bool clock = _clock[c].process(clockInput.getPolyVoltage(c)) && !timer; + float clockVoltage = clockInput.getPolyVoltage(c); + bool clock = _clock[c].process(clockVoltage) && !timer; + bool negativeClock = _negativeClock[c].process(clockVoltage) && _reverseOnNegativeClock && !timer && !clock; int steps = n; if (stepsParam) { steps = clamp(stepsParam->getValue(), 1.0f, (float)n); } int reverse = 1 - 2 * (directionParam.getValue() == 0.0f); - _step[c] = (_step[c] + reverse * clock) % steps; + _step[c] = (_step[c] + reverse * clock + -reverse * negativeClock) % steps; _step[c] += (_step[c] < 0) * steps; _step[c] -= _step[c] * reset; diff --git a/src/addressable_sequence.hpp b/src/addressable_sequence.hpp @@ -12,6 +12,7 @@ struct AddressableSequenceModule : BGModule { int _clockInputID = -1; int _selectInputID = -1; Trigger _clock[maxChannels]; + NegativeTrigger _negativeClock[maxChannels]; Trigger _reset[maxChannels]; Trigger _selectTrigger[maxChannels]; bogaudio::dsp::Timer _timer[maxChannels]; @@ -19,6 +20,7 @@ struct AddressableSequenceModule : BGModule { float _select[maxChannels] {}; bool _selectOnClock = false; bool _triggeredSelect = false; + bool _reverseOnNegativeClock = false; void setInputIDs(int clockInputID, int selectInputID) { _polyInputID = clockInputID; @@ -53,6 +55,8 @@ struct AddressableSequenceBaseModuleWidget : ModuleWidget { p->addItem(OptionMenuItem("CLOCK input", [m]() { return m->_polyInputID == m->_clockInputID; }, [m]() { m->_polyInputID = m->_clockInputID; })); p->addItem(OptionMenuItem("SELECT input", [m]() { return m->_polyInputID == m->_selectInputID; }, [m]() { m->_polyInputID = m->_selectInputID; })); OptionsMenuItem::addToMenu(p, menu); + + menu->addChild(new BoolOptionMenuItem("Reverse step on negative clock", [m]() { return &m->_reverseOnNegativeClock; })); } }; diff --git a/src/rack_overrides.hpp b/src/rack_overrides.hpp @@ -12,6 +12,7 @@ struct Trigger : rack::dsp::SchmittTrigger { : _highThreshold(highThreshold) , _lowThreshold(lowThreshold) { + assert(_highThreshold > _lowThreshold); reset(); } @@ -31,6 +32,34 @@ struct Trigger : rack::dsp::SchmittTrigger { } }; +struct NegativeTrigger : rack::dsp::SchmittTrigger { + float _highThreshold; + float _lowThreshold; + + NegativeTrigger(float highThreshold = -1.0f, float lowThreshold = -0.1f) + : _highThreshold(highThreshold) + , _lowThreshold(lowThreshold) + { + assert(_highThreshold < _lowThreshold); + reset(); + } + + bool process(float in) { + if (state) { + if (in >= _lowThreshold) { + state = false; + } + } + else { + if (in <= _highThreshold) { + state = true; + return true; + } + } + return false; + } +}; + inline float getZoom() { return APP->scene->rackScroll->zoomWidget->zoom; }