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.

135 lines
3.8KB

  1. #include "dsp/digital.hpp"
  2. #include "qwelk.hpp"
  3. #define CHANNELS 4
  4. namespace rack_plugin_Qwelk {
  5. struct ModuleColumn : Module {
  6. enum ParamIds {
  7. PARAM_MASTER,
  8. PARAM_AVG,
  9. PARAM_WEIGHTED,
  10. NUM_PARAMS
  11. };
  12. enum InputIds {
  13. IN_SIG,
  14. IN_UPSTREAM = IN_SIG + CHANNELS,
  15. NUM_INPUTS = IN_UPSTREAM + CHANNELS
  16. };
  17. enum OutputIds {
  18. OUT_SIDE,
  19. OUT_DOWNSTREAM = OUT_SIDE + CHANNELS,
  20. NUM_OUTPUTS = OUT_DOWNSTREAM + CHANNELS
  21. };
  22. enum LightIds {
  23. NUM_LIGHTS
  24. };
  25. bool allow_neg_weights = false;
  26. ModuleColumn() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) {}
  27. void step() override;
  28. };
  29. void ModuleColumn::step()
  30. {
  31. bool avg = params[PARAM_AVG].value == 0.0;
  32. bool weighted = params[PARAM_WEIGHTED].value == 0.0;
  33. float total = 0;
  34. float on_count = 0;
  35. for (int i = 0; i < CHANNELS; ++i) {
  36. float in_upstream = inputs[IN_UPSTREAM + i].value;
  37. float in_sig = inputs[IN_SIG + i].value;
  38. // just forward the input signal as the side stream,
  39. // used for chaining multiple Columns together
  40. outputs[OUT_SIDE + i].value = in_sig;
  41. if (inputs[IN_UPSTREAM + i].active) {
  42. if (weighted)
  43. on_count += allow_neg_weights ? in_upstream : fabs(in_upstream);
  44. else if (in_upstream != 0.0)
  45. on_count += 1;
  46. }
  47. if (!weighted && in_sig != 0.0)
  48. on_count += 1;
  49. float product = weighted ? (in_upstream * in_sig) : (in_upstream + in_sig);
  50. total += product;
  51. outputs[OUT_DOWNSTREAM + i].value = avg ? ((on_count != 0) ? (total / on_count) : 0) : (total);
  52. }
  53. }
  54. struct WidgetColumn : ModuleWidget {
  55. WidgetColumn(ModuleColumn *module);
  56. Menu *createContextMenu() override;
  57. };
  58. WidgetColumn::WidgetColumn(ModuleColumn *module) : ModuleWidget(module) {
  59. setPanel(SVG::load(assetPlugin(plugin, "res/Column.svg")));
  60. addChild(Widget::create<ScrewSilver>(Vec(15, 0)));
  61. addChild(Widget::create<ScrewSilver>(Vec(15, 365)));
  62. addParam(ParamWidget::create<CKSS>(Vec(3.5, 30), module, ModuleColumn::PARAM_AVG, 0.0, 1.0, 1.0));
  63. addParam(ParamWidget::create<CKSS>(Vec(42, 30), module, ModuleColumn::PARAM_WEIGHTED, 0.0, 1.0, 1.0));
  64. float x = 2.5, xstep = 15, ystep = 23.5;
  65. for (int i = 0; i < CHANNELS; ++i)
  66. {
  67. float y = 80 + i * 80;
  68. addInput(Port::create<PJ301MPort>(Vec(x + xstep, y - ystep), Port::INPUT, module, ModuleColumn::IN_UPSTREAM + i));
  69. addOutput(Port::create<PJ301MPort>(Vec(x + xstep*2, y), Port::OUTPUT, module, ModuleColumn::OUT_SIDE + i));
  70. addInput(Port::create<PJ301MPort>(Vec(x, y), Port::INPUT, module, ModuleColumn::IN_SIG + i));
  71. addOutput(Port::create<PJ301MPort>(Vec(x + xstep, y + ystep), Port::OUTPUT, module, ModuleColumn::OUT_DOWNSTREAM + i));
  72. }
  73. }
  74. struct MenuItemAllowNegWeights : MenuItem {
  75. ModuleColumn *col;
  76. void onAction(EventAction &e) override
  77. {
  78. col->allow_neg_weights ^= true;
  79. }
  80. void step () override
  81. {
  82. rightText = (col->allow_neg_weights) ? "✔" : "";
  83. }
  84. };
  85. Menu *WidgetColumn::createContextMenu()
  86. {
  87. Menu *menu = ModuleWidget::createContextMenu();
  88. MenuLabel *spacer = new MenuLabel();
  89. menu->addChild(spacer);
  90. ModuleColumn *column = dynamic_cast<ModuleColumn *>(module);
  91. assert(column);
  92. MenuItemAllowNegWeights *item = new MenuItemAllowNegWeights();
  93. item->text = "Allow Negative Weights";
  94. item->col = column;
  95. menu->addChild(item);
  96. return menu;
  97. }
  98. } // namespace rack_plugin_Qwelk
  99. using namespace rack_plugin_Qwelk;
  100. RACK_PLUGIN_MODEL_INIT(Qwelk, Column) {
  101. Model *modelColumn = Model::create<ModuleColumn, WidgetColumn>(
  102. TOSTRING(SLUG), "Column", "Column", MIXER_TAG);
  103. return modelColumn;
  104. }