BogaudioModules

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

commit 334765b147fadaa193d4730de4c96ebac5ad4b63
parent 2593e2395d62ad049e25d2f81ae2de9bc6a598e2
Author: Matt Demanett <matt@demanett.net>
Date:   Thu,  5 Dec 2019 23:25:18 -0500

Remove all instances where a module can get poly channels from more than one input (on some, the input to use can be set). #93

Diffstat:
Msrc/AMRM.cpp | 2+-
Msrc/AddrSeq.cpp | 4----
Msrc/AddrSeq.hpp | 3+--
Msrc/Bool.cpp | 2+-
Msrc/Clpr.cpp | 2+-
Msrc/Cmp.cpp | 2+-
Msrc/EightOne.cpp | 4----
Msrc/EightOne.hpp | 3+--
Msrc/FMOp.cpp | 2+-
Msrc/Lmtr.cpp | 2+-
Msrc/Matrix88.cpp | 6+-----
Msrc/Nsgt.cpp | 2+-
Msrc/Offset.cpp | 5+----
Msrc/OneEight.cpp | 4----
Msrc/OneEight.hpp | 3+--
Msrc/Pan.cpp | 2+-
Msrc/Pressor.cpp | 2+-
Msrc/SampleHold.cpp | 15++++++++++++++-
Msrc/SampleHold.hpp | 1+
Msrc/Shaper.cpp | 2+-
Msrc/ShaperPlus.cpp | 2+-
Msrc/Sums.cpp | 2+-
Msrc/Switch.cpp | 13+++++--------
Msrc/UMix.cpp | 6+-----
Msrc/VCM.cpp | 5+----
Msrc/VCO.cpp | 27++++++++++++++++++++++++++-
Msrc/VCO.hpp | 3+++
Msrc/Walk.cpp | 39++++++++++++++++++++++++++++++++-------
Msrc/Walk.hpp | 3+++
Msrc/XCO.cpp | 2+-
Msrc/XFade.cpp | 2+-
Msrc/addressable_sequence.cpp | 11+++++++++++
Msrc/addressable_sequence.hpp | 15++++++++++++++-
33 files changed, 130 insertions(+), 68 deletions(-)

diff --git a/src/AMRM.cpp b/src/AMRM.cpp @@ -6,7 +6,7 @@ bool AMRM::active() { } int AMRM::channels() { - return std::max(inputs[MODULATOR_INPUT].getChannels(), inputs[CARRIER_INPUT].getChannels()); + return inputs[CARRIER_INPUT].getChannels(); } void AMRM::processChannel(const ProcessArgs& args, int c) { diff --git a/src/AddrSeq.cpp b/src/AddrSeq.cpp @@ -48,10 +48,6 @@ void AddrSeq::dataFromJson(json_t* root) { } } -int AddrSeq::channels() { - return std::max(1, std::max(inputs[CLOCK_INPUT].getChannels(), inputs[SELECT_INPUT].getChannels())); -} - void AddrSeq::processChannel(const ProcessArgs& args, int c) { int step = nextStep( c, diff --git a/src/AddrSeq.hpp b/src/AddrSeq.hpp @@ -58,7 +58,7 @@ struct AddrSeq : AddressableSequenceModule { void setDisplayValue(float v) override; }; - AddrSeq() { + AddrSeq() : AddressableSequenceModule(CLOCK_INPUT, SELECT_INPUT) { config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); configParam(STEPS_PARAM, 1.0f, 8.0f, 8.0f, "Steps"); configParam(DIRECTION_PARAM, 0.0f, 1.0f, 1.0f, "Direction"); @@ -75,7 +75,6 @@ struct AddrSeq : AddressableSequenceModule { json_t* dataToJson() override; void dataFromJson(json_t* root) override; - int channels() override; void processChannel(const ProcessArgs& args, int c) override; }; diff --git a/src/Bool.cpp b/src/Bool.cpp @@ -4,7 +4,7 @@ void Bool::processChannel(const ProcessArgs& args, int c) { assert(c == 0); - for (int i = 0, cn = std::max(inputs[A_INPUT].getChannels(), inputs[B_INPUT].getChannels()); i < cn; ++i) { + for (int i = 0, cn = inputs[A_INPUT].getChannels(); i < cn; ++i) { bool a = inputs[A_INPUT].getPolyVoltage(i) > 1.0f; bool b = inputs[B_INPUT].getPolyVoltage(i) > 1.0f; outputs[AND_OUTPUT].setChannels(cn); diff --git a/src/Clpr.cpp b/src/Clpr.cpp @@ -6,7 +6,7 @@ bool Clpr::active() { } int Clpr::channels() { - return std::max(inputs[LEFT_INPUT].getChannels(), inputs[RIGHT_INPUT].getChannels()); + return inputs[LEFT_INPUT].getChannels(); } void Clpr::addChannel(int c) { diff --git a/src/Cmp.cpp b/src/Cmp.cpp @@ -18,7 +18,7 @@ bool Cmp::active() { } int Cmp::channels() { - return std::max(1, std::max(inputs[A_INPUT].getChannels(), inputs[B_INPUT].getChannels())); + return std::max(1, inputs[A_INPUT].getChannels()); } void Cmp::modulate() { diff --git a/src/EightOne.cpp b/src/EightOne.cpp @@ -1,10 +1,6 @@ #include "EightOne.hpp" -int EightOne::channels() { - return std::max(1, std::max(inputs[CLOCK_INPUT].getChannels(), inputs[SELECT_INPUT].getChannels())); -} - void EightOne::processChannel(const ProcessArgs& args, int c) { int step = nextStep( c, diff --git a/src/EightOne.hpp b/src/EightOne.hpp @@ -50,14 +50,13 @@ struct EightOne : AddressableSequenceModule { NUM_LIGHTS }; - EightOne() { + EightOne() : AddressableSequenceModule(CLOCK_INPUT, SELECT_INPUT) { config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); 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"); } - int channels() override; void processChannel(const ProcessArgs& args, int c) override; }; diff --git a/src/FMOp.cpp b/src/FMOp.cpp @@ -84,7 +84,7 @@ bool FMOp::active() { } int FMOp::channels() { - return std::max(1, std::max(inputs[PITCH_INPUT].getChannels(), inputs[FM_INPUT].getChannels())); + return std::max(1, inputs[PITCH_INPUT].getChannels()); } void FMOp::addChannel(int c) { diff --git a/src/Lmtr.cpp b/src/Lmtr.cpp @@ -19,7 +19,7 @@ bool Lmtr::active() { } int Lmtr::channels() { - return std::max(inputs[LEFT_INPUT].getChannels(), inputs[RIGHT_INPUT].getChannels()); + return inputs[LEFT_INPUT].getChannels(); } void Lmtr::addChannel(int c) { diff --git a/src/Matrix88.cpp b/src/Matrix88.cpp @@ -2,11 +2,7 @@ #include "Matrix88.hpp" int Matrix88::channels() { - int max = 0; - for (int i = 0; i < 8; ++i) { - max = std::max(max, inputs[IN1_INPUT + i].getChannels()); - } - return max; + return inputs[IN1_INPUT].getChannels(); } void Matrix88::processChannel(const ProcessArgs& args, int c) { diff --git a/src/Nsgt.cpp b/src/Nsgt.cpp @@ -20,7 +20,7 @@ bool Nsgt::active() { } int Nsgt::channels() { - return std::max(inputs[LEFT_INPUT].getChannels(), inputs[RIGHT_INPUT].getChannels()); + return inputs[LEFT_INPUT].getChannels(); } void Nsgt::addChannel(int c) { diff --git a/src/Offset.cpp b/src/Offset.cpp @@ -2,10 +2,7 @@ #include "Offset.hpp" int Offset::channels() { - if (inputs[IN_INPUT].isConnected()) { - return inputs[IN_INPUT].getChannels(); - } - return 1; + return std::max(1, inputs[IN_INPUT].getChannels()); } void Offset::processChannel(const ProcessArgs& args, int c) { diff --git a/src/OneEight.cpp b/src/OneEight.cpp @@ -1,10 +1,6 @@ #include "OneEight.hpp" -int OneEight::channels() { - return std::max(1, std::max(inputs[CLOCK_INPUT].getChannels(), inputs[SELECT_INPUT].getChannels())); -} - void OneEight::processChannel(const ProcessArgs& args, int c) { int step = nextStep( c, diff --git a/src/OneEight.hpp b/src/OneEight.hpp @@ -50,14 +50,13 @@ struct OneEight : AddressableSequenceModule { NUM_LIGHTS }; - OneEight() { + OneEight() : AddressableSequenceModule(CLOCK_INPUT, SELECT_INPUT) { config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); 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"); } - int channels() override; void processChannel(const ProcessArgs& args, int c) override; }; diff --git a/src/Pan.cpp b/src/Pan.cpp @@ -14,7 +14,7 @@ bool Pan::active() { } int Pan::channels() { - return std::max(inputs[IN1_INPUT].getChannels(), inputs[IN2_INPUT].getChannels()); + return inputs[IN1_INPUT].getChannels(); } void Pan::processChannel(const ProcessArgs& args, int c) { diff --git a/src/Pressor.cpp b/src/Pressor.cpp @@ -23,7 +23,7 @@ bool Pressor::active() { } int Pressor::channels() { - return std::max(inputs[LEFT_INPUT].getChannels(), inputs[RIGHT_INPUT].getChannels()); + return inputs[LEFT_INPUT].getChannels(); } void Pressor::addChannel(int c) { diff --git a/src/SampleHold.cpp b/src/SampleHold.cpp @@ -1,6 +1,7 @@ #include "SampleHold.hpp" +#define POLY_INPUT "poly_input" #define NOISE_TYPE "noise_type" #define RANGE_OFFSET "range_offset" #define RANGE_SCALE "range_scale" @@ -16,6 +17,7 @@ void SampleHold::reset() { json_t* SampleHold::dataToJson() { json_t* root = json_object(); + json_object_set_new(root, POLY_INPUT, json_integer(_polyInputID)); json_object_set_new(root, NOISE_TYPE, json_integer((int)_noiseType)); json_object_set_new(root, RANGE_OFFSET, json_real(_rangeOffset)); json_object_set_new(root, RANGE_SCALE, json_real(_rangeScale)); @@ -23,6 +25,11 @@ json_t* SampleHold::dataToJson() { } void SampleHold::dataFromJson(json_t* root) { + json_t* p = json_object_get(root, POLY_INPUT); + if (p) { + _polyInputID = json_integer_value(p); + } + json_t* nt = json_object_get(root, NOISE_TYPE); if (nt) { _noiseType = (NoiseType)json_integer_value(nt); @@ -77,7 +84,7 @@ void SampleHold::processChannel( float* value, Output& out ) { - int n = std::max(1, std::max(triggerInput.getChannels(), in.getChannels())); + int n = std::max(1, _polyInputID == IN1_INPUT ? in.getChannels() : triggerInput.getChannels()); out.setChannels(n); for (int i = 0; i < n; ++i) { float triggerIn = 0.0f; @@ -190,6 +197,12 @@ struct SampleHoldWidget : ModuleWidget { assert(m); menu->addChild(new MenuLabel()); { + OptionsMenuItem* p = new OptionsMenuItem("Polyphony channels from"); + p->addItem(OptionMenuItem("GATE input", [m]() { return m->_polyInputID == SampleHold::TRIGGER1_INPUT; }, [m]() { m->_polyInputID = SampleHold::TRIGGER1_INPUT; })); + p->addItem(OptionMenuItem("IN input", [m]() { return m->_polyInputID == SampleHold::IN1_INPUT; }, [m]() { m->_polyInputID = SampleHold::IN1_INPUT; })); + OptionsMenuItem::addToMenu(p, menu); + } + { OptionsMenuItem* mi = new OptionsMenuItem("Normal noise"); mi->addItem(OptionMenuItem("Blue", [m]() { return m->_noiseType == SampleHold::BLUE_NOISE_TYPE; }, [m]() { m->_noiseType = SampleHold::BLUE_NOISE_TYPE; })); mi->addItem(OptionMenuItem("White", [m]() { return m->_noiseType == SampleHold::WHITE_NOISE_TYPE; }, [m]() { m->_noiseType = SampleHold::WHITE_NOISE_TYPE; })); diff --git a/src/SampleHold.hpp b/src/SampleHold.hpp @@ -52,6 +52,7 @@ struct SampleHold : BGModule { NoiseType _noiseType = WHITE_NOISE_TYPE; float _rangeOffset = 1.0f; float _rangeScale = 5.0f; + int _polyInputID = TRIGGER1_INPUT; SampleHold() { config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS); diff --git a/src/Shaper.cpp b/src/Shaper.cpp @@ -8,7 +8,7 @@ void Shaper::reset() { } int Shaper::channels() { - return std::max(1, std::max(inputs[SIGNAL_INPUT].getChannels(), inputs[TRIGGER_INPUT].getChannels())); + return std::max(1, inputs[TRIGGER_INPUT].getChannels()); } void Shaper::addChannel(int c) { diff --git a/src/ShaperPlus.cpp b/src/ShaperPlus.cpp @@ -8,7 +8,7 @@ void ShaperPlus::reset() { } int ShaperPlus::channels() { - return std::max(1, std::max(inputs[SIGNAL_INPUT].getChannels(), inputs[TRIGGER_INPUT].getChannels())); + return std::max(1, inputs[SIGNAL_INPUT].getChannels()); } void ShaperPlus::addChannel(int c) { diff --git a/src/Sums.cpp b/src/Sums.cpp @@ -4,7 +4,7 @@ void Sums::processChannel(const ProcessArgs& args, int c) { assert(c == 0); - for (int i = 0, cn = std::max(inputs[A_INPUT].getChannels(), inputs[B_INPUT].getChannels()); i < cn; ++i) { + for (int i = 0, cn = inputs[A_INPUT].getChannels(); i < cn; ++i) { float a = inputs[A_INPUT].getPolyVoltage(i); float b = inputs[B_INPUT].getPolyVoltage(i); outputs[SUM_OUTPUT].setChannels(cn); diff --git a/src/Switch.cpp b/src/Switch.cpp @@ -12,10 +12,7 @@ bool bogaudio::Switch::active() { } int bogaudio::Switch::channels() { - if (inputs[GATE_INPUT].isConnected()) { - return inputs[GATE_INPUT].getChannels(); - } - return 1; + return std::max(1, inputs[GATE_INPUT].getChannels()); } void bogaudio::Switch::channelsChanged(int before, int after) { @@ -49,19 +46,19 @@ void bogaudio::Switch::processChannel(const ProcessArgs& args, int c) { outputs[OUT2_OUTPUT].writeVoltages(inputs[HIGH2_INPUT].getVoltages()); } else { - outputs[OUT1_OUTPUT].setChannels(std::max(inputs[LOW1_INPUT].getChannels(), inputs[HIGH1_INPUT].getChannels())); + outputs[OUT1_OUTPUT].setChannels(_channels); outputs[OUT1_OUTPUT].setVoltage(inputs[HIGH1_INPUT].getVoltage(c), c); - outputs[OUT2_OUTPUT].setChannels(std::max(inputs[LOW2_INPUT].getChannels(), inputs[HIGH2_INPUT].getChannels())); + outputs[OUT2_OUTPUT].setChannels(_channels); outputs[OUT2_OUTPUT].setVoltage(inputs[HIGH2_INPUT].getVoltage(c), c); } } else { if (_channels == 1) { - outputs[OUT1_OUTPUT].setChannels(std::max(inputs[LOW1_INPUT].getChannels(), inputs[HIGH1_INPUT].getChannels())); + outputs[OUT1_OUTPUT].setChannels(inputs[LOW1_INPUT].getChannels()); outputs[OUT1_OUTPUT].writeVoltages(inputs[LOW1_INPUT].getVoltages()); - outputs[OUT2_OUTPUT].setChannels(std::max(inputs[LOW2_INPUT].getChannels(), inputs[HIGH2_INPUT].getChannels())); + outputs[OUT2_OUTPUT].setChannels(inputs[LOW2_INPUT].getChannels()); outputs[OUT2_OUTPUT].writeVoltages(inputs[LOW2_INPUT].getVoltages()); } else { diff --git a/src/UMix.cpp b/src/UMix.cpp @@ -28,11 +28,7 @@ bool UMix::active() { } int UMix::channels() { - int max = 0; - for (int i = 0; i < 8; ++i) { - max = std::max(max, inputs[IN1_INPUT + i].getChannels()); - } - return max; + return inputs[IN1_INPUT].getChannels(); } void UMix::processChannel(const ProcessArgs& args, int c) { diff --git a/src/VCM.cpp b/src/VCM.cpp @@ -10,10 +10,7 @@ bool VCM::active() { } int VCM::channels() { - return std::max( - std::max(inputs[IN1_INPUT].getChannels(), inputs[IN2_INPUT].getChannels()), - std::max(inputs[IN3_INPUT].getChannels(), inputs[IN4_INPUT].getChannels()) - ); + return inputs[IN1_INPUT].getChannels(); } void VCM::processChannel(const ProcessArgs& args, int c) { diff --git a/src/VCO.cpp b/src/VCO.cpp @@ -2,6 +2,8 @@ #include "VCO.hpp" #include "dsp/pitch.hpp" +#define POLY_INPUT "poly_input" + float VCO::VCOFrequencyParamQuantity::offset() { VCO* vco = dynamic_cast<VCO*>(module); return vco->_slowMode ? vco->slowModeOffset : 0.0f; @@ -74,6 +76,19 @@ void VCO::sampleRateChange() { } } +json_t* VCO::dataToJson() { + json_t* root = json_object(); + json_object_set_new(root, POLY_INPUT, json_integer(_polyInputID)); + return root; +} + +void VCO::dataFromJson(json_t* root) { + json_t* p = json_object_get(root, POLY_INPUT); + if (p) { + _polyInputID = json_integer_value(p); + } +} + bool VCO::active() { return ( outputs[SQUARE_OUTPUT].isConnected() || @@ -84,7 +99,7 @@ bool VCO::active() { } int VCO::channels() { - return std::max(1, std::max(inputs[PITCH_INPUT].getChannels(), inputs[FM_INPUT].getChannels())); + return std::max(1, _polyInputID == FM_INPUT ? inputs[FM_INPUT].getChannels() : inputs[PITCH_INPUT].getChannels()); } void VCO::addChannel(int c) { @@ -286,6 +301,16 @@ struct VCOWidget : ModuleWidget { addOutput(createOutput<Port24>(triangleOutputPosition, module, VCO::TRIANGLE_OUTPUT)); addOutput(createOutput<Port24>(sineOutputPosition, module, VCO::SINE_OUTPUT)); } + + void appendContextMenu(Menu* menu) override { + VCO* m = dynamic_cast<VCO*>(module); + assert(m); + menu->addChild(new MenuLabel()); + OptionsMenuItem* p = new OptionsMenuItem("Polyphony channels from"); + p->addItem(OptionMenuItem("V/OCT input", [m]() { return m->_polyInputID == VCO::PITCH_INPUT; }, [m]() { m->_polyInputID = VCO::PITCH_INPUT; })); + p->addItem(OptionMenuItem("FM input", [m]() { return m->_polyInputID == VCO::FM_INPUT; }, [m]() { m->_polyInputID = VCO::FM_INPUT; })); + OptionsMenuItem::addToMenu(p, menu); + } }; Model* modelVCO = bogaudio::createModel<VCO, VCOWidget>("Bogaudio-VCO", "VCO", "Oscillator with 4 waveforms, PWM, FM, hard sync", "Oscillator", "Polyphonic"); diff --git a/src/VCO.hpp b/src/VCO.hpp @@ -77,6 +77,7 @@ struct VCO : BGModule { bool _linearMode = false; float _fmDepth = 0.0f; bool _fmLinearMode = false; + int _polyInputID = PITCH_INPUT; struct VCOFrequencyParamQuantity : FrequencyParamQuantity { float offset() override; @@ -97,6 +98,8 @@ struct VCO : BGModule { void reset() override; void sampleRateChange() override; + json_t* dataToJson() override; + void dataFromJson(json_t* root) override; bool active() override; int channels() override; void addChannel(int c) override; diff --git a/src/Walk.cpp b/src/Walk.cpp @@ -1,6 +1,8 @@ #include "Walk.hpp" +#define POLY_INPUT "poly_input" + void Walk::reset() { for (int i = 0; i < maxChannels; ++i) { _jumpTrigger[i].reset(); @@ -13,14 +15,25 @@ void Walk::sampleRateChange() { } } +json_t* Walk::dataToJson() { + json_t* root = json_object(); + json_object_set_new(root, POLY_INPUT, json_integer(_polyInputID)); + return root; +} + +void Walk::dataFromJson(json_t* root) { + json_t* p = json_object_get(root, POLY_INPUT); + if (p) { + _polyInputID = json_integer_value(p); + } +} + int Walk::channels() { - return std::max( - 1, - std::max( - std::max(inputs[RATE_INPUT].getChannels(), inputs[JUMP_INPUT].getChannels()), - std::max(inputs[OFFSET_INPUT].getChannels(), inputs[SCALE_INPUT].getChannels()) - ) - ); + int id = _polyInputID; + if (!(_polyInputID == OFFSET_INPUT || _polyInputID == SCALE_INPUT || _polyInputID == JUMP_INPUT)) { + id = RATE_INPUT; + } + return std::max(1, inputs[id].getChannels()); } void Walk::modulateChannel(int c) { @@ -96,6 +109,18 @@ struct WalkWidget : ModuleWidget { addOutput(createOutput<Port24>(outOutputPosition, module, Walk::OUT_OUTPUT)); } + + void appendContextMenu(Menu* menu) override { + Walk* m = dynamic_cast<Walk*>(module); + assert(m); + menu->addChild(new MenuLabel()); + OptionsMenuItem* p = new OptionsMenuItem("Polyphony channels from"); + p->addItem(OptionMenuItem("RATE input", [m]() { return m->_polyInputID == Walk::RATE_INPUT; }, [m]() { m->_polyInputID = Walk::RATE_INPUT; })); + p->addItem(OptionMenuItem("OFFSET input", [m]() { return m->_polyInputID == Walk::OFFSET_INPUT; }, [m]() { m->_polyInputID = Walk::OFFSET_INPUT; })); + p->addItem(OptionMenuItem("SCALE input", [m]() { return m->_polyInputID == Walk::SCALE_INPUT; }, [m]() { m->_polyInputID = Walk::SCALE_INPUT; })); + p->addItem(OptionMenuItem("JUMP input", [m]() { return m->_polyInputID == Walk::JUMP_INPUT; }, [m]() { m->_polyInputID = Walk::JUMP_INPUT; })); + OptionsMenuItem::addToMenu(p, menu); + } }; Model* modelWalk = bogaudio::createModel<Walk, WalkWidget>("Bogaudio-Walk", "WALK", "Random-walk CV source", "Random", "Polyphonic"); diff --git a/src/Walk.hpp b/src/Walk.hpp @@ -36,6 +36,7 @@ struct Walk : BGModule { Trigger _jumpTrigger[maxChannels]; RandomWalk _walk[maxChannels]; bogaudio::dsp::SlewLimiter _slew[maxChannels]; + int _polyInputID = RATE_INPUT; Walk() { config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS); @@ -48,6 +49,8 @@ struct Walk : BGModule { void reset() override; void sampleRateChange() override; + json_t* dataToJson() override; + void dataFromJson(json_t* root) override; int channels() override; void modulateChannel(int c) override; void processChannel(const ProcessArgs& args, int c) override; diff --git a/src/XCO.cpp b/src/XCO.cpp @@ -67,7 +67,7 @@ bool XCO::active() { } int XCO::channels() { - return std::max(1, std::max(inputs[PITCH_INPUT].getChannels(), inputs[FM_INPUT].getChannels())); + return std::max(1, inputs[PITCH_INPUT].getChannels()); } void XCO::addChannel(int c) { diff --git a/src/XFade.cpp b/src/XFade.cpp @@ -12,7 +12,7 @@ bool XFade::active() { } int XFade::channels() { - return std::max(inputs[A_INPUT].getChannels(), inputs[B_INPUT].getChannels()); + return inputs[A_INPUT].getChannels(); } void XFade::processChannel(const ProcessArgs& args, int c) { diff --git a/src/addressable_sequence.cpp b/src/addressable_sequence.cpp @@ -1,6 +1,7 @@ #include "addressable_sequence.hpp" +#define POLY_INPUT "poly_input" #define SELECT_ON_CLOCK "select_on_clock" #define TRIGGERED_SELECT "triggered_select" @@ -23,12 +24,18 @@ void AddressableSequenceModule::sampleRateChange() { json_t* AddressableSequenceModule::dataToJson() { json_t* root = json_object(); + 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)); return root; } void AddressableSequenceModule::dataFromJson(json_t* root) { + json_t* p = json_object_get(root, POLY_INPUT); + if (p) { + _polyInputID = json_integer_value(p); + } + json_t* s = json_object_get(root, SELECT_ON_CLOCK); if (s) { _selectOnClock = json_is_true(s); @@ -40,6 +47,10 @@ void AddressableSequenceModule::dataFromJson(json_t* root) { } } +int AddressableSequenceModule::channels() { + return std::max(1, _polyInputID == _selectInputID ? inputs[_selectInputID].getChannels() : inputs[_clockInputID].getChannels()); +} + int AddressableSequenceModule::nextStep( int c, Input& resetInput, diff --git a/src/addressable_sequence.hpp b/src/addressable_sequence.hpp @@ -7,6 +7,9 @@ using namespace rack; namespace bogaudio { struct AddressableSequenceModule : BGModule { + int _polyInputID; + int _clockInputID; + int _selectInputID; Trigger _clock[maxChannels]; Trigger _reset[maxChannels]; Trigger _selectTrigger[maxChannels]; @@ -16,7 +19,11 @@ struct AddressableSequenceModule : BGModule { bool _selectOnClock = false; bool _triggeredSelect = false; - AddressableSequenceModule() { + AddressableSequenceModule(int clockInputID, int selectInputID) + : _polyInputID(clockInputID) + , _clockInputID(clockInputID) + , _selectInputID(selectInputID) + { reset(); sampleRateChange(); } @@ -25,6 +32,7 @@ struct AddressableSequenceModule : BGModule { void sampleRateChange() override; json_t* dataToJson() override; void dataFromJson(json_t* root) override; + int channels() override; int nextStep( int c, Input& resetInput, @@ -40,7 +48,12 @@ struct AddressableSequenceModuleWidget : ModuleWidget { void appendContextMenu(Menu* menu) override { AddressableSequenceModule* m = dynamic_cast<AddressableSequenceModule*>(module); assert(m); + menu->addChild(new MenuLabel()); + OptionsMenuItem* p = new OptionsMenuItem("Polyphony channels from"); + 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("Select on clock mode", [m]() { return &m->_selectOnClock; })); menu->addChild(new BoolOptionMenuItem("Triggered select mode", [m]() { return &m->_triggeredSelect; })); }