Inv.cpp (4849B)
1 2 #include "Inv.hpp" 3 4 #define SAVE_LATCHED_TO_PATCH "save_latched_to_patch" 5 #define LATCHED_STATE1 "latched_state1" 6 #define LATCHED_STATE2 "latched_state2" 7 8 void Inv::reset() { 9 for (int c = 0; c < maxChannels; ++c) { 10 _trigger[0][c].reset(); 11 _trigger[1][c].reset(); 12 } 13 } 14 15 json_t* Inv::saveToJson(json_t* root) { 16 json_object_set_new(root, SAVE_LATCHED_TO_PATCH, json_boolean(_saveLatchedToPatch)); 17 if (_saveLatchedToPatch) { 18 if (_latch[0]) { 19 json_t* a = json_array(); 20 for (int c = 0; c < maxChannels; ++c) { 21 json_array_append_new(a, json_boolean(_latchedHigh[0][c])); 22 } 23 json_object_set_new(root, LATCHED_STATE1, a); 24 } 25 26 if (_latch[1]) { 27 json_t* a = json_array(); 28 for (int c = 0; c < maxChannels; ++c) { 29 json_array_append_new(a, json_boolean(_latchedHigh[1][c])); 30 } 31 json_object_set_new(root, LATCHED_STATE2, a); 32 } 33 } 34 return root; 35 } 36 37 void Inv::loadFromJson(json_t* root) { 38 json_t* sl = json_object_get(root, SAVE_LATCHED_TO_PATCH); 39 if (sl) { 40 _saveLatchedToPatch = json_is_true(sl); 41 if (_saveLatchedToPatch) { 42 json_t* a1 = json_object_get(root, LATCHED_STATE1); 43 if (a1 && json_array_size(a1) == maxChannels) { 44 for (int c = 0; c < maxChannels; ++c) { 45 json_t* ls = json_array_get(a1, c); 46 if (ls && json_is_true(ls)) { 47 _latchedHigh[0][c] = true; 48 } 49 } 50 } 51 52 json_t* a2 = json_object_get(root, LATCHED_STATE2); 53 if (a2 && json_array_size(a2) == maxChannels) { 54 for (int c = 0; c < maxChannels; ++c) { 55 json_t* ls = json_array_get(a2, c); 56 if (ls && json_is_true(ls)) { 57 _latchedHigh[1][c] = true; 58 } 59 } 60 } 61 } 62 } 63 } 64 65 void Inv::modulate() { 66 _latch[0] = params[LATCH1_PARAM].getValue() > 0.5f; 67 _latch[1] = params[LATCH2_PARAM].getValue() > 0.5f; 68 } 69 70 void Inv::processAll(const ProcessArgs& args) { 71 processDual(0); 72 processDual(1); 73 } 74 75 void Inv::processDual(int i) { 76 int channels = inputs[IN1_INPUT + 2 * i].getChannels(); 77 outputs[OUT1_OUTPUT + i].setChannels(channels); 78 int lightsOn = 0; 79 80 for (int c = 0; c < channels; ++c) { 81 bool triggered = _trigger[i][c].process(params[GATE1_PARAM + 2 * i].getValue() + inputs[GATE1_INPUT + 2 * i].getPolyVoltage(c)); 82 if (_latch[i]) { 83 if (triggered) { 84 _latchedHigh[i][c] = !_latchedHigh[i][c]; 85 } 86 } 87 else { 88 _latchedHigh[i][c] = false; 89 } 90 91 float in = inputs[IN1_INPUT + 2 * i].getPolyVoltage(c); 92 if (_latchedHigh[i][c] || (!_latch[i] && _trigger[i][c].isHigh())) { 93 in = -in; 94 ++lightsOn; 95 } 96 outputs[OUT1_OUTPUT + i].setVoltage(in, c); 97 } 98 99 float red = lights[HIGH1_LIGHT + 2 * i].value = lightsOn / (float)channels; 100 lights[LOW1_LIGHT + 2 * i].value = 1.0f - red; 101 } 102 103 struct InvWidget : BGModuleWidget { 104 static constexpr int hp = 3; 105 106 InvWidget(Inv* module) { 107 setModule(module); 108 box.size = Vec(RACK_GRID_WIDTH * hp, RACK_GRID_HEIGHT); 109 setPanel(box.size, "Inv"); 110 createScrews(); 111 112 // generated by svg_widgets.rb 113 auto gate1ParamPosition = Vec(13.5, 22.0); 114 auto latch1ParamPosition = Vec(29.5, 82.0); 115 auto gate2ParamPosition = Vec(13.5, 187.0); 116 auto latch2ParamPosition = Vec(29.5, 247.0); 117 118 auto gate1InputPosition = Vec(10.5, 44.0); 119 auto in1InputPosition = Vec(10.5, 96.0); 120 auto gate2InputPosition = Vec(10.5, 209.0); 121 auto in2InputPosition = Vec(10.5, 261.0); 122 123 auto out1OutputPosition = Vec(10.5, 134.0); 124 auto out2OutputPosition = Vec(10.5, 299.0); 125 126 auto low1LightPosition = Vec(10.5, 160.3); 127 auto low2LightPosition = Vec(10.5, 325.3); 128 // end generated by svg_widgets.rb 129 130 addParam(createParam<Button18>(gate1ParamPosition, module, Inv::GATE1_PARAM)); 131 addParam(createParam<IndicatorButtonGreen9>(latch1ParamPosition, module, Inv::LATCH1_PARAM)); 132 addParam(createParam<Button18>(gate2ParamPosition, module, Inv::GATE2_PARAM)); 133 addParam(createParam<IndicatorButtonGreen9>(latch2ParamPosition, module, Inv::LATCH2_PARAM)); 134 135 addInput(createInput<Port24>(gate1InputPosition, module, Inv::GATE1_INPUT)); 136 addInput(createInput<Port24>(in1InputPosition, module, Inv::IN1_INPUT)); 137 addInput(createInput<Port24>(gate2InputPosition, module, Inv::GATE2_INPUT)); 138 addInput(createInput<Port24>(in2InputPosition, module, Inv::IN2_INPUT)); 139 140 addOutput(createOutput<Port24>(out1OutputPosition, module, Inv::OUT1_OUTPUT)); 141 addOutput(createOutput<Port24>(out2OutputPosition, module, Inv::OUT2_OUTPUT)); 142 143 addChild(createLight<BGSmallLight<GreenRedLight>>(low1LightPosition, module, Inv::LOW1_LIGHT)); 144 addChild(createLight<BGSmallLight<GreenRedLight>>(low2LightPosition, module, Inv::LOW2_LIGHT)); 145 } 146 147 void contextMenu(Menu* menu) override { 148 auto m = dynamic_cast<Inv*>(module); 149 assert(m); 150 menu->addChild(new BoolOptionMenuItem("Save latched state to patch", [m]() { return &m->_saveLatchedToPatch; })); 151 } 152 }; 153 154 Model* modelInv = createModel<Inv, InvWidget>("Bogaudio-Inv", "INV", "Dual signal inverter", "Logic", "Dual", "Polyphonic");