computerscare-vcv-modules

ComputerScare modules for VCV Rack
Log | Files | Refs

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");