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.

105 lines
4.4KB

  1. ////////////////////////////////////////////////////////////////////////////////////////////////////
  2. ////// Splitter 1x9 ///
  3. ////// 2 HP module, having 1 input sent "splitted" to 9 outputs, but limited voltages must stay ///
  4. ////// in -11.7V/+11.7V bounds to every output ("hard clipping"). ///
  5. ////////////////////////////////////////////////////////////////////////////////////////////////////
  6. #include "Ohmer.hpp"
  7. namespace rack_plugin_Ohmer {
  8. struct Splitter1x9Module : Module {
  9. enum ParamIds {
  10. NUM_PARAMS
  11. };
  12. enum InputIds {
  13. MAIN_INPUT,
  14. NUM_INPUTS
  15. };
  16. enum OutputIds {
  17. OUTPUT_1,
  18. OUTPUT_2,
  19. OUTPUT_3,
  20. OUTPUT_4,
  21. OUTPUT_5,
  22. OUTPUT_6,
  23. OUTPUT_7,
  24. OUTPUT_8,
  25. OUTPUT_9,
  26. NUM_OUTPUTS
  27. };
  28. enum LightIds {
  29. LED_CLIP,
  30. NUM_LIGHTS
  31. };
  32. // Counter used for red LED afterglow (used together with "ledClipAfterglow" boolean flag).
  33. unsigned long ledClipDelay = 0; // long type is required for highest engine samplerates!
  34. // This flag controls red LED afterglow (active or not).
  35. bool ledClipAfterglow = false;
  36. Splitter1x9Module() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) {}
  37. void step() override;
  38. };
  39. void Splitter1x9Module::step() {
  40. // Consider an incoming voltage on input port...
  41. //
  42. float raw_input_voltage = inputs[MAIN_INPUT].value;
  43. float splitted_out_voltage = clamp(raw_input_voltage, -11.7f, 11.7f); // These -11.7V/+11.7V limits are max. possible voltage on Eurorack.
  44. if (!ledClipAfterglow && (raw_input_voltage != splitted_out_voltage)) {
  45. // Different is meaning... the voltage was clipped: turn on the LED (reset its afterglow counter).
  46. ledClipDelay = 0;
  47. ledClipAfterglow = true;
  48. }
  49. for (int i=OUTPUT_1; i<NUM_OUTPUTS; i++) {
  50. // ...then transmit the same voltage to all output ports, but "clip" the voltage first if it's out of bounds if necessary!
  51. outputs[i].value = splitted_out_voltage;
  52. }
  53. // Afterglow for red LED.
  54. if (ledClipAfterglow && (ledClipDelay < round(engineGetSampleRate() / 3)))
  55. ledClipDelay++;
  56. else {
  57. ledClipAfterglow = false;
  58. ledClipDelay = 0;
  59. }
  60. // Lit or unlit LED (depending "ledClipAfterglow" flag).
  61. lights[LED_CLIP].value = ledClipAfterglow ? 1.0 : 0.0f;
  62. }
  63. struct Splitter1x9Widget : ModuleWidget {
  64. Splitter1x9Widget(Splitter1x9Module *module);
  65. };
  66. Splitter1x9Widget::Splitter1x9Widget(Splitter1x9Module *module) : ModuleWidget(module) {
  67. setPanel(SVG::load(assetPlugin(plugin, "res/Splitter1x9.svg")));
  68. // Using four screws configuration (even for 2 HP module), due to mechanical constraints on connectors, and by the way, on this small plate :-)
  69. addChild(Widget::create<Torx_Silver>(Vec(0, 0)));
  70. addChild(Widget::create<Torx_Silver>(Vec(box.size.x - RACK_GRID_WIDTH, 0)));
  71. addChild(Widget::create<Torx_Silver>(Vec(0, RACK_GRID_HEIGHT - RACK_GRID_WIDTH)));
  72. addChild(Widget::create<Torx_Silver>(Vec(box.size.x - RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH)));
  73. // Input port.
  74. addInput(Port::create<PJ301M_In>(Vec(2.5, 22), Port::INPUT, module, Splitter1x9Module::MAIN_INPUT));
  75. // Output ports.
  76. addOutput(Port::create<PJ301M_Out>(Vec(2.5, 70), Port::OUTPUT, module, Splitter1x9Module::OUTPUT_1));
  77. addOutput(Port::create<PJ301M_Out>(Vec(2.5, 100), Port::OUTPUT, module, Splitter1x9Module::OUTPUT_2));
  78. addOutput(Port::create<PJ301M_Out>(Vec(2.5, 130), Port::OUTPUT, module, Splitter1x9Module::OUTPUT_3));
  79. addOutput(Port::create<PJ301M_Out>(Vec(2.5, 160), Port::OUTPUT, module, Splitter1x9Module::OUTPUT_4));
  80. addOutput(Port::create<PJ301M_Out>(Vec(2.5, 190), Port::OUTPUT, module, Splitter1x9Module::OUTPUT_5));
  81. addOutput(Port::create<PJ301M_Out>(Vec(2.5, 220), Port::OUTPUT, module, Splitter1x9Module::OUTPUT_6));
  82. addOutput(Port::create<PJ301M_Out>(Vec(2.5, 250), Port::OUTPUT, module, Splitter1x9Module::OUTPUT_7));
  83. addOutput(Port::create<PJ301M_Out>(Vec(2.5, 280), Port::OUTPUT, module, Splitter1x9Module::OUTPUT_8));
  84. addOutput(Port::create<PJ301M_Out>(Vec(3, 310), Port::OUTPUT, module, Splitter1x9Module::OUTPUT_9));
  85. // Clipping red LED.
  86. addChild(ModuleLightWidget::create<MediumLight<RedLight>>(Vec(18, 47), module, Splitter1x9Module::LED_CLIP));
  87. }
  88. } // namespace rack_plugin_Ohmer
  89. using namespace rack_plugin_Ohmer;
  90. RACK_PLUGIN_MODEL_INIT(Ohmer, Splitter1x9) {
  91. Model *modelSplitter1x9 = Model::create<Splitter1x9Module, Splitter1x9Widget>("Ohmer Modules", "SplitterModule", "Splitter 1x9", MULTIPLE_TAG, UTILITY_TAG);
  92. return modelSplitter1x9;
  93. }