| @@ -24,9 +24,9 @@ Aeolian 3 1-2-3-4-5-b6-b7 | |||||
| Locrian 2 1-2-b3-4-b5-b6-b7 | Locrian 2 1-2-b3-4-b5-b6-b7 | ||||
| Locrian b4 1-b2-b3-b4-b5-b6-b7 | Locrian b4 1-b2-b3-b4-b5-b6-b7 | ||||
| Bebop Dominant 1-2-3-4-5-6-#6-7 | 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 Major 1-2-b3-3-5-6 | ||||
| Blues Minor 1-b3-4-b5-5-b7 | Blues Minor 1-b3-4-b5-5-b7 | ||||
| Blues Diminished 1-b2-b3-3-b5-5-6-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") | path = os.path.join(dir, f"{count:02d}_{name}.vcvm") | ||||
| print(path) | print(path) | ||||
| print(data) | print(data) | ||||
| with open(path, "w") as f: | |||||
| with open(path, "w", newline='\n') as f: | |||||
| json.dump(data, f, indent=2) | json.dump(data, f, indent=2) | ||||
| count += 1 | count += 1 | ||||
| @@ -183,6 +183,16 @@ struct ADSR : Module { | |||||
| lights[PUSH_LIGHT].setBrightness(anyGate); | 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. | // 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[FEEDBACK_CV_PARAM].setValue(1.f); | ||||
| params[TONE_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. | // The time input scaling has changed, so don't set to 1. | ||||
| // params[TIME_CV_PARAM].setValue(1.f); | // params[TIME_CV_PARAM].setValue(1.f); | ||||
| Module::fromJson(rootJ); | |||||
| Module::paramsFromJson(rootJ); | |||||
| } | } | ||||
| }; | }; | ||||
| @@ -6,7 +6,7 @@ struct Random : Module { | |||||
| RATE_PARAM, | RATE_PARAM, | ||||
| SHAPE_PARAM, | SHAPE_PARAM, | ||||
| OFFSET_PARAM, | OFFSET_PARAM, | ||||
| MODE_PARAM, | |||||
| MODE_PARAM, // removed in 2.0 | |||||
| // new in 2.0 | // new in 2.0 | ||||
| PROB_PARAM, | PROB_PARAM, | ||||
| RAND_PARAM, | RAND_PARAM, | ||||
| @@ -148,7 +148,7 @@ struct Random : Module { | |||||
| // Advance clock phase by rate | // Advance clock phase by rate | ||||
| float rate = params[RATE_PARAM].getValue(); | float rate = params[RATE_PARAM].getValue(); | ||||
| rate += inputs[RATE_PARAM].getVoltage() * params[RATE_CV_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); | deltaPhase = std::fmin(clockFreq * args.sampleTime, 0.5f); | ||||
| clockPhase += deltaPhase; | clockPhase += deltaPhase; | ||||
| // Trigger | // Trigger | ||||
| @@ -233,7 +233,15 @@ struct Random : Module { | |||||
| params[SHAPE_CV_PARAM].setValue(1.f); | params[SHAPE_CV_PARAM].setValue(1.f); | ||||
| params[PROB_CV_PARAM].setValue(1.f); | params[PROB_CV_PARAM].setValue(1.f); | ||||
| params[RAND_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); | 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, | TEMPO_PARAM, | ||||
| RUN_PARAM, | RUN_PARAM, | ||||
| RESET_PARAM, | RESET_PARAM, | ||||
| STEPS_PARAM, | |||||
| TRIG_PARAM, | |||||
| ENUMS(CV_PARAMS, 3 * 8), | ENUMS(CV_PARAMS, 3 * 8), | ||||
| ENUMS(GATE_PARAMS, 8), | ENUMS(GATE_PARAMS, 8), | ||||
| // added in 2.0 | // added in 2.0 | ||||
| @@ -24,7 +24,7 @@ struct SEQ3 : Module { | |||||
| NUM_INPUTS | NUM_INPUTS | ||||
| }; | }; | ||||
| enum OutputIds { | enum OutputIds { | ||||
| GATE_OUTPUT, | |||||
| TRIG_OUTPUT, | |||||
| ENUMS(CV_OUTPUTS, 3), | ENUMS(CV_OUTPUTS, 3), | ||||
| ENUMS(STEP_OUTPUTS, 8), | ENUMS(STEP_OUTPUTS, 8), | ||||
| // added in 2.0 | // added in 2.0 | ||||
| @@ -44,6 +44,7 @@ struct SEQ3 : Module { | |||||
| }; | }; | ||||
| bool running = true; | bool running = true; | ||||
| bool clockPassthrough = false; | |||||
| dsp::BooleanTrigger runButtonTrigger; | dsp::BooleanTrigger runButtonTrigger; | ||||
| dsp::BooleanTrigger resetButtonTrigger; | dsp::BooleanTrigger resetButtonTrigger; | ||||
| @@ -69,18 +70,18 @@ struct SEQ3 : Module { | |||||
| getParamQuantity(TEMPO_CV_PARAM)->randomizeEnabled = false; | getParamQuantity(TEMPO_CV_PARAM)->randomizeEnabled = false; | ||||
| configButton(RUN_PARAM, "Run"); | configButton(RUN_PARAM, "Run"); | ||||
| configButton(RESET_PARAM, "Reset"); | 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); | configParam(STEPS_CV_PARAM, 0.f, 1.f, 1.f, "Steps CV", "%", 0, 100); | ||||
| getParamQuantity(STEPS_CV_PARAM)->randomizeEnabled = false; | 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 j = 0; j < 3; j++) { | ||||
| for (int i = 0; i < 8; i++) { | 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"); | 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++) { | 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"); | configInput(TEMPO_INPUT, "Tempo"); | ||||
| @@ -95,7 +96,7 @@ struct SEQ3 : Module { | |||||
| for (int j = 0; j < 3; j++) { | for (int j = 0; j < 3; j++) { | ||||
| configOutput(CV_OUTPUTS + j, string::f("CV %d", j + 1)); | configOutput(CV_OUTPUTS + j, string::f("CV %d", j + 1)); | ||||
| } | } | ||||
| configOutput(GATE_OUTPUT, "Trigger"); | |||||
| configOutput(TRIG_OUTPUT, "Trigger"); | |||||
| configOutput(STEPS_OUTPUT, "Steps"); | configOutput(STEPS_OUTPUT, "Steps"); | ||||
| configOutput(CLOCK_OUTPUT, "Clock"); | configOutput(CLOCK_OUTPUT, "Clock"); | ||||
| configOutput(RUN_OUTPUT, "Run"); | configOutput(RUN_OUTPUT, "Run"); | ||||
| @@ -107,6 +108,7 @@ struct SEQ3 : Module { | |||||
| } | } | ||||
| void onReset() override { | void onReset() override { | ||||
| clockPassthrough = false; | |||||
| for (int i = 0; i < 8; i++) { | for (int i = 0; i < 8; i++) { | ||||
| gates[i] = true; | gates[i] = true; | ||||
| } | } | ||||
| @@ -164,6 +166,7 @@ struct SEQ3 : Module { | |||||
| // Clock | // Clock | ||||
| bool clock = false; | bool clock = false; | ||||
| bool clockGate = false; | |||||
| if (running) { | if (running) { | ||||
| if (inputs[CLOCK_INPUT].isConnected()) { | if (inputs[CLOCK_INPUT].isConnected()) { | ||||
| // External clock | // External clock | ||||
| @@ -171,6 +174,7 @@ struct SEQ3 : Module { | |||||
| if (clockTrigger.process(inputs[CLOCK_INPUT].getVoltage(), 0.1f, 2.f) && !resetGate) { | if (clockTrigger.process(inputs[CLOCK_INPUT].getVoltage(), 0.1f, 2.f) && !resetGate) { | ||||
| clock = true; | clock = true; | ||||
| } | } | ||||
| clockGate = clockTrigger.isHigh(); | |||||
| } | } | ||||
| else { | else { | ||||
| // Internal clock | // Internal clock | ||||
| @@ -181,11 +185,12 @@ struct SEQ3 : Module { | |||||
| clock = true; | clock = true; | ||||
| } | } | ||||
| phase -= std::trunc(phase); | phase -= std::trunc(phase); | ||||
| clockGate = (phase < 0.5f); | |||||
| } | } | ||||
| } | } | ||||
| // Get number of steps | // 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); | int numSteps = (int) clamp(std::round(steps), 1.f, 8.f); | ||||
| // Advance step | // Advance step | ||||
| @@ -195,7 +200,9 @@ struct SEQ3 : Module { | |||||
| if (index >= numSteps) | if (index >= numSteps) | ||||
| index = 0; | 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 | // Gate buttons | ||||
| for (int i = 0; i < 8; i++) { | 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 + 0].setVoltage(params[CV_PARAMS + 8 * 0 + index].getValue()); | ||||
| outputs[CV_OUTPUTS + 1].setVoltage(params[CV_PARAMS + 8 * 1 + 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[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[STEPS_OUTPUT].setVoltage((numSteps - 1) * 1.f); | ||||
| outputs[CLOCK_OUTPUT].setVoltage(clockGate ? 10.f : 0.f); | outputs[CLOCK_OUTPUT].setVoltage(clockGate ? 10.f : 0.f); | ||||
| @@ -240,6 +247,9 @@ struct SEQ3 : Module { | |||||
| } | } | ||||
| json_object_set_new(rootJ, "gates", gatesJ); | json_object_set_new(rootJ, "gates", gatesJ); | ||||
| // clockPassthrough | |||||
| json_object_set_new(rootJ, "clockPassthrough", json_boolean(clockPassthrough)); | |||||
| return rootJ; | return rootJ; | ||||
| } | } | ||||
| @@ -258,6 +268,13 @@ struct SEQ3 : Module { | |||||
| gates[i] = !!json_integer_value(gateJ); | 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))); | 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(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(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(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)); | 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(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(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(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(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(75.406, 113.115)), module, SEQ3::CLOCK_OUTPUT)); | ||||
| addOutput(createOutputCentered<PJ301MPort>(mm2px(Vec(88.424, 113.115)), module, SEQ3::RUN_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(new MenuSeparator); | ||||
| menu->addChild(createBoolPtrMenuItem("Clock passthrough", "", &module->clockPassthrough)); | |||||
| menu->addChild(new MenuSeparator); | |||||
| menu->addChild(createMenuItem("Rotate left", "", | menu->addChild(createMenuItem("Rotate left", "", | ||||
| [=]() {module->rotateStates(-1);} | [=]() {module->rotateStates(-1);} | ||||
| )); | )); | ||||
| @@ -32,7 +32,7 @@ struct Sum : Module { | |||||
| vuMeter.lambda = 1 / 0.1f; | vuMeter.lambda = 1 / 0.1f; | ||||
| vuDivider.setDivision(16); | vuDivider.setDivision(16); | ||||
| lightDivider.setDivision(256); | |||||
| lightDivider.setDivision(512); | |||||
| } | } | ||||
| void process(const ProcessArgs& args) override { | void process(const ProcessArgs& args) override { | ||||
| @@ -48,10 +48,12 @@ struct Sum : Module { | |||||
| if (lightDivider.process()) { | if (lightDivider.process()) { | ||||
| lastChannels = inputs[POLY_INPUT].getChannels(); | 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 { | struct SumDisplay : LedDisplay { | ||||
| Sum* module; | 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 { | struct SumChannelDisplay : ChannelDisplay { | ||||
| Sum* module; | Sum* module; | ||||
| void step() override { | void step() override { | ||||
| int channels = 16; | int channels = 16; | ||||
| if (module) | if (module) | ||||
| @@ -89,18 +126,18 @@ struct SumWidget : ModuleWidget { | |||||
| addOutput(createOutputCentered<PJ301MPort>(mm2px(Vec(7.62, 113.066)), module, Sum::MONO_OUTPUT)); | 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))); | SumDisplay* display = createWidget<SumDisplay>(mm2px(Vec(0.0, 12.834))); | ||||
| display->box.size = mm2px(Vec(15.241, 36.981)); | display->box.size = mm2px(Vec(15.241, 36.981)); | ||||
| display->module = module; | display->module = module; | ||||
| addChild(display); | 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))); | SumChannelDisplay* channelDisplay = createWidget<SumChannelDisplay>(mm2px(Vec(3.521, 77.191))); | ||||
| channelDisplay->box.size = mm2px(Vec(8.197, 8.197)); | channelDisplay->box.size = mm2px(Vec(8.197, 8.197)); | ||||
| channelDisplay->module = module; | channelDisplay->module = module; | ||||
| @@ -83,7 +83,7 @@ struct VizDisplay : LedDisplay { | |||||
| else | else | ||||
| nvgFillColor(args.vg, nvgRGB(99, 99, 99)); | nvgFillColor(args.vg, nvgRGB(99, 99, 99)); | ||||
| std::string text = string::f("%d", c + 1); | 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); | nvgRestore(args.vg); | ||||
| } | } | ||||
| @@ -104,27 +104,27 @@ struct VizWidget : ModuleWidget { | |||||
| addInput(createInputCentered<PJ301MPort>(mm2px(Vec(7.62, 113.115)), module, Viz::POLY_INPUT)); | 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))); | VizDisplay* display = createWidget<VizDisplay>(mm2px(Vec(0.003, 13.039))); | ||||
| display->box.size = mm2px(Vec(15.237, 89.344)); | display->box.size = mm2px(Vec(15.237, 89.344)); | ||||
| display->module = module; | display->module = module; | ||||
| addChild(display); | 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* dataToJson() override { | ||||
| json_t* rootJ = json_object(); | json_t* rootJ = json_object(); | ||||
| // Merge wavetable | // 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* dataToJson() override { | ||||
| json_t* rootJ = json_object(); | json_t* rootJ = json_object(); | ||||
| // Merge wavetable | // Merge wavetable | ||||