Pgmr.cpp (11332B)
1 2 #include "Pgmr.hpp" 3 4 #define SELECT_TRIGGERS "SELECT_TRIGGERS" 5 #define SAVE_LAST_TRIGGERED_TO_PATCH "save_last_triggered_to_patch" 6 #define LAST_TRIGGERED_STEP "last_triggered_step" 7 #define LAST_TRIGGERED_ELEMENTS_COUNT "last_triggered_elements_count" 8 9 void Pgmr::reset() { 10 std::lock_guard<SpinLock> lock(_elementsLock); 11 12 for (int c = 0; c < maxChannels; ++c) { 13 _lastSteps[c] = -1; 14 _allPulseGens[c].process(1000.0f); 15 } 16 for (auto* element : _elements) { 17 element->reset(); 18 } 19 } 20 21 void Pgmr::sampleRateChange() { 22 _sampleTime = APP->engine->getSampleTime(); 23 } 24 25 json_t* Pgmr::saveToJson(json_t* root) { 26 root = OutputRangeAddressableSequenceModule::saveToJson(root); 27 json_object_set_new(root, SELECT_TRIGGERS, json_boolean(_selectTriggers)); 28 json_object_set_new(root, SAVE_LAST_TRIGGERED_TO_PATCH, json_boolean(_saveLastTriggeredToPatch)); 29 if (_saveLastTriggeredToPatch) { 30 json_t* a = json_array(); 31 for (int c = 0; c < maxChannels; ++c) { 32 json_array_append_new(a, json_integer(_step[c])); 33 } 34 json_object_set_new(root, LAST_TRIGGERED_STEP, a); 35 json_object_set_new(root, LAST_TRIGGERED_ELEMENTS_COUNT, json_integer(_elements.size())); 36 } 37 return root; 38 } 39 40 void Pgmr::loadFromJson(json_t* root) { 41 OutputRangeAddressableSequenceModule::loadFromJson(root); 42 43 json_t* st = json_object_get(root, SELECT_TRIGGERS); 44 if (st) { 45 _selectTriggers = json_is_true(st); 46 } 47 48 json_t* sl = json_object_get(root, SAVE_LAST_TRIGGERED_TO_PATCH); 49 if (sl) { 50 _saveLastTriggeredToPatch = json_is_true(sl); 51 if (_saveLastTriggeredToPatch) { 52 json_t* a = json_object_get(root, LAST_TRIGGERED_STEP); 53 json_t* sz = json_object_get(root, LAST_TRIGGERED_ELEMENTS_COUNT); 54 if (a && json_array_size(a) == maxChannels && sz) { 55 _restoreLastTriggeredExpectedElementsN = json_integer_value(sz); 56 std::vector<int> restoreSteps(maxChannels); 57 for (int c = 0; c < maxChannels; ++c) { 58 json_t* s = json_array_get(a, c); 59 if (s) { 60 restoreSteps[c] = json_integer_value(s); 61 } 62 } 63 _restoreLastTriggered = new std::function<void()>([this, restoreSteps]() { 64 for (int c = 0; c < maxChannels; ++c) { 65 setStep(c, restoreSteps[c], _elements.size()); 66 } 67 }); 68 } 69 } 70 } 71 } 72 73 void Pgmr::modulate() { 74 _selectOnClock = params[SELECT_ON_CLOCK_PARAM].getValue() > 0.5f; 75 } 76 77 void Pgmr::processAlways(const ProcessArgs& args) { 78 if (expanderConnected()) { 79 PgmrExpanderMessage* te = toExpander(); 80 te->baseID = _id; 81 te->position = 1; 82 te->rangeOffset = _rangeOffset; 83 te->rangeScale = _rangeScale; 84 } 85 } 86 87 void Pgmr::processChannel(const ProcessArgs& args, int c) { 88 std::lock_guard<SpinLock> lock(_elementsLock); 89 std::vector<PgmrStep*>& steps = _elements; 90 int stepsN = steps.size(); 91 92 if (c == 0) { 93 for (int i = 0; i < stepsN; ++i) { 94 steps[i]->lightSum = 0.0f; 95 } 96 } 97 98 int step = nextStep( 99 c, 100 NULL, 101 inputs[CLOCK_INPUT], 102 NULL, 103 params[DIRECTION_PARAM], 104 NULL, 105 inputs[SELECT_INPUT], 106 stepsN 107 ); 108 for (int i = 0; i < stepsN; ++i) { 109 if (steps[i]->triggers[c].process(steps[i]->selectParam.getValue() + steps[i]->selectInput.getPolyVoltage(c))) { 110 step = setStep(c, i, stepsN); 111 } 112 } 113 114 { 115 float out = steps[step]->aParam.getValue(); 116 out += _rangeOffset; 117 out *= _rangeScale; 118 outputs[A_OUTPUT].setChannels(_channels); 119 outputs[A_OUTPUT].setVoltage(out, c); 120 } 121 { 122 float out = steps[step]->bParam.getValue(); 123 out += _rangeOffset; 124 out *= _rangeScale; 125 outputs[B_OUTPUT].setChannels(_channels); 126 outputs[B_OUTPUT].setVoltage(out, c); 127 } 128 { 129 float out = steps[step]->cParam.getValue(); 130 out += _rangeOffset; 131 out *= _rangeScale; 132 outputs[C_OUTPUT].setChannels(_channels); 133 outputs[C_OUTPUT].setVoltage(out, c); 134 } 135 { 136 float out = steps[step]->dParam.getValue(); 137 out += _rangeOffset; 138 out *= _rangeScale; 139 outputs[D_OUTPUT].setChannels(_channels); 140 outputs[D_OUTPUT].setVoltage(out, c); 141 } 142 143 if (step != _lastSteps[c]) { 144 _lastSteps[c] = step; 145 _allPulseGens[c].trigger(0.001f); 146 steps[step]->pulseGens[c].trigger(0.001f); 147 } 148 outputs[SELECT_ALL_OUTPUT].setChannels(_channels); 149 outputs[SELECT_ALL_OUTPUT].setVoltage(_allPulseGens[c].process(_sampleTime) * 5.0f, c); 150 151 for (int i = 0; i < stepsN; ++i) { 152 steps[i]->selectedOutput.setChannels(_channels); 153 steps[i]->selectedOutput.setVoltage((steps[i]->pulseGens[c].process(_sampleTime) || (!_selectTriggers && step == i)) * 5.0f, c); 154 155 steps[i]->lightSum += step == i; 156 } 157 158 if (c == _channels - 1) { 159 for (int i = 0; i < stepsN; ++i) { 160 steps[i]->selectedLight.value = steps[i]->lightSum * _inverseChannels; 161 } 162 } 163 } 164 165 void Pgmr::elementsChanged() { 166 if (_restoreLastTriggered && (int)_elements.size() == _restoreLastTriggeredExpectedElementsN) { 167 (*_restoreLastTriggered)(); 168 delete _restoreLastTriggered; 169 _restoreLastTriggered = NULL; 170 } 171 } 172 173 174 struct PgmrWidget : AddressableSequenceBaseModuleWidget { 175 static constexpr int hp = 15; 176 177 PgmrWidget(Pgmr* module) { 178 setModule(module); 179 box.size = Vec(RACK_GRID_WIDTH * hp, RACK_GRID_HEIGHT); 180 setPanel(box.size, "Pgmr"); 181 createScrews(); 182 183 // generated by svg_widgets.rb 184 auto directionParamPosition = Vec(28.0, 263.7); 185 auto selectOnClockParamPosition = Vec(28.0, 277.2); 186 auto cva1ParamPosition = Vec(54.5, 40.5); 187 auto cvb1ParamPosition = Vec(54.5, 94.5); 188 auto cvc1ParamPosition = Vec(54.5, 148.5); 189 auto cvd1ParamPosition = Vec(54.5, 202.5); 190 auto select1ParamPosition = Vec(58.5, 267.0); 191 auto cva2ParamPosition = Vec(99.5, 40.5); 192 auto cvb2ParamPosition = Vec(99.5, 94.5); 193 auto cvc2ParamPosition = Vec(99.5, 148.5); 194 auto cvd2ParamPosition = Vec(99.5, 202.5); 195 auto select2ParamPosition = Vec(103.5, 267.0); 196 auto cva3ParamPosition = Vec(144.5, 40.5); 197 auto cvb3ParamPosition = Vec(144.5, 94.5); 198 auto cvc3ParamPosition = Vec(144.5, 148.5); 199 auto cvd3ParamPosition = Vec(144.5, 202.5); 200 auto select3ParamPosition = Vec(148.5, 267.0); 201 auto cva4ParamPosition = Vec(189.5, 40.5); 202 auto cvb4ParamPosition = Vec(189.5, 94.5); 203 auto cvc4ParamPosition = Vec(189.5, 148.5); 204 auto cvd4ParamPosition = Vec(189.5, 202.5); 205 auto select4ParamPosition = Vec(193.5, 267.0); 206 207 auto clockInputPosition = Vec(10.5, 226.0); 208 auto selectInputPosition = Vec(10.5, 290.0); 209 auto select1InputPosition = Vec(55.5, 290.0); 210 auto select2InputPosition = Vec(100.5, 290.0); 211 auto select3InputPosition = Vec(145.5, 290.0); 212 auto select4InputPosition = Vec(190.5, 290.0); 213 214 auto aOutputPosition = Vec(10.5, 59.0); 215 auto bOutputPosition = Vec(10.5, 94.0); 216 auto cOutputPosition = Vec(10.5, 129.0); 217 auto dOutputPosition = Vec(10.5, 164.0); 218 auto selectAllOutputPosition = Vec(10.5, 330.0); 219 auto select1OutputPosition = Vec(55.5, 330.0); 220 auto select2OutputPosition = Vec(100.5, 330.0); 221 auto select3OutputPosition = Vec(145.5, 330.0); 222 auto select4OutputPosition = Vec(190.5, 330.0); 223 224 auto select1LightPosition = Vec(64.3, 255.0); 225 auto select2LightPosition = Vec(109.3, 255.0); 226 auto select3LightPosition = Vec(154.3, 255.0); 227 auto select4LightPosition = Vec(199.3, 255.0); 228 // end generated by svg_widgets.rb 229 230 addParam(createParam<IndicatorButtonGreen9>(directionParamPosition, module, Pgmr::DIRECTION_PARAM)); 231 addParam(createParam<IndicatorButtonGreen9>(selectOnClockParamPosition, module, Pgmr::SELECT_ON_CLOCK_PARAM)); 232 addParam(createParam<Knob26>(cva1ParamPosition, module, Pgmr::CVA1_PARAM)); 233 addParam(createParam<Knob26>(cvb1ParamPosition, module, Pgmr::CVB1_PARAM)); 234 addParam(createParam<Knob26>(cvc1ParamPosition, module, Pgmr::CVC1_PARAM)); 235 addParam(createParam<Knob26>(cvd1ParamPosition, module, Pgmr::CVD1_PARAM)); 236 addParam(createParam<Button18>(select1ParamPosition, module, Pgmr::SELECT1_PARAM)); 237 addParam(createParam<Knob26>(cva2ParamPosition, module, Pgmr::CVA2_PARAM)); 238 addParam(createParam<Knob26>(cvb2ParamPosition, module, Pgmr::CVB2_PARAM)); 239 addParam(createParam<Knob26>(cvc2ParamPosition, module, Pgmr::CVC2_PARAM)); 240 addParam(createParam<Knob26>(cvd2ParamPosition, module, Pgmr::CVD2_PARAM)); 241 addParam(createParam<Button18>(select2ParamPosition, module, Pgmr::SELECT2_PARAM)); 242 addParam(createParam<Knob26>(cva3ParamPosition, module, Pgmr::CVA3_PARAM)); 243 addParam(createParam<Knob26>(cvb3ParamPosition, module, Pgmr::CVB3_PARAM)); 244 addParam(createParam<Knob26>(cvc3ParamPosition, module, Pgmr::CVC3_PARAM)); 245 addParam(createParam<Knob26>(cvd3ParamPosition, module, Pgmr::CVD3_PARAM)); 246 addParam(createParam<Button18>(select3ParamPosition, module, Pgmr::SELECT3_PARAM)); 247 addParam(createParam<Knob26>(cva4ParamPosition, module, Pgmr::CVA4_PARAM)); 248 addParam(createParam<Knob26>(cvb4ParamPosition, module, Pgmr::CVB4_PARAM)); 249 addParam(createParam<Knob26>(cvc4ParamPosition, module, Pgmr::CVC4_PARAM)); 250 addParam(createParam<Knob26>(cvd4ParamPosition, module, Pgmr::CVD4_PARAM)); 251 addParam(createParam<Button18>(select4ParamPosition, module, Pgmr::SELECT4_PARAM)); 252 253 addInput(createInput<Port24>(clockInputPosition, module, Pgmr::CLOCK_INPUT)); 254 addInput(createInput<Port24>(selectInputPosition, module, Pgmr::SELECT_INPUT)); 255 addInput(createInput<Port24>(select1InputPosition, module, Pgmr::SELECT1_INPUT)); 256 addInput(createInput<Port24>(select2InputPosition, module, Pgmr::SELECT2_INPUT)); 257 addInput(createInput<Port24>(select3InputPosition, module, Pgmr::SELECT3_INPUT)); 258 addInput(createInput<Port24>(select4InputPosition, module, Pgmr::SELECT4_INPUT)); 259 260 addOutput(createOutput<Port24>(aOutputPosition, module, Pgmr::A_OUTPUT)); 261 addOutput(createOutput<Port24>(bOutputPosition, module, Pgmr::B_OUTPUT)); 262 addOutput(createOutput<Port24>(cOutputPosition, module, Pgmr::C_OUTPUT)); 263 addOutput(createOutput<Port24>(dOutputPosition, module, Pgmr::D_OUTPUT)); 264 addOutput(createOutput<Port24>(selectAllOutputPosition, module, Pgmr::SELECT_ALL_OUTPUT)); 265 addOutput(createOutput<Port24>(select1OutputPosition, module, Pgmr::SELECT1_OUTPUT)); 266 addOutput(createOutput<Port24>(select2OutputPosition, module, Pgmr::SELECT2_OUTPUT)); 267 addOutput(createOutput<Port24>(select3OutputPosition, module, Pgmr::SELECT3_OUTPUT)); 268 addOutput(createOutput<Port24>(select4OutputPosition, module, Pgmr::SELECT4_OUTPUT)); 269 270 addChild(createLight<BGSmallLight<GreenLight>>(select1LightPosition, module, Pgmr::SELECT1_LIGHT)); 271 addChild(createLight<BGSmallLight<GreenLight>>(select2LightPosition, module, Pgmr::SELECT2_LIGHT)); 272 addChild(createLight<BGSmallLight<GreenLight>>(select3LightPosition, module, Pgmr::SELECT3_LIGHT)); 273 addChild(createLight<BGSmallLight<GreenLight>>(select4LightPosition, module, Pgmr::SELECT4_LIGHT)); 274 } 275 276 void contextMenu(Menu* menu) override { 277 AddressableSequenceBaseModuleWidget::contextMenu(menu); 278 279 auto m = dynamic_cast<Pgmr*>(module); 280 assert(m); 281 OptionsMenuItem* so = new OptionsMenuItem("Output on selected step"); 282 so->addItem(OptionMenuItem("Gate", [m]() { return !m->_selectTriggers; }, [m]() { m->_selectTriggers = false; })); 283 so->addItem(OptionMenuItem("Trigger", [m]() { return m->_selectTriggers; }, [m]() { m->_selectTriggers = true; })); 284 OptionsMenuItem::addToMenu(so, menu); 285 286 menu->addChild(new BoolOptionMenuItem("Save last selected step to patch", [m]() { return &m->_saveLastTriggeredToPatch; })); 287 288 OutputRangeOptionMenuItem::addOutputRangeOptionsToMenu(module, menu); 289 } 290 }; 291 292 Model* modelPgmr = createModel<Pgmr, PgmrWidget>("Bogaudio-Pgmr", "PGMR", "4-step programmer and sequencer", "Sequencer", "Polyphonic");