ComputerscareMolyPatrix.cpp (8871B)
1 #include "Computerscare.hpp" 2 3 struct ComputerscareMolyPatrix; 4 5 const int numKnobs = 256; 6 const int numRows = 16; 7 const int numColumns = 16; 8 9 const int numOutputs = 1; 10 11 struct ComputerscareMolyPatrix : ComputerscarePolyModule { 12 int counter = 0; 13 int numInputChannels = 0; 14 ComputerscareSVGPanel* panelRef; 15 enum ParamIds { 16 KNOB, 17 INPUT_ROW_TRIM = KNOB + numKnobs, 18 OUTPUT_COLUMN_TRIM = INPUT_ROW_TRIM + numRows, 19 OUTPUT_TRIM = OUTPUT_COLUMN_TRIM + numColumns, 20 POLY_CHANNELS, 21 INPUT_TRIM, 22 INPUT_OFFSET, 23 OUTPUT_OFFSET, 24 NUM_PARAMS 25 }; 26 enum InputIds { 27 POLY_INPUT, 28 ZERO_INPUT, 29 ONE_INPUT, 30 INPUT_ATTENUATION_CV, 31 INPUT_OFFSET_CV, 32 OUTPUT_ATTENUATION_CV, 33 OUTPUT_OFFSET_CV, 34 NUM_INPUTS 35 }; 36 enum OutputIds { 37 POLY_OUTPUT, 38 NUM_OUTPUTS = POLY_OUTPUT + numOutputs 39 }; 40 enum LightIds { 41 NUM_LIGHTS 42 }; 43 44 45 ComputerscareMolyPatrix() { 46 47 config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); 48 /*for(int n = 0; n < numKnobs; n++) { 49 configParam(KNOB+n,-1.f,1.f,0.f); 50 }*/ 51 for (int i = 0; i < numRows; i++) { 52 configParam(INPUT_ROW_TRIM + i, -2.f, 2.f, 1.f, "Input Channel " + std::to_string(i + 1) + " Attenuation"); 53 configParam(OUTPUT_COLUMN_TRIM + i, -2.f, 2.f, 1.f, "Output Channel " + std::to_string(i + 1) + " Attenuation"); 54 55 getParamQuantity(INPUT_ROW_TRIM + i)->randomizeEnabled = false; 56 getParamQuantity(OUTPUT_COLUMN_TRIM + i)->randomizeEnabled = false; 57 58 for (int j = 0; j < numColumns; j++) { 59 configParam(KNOB + i * 16 + j, -2.f, 2.f, i == j ? 1.f : 0.f, "Input ch." + std::to_string(i + 1) + " → Output ch." + std::to_string(j + 1)); 60 } 61 62 } 63 configParam(OUTPUT_TRIM, -2.f, 2.f, 1.f, "Output Attenuation"); 64 configParam(OUTPUT_OFFSET, -10.f, 10.f, 0.f, "Output Offset"); 65 configParam(INPUT_TRIM, -2.f, 2.f, 1.f, "Input Attenuation"); 66 configParam(INPUT_OFFSET, -10.f, 10.f, 0.f, "Input Offset"); 67 getParamQuantity(OUTPUT_TRIM)->randomizeEnabled = false; 68 getParamQuantity(OUTPUT_OFFSET)->randomizeEnabled = false; 69 getParamQuantity(INPUT_TRIM)->randomizeEnabled = false; 70 getParamQuantity(INPUT_OFFSET)->randomizeEnabled = false; 71 72 73 configParam<AutoParamQuantity>(POLY_CHANNELS, 0.f, 16.f, 0.f, "Poly Channels"); 74 getParamQuantity(POLY_CHANNELS)->randomizeEnabled = false; 75 getParamQuantity(POLY_CHANNELS)->resetEnabled = false; 76 77 configInput(POLY_INPUT, "Main"); 78 79 configInput(INPUT_ATTENUATION_CV, "Input Attenuation"); 80 configInput(OUTPUT_ATTENUATION_CV, "Output Attenuation"); 81 82 configOutput(POLY_OUTPUT, "Main"); 83 84 } 85 void checkPoly() override { 86 numInputChannels = inputs[POLY_INPUT].getChannels(); 87 int knobSetting = params[POLY_CHANNELS].getValue(); 88 if (numInputChannels > 0) { 89 if (knobSetting == 0) { 90 polyChannels = numInputChannels; 91 } 92 else { 93 polyChannels = knobSetting; 94 } 95 } else { 96 polyChannels = knobSetting == 0 ? 16 : knobSetting; 97 } 98 outputs[POLY_OUTPUT].setChannels(polyChannels); 99 } 100 void process(const ProcessArgs &args) override { 101 ComputerscarePolyModule::checkCounter(); 102 float outTrim = params[OUTPUT_TRIM].getValue(); 103 float outOffset = params[OUTPUT_OFFSET].getValue(); 104 105 float inOffset = params[INPUT_OFFSET].getValue(); 106 107 int numInputTrimChannels = inputs[INPUT_ATTENUATION_CV].getChannels(); 108 int numOutputTrimChannels = inputs[OUTPUT_ATTENUATION_CV].getChannels(); 109 110 111 112 float inputTrims[16] = {}; 113 float outputTrims[16] = {}; 114 float inputVals[16] = {}; 115 116 if (numInputChannels > 0) { 117 inputs[POLY_INPUT].readVoltages(inputVals); 118 } 119 if (numInputTrimChannels > 0) { 120 inputs[INPUT_ATTENUATION_CV].readVoltages(inputTrims); 121 } 122 if (numOutputTrimChannels > 0) { 123 inputs[OUTPUT_ATTENUATION_CV].readVoltages(outputTrims); 124 } 125 126 127 128 129 for (int outIndex = 0; outIndex < numRows; outIndex++) { 130 float outVoltage = 0.f; 131 for (int i = 0; i < numColumns; i++) { 132 outVoltage += params[KNOB + i * 16 + outIndex].getValue() * (inputVals[i] + inOffset) * params[INPUT_ROW_TRIM + i].getValue() * (params[INPUT_TRIM].getValue() * (numInputTrimChannels > 0 ? inputTrims[numInputTrimChannels == 1 ? 0 : i] / 10 : 1)); 133 } 134 outputs[POLY_OUTPUT].setVoltage(params[OUTPUT_COLUMN_TRIM + outIndex].getValue() * (outTrim * (numOutputTrimChannels > 0 ? outputTrims[numOutputTrimChannels == 1 ? 0 : outIndex] / 10 : 1)) * outVoltage + outOffset, outIndex); 135 } 136 } 137 }; 138 139 140 141 struct DisableableSmallKnob : RoundKnob { 142 143 std::vector<std::shared_ptr<Svg>> enabledThemes = {APP->window->loadSvg(asset::plugin(pluginInstance, "res/computerscare-small-knob-effed.svg")), APP->window->loadSvg(asset::plugin(pluginInstance, "res/computerscare-small-knob-effed-dark.svg"))}; 144 145 146 std::shared_ptr<Svg> enabledSvg = APP->window->loadSvg(asset::plugin(pluginInstance, "res/computerscare-small-knob-effed.svg")); 147 std::shared_ptr<Svg> disabledSvg = APP->window->loadSvg(asset::plugin(pluginInstance, "res/computerscare-small-knob-effed-disabled.svg")); 148 149 int inputChannel = 0; 150 int outputChannel = 0; 151 int themeIndex = 0; 152 bool disabled = false; 153 bool initialized = false; 154 bool randomizable = true; 155 ComputerscareMolyPatrix *module; 156 157 DisableableSmallKnob() { 158 setSvg(enabledThemes[themeIndex]); 159 shadow->box.size = math::Vec(0, 0); 160 shadow->opacity = 0.f; 161 } 162 163 void draw(const DrawArgs& args) override { 164 if (module) { 165 bool candidateDisabled = (module->numInputChannels != 0 && inputChannel > module->numInputChannels - 1 || outputChannel > module->polyChannels - 1) ; 166 if (disabled != candidateDisabled || !initialized) { 167 setSvg(candidateDisabled ? disabledSvg : enabledThemes[themeIndex]); 168 disabled = candidateDisabled; 169 onChange(*(new event::Change())); 170 fb->dirty = true; 171 initialized = true; 172 } 173 } 174 else { 175 } 176 RoundKnob::draw(args); 177 } 178 }; 179 180 struct ComputerscareMolyPatrixWidget : ModuleWidget { 181 182 ComputerscareMolyPatrixWidget(ComputerscareMolyPatrix *module) { 183 184 setModule(module); 185 186 //setPanel(APP->window->loadSvg(asset::plugin(pluginInstance, "res/ComputerscareMolyPatrixPanel.svg"))); 187 box.size = Vec(28 * 15, 380); 188 { 189 ComputerscareSVGPanel *panel = new ComputerscareSVGPanel(); 190 panel->box.size = box.size; 191 panel->setBackground(APP->window->loadSvg(asset::plugin(pluginInstance, "res/ComputerscareMolyPatrixPanel.svg"))); 192 193 //module->panelRef = panel; 194 195 addChild(panel); 196 197 } 198 float xx; 199 float yy; 200 float x0 = 30; 201 float dx = 21.4; 202 float y0 = 43; 203 float dy = 21; 204 205 float inX = 28; 206 207 addInput(createInput<PointingUpPentagonPort>(Vec(inX + 0, 12), module, ComputerscareMolyPatrix::POLY_INPUT)); 208 addKnob(inX + 28, 12, module, ComputerscareMolyPatrix::INPUT_TRIM, 0, 0, 1, 0); 209 addInput(createInput<TinyJack>(Vec(inX + 41, 25), module, ComputerscareMolyPatrix::INPUT_ATTENUATION_CV)); 210 211 addParam(createParam<SmoothKnobNoRandom>(Vec(inX + 58, 14), module, ComputerscareMolyPatrix::INPUT_OFFSET)); 212 213 214 //addKnob(60, 16, module, ComputerscareMolyPatrix::INPUT_TRIM, 0, 0,1,0); 215 216 217 for (int i = 0; i < numRows; i++) { 218 for (int j = 0; j < numColumns; j++) { 219 xx = x0 + j * dx; 220 yy = y0 + i * dy; 221 addKnob( xx, yy, module, i * 16 + j, i, j); 222 } 223 addKnob( x0 - 25, y0 + i * dy, module, ComputerscareMolyPatrix::INPUT_ROW_TRIM + i, i, 0, 1, 0); 224 addKnob( 420 - 40, y0 + i * dy, module, ComputerscareMolyPatrix::OUTPUT_COLUMN_TRIM + i, 0, i, 1, 0); 225 226 } 227 228 229 float outX = 302; 230 231 232 addKnob(outX + 0, 1, module, ComputerscareMolyPatrix::OUTPUT_TRIM, 0, 0, 1, 0); 233 addInput(createInput<TinyJack>(Vec(outX + 10, 15), module, ComputerscareMolyPatrix::OUTPUT_ATTENUATION_CV)); 234 235 addParam(createParam<SmoothKnobNoRandom>(Vec(outX + 28, 4), module, ComputerscareMolyPatrix::OUTPUT_OFFSET)); 236 237 channelWidget = new PolyOutputChannelsWidget(Vec(outX + 55, 1), module, ComputerscareMolyPatrix::POLY_CHANNELS); 238 addChild(channelWidget); 239 240 addOutput(createOutput<InPort>(Vec(outX + 80, 1), module, ComputerscareMolyPatrix::POLY_OUTPUT)); 241 242 243 } 244 void addKnob(int x, int y, ComputerscareMolyPatrix *module, int index, int row, int column, int theme = 0, bool randomizable = true) { 245 246 knob = createParam<DisableableSmallKnob>(Vec(x, y), module, ComputerscareMolyPatrix::KNOB + index); 247 248 knob->module = module; 249 knob->inputChannel = row; 250 knob->outputChannel = column; 251 knob->themeIndex = theme; 252 knob->randomizable = randomizable; 253 addParam(knob); 254 255 } 256 DisableableSmallKnob* knob; 257 PolyOutputChannelsWidget* channelWidget; 258 SmallLetterDisplay* smallLetterDisplay; 259 }; 260 261 Model *modelComputerscareMolyPatrix = createModel<ComputerscareMolyPatrix, ComputerscareMolyPatrixWidget>("computerscare-moly-patrix");