PolyOff8.cpp (7735B)
1 2 #include "PolyOff8.hpp" 3 4 #define OFFSET_FIRST "offset_first" 5 6 json_t* PolyOff8::saveToJson(json_t* root) { 7 root = OutputRangeModule<BGModule>::saveToJson(root); 8 json_object_set_new(root, OFFSET_FIRST, json_boolean(_offsetFirst)); 9 return root; 10 } 11 12 void PolyOff8::loadFromJson(json_t* root) { 13 OutputRangeModule<BGModule>::loadFromJson(root); 14 json_t* of = json_object_get(root, OFFSET_FIRST); 15 if (of) { 16 _offsetFirst = json_boolean_value(of); 17 } 18 } 19 20 void PolyOff8::processAll(const ProcessArgs& args) { 21 int cn = 1; 22 if (inputs[IN_INPUT].isConnected()) { 23 cn = clamp(inputs[IN_INPUT].getChannels(), 1, 8); 24 outputs[OUT_OUTPUT].setChannels(cn); 25 26 for (int c = 0; c < cn; ++c) { 27 float offset = clamp(params[OFFSET1_PARAM + 2 * c].getValue(), -1.0f, 1.0f); 28 if (inputs[CV1_INPUT + c].isConnected()) { 29 offset *= clamp(inputs[CV1_INPUT + c].getVoltage() / 5.0f, -1.0f, 1.0f); 30 } 31 offset += _rangeOffset; 32 offset *= _rangeScale; 33 34 float scale = clamp(params[SCALE1_PARAM + 2 * c].getValue(), -1.0f, 1.0f); 35 36 float out = inputs[IN_INPUT].getPolyVoltage(c); 37 if (_offsetFirst) { 38 out += offset; 39 out *= scale; 40 } 41 else { 42 out *= scale; 43 out += offset; 44 } 45 outputs[OUT_OUTPUT].setVoltage(clamp(out, -12.0f, 12.0f), c); 46 } 47 } 48 else { 49 cn = clamp(params[CHANNELS_PARAM].getValue(), 1.0f, 8.0f); 50 outputs[OUT_OUTPUT].setChannels(cn); 51 52 for (int c = 0; c < cn; ++c) { 53 float offset = clamp(params[OFFSET1_PARAM + 2 * c].getValue(), -1.0f, 1.0f); 54 offset += _rangeOffset; 55 offset *= _rangeScale; 56 57 float scale = clamp(params[SCALE1_PARAM + 2 * c].getValue(), -1.0f, 1.0f); 58 59 float out = inputs[CV1_INPUT + c].getVoltage(); 60 if (_offsetFirst) { 61 out += offset; 62 out *= scale; 63 } 64 else { 65 out *= scale; 66 out += offset; 67 } 68 outputs[OUT_OUTPUT].setVoltage(clamp(out, -12.0f, 12.0f), c); 69 } 70 } 71 72 for (int c = 0; c < 8; ++c) { 73 lights[CHANNEL1_LIGHT + c].value = (c < cn) * 1.0f; 74 } 75 } 76 77 struct PolyOff8Widget : BGModuleWidget { 78 static constexpr int hp = 8; 79 80 PolyOff8Widget(PolyOff8* module) { 81 setModule(module); 82 box.size = Vec(RACK_GRID_WIDTH * hp, RACK_GRID_HEIGHT); 83 setPanel(box.size, "PolyOff8"); 84 createScrews(); 85 86 // generated by svg_widgets.rb 87 auto offset1ParamPosition = Vec(62.5, 33.0); 88 auto scale1ParamPosition = Vec(93.5, 33.0); 89 auto offset2ParamPosition = Vec(62.5, 68.0); 90 auto scale2ParamPosition = Vec(93.5, 68.0); 91 auto offset3ParamPosition = Vec(62.5, 103.0); 92 auto scale3ParamPosition = Vec(93.5, 103.0); 93 auto offset4ParamPosition = Vec(62.5, 138.0); 94 auto scale4ParamPosition = Vec(93.5, 138.0); 95 auto offset5ParamPosition = Vec(62.5, 173.0); 96 auto scale5ParamPosition = Vec(93.5, 173.0); 97 auto offset6ParamPosition = Vec(62.5, 208.0); 98 auto scale6ParamPosition = Vec(93.5, 208.0); 99 auto offset7ParamPosition = Vec(62.5, 243.0); 100 auto scale7ParamPosition = Vec(93.5, 243.0); 101 auto offset8ParamPosition = Vec(62.5, 278.0); 102 auto scale8ParamPosition = Vec(93.5, 278.0); 103 auto channelsParamPosition = Vec(23.0, 332.0); 104 105 auto cv1InputPosition = Vec(10.5, 29.0); 106 auto cv2InputPosition = Vec(10.5, 64.0); 107 auto cv3InputPosition = Vec(10.5, 99.0); 108 auto cv4InputPosition = Vec(10.5, 134.0); 109 auto cv5InputPosition = Vec(10.5, 169.0); 110 auto cv6InputPosition = Vec(10.5, 204.0); 111 auto cv7InputPosition = Vec(10.5, 239.0); 112 auto cv8InputPosition = Vec(10.5, 274.0); 113 auto inInputPosition = Vec(55.5, 322.0); 114 115 auto outOutputPosition = Vec(86.5, 322.0); 116 117 auto channel1LightPosition = Vec(46.8, 43.0); 118 auto channel2LightPosition = Vec(46.8, 78.0); 119 auto channel3LightPosition = Vec(46.8, 113.0); 120 auto channel4LightPosition = Vec(46.8, 148.0); 121 auto channel5LightPosition = Vec(46.8, 183.0); 122 auto channel6LightPosition = Vec(46.8, 218.0); 123 auto channel7LightPosition = Vec(46.8, 253.0); 124 auto channel8LightPosition = Vec(46.8, 288.0); 125 // end generated by svg_widgets.rb 126 127 addParam(createParam<Knob16>(offset1ParamPosition, module, PolyOff8::OFFSET1_PARAM)); 128 addParam(createParam<Knob16>(scale1ParamPosition, module, PolyOff8::SCALE1_PARAM)); 129 addParam(createParam<Knob16>(offset2ParamPosition, module, PolyOff8::OFFSET2_PARAM)); 130 addParam(createParam<Knob16>(scale2ParamPosition, module, PolyOff8::SCALE2_PARAM)); 131 addParam(createParam<Knob16>(offset3ParamPosition, module, PolyOff8::OFFSET3_PARAM)); 132 addParam(createParam<Knob16>(scale3ParamPosition, module, PolyOff8::SCALE3_PARAM)); 133 addParam(createParam<Knob16>(offset4ParamPosition, module, PolyOff8::OFFSET4_PARAM)); 134 addParam(createParam<Knob16>(scale4ParamPosition, module, PolyOff8::SCALE4_PARAM)); 135 addParam(createParam<Knob16>(offset5ParamPosition, module, PolyOff8::OFFSET5_PARAM)); 136 addParam(createParam<Knob16>(scale5ParamPosition, module, PolyOff8::SCALE5_PARAM)); 137 addParam(createParam<Knob16>(offset6ParamPosition, module, PolyOff8::OFFSET6_PARAM)); 138 addParam(createParam<Knob16>(scale6ParamPosition, module, PolyOff8::SCALE6_PARAM)); 139 addParam(createParam<Knob16>(offset7ParamPosition, module, PolyOff8::OFFSET7_PARAM)); 140 addParam(createParam<Knob16>(scale7ParamPosition, module, PolyOff8::SCALE7_PARAM)); 141 addParam(createParam<Knob16>(offset8ParamPosition, module, PolyOff8::OFFSET8_PARAM)); 142 addParam(createParam<Knob16>(scale8ParamPosition, module, PolyOff8::SCALE8_PARAM)); 143 addParam(createParam<Knob16>(channelsParamPosition, module, PolyOff8::CHANNELS_PARAM)); 144 145 addInput(createInput<Port24>(cv1InputPosition, module, PolyOff8::CV1_INPUT)); 146 addInput(createInput<Port24>(cv2InputPosition, module, PolyOff8::CV2_INPUT)); 147 addInput(createInput<Port24>(cv3InputPosition, module, PolyOff8::CV3_INPUT)); 148 addInput(createInput<Port24>(cv4InputPosition, module, PolyOff8::CV4_INPUT)); 149 addInput(createInput<Port24>(cv5InputPosition, module, PolyOff8::CV5_INPUT)); 150 addInput(createInput<Port24>(cv6InputPosition, module, PolyOff8::CV6_INPUT)); 151 addInput(createInput<Port24>(cv7InputPosition, module, PolyOff8::CV7_INPUT)); 152 addInput(createInput<Port24>(cv8InputPosition, module, PolyOff8::CV8_INPUT)); 153 addInput(createInput<Port24>(inInputPosition, module, PolyOff8::IN_INPUT)); 154 155 addOutput(createOutput<Port24>(outOutputPosition, module, PolyOff8::OUT_OUTPUT)); 156 157 addChild(createLight<BGTinyLight<GreenLight>>(channel1LightPosition, module, PolyOff8::CHANNEL1_LIGHT)); 158 addChild(createLight<BGTinyLight<GreenLight>>(channel2LightPosition, module, PolyOff8::CHANNEL2_LIGHT)); 159 addChild(createLight<BGTinyLight<GreenLight>>(channel3LightPosition, module, PolyOff8::CHANNEL3_LIGHT)); 160 addChild(createLight<BGTinyLight<GreenLight>>(channel4LightPosition, module, PolyOff8::CHANNEL4_LIGHT)); 161 addChild(createLight<BGTinyLight<GreenLight>>(channel5LightPosition, module, PolyOff8::CHANNEL5_LIGHT)); 162 addChild(createLight<BGTinyLight<GreenLight>>(channel6LightPosition, module, PolyOff8::CHANNEL6_LIGHT)); 163 addChild(createLight<BGTinyLight<GreenLight>>(channel7LightPosition, module, PolyOff8::CHANNEL7_LIGHT)); 164 addChild(createLight<BGTinyLight<GreenLight>>(channel8LightPosition, module, PolyOff8::CHANNEL8_LIGHT)); 165 } 166 167 void contextMenu(Menu* menu) override { 168 OutputRangeOptionMenuItem::addOutputRangeOptionsToMenu(module, menu); 169 170 auto m = dynamic_cast<PolyOff8*>(module); 171 assert(m); 172 173 OptionsMenuItem* ooo = new OptionsMenuItem("Order of operations"); 174 ooo->addItem(OptionMenuItem("Scale, then offset", [m]() { return !m->_offsetFirst; }, [m]() { m->_offsetFirst = false; })); 175 ooo->addItem(OptionMenuItem("Offset, then scale", [m]() { return m->_offsetFirst; }, [m]() { m->_offsetFirst = true; })); 176 OptionsMenuItem::addToMenu(ooo, menu); 177 } 178 }; 179 180 Model* modelPolyOff8 = createModel<PolyOff8, PolyOff8Widget>("Bogaudio-PolyOff8", "POLYOFF8", "Polyphonic per-channel offset and scale", "Polyphonic");