diff --git a/res/Random.svg b/res/Random.svg index b26a2f8..a2a5518 100644 --- a/res/Random.svg +++ b/res/Random.svg @@ -1,6 +1,4 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + id="svg291" + sodipodi:docname="RANDOM.svg" + inkscape:version="0.92.3 (2405546, 2018-03-11)"> + id="metadata295"> image/svg+xml - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + id="b1ee2ad7-f2cc-4d5c-a8a9-017d6a13c113" + data-name="FND TXT"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/res/Viz.svg b/res/Viz.svg index 97ecf4f..34c452e 100644 --- a/res/Viz.svg +++ b/res/Viz.svg @@ -1,6 +1,4 @@ - - - - + id="svg154" + sodipodi:docname="VIZ.svg" + inkscape:version="0.92.3 (2405546, 2018-03-11)"> + id="metadata158"> image/svg+xml - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + style="display:none"> + + + style="fill:#ff00ff" /> + style="fill:#ff00ff" /> + style="fill:#ff00ff" /> + style="fill:#ff00ff" /> + style="fill:#ff00ff" /> + style="fill:#ff00ff" /> + style="fill:#ff00ff" /> + style="fill:#ff00ff" /> + style="fill:#ff00ff" /> + style="fill:#ff00ff" /> + style="fill:#ff00ff" /> + style="fill:#ff00ff" /> + style="fill:#ff00ff" /> - - diff --git a/src/Random.cpp b/src/Random.cpp index 27267d2..1b0a430 100644 --- a/src/Random.cpp +++ b/src/Random.cpp @@ -7,6 +7,13 @@ struct Random : Module { SHAPE_PARAM, OFFSET_PARAM, MODE_PARAM, + // new in 2.0 + PROB_PARAM, // TODO + RANDOM_PARAM, // TODO + RATE_CV_PARAM, + SHAPE_CV_PARAM, + PROB_CV_PARAM, + RANDOM_CV_PARAM, NUM_PARAMS }; enum InputIds { @@ -14,6 +21,9 @@ struct Random : Module { SHAPE_INPUT, TRIGGER_INPUT, EXTERNAL_INPUT, + // new in 2.0 + PROB_INPUT, + RANDOM_INPUT, NUM_INPUTS }; enum OutputIds { @@ -21,35 +31,64 @@ struct Random : Module { LINEAR_OUTPUT, SMOOTH_OUTPUT, EXPONENTIAL_OUTPUT, + // new in 2.0 + GATE_OUTPUT, // TODO NUM_OUTPUTS }; enum LightIds { RATE_LIGHT, SHAPE_LIGHT, + PROB_LIGHT, + RANDOM_LIGHT, + OFFSET_LIGHT, NUM_LIGHTS }; dsp::SchmittTrigger trigTrigger; + dsp::BooleanTrigger offsetTrigger; float lastValue = 0.f; float value = 0.f; float clockPhase = 0.f; int trigFrame = 0; int lastTrigFrames = INT_MAX; + bool offset = false; Random() { config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); configParam(RATE_PARAM, std::log2(0.002f), std::log2(2000.f), std::log2(2.f), "Rate", " Hz", 2); - configParam(SHAPE_PARAM, 0.f, 1.f, 0.5f, "Shape", "%", 0, 100); - configSwitch(OFFSET_PARAM, 0.f, 1.f, 1.f, "Offset", {"Bipolar", "Unipolar"}); - configSwitch(MODE_PARAM, 0.f, 1.f, 1.f, "Randomness mode", {"Relative", "Absolute"}); + configParam(SHAPE_PARAM, 0.f, 1.f, 1.f, "Shape", "%", 0, 100); + configParam(PROB_PARAM, 0.f, 1.f, 1.f, "Probability", "%", 0, 100); + configParam(RANDOM_PARAM, 0.f, 1.f, 1.f, "Randomness", "%", 0, 100); + + configParam(RATE_CV_PARAM, -1.f, 1.f, 0.f, "Rate CV", "%", 0, 100); + getParamQuantity(RATE_CV_PARAM)->randomizeEnabled = false; + configParam(SHAPE_CV_PARAM, -1.f, 1.f, 0.f, "Shape CV", "%", 0, 100); + getParamQuantity(SHAPE_CV_PARAM)->randomizeEnabled = false; + configParam(PROB_CV_PARAM, -1.f, 1.f, 0.f, "Probability CV", "%", 0, 100); + getParamQuantity(PROB_CV_PARAM)->randomizeEnabled = false; + configParam(RANDOM_CV_PARAM, -1.f, 1.f, 0.f, "Randomness CV", "%", 0, 100); + getParamQuantity(RANDOM_CV_PARAM)->randomizeEnabled = false; + + configButton(OFFSET_PARAM, "Offset 0-10V"); + configInput(RATE_INPUT, "Rate"); configInput(SHAPE_INPUT, "Shape"); + configInput(PROB_INPUT, "Probability"); + configInput(RANDOM_INPUT, "Randomness"); configInput(TRIGGER_INPUT, "Trigger"); configInput(EXTERNAL_INPUT, "External"); + configOutput(STEPPED_OUTPUT, "Stepped"); configOutput(LINEAR_OUTPUT, "Linear"); configOutput(SMOOTH_OUTPUT, "Smooth"); configOutput(EXPONENTIAL_OUTPUT, "Exponential"); + configOutput(GATE_OUTPUT, "Gate"); + + onReset(); + } + + void onReset() override { + offset = false; } void trigger() { @@ -87,6 +126,10 @@ struct Random : Module { } void process(const ProcessArgs& args) override { + if (offsetTrigger.process(params[OFFSET_PARAM].getValue() > 0.f)) { + offset ^= true; + } + if (inputs[TRIGGER_INPUT].isConnected()) { // Advance clock phase based on tempo estimate trigFrame++; @@ -104,7 +147,7 @@ struct Random : Module { else { // Advance clock phase by rate float rate = params[RATE_PARAM].getValue(); - rate += inputs[RATE_PARAM].getVoltage(); + rate += inputs[RATE_PARAM].getVoltage() * params[RATE_CV_PARAM].getValue(); float clockFreq = std::pow(2.f, rate); float deltaPhase = std::fmin(clockFreq * args.sampleTime, 0.5f); clockPhase += deltaPhase; @@ -115,10 +158,9 @@ struct Random : Module { } } - // Shape float shape = params[SHAPE_PARAM].getValue(); - shape += inputs[SHAPE_INPUT].getVoltage() / 10.f; + shape += inputs[SHAPE_INPUT].getVoltage() / 10.f * params[SHAPE_CV_PARAM].getValue(); shape = clamp(shape, 0.f, 1.f); // Stepped @@ -178,6 +220,35 @@ struct Random : Module { // Lights lights[RATE_LIGHT].setSmoothBrightness(0.f, args.sampleTime); lights[SHAPE_LIGHT].setBrightness(shape); + lights[OFFSET_LIGHT].setBrightness(offset); + } + + 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[RATE_CV_PARAM].setValue(1.f); + params[SHAPE_CV_PARAM].setValue(1.f); + params[PROB_CV_PARAM].setValue(1.f); + params[RANDOM_CV_PARAM].setValue(1.f); + Module::paramsFromJson(rootJ); + // In <2.0, OFFSET_PARAM was a toggle switch instead of a momentary button, so if param is on after deserializing, set boolean states instead. + if (params[OFFSET_PARAM].getValue() > 0.f) { + offset = true; + params[OFFSET_PARAM].setValue(0.f); + } + } + + json_t* dataToJson() override { + json_t* rootJ = json_object(); + // offset + json_object_set_new(rootJ, "offset", json_boolean(offset)); + return rootJ; + } + + void dataFromJson(json_t* rootJ) override { + // offset + json_t* offsetJ = json_object_get(rootJ, "offset"); + if (offsetJ) + offset = json_boolean_value(offsetJ); } }; @@ -192,20 +263,28 @@ struct RandomWidget : ModuleWidget { addChild(createWidget(Vec(RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH))); addChild(createWidget(Vec(box.size.x - 2 * RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH))); - addParam(createLightParamCentered>(mm2px(Vec(7.215, 30.858)), module, Random::RATE_PARAM, Random::RATE_LIGHT)); - addParam(createLightParamCentered>(mm2px(Vec(18.214, 30.858)), module, Random::SHAPE_PARAM, Random::SHAPE_LIGHT)); - addParam(createParamCentered(mm2px(Vec(7.214, 78.259)), module, Random::OFFSET_PARAM)); - addParam(createParamCentered(mm2px(Vec(18.214, 78.259)), module, Random::MODE_PARAM)); + addParam(createLightParamCentered>(mm2px(Vec(6.479, 33.605)), module, Random::RATE_PARAM, Random::RATE_LIGHT)); + addParam(createLightParamCentered>(mm2px(Vec(17.315, 33.605)), module, Random::PROB_PARAM, Random::PROB_LIGHT)); + addParam(createLightParamCentered>(mm2px(Vec(28.152, 33.605)), module, Random::RANDOM_PARAM, Random::RANDOM_LIGHT)); + addParam(createLightParamCentered>(mm2px(Vec(38.98, 33.605)), module, Random::SHAPE_PARAM, Random::SHAPE_LIGHT)); + addParam(createParamCentered(mm2px(Vec(6.479, 64.347)), module, Random::RATE_CV_PARAM)); + addParam(createParamCentered(mm2px(Vec(17.317, 64.347)), module, Random::PROB_CV_PARAM)); + addParam(createParamCentered(mm2px(Vec(28.154, 64.347)), module, Random::RANDOM_CV_PARAM)); + addParam(createParamCentered(mm2px(Vec(38.991, 64.347)), module, Random::SHAPE_CV_PARAM)); + addParam(createLightParamCentered>>(mm2px(Vec(28.154, 96.859)), module, Random::OFFSET_PARAM, Random::OFFSET_LIGHT)); - addInput(createInputCentered(mm2px(Vec(7.214, 50.726)), module, Random::RATE_INPUT)); - addInput(createInputCentered(mm2px(Vec(18.214, 50.726)), module, Random::SHAPE_INPUT)); - addInput(createInputCentered(mm2px(Vec(7.214, 64.513)), module, Random::TRIGGER_INPUT)); - addInput(createInputCentered(mm2px(Vec(18.214, 64.513)), module, Random::EXTERNAL_INPUT)); + addInput(createInputCentered(mm2px(Vec(6.479, 80.549)), module, Random::RATE_INPUT)); + addInput(createInputCentered(mm2px(Vec(17.317, 80.549)), module, Random::PROB_INPUT)); + addInput(createInputCentered(mm2px(Vec(28.154, 80.553)), module, Random::RANDOM_INPUT)); + addInput(createInputCentered(mm2px(Vec(38.991, 80.557)), module, Random::SHAPE_INPUT)); + addInput(createInputCentered(mm2px(Vec(6.479, 96.859)), module, Random::TRIGGER_INPUT)); + addInput(createInputCentered(mm2px(Vec(17.317, 96.859)), module, Random::EXTERNAL_INPUT)); - addOutput(createOutputCentered(mm2px(Vec(7.214, 96.727)), module, Random::STEPPED_OUTPUT)); - addOutput(createOutputCentered(mm2px(Vec(18.214, 96.727)), module, Random::LINEAR_OUTPUT)); - addOutput(createOutputCentered(mm2px(Vec(7.214, 112.182)), module, Random::SMOOTH_OUTPUT)); - addOutput(createOutputCentered(mm2px(Vec(18.214, 112.182)), module, Random::EXPONENTIAL_OUTPUT)); + addOutput(createOutputCentered(mm2px(Vec(38.991, 96.859)), module, Random::GATE_OUTPUT)); + addOutput(createOutputCentered(mm2px(Vec(6.479, 113.115)), module, Random::STEPPED_OUTPUT)); + addOutput(createOutputCentered(mm2px(Vec(17.317, 113.115)), module, Random::LINEAR_OUTPUT)); + addOutput(createOutputCentered(mm2px(Vec(28.154, 113.115)), module, Random::EXPONENTIAL_OUTPUT)); + addOutput(createOutputCentered(mm2px(Vec(38.991, 113.115)), module, Random::SMOOTH_OUTPUT)); } };