@@ -24,16 +24,8 @@ struct RandomValues : Module { | |||
dsp::BooleanTrigger pushTrigger; | |||
dsp::TSchmittTrigger<float_4> trigTriggers[4]; | |||
struct Range { | |||
float gain; | |||
float offset; | |||
bool operator==(const Range& other) const { | |||
return gain == other.gain && offset == other.offset; | |||
} | |||
}; | |||
Range range = {10.f, 0.f}; | |||
float randomGain = 10.f; | |||
float randomOffset = 0.f; | |||
RandomValues() { | |||
config(PARAMS_LEN, INPUTS_LEN, OUTPUTS_LEN, LIGHTS_LEN); | |||
@@ -45,7 +37,8 @@ struct RandomValues : Module { | |||
void onReset(const ResetEvent& e) override { | |||
Module::onReset(e); | |||
range = {10.f, 0.f}; | |||
randomGain = 10.f; | |||
randomOffset = 0.f; | |||
} | |||
void process(const ProcessArgs& args) override { | |||
@@ -65,8 +58,7 @@ struct RandomValues : Module { | |||
for (int c2 = 0; c2 < std::min(4, channels - c); c2++) { | |||
if (pushed || (triggeredMask & (1 << c2))) { | |||
for (int i = 0; i < 7; i++) { | |||
float r = random::get<float>(); | |||
r = r * range.gain + range.offset; | |||
float r = random::get<float>() * randomGain + randomOffset; | |||
outputs[RND_OUTPUTS + i].setVoltage(r, c + c2); | |||
} | |||
} | |||
@@ -82,19 +74,19 @@ struct RandomValues : Module { | |||
json_t* dataToJson() override { | |||
json_t* rootJ = json_object(); | |||
json_object_set_new(rootJ, "gain", json_real(range.gain)); | |||
json_object_set_new(rootJ, "offset", json_real(range.offset)); | |||
json_object_set_new(rootJ, "randomGain", json_real(randomGain)); | |||
json_object_set_new(rootJ, "randomOffset", json_real(randomOffset)); | |||
return rootJ; | |||
} | |||
void dataFromJson(json_t* rootJ) override { | |||
json_t* gainJ = json_object_get(rootJ, "gain"); | |||
if (gainJ) | |||
range.gain = json_number_value(gainJ); | |||
json_t* randomGainJ = json_object_get(rootJ, "randomGain"); | |||
if (randomGainJ) | |||
randomGain = json_number_value(randomGainJ); | |||
json_t* offsetJ = json_object_get(rootJ, "offset"); | |||
if (offsetJ) | |||
range.offset = json_number_value(offsetJ); | |||
json_t* randomOffsetJ = json_object_get(rootJ, "randomOffset"); | |||
if (randomOffsetJ) | |||
randomOffset = json_number_value(randomOffsetJ); | |||
} | |||
}; | |||
@@ -127,31 +119,7 @@ struct RandomValuesWidget : ModuleWidget { | |||
menu->addChild(new MenuSeparator); | |||
static const std::vector<RandomValues::Range> ranges = { | |||
{10.f, 0.f}, | |||
{5.f, 0.f}, | |||
{1.f, 0.f}, | |||
{20.f, -10.f}, | |||
{10.f, -5.f}, | |||
{2.f, -1.f}, | |||
}; | |||
static const std::vector<std::string> labels = { | |||
"0V to 10V", | |||
"0V to 5V", | |||
"0V to 1V", | |||
"-10V to 10V", | |||
"-5V to 5V", | |||
"-1V to 1V", | |||
}; | |||
menu->addChild(createIndexSubmenuItem("Voltage range", labels, | |||
[=]() { | |||
auto it = std::find(ranges.begin(), ranges.end(), module->range); | |||
return std::distance(ranges.begin(), it); | |||
}, | |||
[=](int i) { | |||
module->range = ranges[i]; | |||
} | |||
)); | |||
menu->addChild(createRangeItem("Random range", &module->randomGain, &module->randomOffset)); | |||
} | |||
}; | |||
@@ -28,6 +28,8 @@ struct SHASR : Module { | |||
dsp::BooleanTrigger clearTrigger; | |||
dsp::SchmittTrigger triggers[8]; | |||
float values[8] = {}; | |||
float randomGain = 10.f; | |||
float randomOffset = 0.f; | |||
SHASR() { | |||
config(PARAMS_LEN, INPUTS_LEN, OUTPUTS_LEN, LIGHTS_LEN); | |||
@@ -47,6 +49,8 @@ struct SHASR : Module { | |||
for (int i = 0; i < 8; i++) { | |||
values[i] = 0.f; | |||
} | |||
randomGain = 10.f; | |||
randomOffset = 0.f; | |||
Module::onReset(e); | |||
} | |||
@@ -61,9 +65,11 @@ struct SHASR : Module { | |||
lastTrig = triggers[i].process(inputs[TRIG_INPUTS + i].getVoltage(), 0.1f, 1.f); | |||
} | |||
if (lastTrig) { | |||
float sample; | |||
float sample = 0.f; | |||
if (i == 0) { | |||
sample = randomize ? random::uniform() * 10.f : 0.f; | |||
if (randomize) { | |||
sample = random::get<float>() * randomGain + randomOffset; | |||
} | |||
} | |||
else { | |||
sample = outputs[SH_OUTPUTS + i - 1].getVoltage(); | |||
@@ -84,6 +90,40 @@ struct SHASR : Module { | |||
lights[PUSH_LIGHT].setBrightnessSmooth(push * 2.f, args.sampleTime); | |||
lights[CLEAR_LIGHT].setBrightnessSmooth(clear * 2.f, args.sampleTime); | |||
} | |||
json_t* dataToJson() override { | |||
json_t* rootJ = json_object(); | |||
json_t* valuesJ = json_array(); | |||
for (int i = 0; i < 8; i++) { | |||
json_array_insert_new(valuesJ, i, json_real(values[i])); | |||
} | |||
json_object_set_new(rootJ, "values", valuesJ); | |||
json_object_set_new(rootJ, "randomGain", json_real(randomGain)); | |||
json_object_set_new(rootJ, "randomOffset", json_real(randomOffset)); | |||
return rootJ; | |||
} | |||
void dataFromJson(json_t* rootJ) override { | |||
json_t* valuesJ = json_object_get(rootJ, "values"); | |||
if (valuesJ) { | |||
for (int i = 0; i < 8; i++) { | |||
json_t* valueJ = json_array_get(valuesJ, i); | |||
if (valueJ) | |||
values[i] = json_number_value(valueJ); | |||
} | |||
} | |||
json_t* randomGainJ = json_object_get(rootJ, "randomGain"); | |||
if (randomGainJ) | |||
randomGain = json_number_value(randomGainJ); | |||
json_t* randomOffsetJ = json_object_get(rootJ, "randomOffset"); | |||
if (randomOffsetJ) | |||
randomOffset = json_number_value(randomOffsetJ); | |||
} | |||
}; | |||
@@ -127,6 +167,14 @@ struct SHASRWidget : ModuleWidget { | |||
addOutput(createOutputCentered<ThemedPJ301MPort>(mm2px(Vec(28.6, 102.878)), module, SHASR::SH_OUTPUTS + 6)); | |||
addOutput(createOutputCentered<ThemedPJ301MPort>(mm2px(Vec(28.6, 113.005)), module, SHASR::SH_OUTPUTS + 7)); | |||
} | |||
void appendContextMenu(Menu* menu) override { | |||
SHASR* module = getModule<SHASR>(); | |||
menu->addChild(new MenuSeparator); | |||
menu->addChild(createRangeItem("Random range", &module->randomGain, &module->randomOffset)); | |||
} | |||
}; | |||
@@ -46,3 +46,43 @@ void init(Plugin* p) { | |||
p->addModel(modelPush); | |||
p->addModel(modelSHASR); | |||
} | |||
MenuItem* createRangeItem(std::string label, float* gain, float* offset) { | |||
struct Range { | |||
float gain; | |||
float offset; | |||
bool operator==(const Range& other) const { | |||
return gain == other.gain && offset == other.offset; | |||
} | |||
}; | |||
static const std::vector<Range> ranges = { | |||
{10.f, 0.f}, | |||
{5.f, 0.f}, | |||
{1.f, 0.f}, | |||
{20.f, -10.f}, | |||
{10.f, -5.f}, | |||
{2.f, -1.f}, | |||
}; | |||
static const std::vector<std::string> labels = { | |||
"0V to 10V", | |||
"0V to 5V", | |||
"0V to 1V", | |||
"-10V to 10V", | |||
"-5V to 5V", | |||
"-1V to 1V", | |||
}; | |||
return createIndexSubmenuItem(label, labels, | |||
[=]() { | |||
auto it = std::find(ranges.begin(), ranges.end(), Range{*gain, *offset}); | |||
return std::distance(ranges.begin(), it); | |||
}, | |||
[=](int i) { | |||
*gain = ranges[i].gain; | |||
*offset = ranges[i].offset; | |||
} | |||
); | |||
} |
@@ -138,3 +138,6 @@ struct VCVBezelLightBig : TBase { | |||
this->box.size = mm2px(math::Vec(11.1936, 11.1936)); | |||
} | |||
}; | |||
MenuItem* createRangeItem(std::string label, float* gain, float* offset); |