Guest User

Untitled

a guest
May 28th, 2019
171
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 10.97 KB | None | 0 0
  1. //**************************************************************************************
  2. //16-Steps Sequencer Module for VCV Rack by Autodafe http://www.autodafe.net
  3. //
  4. //Based on code taken from the Fundamentals plugins by Andrew Belt http://www.vcvrack.com
  5. //**************************************************************************************
  6.  
  7.  
  8. #include "plugin.hpp"
  9.  
  10.  
  11. struct SEQ16 : Module {
  12.     enum ParamIds {
  13.         CLOCK_PARAM,
  14.         RUN_PARAM,
  15.         RESET_PARAM,
  16.         STEPS_PARAM,
  17.         ROW1_PARAM,
  18.         ROW2_PARAM = ROW1_PARAM + 16,
  19.         ROW3_PARAM = ROW2_PARAM + 16,
  20.         GATE_PARAM = ROW3_PARAM + 16,
  21.         NUM_PARAMS = GATE_PARAM + 16
  22.     };
  23.     enum InputIds {
  24.         CLOCK_INPUT,
  25.         EXT_CLOCK_INPUT,
  26.         START_INPUT,
  27.         STOP_INPUT,
  28.         RESET_INPUT,
  29.         STEPS_INPUT,
  30.         NUM_INPUTS
  31.     };
  32.     enum OutputIds {
  33.         CLOCK_OUT,
  34.         CLOCK_GATE_OUT,
  35.         GATES_OUTPUT,
  36.         ROW1_OUTPUT,
  37.         ROW2_OUTPUT,
  38.         ROW3_OUTPUT,
  39.         GATE_OUTPUT,
  40.         NUM_OUTPUTS = GATE_OUTPUT + 16
  41.     };
  42.  
  43. enum LightIds {
  44.         RUNNING_LIGHT,
  45.         RESET_LIGHT,
  46.         GATES_LIGHT,
  47.         ROW_LIGHTS,
  48.         GATE_LIGHTS = ROW_LIGHTS + 3,
  49.         NUM_LIGHTS = GATE_LIGHTS + 16
  50.     };
  51.  
  52.  
  53. bool running = true;
  54.     SchmittTrigger clockTrigger; // for external clock
  55.     // For buttons
  56.     SchmittTrigger runningTrigger;
  57.     SchmittTrigger resetTrigger;
  58.     SchmittTrigger gateTriggers[16];
  59.     float phase = 0.0;
  60.     int index = 0;
  61.     bool gateState[16] = {};
  62.     float resetLight = 0.0;
  63.     float stepLights[16] = {};
  64.  
  65.  
  66.  
  67.     enum GateMode {
  68.         TRIGGER,
  69.         RETRIGGER,
  70.         CONTINUOUS,
  71.     };
  72.     GateMode gateMode = TRIGGER;
  73.     PulseGenerator gatePulse;
  74.  
  75.  
  76.     SEQ16() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) {}
  77.     void step() override;
  78.  
  79.     json_t *dataToJson() override {
  80.         json_t *rootJ = json_object();
  81.  
  82.         // running
  83.         json_object_set_new(rootJ, "running", json_boolean(running));
  84.  
  85.         // gates
  86.         json_t *gatesJ = json_array();
  87.         for (int i = 0; i < 16; i++) {
  88.             json_t *gateJ = json_integer((int) gateState[i]);
  89.             json_array_append_new(gatesJ, gateJ);
  90.         }
  91.         json_object_set_new(rootJ, "gates", gatesJ);
  92.  
  93.         // gateMode
  94.         json_t *gateModeJ = json_integer((int) gateMode);
  95.         json_object_set_new(rootJ, "gateMode", gateModeJ);
  96.  
  97.         return rootJ;
  98.     }
  99.  
  100.     void dataFromJson(json_t *rootJ) override {
  101.         // running
  102.         json_t *runningJ = json_object_get(rootJ, "running");
  103.         if (runningJ)
  104.             running = json_is_true(runningJ);
  105.  
  106.         // gates
  107.         json_t *gatesJ = json_object_get(rootJ, "gates");
  108.         if (gatesJ) {
  109.             for (int i = 0; i < 16; i++) {
  110.                 json_t *gateJ = json_array_get(gatesJ, i);
  111.                 if (gateJ)
  112.                     gateState[i] = !!json_integer_value(gateJ);
  113.             }
  114.         }
  115.  
  116.         // gateMode
  117.         json_t *gateModeJ = json_object_get(rootJ, "gateMode");
  118.         if (gateModeJ)
  119.             gateMode = (GateMode)json_integer_value(gateModeJ);
  120.     }
  121.  
  122.     void onReset() override {
  123.         for (int i = 0; i < 16; i++) {
  124.             gateState[i] = false;
  125.         }
  126.     }
  127.  
  128.     void onRandomize() override {
  129.         for (int i = 0; i < 16; i++) {
  130.             gateState[i] = (random() > 0.5f);
  131.         }
  132.     }
  133. };
  134.  
  135.  
  136.  
  137.  
  138. void SEQ16::step()  {
  139.     const float lightLambda = 0.075;
  140.  
  141.  
  142. outputs[CLOCK_OUT].value=0;
  143.  
  144.     outputs[CLOCK_GATE_OUT].value=0;
  145.  
  146.  
  147.  
  148.     // Run
  149.     if (runningTrigger.process(params[RUN_PARAM].value)) {
  150.         running = !running;
  151.     }
  152.  
  153.  
  154.  
  155. if(inputs[START_INPUT].value>0){running=true;}
  156.  
  157.     if(inputs[STOP_INPUT].value>0){running=false;}
  158.  
  159.  
  160.  
  161.     lights[RUNNING_LIGHT].value = running ? 1.0 : 0.0;
  162.  
  163.     bool nextStep = false;
  164.  
  165.     if (running) {
  166.         if (inputs[EXT_CLOCK_INPUT].active) {
  167.             // External clock
  168.             if (clockTrigger.process(inputs[EXT_CLOCK_INPUT].value)) {
  169.                 phase = 0.0;
  170.                 nextStep = true;
  171. outputs[CLOCK_OUT].value=1;
  172.             }
  173.         }
  174.         else {
  175.             // Internal clock
  176.             float clockTime = powf(2.0, params[CLOCK_PARAM].value + inputs[CLOCK_INPUT].value);
  177.             phase += clockTime / engineGetSampleRate();
  178.             if (phase >= 1.0) {
  179.                 phase -= 1.0;
  180.                 nextStep = true;
  181.                 outputs[CLOCK_OUT].value=1;
  182.             }
  183.         }
  184.     }
  185.  
  186.     // Reset
  187.     if (resetTrigger.process(params[RESET_PARAM].value + inputs[RESET_INPUT].value)) {
  188.         phase = 0.0;
  189.         index = 16;
  190.         nextStep = true;
  191.         resetLight = 1.0;
  192.     }
  193.  
  194.     if (nextStep) {
  195.         // Advance step
  196.         int numSteps = clamp(roundf(params[STEPS_PARAM].value + inputs[STEPS_INPUT].value), 1.0f, 16.0f);
  197.         index += 1;
  198.         if (index >= numSteps) {
  199.             index = 0;
  200.         }
  201.         stepLights[index] = 1.0;
  202.         gatePulse.trigger(1e-3);
  203.     }
  204.  
  205.     resetLight -= resetLight / lightLambda / engineGetSampleRate();
  206.  
  207.     bool pulse = gatePulse.process(1.0 / engineGetSampleRate());
  208.  
  209.  
  210.  
  211.     // Gate buttons
  212.     for (int i = 0; i < 16; i++) {
  213.         if (gateTriggers[i].process(params[GATE_PARAM + i].value)) {
  214.             gateState[i] = !gateState[i];
  215.         }
  216.         bool gateOn = (running && i == index && gateState[i]);
  217.         if (gateMode == TRIGGER)
  218.             gateOn = gateOn && pulse;
  219.         else if (gateMode == RETRIGGER)
  220.             gateOn = gateOn && !pulse;
  221.  
  222.         outputs[GATE_OUTPUT + i].value = gateOn ? 10.0 : 0.0;
  223.  
  224.  
  225.  
  226.  
  227.         if (outputs[GATE_OUTPUT + i].value!=0)
  228.         {
  229.             outputs[CLOCK_GATE_OUT].value=gateOn ? 1.0 : 0.0;
  230.         }
  231.  
  232.  
  233.         stepLights[i] -= stepLights[i] / lightLambda / engineGetSampleRate();
  234.         lights[GATE_LIGHTS + i].value = gateState[i] ? 1.0 - stepLights[i] : stepLights[i];
  235.     }
  236.  
  237.     // Rows
  238.     float row1 = params[ROW1_PARAM + index].value;
  239.     float row2 = params[ROW2_PARAM + index].value;
  240.     float row3 = params[ROW3_PARAM + index].value;
  241.  
  242.     bool gatesOn = (running && gateState[index]);
  243.     if (gateMode == TRIGGER)
  244.         gatesOn = gatesOn && pulse;
  245.     else if (gateMode == RETRIGGER)
  246.         gatesOn = gatesOn && !pulse;
  247.    
  248.         outputs[ROW1_OUTPUT].value = row1;
  249.     outputs[ROW2_OUTPUT].value = row2;
  250.     outputs[ROW3_OUTPUT].value = row3;
  251.     outputs[GATES_OUTPUT].value = gatesOn ? 10.0 : 0.0;
  252.     lights[RESET_LIGHT].value = resetLight;
  253.     lights[GATES_LIGHT].value = gatesOn ? 1.0 : 0.0;
  254.     lights[ROW_LIGHTS].value = row1 / 10.0;
  255.     lights[ROW_LIGHTS + 1].value = row2 / 10.0;
  256.     lights[ROW_LIGHTS + 2].value = row3 / 10.0;
  257. }
  258.  
  259. struct AutodafePurpleLight : ModuleLightWidget {
  260.     AutodafePurpleLight() {
  261.         addBaseColor(nvgRGB(0x89, 0x13, 0xC4));
  262.     }
  263. };
  264.  
  265.  
  266.  
  267.  
  268. struct SEQ16Widget : ModuleWidget {
  269.     SEQ16Widget(SEQ16 *module);
  270.  
  271.     Menu *createContextMenu() override;
  272. };
  273.  
  274.     SEQ16Widget::SEQ16Widget(SEQ16 *module) : ModuleWidget(module) {
  275.     box.size = Vec(15*42, 380);
  276.  
  277.     {
  278.         SVGPanel *panel = new SVGPanel();
  279.         panel->box.size = box.size;
  280.    
  281.  
  282.         panel->setBackground(SVG::load(assetPlugin(pluginInstance, "res/SEQ16.svg")));
  283.         addChild(panel);
  284.     }
  285.  
  286.     addChild(createWidget<ScrewSilver>(Vec(5, 0)));
  287.     addChild(createWidget<ScrewSilver>(Vec(box.size.x-20, 0)));
  288.     addChild(createWidget<ScrewSilver>(Vec(5, 365)));
  289.     addChild(createWidget<ScrewSilver>(Vec(box.size.x-20, 365)));
  290.  
  291.     addParam(createParam<AutodafeKnobPurpleSmall>(Vec(18, 56), module, SEQ16::CLOCK_PARAM, -2.0, 6.0, 2.0));
  292.     addParam(createParam<LEDButton>(Vec(60, 61-1), module, SEQ16::RUN_PARAM, 0.0, 1.0, 0.0));
  293.  
  294.     addChild(createLight<MediumLight<AutodafePurpleLight>>(Vec(64.4, 64.4), module, SEQ16::RUNNING_LIGHT));
  295.     addParam(createParam<LEDButton>(Vec(98, 61-1), module, SEQ16::RESET_PARAM, 0.0, 1.0, 0.0));
  296.  
  297.  
  298.  
  299.     addOutput(createPort<PJ301MPort>(Vec(403, 98), PortWidget::OUTPUT, module, SEQ16::CLOCK_OUT));
  300.     addOutput(createPort<PJ301MPort>(Vec(442, 98), PortWidget::OUTPUT, module, SEQ16::CLOCK_GATE_OUT));
  301.  
  302.  
  303.     addInput(createPort<PJ301MPort>(Vec(327, 98), PortWidget::INPUT, module, SEQ16::START_INPUT));
  304.     addInput(createPort<PJ301MPort>(Vec(365, 98), PortWidget::INPUT, module, SEQ16::STOP_INPUT));
  305.  
  306.  
  307.  
  308.  
  309.     addChild(createLight<MediumLight<AutodafePurpleLight>>(Vec(103.4, 64.4), module, SEQ16::RESET_LIGHT));
  310.  
  311.     addParam(createParam<AutodafeKnobPurple>(Vec(128, 52), module, SEQ16::STEPS_PARAM, 1.0, 16.0, 16.0));
  312.  
  313.     addChild(createLight<MediumLight<AutodafePurpleLight>>(Vec(179.4, 64.4), module, SEQ16::GATES_LIGHT));
  314.     addChild(createLight<MediumLight<AutodafePurpleLight>>(Vec(218.4, 64.4), module, SEQ16::ROW_LIGHTS));
  315.     addChild(createLight<MediumLight<AutodafePurpleLight>>(Vec(256.4, 64.4), module, SEQ16::ROW_LIGHTS + 1));
  316.     addChild(createLight<MediumLight<AutodafePurpleLight>>(Vec(295.4, 64.4), module, SEQ16::ROW_LIGHTS + 2));
  317.  
  318.     static const float portX[16] = {19,57,96,134,173,211,250,288,326,364,402,440,478,516,554,592};
  319.     addInput(createPort<PJ301MPort>(Vec(portX[0]-1, 99-1), PortWidget::INPUT, module, SEQ16::CLOCK_INPUT));
  320.     addInput(createPort<PJ301MPort>(Vec(portX[1]-1, 99-1), PortWidget::INPUT, module, SEQ16::EXT_CLOCK_INPUT));
  321.     addInput(createPort<PJ301MPort>(Vec(portX[2]-1, 99-1), PortWidget::INPUT, module, SEQ16::RESET_INPUT));
  322.     addInput(createPort<PJ301MPort>(Vec(portX[3]-1, 99-1), PortWidget::INPUT, module, SEQ16::STEPS_INPUT));
  323.     addOutput(createPort<PJ301MPort>(Vec(portX[4]-1, 99-1), PortWidget::OUTPUT, module, SEQ16::GATES_OUTPUT));
  324.     addOutput(createPort<PJ301MPort>(Vec(portX[5]-1, 99-1), PortWidget::OUTPUT, module, SEQ16::ROW1_OUTPUT));
  325.     addOutput(createPort<PJ301MPort>(Vec(portX[6]-1, 99-1), PortWidget::OUTPUT, module, SEQ16::ROW2_OUTPUT));
  326.     addOutput(createPort<PJ301MPort>(Vec(portX[7]-1, 99-1), PortWidget::OUTPUT, module, SEQ16::ROW3_OUTPUT));
  327.  
  328.  
  329.     for (int i = 0; i < 16; i++) {
  330.         addParam(createParam<AutodafeKnobPurpleSmall>(Vec(portX[i] - 2, 157), module, SEQ16::ROW1_PARAM + i, 0.0, 6.0, 0.0));
  331.         addParam(createParam<AutodafeKnobPurpleSmall>(Vec(portX[i] - 2, 198), module, SEQ16::ROW2_PARAM + i, 0.0, 6.0, 0.0));
  332.         addParam(createParam<AutodafeKnobPurpleSmall>(Vec(portX[i] - 2, 240), module, SEQ16::ROW3_PARAM + i, 0.0, 6.0, 0.0));
  333.         addParam(createParam<LEDButton>(Vec(portX[i] + 2, 278 - 1), module, SEQ16::GATE_PARAM + i, 0.0, 1.0, 0.0));
  334.        
  335.  
  336.         addChild(createLight<MediumLight<AutodafePurpleLight>>(Vec(portX[i]+6.4, 281.4), module, SEQ16::GATE_LIGHTS + i));
  337.         addOutput(createPort<PJ301MPort>(Vec(portX[i] - 1, 308 - 1), PortWidget::OUTPUT, module, SEQ16::GATE_OUTPUT + i));
  338.     }
  339.  
  340. }
  341.  
  342.  
  343.  
  344.  
  345. struct SEQ16GateModeItem : MenuItem {
  346.     SEQ16 *SEQ16;
  347.     SEQ16::GateMode gateMode;
  348.     void Action()  {
  349.         SEQ16->gateMode = gateMode;
  350.     }
  351.     void step() override {
  352.         rightText = (SEQ16->gateMode == gateMode) ? "✔" : "";
  353.     }
  354. };
  355.  
  356. Menu *SEQ16createWidgetContextMenu() {
  357.     Menu *menu = SEQ16createWidgetContextMenu();
  358.  
  359.     MenuLabel *spacerLabel = new MenuLabel();
  360.     menu->addChild(spacerLabel);
  361.  
  362.     SEQ16 *SEQ16 = dynamic_cast<struct SEQ16*>(APP->engine->getModule(id));
  363.  
  364.     //MyModule *module = dynamic_cast<MyModule*>(APP->engine->getModule(moduleId));
  365.     assert(SEQ16);
  366.  
  367.     MenuLabel *modeLabel = new MenuLabel();
  368.     modeLabel->text = "Gate Mode";
  369.     menu->addChild(modeLabel);
  370.  
  371.     SEQ16GateModeItem *triggerItem = new SEQ16GateModeItem();
  372.     triggerItem->text = "Trigger";
  373.     triggerItem->SEQ16 = SEQ16;
  374.     triggerItem->gateMode = SEQ16::TRIGGER;
  375.     menu->addChild(triggerItem);
  376.  
  377.     SEQ16GateModeItem *retriggerItem = new SEQ16GateModeItem();
  378.     retriggerItem->text = "Retrigger";
  379.     retriggerItem->SEQ16 = SEQ16;
  380.     retriggerItem->gateMode = SEQ16::RETRIGGER;
  381.     menu->addChild(retriggerItem);
  382.  
  383.     SEQ16GateModeItem *continuousItem = new SEQ16GateModeItem();
  384.     continuousItem->text = "Continuous";
  385.     continuousItem->SEQ16 = SEQ16;
  386.     continuousItem->gateMode = SEQ16::CONTINUOUS;
  387.     menu->addChild(continuousItem);
  388.  
  389.     return menu;
  390. }
  391.  
  392.  
  393.  
  394. Model *modelSEQ16 = createModel<SEQ16, SEQ16Widget>("16-Step Sequencer");
Advertisement
Add Comment
Please, Sign In to add comment