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 @@
-
-
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 @@
-
-
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));
}
};