| @@ -24,9 +24,9 @@ Aeolian 3 1-2-3-4-5-b6-b7 | |||
| Locrian 2 1-2-b3-4-b5-b6-b7 | |||
| Locrian b4 1-b2-b3-b4-b5-b6-b7 | |||
| Bebop Dominant 1-2-3-4-5-6-#6-7 | |||
| Bebob Major 1-2-3-4-5-b6-6-7 | |||
| Bebob Minor 1-2-b3-3-4-5-6-b7 | |||
| Bebob Melodic Minor 1-2-b3-4-5-b6-6-7 | |||
| Bebop Major 1-2-3-4-5-b6-6-7 | |||
| Bebop Minor 1-2-b3-3-4-5-6-b7 | |||
| Bebop Melodic Minor 1-2-b3-4-5-b6-6-7 | |||
| Blues Major 1-2-b3-3-5-6 | |||
| Blues Minor 1-b3-4-b5-5-b7 | |||
| Blues Diminished 1-b2-b3-3-b5-5-6-b7 | |||
| @@ -122,7 +122,7 @@ for line in scales.splitlines(): | |||
| path = os.path.join(dir, f"{count:02d}_{name}.vcvm") | |||
| print(path) | |||
| print(data) | |||
| with open(path, "w") as f: | |||
| with open(path, "w", newline='\n') as f: | |||
| json.dump(data, f, indent=2) | |||
| count += 1 | |||
| @@ -183,6 +183,16 @@ struct ADSR : Module { | |||
| lights[PUSH_LIGHT].setBrightness(anyGate); | |||
| } | |||
| } | |||
| void paramsFromJson(json_t* rootJ) override { | |||
| // These attenuators didn't exist in version <2.0, so set to 1 in case they are not overwritten. | |||
| params[ATTACK_CV_PARAM].setValue(1.f); | |||
| params[DECAY_CV_PARAM].setValue(1.f); | |||
| params[SUSTAIN_CV_PARAM].setValue(1.f); | |||
| params[RELEASE_CV_PARAM].setValue(1.f); | |||
| Module::paramsFromJson(rootJ); | |||
| } | |||
| }; | |||
| @@ -193,7 +193,7 @@ struct Delay : Module { | |||
| } | |||
| } | |||
| void fromJson(json_t* rootJ) override { | |||
| void paramsFromJson(json_t* rootJ) override { | |||
| // These attenuators didn't exist in version <2.0, so set to 1 in case they are not overwritten. | |||
| params[FEEDBACK_CV_PARAM].setValue(1.f); | |||
| params[TONE_CV_PARAM].setValue(1.f); | |||
| @@ -201,7 +201,7 @@ struct Delay : Module { | |||
| // The time input scaling has changed, so don't set to 1. | |||
| // params[TIME_CV_PARAM].setValue(1.f); | |||
| Module::fromJson(rootJ); | |||
| Module::paramsFromJson(rootJ); | |||
| } | |||
| }; | |||
| @@ -6,7 +6,7 @@ struct Random : Module { | |||
| RATE_PARAM, | |||
| SHAPE_PARAM, | |||
| OFFSET_PARAM, | |||
| MODE_PARAM, | |||
| MODE_PARAM, // removed in 2.0 | |||
| // new in 2.0 | |||
| PROB_PARAM, | |||
| RAND_PARAM, | |||
| @@ -148,7 +148,7 @@ struct Random : Module { | |||
| // Advance clock phase by rate | |||
| float rate = params[RATE_PARAM].getValue(); | |||
| rate += inputs[RATE_PARAM].getVoltage() * params[RATE_CV_PARAM].getValue(); | |||
| clockFreq = std::pow(2.f, rate); | |||
| clockFreq = 2.f * std::pow(2.f, rate); | |||
| deltaPhase = std::fmin(clockFreq * args.sampleTime, 0.5f); | |||
| clockPhase += deltaPhase; | |||
| // Trigger | |||
| @@ -233,7 +233,15 @@ struct Random : Module { | |||
| params[SHAPE_CV_PARAM].setValue(1.f); | |||
| params[PROB_CV_PARAM].setValue(1.f); | |||
| params[RAND_CV_PARAM].setValue(1.f); | |||
| // In <2.0, mode=0 implied relative mode, corresponding to about 20% RND. | |||
| params[RAND_PARAM].setValue(0.2f); | |||
| Module::paramsFromJson(rootJ); | |||
| // In <2.0, mode was used for absolute/relative mode. RND is a generalization so set it if mode is enabled. | |||
| if (params[MODE_PARAM].getValue() > 0.f) { | |||
| params[MODE_PARAM].setValue(0.f); | |||
| params[RAND_PARAM].setValue(1.f); | |||
| } | |||
| } | |||
| }; | |||
| @@ -6,7 +6,7 @@ struct SEQ3 : Module { | |||
| TEMPO_PARAM, | |||
| RUN_PARAM, | |||
| RESET_PARAM, | |||
| STEPS_PARAM, | |||
| TRIG_PARAM, | |||
| ENUMS(CV_PARAMS, 3 * 8), | |||
| ENUMS(GATE_PARAMS, 8), | |||
| // added in 2.0 | |||
| @@ -24,7 +24,7 @@ struct SEQ3 : Module { | |||
| NUM_INPUTS | |||
| }; | |||
| enum OutputIds { | |||
| GATE_OUTPUT, | |||
| TRIG_OUTPUT, | |||
| ENUMS(CV_OUTPUTS, 3), | |||
| ENUMS(STEP_OUTPUTS, 8), | |||
| // added in 2.0 | |||
| @@ -44,6 +44,7 @@ struct SEQ3 : Module { | |||
| }; | |||
| bool running = true; | |||
| bool clockPassthrough = false; | |||
| dsp::BooleanTrigger runButtonTrigger; | |||
| dsp::BooleanTrigger resetButtonTrigger; | |||
| @@ -69,18 +70,18 @@ struct SEQ3 : Module { | |||
| getParamQuantity(TEMPO_CV_PARAM)->randomizeEnabled = false; | |||
| configButton(RUN_PARAM, "Run"); | |||
| configButton(RESET_PARAM, "Reset"); | |||
| configParam(STEPS_PARAM, 1.f, 8.f, 8.f, "Steps"); | |||
| getParamQuantity(STEPS_PARAM)->randomizeEnabled = false; | |||
| configParam(TRIG_PARAM, 1.f, 8.f, 8.f, "Steps"); | |||
| getParamQuantity(TRIG_PARAM)->randomizeEnabled = false; | |||
| configParam(STEPS_CV_PARAM, 0.f, 1.f, 1.f, "Steps CV", "%", 0, 100); | |||
| getParamQuantity(STEPS_CV_PARAM)->randomizeEnabled = false; | |||
| paramQuantities[STEPS_PARAM]->snapEnabled = true; | |||
| paramQuantities[TRIG_PARAM]->snapEnabled = true; | |||
| for (int j = 0; j < 3; j++) { | |||
| for (int i = 0; i < 8; i++) { | |||
| configParam(CV_PARAMS + 8 * j + i, -10.f, 10.f, 0.f, string::f("CV %d step %d", j + 1, i + 1), " V"); | |||
| } | |||
| } | |||
| for (int i = 0; i < 8; i++) { | |||
| configButton(GATE_PARAMS + i, string::f("Step %d gate", i + 1)); | |||
| configButton(GATE_PARAMS + i, string::f("Step %d trigger", i + 1)); | |||
| } | |||
| configInput(TEMPO_INPUT, "Tempo"); | |||
| @@ -95,7 +96,7 @@ struct SEQ3 : Module { | |||
| for (int j = 0; j < 3; j++) { | |||
| configOutput(CV_OUTPUTS + j, string::f("CV %d", j + 1)); | |||
| } | |||
| configOutput(GATE_OUTPUT, "Trigger"); | |||
| configOutput(TRIG_OUTPUT, "Trigger"); | |||
| configOutput(STEPS_OUTPUT, "Steps"); | |||
| configOutput(CLOCK_OUTPUT, "Clock"); | |||
| configOutput(RUN_OUTPUT, "Run"); | |||
| @@ -107,6 +108,7 @@ struct SEQ3 : Module { | |||
| } | |||
| void onReset() override { | |||
| clockPassthrough = false; | |||
| for (int i = 0; i < 8; i++) { | |||
| gates[i] = true; | |||
| } | |||
| @@ -164,6 +166,7 @@ struct SEQ3 : Module { | |||
| // Clock | |||
| bool clock = false; | |||
| bool clockGate = false; | |||
| if (running) { | |||
| if (inputs[CLOCK_INPUT].isConnected()) { | |||
| // External clock | |||
| @@ -171,6 +174,7 @@ struct SEQ3 : Module { | |||
| if (clockTrigger.process(inputs[CLOCK_INPUT].getVoltage(), 0.1f, 2.f) && !resetGate) { | |||
| clock = true; | |||
| } | |||
| clockGate = clockTrigger.isHigh(); | |||
| } | |||
| else { | |||
| // Internal clock | |||
| @@ -181,11 +185,12 @@ struct SEQ3 : Module { | |||
| clock = true; | |||
| } | |||
| phase -= std::trunc(phase); | |||
| clockGate = (phase < 0.5f); | |||
| } | |||
| } | |||
| // Get number of steps | |||
| float steps = params[STEPS_PARAM].getValue() + inputs[STEPS_INPUT].getVoltage() * params[STEPS_CV_PARAM].getValue(); | |||
| float steps = params[TRIG_PARAM].getValue() + inputs[STEPS_INPUT].getVoltage() * params[STEPS_CV_PARAM].getValue(); | |||
| int numSteps = (int) clamp(std::round(steps), 1.f, 8.f); | |||
| // Advance step | |||
| @@ -195,7 +200,9 @@ struct SEQ3 : Module { | |||
| if (index >= numSteps) | |||
| index = 0; | |||
| } | |||
| bool clockGate = clockPulse.process(args.sampleTime); | |||
| // Unless we're passing the clock gate, generate a pulse | |||
| if (!clockPassthrough) | |||
| clockGate = clockPulse.process(args.sampleTime); | |||
| // Gate buttons | |||
| for (int i = 0; i < 8; i++) { | |||
| @@ -215,7 +222,7 @@ struct SEQ3 : Module { | |||
| outputs[CV_OUTPUTS + 0].setVoltage(params[CV_PARAMS + 8 * 0 + index].getValue()); | |||
| outputs[CV_OUTPUTS + 1].setVoltage(params[CV_PARAMS + 8 * 1 + index].getValue()); | |||
| outputs[CV_OUTPUTS + 2].setVoltage(params[CV_PARAMS + 8 * 2 + index].getValue()); | |||
| outputs[GATE_OUTPUT].setVoltage((clockGate && gates[index]) ? 10.f : 0.f); | |||
| outputs[TRIG_OUTPUT].setVoltage((clockGate && gates[index]) ? 10.f : 0.f); | |||
| outputs[STEPS_OUTPUT].setVoltage((numSteps - 1) * 1.f); | |||
| outputs[CLOCK_OUTPUT].setVoltage(clockGate ? 10.f : 0.f); | |||
| @@ -240,6 +247,9 @@ struct SEQ3 : Module { | |||
| } | |||
| json_object_set_new(rootJ, "gates", gatesJ); | |||
| // clockPassthrough | |||
| json_object_set_new(rootJ, "clockPassthrough", json_boolean(clockPassthrough)); | |||
| return rootJ; | |||
| } | |||
| @@ -258,6 +268,13 @@ struct SEQ3 : Module { | |||
| gates[i] = !!json_integer_value(gateJ); | |||
| } | |||
| } | |||
| // clockPassthrough | |||
| json_t* clockPassthroughJ = json_object_get(rootJ, "clockPassthrough"); | |||
| if (clockPassthroughJ) | |||
| clockPassthrough = json_is_true(clockPassthroughJ); | |||
| else | |||
| clockPassthrough = true; | |||
| } | |||
| }; | |||
| @@ -273,7 +290,7 @@ struct SEQ3Widget : ModuleWidget { | |||
| addChild(createWidget<ScrewSilver>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH))); | |||
| addParam(createParamCentered<RoundLargeBlackKnob>(mm2px(Vec(11.753, 26.755)), module, SEQ3::TEMPO_PARAM)); | |||
| addParam(createParamCentered<RoundLargeBlackKnob>(mm2px(Vec(32.077, 26.782)), module, SEQ3::STEPS_PARAM)); | |||
| addParam(createParamCentered<RoundLargeBlackKnob>(mm2px(Vec(32.077, 26.782)), module, SEQ3::TRIG_PARAM)); | |||
| addParam(createParamCentered<Trimpot>(mm2px(Vec(49.372, 34.066)), module, SEQ3::TEMPO_CV_PARAM)); | |||
| addParam(createLightParamCentered<VCVLightButton<MediumSimpleLight<WhiteLight>>>(mm2px(Vec(88.424, 33.679)), module, SEQ3::RUN_PARAM, SEQ3::RUN_LIGHT)); | |||
| addParam(createParamCentered<Trimpot>(mm2px(Vec(62.39, 34.066)), module, SEQ3::STEPS_CV_PARAM)); | |||
| @@ -333,7 +350,7 @@ struct SEQ3Widget : ModuleWidget { | |||
| addOutput(createOutputCentered<PJ301MPort>(mm2px(Vec(10.319, 113.115)), module, SEQ3::CV_OUTPUTS + 0)); | |||
| addOutput(createOutputCentered<PJ301MPort>(mm2px(Vec(23.336, 113.115)), module, SEQ3::CV_OUTPUTS + 1)); | |||
| addOutput(createOutputCentered<PJ301MPort>(mm2px(Vec(36.354, 113.115)), module, SEQ3::CV_OUTPUTS + 2)); | |||
| addOutput(createOutputCentered<PJ301MPort>(mm2px(Vec(49.371, 113.115)), module, SEQ3::GATE_OUTPUT)); | |||
| addOutput(createOutputCentered<PJ301MPort>(mm2px(Vec(49.371, 113.115)), module, SEQ3::TRIG_OUTPUT)); | |||
| addOutput(createOutputCentered<PJ301MPort>(mm2px(Vec(62.389, 113.115)), module, SEQ3::STEPS_OUTPUT)); | |||
| addOutput(createOutputCentered<PJ301MPort>(mm2px(Vec(75.406, 113.115)), module, SEQ3::CLOCK_OUTPUT)); | |||
| addOutput(createOutputCentered<PJ301MPort>(mm2px(Vec(88.424, 113.115)), module, SEQ3::RUN_OUTPUT)); | |||
| @@ -357,6 +374,10 @@ struct SEQ3Widget : ModuleWidget { | |||
| menu->addChild(new MenuSeparator); | |||
| menu->addChild(createBoolPtrMenuItem("Clock passthrough", "", &module->clockPassthrough)); | |||
| menu->addChild(new MenuSeparator); | |||
| menu->addChild(createMenuItem("Rotate left", "", | |||
| [=]() {module->rotateStates(-1);} | |||
| )); | |||
| @@ -32,7 +32,7 @@ struct Sum : Module { | |||
| vuMeter.lambda = 1 / 0.1f; | |||
| vuDivider.setDivision(16); | |||
| lightDivider.setDivision(256); | |||
| lightDivider.setDivision(512); | |||
| } | |||
| void process(const ProcessArgs& args) override { | |||
| @@ -48,10 +48,12 @@ struct Sum : Module { | |||
| if (lightDivider.process()) { | |||
| lastChannels = inputs[POLY_INPUT].getChannels(); | |||
| lights[VU_LIGHTS + 0].setBrightness(vuMeter.getBrightness(0.f, 0.f)); | |||
| for (int i = 1; i < 6; i++) { | |||
| lights[VU_LIGHTS + i].setBrightness(vuMeter.getBrightness(-3.f * i, -3.f * (i - 1))); | |||
| } | |||
| lights[VU_LIGHTS + 0].setBrightness(vuMeter.getBrightness(0, 0)); | |||
| lights[VU_LIGHTS + 1].setBrightness(vuMeter.getBrightness(-3, 0)); | |||
| lights[VU_LIGHTS + 2].setBrightness(vuMeter.getBrightness(-6, -3)); | |||
| lights[VU_LIGHTS + 3].setBrightness(vuMeter.getBrightness(-12, -6)); | |||
| lights[VU_LIGHTS + 4].setBrightness(vuMeter.getBrightness(-24, -12)); | |||
| lights[VU_LIGHTS + 5].setBrightness(vuMeter.getBrightness(-36, -24)); | |||
| } | |||
| } | |||
| }; | |||
| @@ -59,11 +61,46 @@ struct Sum : Module { | |||
| struct SumDisplay : LedDisplay { | |||
| Sum* module; | |||
| void drawLayer(const DrawArgs& args, int layer) override { | |||
| if (layer == 1) { | |||
| static const std::vector<float> posY = { | |||
| mm2px(18.068 - 13.039), | |||
| mm2px(23.366 - 13.039), | |||
| mm2px(28.663 - 13.039), | |||
| mm2px(33.961 - 13.039), | |||
| mm2px(39.258 - 13.039), | |||
| mm2px(44.556 - 13.039), | |||
| }; | |||
| static const std::vector<std::string> texts = { | |||
| " 0", "-3", "-6", "-12", "-24", "-36", | |||
| }; | |||
| std::string fontPath = asset::system("res/fonts/Nunito-Bold.ttf"); | |||
| std::shared_ptr<Font> font = APP->window->loadFont(fontPath); | |||
| if (!font) | |||
| return; | |||
| nvgSave(args.vg); | |||
| nvgFontFaceId(args.vg, font->handle); | |||
| nvgFontSize(args.vg, 11); | |||
| nvgTextLetterSpacing(args.vg, 0.0); | |||
| nvgTextAlign(args.vg, NVG_ALIGN_CENTER | NVG_ALIGN_MIDDLE); | |||
| nvgFillColor(args.vg, nvgRGB(99, 99, 99)); | |||
| for (int i = 0; i < 6; i++) { | |||
| nvgText(args.vg, 15.0, posY[i], texts[i].c_str(), NULL); | |||
| } | |||
| nvgRestore(args.vg); | |||
| } | |||
| LedDisplay::drawLayer(args, layer); | |||
| } | |||
| }; | |||
| struct SumChannelDisplay : ChannelDisplay { | |||
| Sum* module; | |||
| void step() override { | |||
| int channels = 16; | |||
| if (module) | |||
| @@ -89,18 +126,18 @@ struct SumWidget : ModuleWidget { | |||
| addOutput(createOutputCentered<PJ301MPort>(mm2px(Vec(7.62, 113.066)), module, Sum::MONO_OUTPUT)); | |||
| addChild(createLightCentered<RedLight>(mm2px(Vec(10.808, 18.081)), module, Sum::VU_LIGHTS + 0)); | |||
| addChild(createLightCentered<RedLight>(mm2px(Vec(10.808, 23.378)), module, Sum::VU_LIGHTS + 1)); | |||
| addChild(createLightCentered<RedLight>(mm2px(Vec(10.808, 28.676)), module, Sum::VU_LIGHTS + 2)); | |||
| addChild(createLightCentered<RedLight>(mm2px(Vec(10.808, 33.973)), module, Sum::VU_LIGHTS + 3)); | |||
| addChild(createLightCentered<RedLight>(mm2px(Vec(10.808, 39.271)), module, Sum::VU_LIGHTS + 4)); | |||
| addChild(createLightCentered<RedLight>(mm2px(Vec(10.808, 44.568)), module, Sum::VU_LIGHTS + 5)); | |||
| SumDisplay* display = createWidget<SumDisplay>(mm2px(Vec(0.0, 12.834))); | |||
| display->box.size = mm2px(Vec(15.241, 36.981)); | |||
| display->module = module; | |||
| addChild(display); | |||
| addChild(createLightCentered<SmallSimpleLight<RedLight>>(mm2px(Vec(10.808, 18.081)), module, Sum::VU_LIGHTS + 0)); | |||
| addChild(createLightCentered<SmallSimpleLight<YellowLight>>(mm2px(Vec(10.808, 23.378)), module, Sum::VU_LIGHTS + 1)); | |||
| addChild(createLightCentered<SmallSimpleLight<GreenLight>>(mm2px(Vec(10.808, 28.676)), module, Sum::VU_LIGHTS + 2)); | |||
| addChild(createLightCentered<SmallSimpleLight<GreenLight>>(mm2px(Vec(10.808, 33.973)), module, Sum::VU_LIGHTS + 3)); | |||
| addChild(createLightCentered<SmallSimpleLight<GreenLight>>(mm2px(Vec(10.808, 39.271)), module, Sum::VU_LIGHTS + 4)); | |||
| addChild(createLightCentered<SmallSimpleLight<GreenLight>>(mm2px(Vec(10.808, 44.568)), module, Sum::VU_LIGHTS + 5)); | |||
| SumChannelDisplay* channelDisplay = createWidget<SumChannelDisplay>(mm2px(Vec(3.521, 77.191))); | |||
| channelDisplay->box.size = mm2px(Vec(8.197, 8.197)); | |||
| channelDisplay->module = module; | |||
| @@ -83,7 +83,7 @@ struct VizDisplay : LedDisplay { | |||
| else | |||
| nvgFillColor(args.vg, nvgRGB(99, 99, 99)); | |||
| std::string text = string::f("%d", c + 1); | |||
| nvgText(args.vg, 36.0, posY[c], text.c_str(), NULL); | |||
| nvgText(args.vg, 15.0, posY[c], text.c_str(), NULL); | |||
| } | |||
| nvgRestore(args.vg); | |||
| } | |||
| @@ -104,27 +104,27 @@ struct VizWidget : ModuleWidget { | |||
| addInput(createInputCentered<PJ301MPort>(mm2px(Vec(7.62, 113.115)), module, Viz::POLY_INPUT)); | |||
| addChild(createLightCentered<RedLight>(mm2px(Vec(10.846, 18.068)), module, Viz::VU_LIGHTS + 0)); | |||
| addChild(createLightCentered<RedLight>(mm2px(Vec(10.846, 23.366)), module, Viz::VU_LIGHTS + 1)); | |||
| addChild(createLightCentered<RedLight>(mm2px(Vec(10.846, 28.663)), module, Viz::VU_LIGHTS + 2)); | |||
| addChild(createLightCentered<RedLight>(mm2px(Vec(10.846, 33.961)), module, Viz::VU_LIGHTS + 3)); | |||
| addChild(createLightCentered<RedLight>(mm2px(Vec(10.846, 39.258)), module, Viz::VU_LIGHTS + 4)); | |||
| addChild(createLightCentered<RedLight>(mm2px(Vec(10.846, 44.556)), module, Viz::VU_LIGHTS + 5)); | |||
| addChild(createLightCentered<RedLight>(mm2px(Vec(10.846, 49.919)), module, Viz::VU_LIGHTS + 6)); | |||
| addChild(createLightCentered<RedLight>(mm2px(Vec(10.846, 55.217)), module, Viz::VU_LIGHTS + 7)); | |||
| addChild(createLightCentered<RedLight>(mm2px(Vec(10.846, 60.514)), module, Viz::VU_LIGHTS + 8)); | |||
| addChild(createLightCentered<RedLight>(mm2px(Vec(10.846, 65.812)), module, Viz::VU_LIGHTS + 9)); | |||
| addChild(createLightCentered<RedLight>(mm2px(Vec(10.846, 71.109)), module, Viz::VU_LIGHTS + 10)); | |||
| addChild(createLightCentered<RedLight>(mm2px(Vec(10.846, 76.473)), module, Viz::VU_LIGHTS + 11)); | |||
| addChild(createLightCentered<RedLight>(mm2px(Vec(10.846, 81.771)), module, Viz::VU_LIGHTS + 12)); | |||
| addChild(createLightCentered<RedLight>(mm2px(Vec(10.846, 87.068)), module, Viz::VU_LIGHTS + 13)); | |||
| addChild(createLightCentered<RedLight>(mm2px(Vec(10.846, 92.366)), module, Viz::VU_LIGHTS + 14)); | |||
| addChild(createLightCentered<RedLight>(mm2px(Vec(10.846, 97.663)), module, Viz::VU_LIGHTS + 15)); | |||
| VizDisplay* display = createWidget<VizDisplay>(mm2px(Vec(0.003, 13.039))); | |||
| display->box.size = mm2px(Vec(15.237, 89.344)); | |||
| display->module = module; | |||
| addChild(display); | |||
| addChild(createLightCentered<SmallSimpleLight<GreenRedLight>>(mm2px(Vec(10.846, 18.068)), module, Viz::VU_LIGHTS + 2 * 0)); | |||
| addChild(createLightCentered<SmallSimpleLight<GreenRedLight>>(mm2px(Vec(10.846, 23.366)), module, Viz::VU_LIGHTS + 2 * 1)); | |||
| addChild(createLightCentered<SmallSimpleLight<GreenRedLight>>(mm2px(Vec(10.846, 28.663)), module, Viz::VU_LIGHTS + 2 * 2)); | |||
| addChild(createLightCentered<SmallSimpleLight<GreenRedLight>>(mm2px(Vec(10.846, 33.961)), module, Viz::VU_LIGHTS + 2 * 3)); | |||
| addChild(createLightCentered<SmallSimpleLight<GreenRedLight>>(mm2px(Vec(10.846, 39.258)), module, Viz::VU_LIGHTS + 2 * 4)); | |||
| addChild(createLightCentered<SmallSimpleLight<GreenRedLight>>(mm2px(Vec(10.846, 44.556)), module, Viz::VU_LIGHTS + 2 * 5)); | |||
| addChild(createLightCentered<SmallSimpleLight<GreenRedLight>>(mm2px(Vec(10.846, 49.919)), module, Viz::VU_LIGHTS + 2 * 6)); | |||
| addChild(createLightCentered<SmallSimpleLight<GreenRedLight>>(mm2px(Vec(10.846, 55.217)), module, Viz::VU_LIGHTS + 2 * 7)); | |||
| addChild(createLightCentered<SmallSimpleLight<GreenRedLight>>(mm2px(Vec(10.846, 60.514)), module, Viz::VU_LIGHTS + 2 * 8)); | |||
| addChild(createLightCentered<SmallSimpleLight<GreenRedLight>>(mm2px(Vec(10.846, 65.812)), module, Viz::VU_LIGHTS + 2 * 9)); | |||
| addChild(createLightCentered<SmallSimpleLight<GreenRedLight>>(mm2px(Vec(10.846, 71.109)), module, Viz::VU_LIGHTS + 2 * 10)); | |||
| addChild(createLightCentered<SmallSimpleLight<GreenRedLight>>(mm2px(Vec(10.846, 76.473)), module, Viz::VU_LIGHTS + 2 * 11)); | |||
| addChild(createLightCentered<SmallSimpleLight<GreenRedLight>>(mm2px(Vec(10.846, 81.771)), module, Viz::VU_LIGHTS + 2 * 12)); | |||
| addChild(createLightCentered<SmallSimpleLight<GreenRedLight>>(mm2px(Vec(10.846, 87.068)), module, Viz::VU_LIGHTS + 2 * 13)); | |||
| addChild(createLightCentered<SmallSimpleLight<GreenRedLight>>(mm2px(Vec(10.846, 92.366)), module, Viz::VU_LIGHTS + 2 * 14)); | |||
| addChild(createLightCentered<SmallSimpleLight<GreenRedLight>>(mm2px(Vec(10.846, 97.663)), module, Viz::VU_LIGHTS + 2 * 15)); | |||
| } | |||
| }; | |||
| @@ -226,6 +226,12 @@ struct WTLFO : Module { | |||
| } | |||
| } | |||
| void paramsFromJson(json_t* rootJ) override { | |||
| // In <2.0, there were no attenuverters, so set them to 1.0 in case they are not overwritten. | |||
| params[POS_CV_PARAM].setValue(1.f); | |||
| Module::paramsFromJson(rootJ); | |||
| } | |||
| json_t* dataToJson() override { | |||
| json_t* rootJ = json_object(); | |||
| // Merge wavetable | |||
| @@ -258,6 +258,12 @@ struct WTVCO : Module { | |||
| } | |||
| } | |||
| void paramsFromJson(json_t* rootJ) override { | |||
| // In <2.0, there were no attenuverters, so set them to 1.0 in case they are not overwritten. | |||
| params[POS_CV_PARAM].setValue(1.f); | |||
| Module::paramsFromJson(rootJ); | |||
| } | |||
| json_t* dataToJson() override { | |||
| json_t* rootJ = json_object(); | |||
| // Merge wavetable | |||