You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

127 lines
4.2KB

  1. #include "plugin.hpp"
  2. using simd::float_4;
  3. struct RandomValues : Module {
  4. enum ParamId {
  5. PUSH_PARAM,
  6. PARAMS_LEN
  7. };
  8. enum InputId {
  9. TRIG_INPUT,
  10. INPUTS_LEN
  11. };
  12. enum OutputId {
  13. ENUMS(RND_OUTPUTS, 7),
  14. OUTPUTS_LEN
  15. };
  16. enum LightId {
  17. PUSH_LIGHT,
  18. LIGHTS_LEN
  19. };
  20. dsp::BooleanTrigger pushTrigger;
  21. dsp::TSchmittTrigger<float_4> trigTriggers[4];
  22. float randomGain = 10.f;
  23. float randomOffset = 0.f;
  24. RandomValues() {
  25. config(PARAMS_LEN, INPUTS_LEN, OUTPUTS_LEN, LIGHTS_LEN);
  26. configButton(PUSH_PARAM, "Push");
  27. configInput(TRIG_INPUT, "Trigger");
  28. for (int i = 0; i < 7; i++)
  29. configOutput(RND_OUTPUTS + i, string::f("Random %d", i + 1));
  30. }
  31. void onReset(const ResetEvent& e) override {
  32. Module::onReset(e);
  33. randomGain = 10.f;
  34. randomOffset = 0.f;
  35. }
  36. void process(const ProcessArgs& args) override {
  37. int channels = std::max(1, inputs[TRIG_INPUT].getChannels());
  38. bool pushed = pushTrigger.process(params[PUSH_PARAM].getValue());
  39. bool light = false;
  40. for (int c = 0; c < channels; c += 4) {
  41. float_4 triggered = trigTriggers[c / 4].process(inputs[TRIG_INPUT].getVoltageSimd<float_4>(c), 0.1f, 1.f);
  42. int triggeredMask = simd::movemask(triggered);
  43. // This branch is infrequent so we don't need to use SIMD.
  44. if (pushed || triggeredMask) {
  45. light = true;
  46. for (int c2 = 0; c2 < std::min(4, channels - c); c2++) {
  47. if (pushed || (triggeredMask & (1 << c2))) {
  48. for (int i = 0; i < 7; i++) {
  49. float r = random::get<float>() * randomGain + randomOffset;
  50. outputs[RND_OUTPUTS + i].setVoltage(r, c + c2);
  51. }
  52. }
  53. }
  54. }
  55. }
  56. for (int i = 0; i < 7; i++) {
  57. outputs[RND_OUTPUTS + i].setChannels(channels);
  58. }
  59. lights[PUSH_LIGHT].setBrightnessSmooth(light, args.sampleTime);
  60. }
  61. json_t* dataToJson() override {
  62. json_t* rootJ = json_object();
  63. json_object_set_new(rootJ, "randomGain", json_real(randomGain));
  64. json_object_set_new(rootJ, "randomOffset", json_real(randomOffset));
  65. return rootJ;
  66. }
  67. void dataFromJson(json_t* rootJ) override {
  68. json_t* randomGainJ = json_object_get(rootJ, "randomGain");
  69. if (randomGainJ)
  70. randomGain = json_number_value(randomGainJ);
  71. json_t* randomOffsetJ = json_object_get(rootJ, "randomOffset");
  72. if (randomOffsetJ)
  73. randomOffset = json_number_value(randomOffsetJ);
  74. }
  75. };
  76. struct RandomValuesWidget : ModuleWidget {
  77. RandomValuesWidget(RandomValues* module) {
  78. setModule(module);
  79. setPanel(createPanel(asset::plugin(pluginInstance, "res/RandomValues.svg"), asset::plugin(pluginInstance, "res/RandomValues-dark.svg")));
  80. addChild(createWidget<ThemedScrew>(Vec(RACK_GRID_WIDTH, 0)));
  81. addChild(createWidget<ThemedScrew>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, 0)));
  82. addChild(createWidget<ThemedScrew>(Vec(RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH)));
  83. addChild(createWidget<ThemedScrew>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH)));
  84. addParam(createLightParamCentered<LEDLightBezel<>>(mm2px(Vec(7.62, 21.968)), module, RandomValues::PUSH_PARAM, RandomValues::PUSH_LIGHT));
  85. addInput(createInputCentered<ThemedPJ301MPort>(mm2px(Vec(7.622, 38.225)), module, RandomValues::TRIG_INPUT));
  86. addOutput(createOutputCentered<ThemedPJ301MPort>(mm2px(Vec(7.622, 52.35)), module, RandomValues::RND_OUTPUTS + 0));
  87. addOutput(createOutputCentered<ThemedPJ301MPort>(mm2px(Vec(7.622, 62.477)), module, RandomValues::RND_OUTPUTS + 1));
  88. addOutput(createOutputCentered<ThemedPJ301MPort>(mm2px(Vec(7.622, 72.605)), module, RandomValues::RND_OUTPUTS + 2));
  89. addOutput(createOutputCentered<ThemedPJ301MPort>(mm2px(Vec(7.622, 82.732)), module, RandomValues::RND_OUTPUTS + 3));
  90. addOutput(createOutputCentered<ThemedPJ301MPort>(mm2px(Vec(7.622, 92.86)), module, RandomValues::RND_OUTPUTS + 4));
  91. addOutput(createOutputCentered<ThemedPJ301MPort>(mm2px(Vec(7.622, 102.987)), module, RandomValues::RND_OUTPUTS + 5));
  92. addOutput(createOutputCentered<ThemedPJ301MPort>(mm2px(Vec(7.622, 113.013)), module, RandomValues::RND_OUTPUTS + 6));
  93. }
  94. void appendContextMenu(Menu* menu) override {
  95. RandomValues* module = getModule<RandomValues>();
  96. menu->addChild(new MenuSeparator);
  97. menu->addChild(createRangeItem("Random range", &module->randomGain, &module->randomOffset));
  98. }
  99. };
  100. Model* modelRandomValues = createModel<RandomValues, RandomValuesWidget>("RandomValues");