@@ -24,16 +24,8 @@ struct RandomValues : Module { | |||||
dsp::BooleanTrigger pushTrigger; | dsp::BooleanTrigger pushTrigger; | ||||
dsp::TSchmittTrigger<float_4> trigTriggers[4]; | 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() { | RandomValues() { | ||||
config(PARAMS_LEN, INPUTS_LEN, OUTPUTS_LEN, LIGHTS_LEN); | config(PARAMS_LEN, INPUTS_LEN, OUTPUTS_LEN, LIGHTS_LEN); | ||||
@@ -45,7 +37,8 @@ struct RandomValues : Module { | |||||
void onReset(const ResetEvent& e) override { | void onReset(const ResetEvent& e) override { | ||||
Module::onReset(e); | Module::onReset(e); | ||||
range = {10.f, 0.f}; | |||||
randomGain = 10.f; | |||||
randomOffset = 0.f; | |||||
} | } | ||||
void process(const ProcessArgs& args) override { | void process(const ProcessArgs& args) override { | ||||
@@ -65,8 +58,7 @@ struct RandomValues : Module { | |||||
for (int c2 = 0; c2 < std::min(4, channels - c); c2++) { | for (int c2 = 0; c2 < std::min(4, channels - c); c2++) { | ||||
if (pushed || (triggeredMask & (1 << c2))) { | if (pushed || (triggeredMask & (1 << c2))) { | ||||
for (int i = 0; i < 7; i++) { | 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); | outputs[RND_OUTPUTS + i].setVoltage(r, c + c2); | ||||
} | } | ||||
} | } | ||||
@@ -82,19 +74,19 @@ struct RandomValues : Module { | |||||
json_t* dataToJson() override { | json_t* dataToJson() override { | ||||
json_t* rootJ = json_object(); | 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; | return rootJ; | ||||
} | } | ||||
void dataFromJson(json_t* rootJ) override { | 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); | 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::BooleanTrigger clearTrigger; | ||||
dsp::SchmittTrigger triggers[8]; | dsp::SchmittTrigger triggers[8]; | ||||
float values[8] = {}; | float values[8] = {}; | ||||
float randomGain = 10.f; | |||||
float randomOffset = 0.f; | |||||
SHASR() { | SHASR() { | ||||
config(PARAMS_LEN, INPUTS_LEN, OUTPUTS_LEN, LIGHTS_LEN); | config(PARAMS_LEN, INPUTS_LEN, OUTPUTS_LEN, LIGHTS_LEN); | ||||
@@ -47,6 +49,8 @@ struct SHASR : Module { | |||||
for (int i = 0; i < 8; i++) { | for (int i = 0; i < 8; i++) { | ||||
values[i] = 0.f; | values[i] = 0.f; | ||||
} | } | ||||
randomGain = 10.f; | |||||
randomOffset = 0.f; | |||||
Module::onReset(e); | Module::onReset(e); | ||||
} | } | ||||
@@ -61,9 +65,11 @@ struct SHASR : Module { | |||||
lastTrig = triggers[i].process(inputs[TRIG_INPUTS + i].getVoltage(), 0.1f, 1.f); | lastTrig = triggers[i].process(inputs[TRIG_INPUTS + i].getVoltage(), 0.1f, 1.f); | ||||
} | } | ||||
if (lastTrig) { | if (lastTrig) { | ||||
float sample; | |||||
float sample = 0.f; | |||||
if (i == 0) { | if (i == 0) { | ||||
sample = randomize ? random::uniform() * 10.f : 0.f; | |||||
if (randomize) { | |||||
sample = random::get<float>() * randomGain + randomOffset; | |||||
} | |||||
} | } | ||||
else { | else { | ||||
sample = outputs[SH_OUTPUTS + i - 1].getVoltage(); | sample = outputs[SH_OUTPUTS + i - 1].getVoltage(); | ||||
@@ -84,6 +90,40 @@ struct SHASR : Module { | |||||
lights[PUSH_LIGHT].setBrightnessSmooth(push * 2.f, args.sampleTime); | lights[PUSH_LIGHT].setBrightnessSmooth(push * 2.f, args.sampleTime); | ||||
lights[CLEAR_LIGHT].setBrightnessSmooth(clear * 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, 102.878)), module, SHASR::SH_OUTPUTS + 6)); | ||||
addOutput(createOutputCentered<ThemedPJ301MPort>(mm2px(Vec(28.6, 113.005)), module, SHASR::SH_OUTPUTS + 7)); | 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(modelPush); | ||||
p->addModel(modelSHASR); | 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)); | this->box.size = mm2px(math::Vec(11.1936, 11.1936)); | ||||
} | } | ||||
}; | }; | ||||
MenuItem* createRangeItem(std::string label, float* gain, float* offset); |