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