@@ -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 | |||