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.

165 lines
6.2KB

  1. #include "plugin.hpp"
  2. struct Unity : Module {
  3. enum ParamIds {
  4. AVG1_PARAM,
  5. AVG2_PARAM,
  6. NUM_PARAMS
  7. };
  8. enum InputIds {
  9. ENUMS(IN_INPUTS, 2 * 6),
  10. NUM_INPUTS
  11. };
  12. enum OutputIds {
  13. MIX1_OUTPUT,
  14. INV1_OUTPUT,
  15. MIX2_OUTPUT,
  16. INV2_OUTPUT,
  17. NUM_OUTPUTS
  18. };
  19. enum LightIds {
  20. ENUMS(VU_LIGHTS, 2 * 5),
  21. NUM_LIGHTS
  22. };
  23. bool merge = false;
  24. dsp::VuMeter2 vuMeters[2];
  25. dsp::ClockDivider lightDivider;
  26. Unity() {
  27. config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS);
  28. configSwitch(AVG1_PARAM, 0.0, 1.0, 0.0, "Channel 1 mode", {"Sum", "Average"});
  29. configSwitch(AVG2_PARAM, 0.0, 1.0, 0.0, "Channel 2 mode", {"Sum", "Average"});
  30. for (int i = 0; i < 2; i++) {
  31. for (int j = 0; j < 6; j++) {
  32. configInput(IN_INPUTS + i * 6 + j, string::f("Channel %d #%d", i + 1, j + 1));
  33. }
  34. }
  35. configOutput(MIX1_OUTPUT, "Channel 1 mix");
  36. configOutput(INV1_OUTPUT, "Channel 1 inverse mix");
  37. configOutput(MIX2_OUTPUT, "Channel 2 mix");
  38. configOutput(INV2_OUTPUT, "Channel 2 inverse mix");
  39. lightDivider.setDivision(256);
  40. }
  41. void process(const ProcessArgs& args) override {
  42. float mix[2] = {};
  43. int count[2] = {};
  44. for (int i = 0; i < 2; i++) {
  45. // Inputs
  46. for (int j = 0; j < 6; j++) {
  47. mix[i] += inputs[IN_INPUTS + 6 * i + j].getVoltage();
  48. if (inputs[IN_INPUTS + 6 * i + j].isConnected())
  49. count[i]++;
  50. }
  51. }
  52. // Combine
  53. if (merge) {
  54. mix[0] += mix[1];
  55. mix[1] = mix[0];
  56. count[0] += count[1];
  57. count[1] = count[0];
  58. }
  59. for (int i = 0; i < 2; i++) {
  60. // Params
  61. if (count[i] > 0 && (int) std::round(params[AVG1_PARAM + i].getValue()) == 1)
  62. mix[i] /= count[i];
  63. // Outputs
  64. outputs[MIX1_OUTPUT + 2 * i].setVoltage(mix[i]);
  65. outputs[INV1_OUTPUT + 2 * i].setVoltage(-mix[i]);
  66. vuMeters[i].process(args.sampleTime, mix[i] / 10.f);
  67. }
  68. if (lightDivider.process()) {
  69. // Lights
  70. for (int i = 0; i < 2; i++) {
  71. lights[VU_LIGHTS + 5 * i + 0].setBrightness(vuMeters[i].getBrightness(0.f, 0.f));
  72. for (int j = 1; j < 5; j++) {
  73. lights[VU_LIGHTS + 5 * i + j].setBrightness(vuMeters[i].getBrightness(-6.f * (j + 1), -6.f * j));
  74. }
  75. }
  76. }
  77. }
  78. void onReset() override {
  79. merge = false;
  80. }
  81. json_t* dataToJson() override {
  82. json_t* rootJ = json_object();
  83. // merge
  84. json_object_set_new(rootJ, "merge", json_boolean(merge));
  85. return rootJ;
  86. }
  87. void dataFromJson(json_t* rootJ) override {
  88. // merge
  89. json_t* mergeJ = json_object_get(rootJ, "merge");
  90. if (mergeJ)
  91. merge = json_boolean_value(mergeJ);
  92. }
  93. };
  94. struct UnityWidget : ModuleWidget {
  95. UnityWidget(Unity* module) {
  96. setModule(module);
  97. setPanel(createPanel(asset::plugin(pluginInstance, "res/Unity.svg"), asset::plugin(pluginInstance, "res/Unity-dark.svg")));
  98. addChild(createWidget<ThemedScrew>(Vec(15, 0)));
  99. addChild(createWidget<ThemedScrew>(Vec(box.size.x - 30, 0)));
  100. addChild(createWidget<ThemedScrew>(Vec(15, 365)));
  101. addChild(createWidget<ThemedScrew>(Vec(box.size.x - 30, 365)));
  102. addParam(createParam<CKSS>(mm2px(Vec(12.867, 52.961)), module, Unity::AVG1_PARAM));
  103. addParam(createParam<CKSS>(mm2px(Vec(12.867, 107.006)), module, Unity::AVG2_PARAM));
  104. addInput(createInput<ThemedPJ301MPort>(mm2px(Vec(2.361, 17.144)), module, Unity::IN_INPUTS + 0 * 6 + 0));
  105. addInput(createInput<ThemedPJ301MPort>(mm2px(Vec(19.907, 17.144)), module, Unity::IN_INPUTS + 0 * 6 + 1));
  106. addInput(createInput<ThemedPJ301MPort>(mm2px(Vec(2.361, 28.145)), module, Unity::IN_INPUTS + 0 * 6 + 2));
  107. addInput(createInput<ThemedPJ301MPort>(mm2px(Vec(19.907, 28.145)), module, Unity::IN_INPUTS + 0 * 6 + 3));
  108. addInput(createInput<ThemedPJ301MPort>(mm2px(Vec(2.361, 39.145)), module, Unity::IN_INPUTS + 0 * 6 + 4));
  109. addInput(createInput<ThemedPJ301MPort>(mm2px(Vec(19.907, 39.145)), module, Unity::IN_INPUTS + 0 * 6 + 5));
  110. addInput(createInput<ThemedPJ301MPort>(mm2px(Vec(2.361, 71.145)), module, Unity::IN_INPUTS + 1 * 6 + 0));
  111. addInput(createInput<ThemedPJ301MPort>(mm2px(Vec(19.907, 71.145)), module, Unity::IN_INPUTS + 1 * 6 + 1));
  112. addInput(createInput<ThemedPJ301MPort>(mm2px(Vec(2.361, 82.145)), module, Unity::IN_INPUTS + 1 * 6 + 2));
  113. addInput(createInput<ThemedPJ301MPort>(mm2px(Vec(19.907, 82.145)), module, Unity::IN_INPUTS + 1 * 6 + 3));
  114. addInput(createInput<ThemedPJ301MPort>(mm2px(Vec(2.361, 93.144)), module, Unity::IN_INPUTS + 1 * 6 + 4));
  115. addInput(createInput<ThemedPJ301MPort>(mm2px(Vec(19.907, 93.144)), module, Unity::IN_INPUTS + 1 * 6 + 5));
  116. addOutput(createOutput<ThemedPJ301MPort>(mm2px(Vec(2.361, 54.15)), module, Unity::MIX1_OUTPUT));
  117. addOutput(createOutput<ThemedPJ301MPort>(mm2px(Vec(19.907, 54.15)), module, Unity::INV1_OUTPUT));
  118. addOutput(createOutput<ThemedPJ301MPort>(mm2px(Vec(2.361, 108.144)), module, Unity::MIX2_OUTPUT));
  119. addOutput(createOutput<ThemedPJ301MPort>(mm2px(Vec(19.907, 108.144)), module, Unity::INV2_OUTPUT));
  120. addChild(createLight<MediumLight<RedLight>>(mm2px(Vec(13.652, 19.663)), module, Unity::VU_LIGHTS + 0 * 5 + 0));
  121. addChild(createLight<MediumLight<YellowLight>>(mm2px(Vec(13.652, 25.163)), module, Unity::VU_LIGHTS + 0 * 5 + 1));
  122. addChild(createLight<MediumLight<GreenLight>>(mm2px(Vec(13.652, 30.663)), module, Unity::VU_LIGHTS + 0 * 5 + 2));
  123. addChild(createLight<MediumLight<GreenLight>>(mm2px(Vec(13.652, 36.162)), module, Unity::VU_LIGHTS + 0 * 5 + 3));
  124. addChild(createLight<MediumLight<GreenLight>>(mm2px(Vec(13.652, 41.662)), module, Unity::VU_LIGHTS + 0 * 5 + 4));
  125. addChild(createLight<MediumLight<RedLight>>(mm2px(Vec(13.652, 73.663)), module, Unity::VU_LIGHTS + 1 * 5 + 0));
  126. addChild(createLight<MediumLight<YellowLight>>(mm2px(Vec(13.652, 79.163)), module, Unity::VU_LIGHTS + 1 * 5 + 1));
  127. addChild(createLight<MediumLight<GreenLight>>(mm2px(Vec(13.652, 84.663)), module, Unity::VU_LIGHTS + 1 * 5 + 2));
  128. addChild(createLight<MediumLight<GreenLight>>(mm2px(Vec(13.652, 90.162)), module, Unity::VU_LIGHTS + 1 * 5 + 3));
  129. addChild(createLight<MediumLight<GreenLight>>(mm2px(Vec(13.652, 95.662)), module, Unity::VU_LIGHTS + 1 * 5 + 4));
  130. }
  131. void appendContextMenu(Menu* menu) override {
  132. Unity* module = dynamic_cast<Unity*>(this->module);
  133. assert(module);
  134. menu->addChild(new MenuSeparator);
  135. menu->addChild(createBoolPtrMenuItem("Merge channels 1 & 2", "", &module->merge));
  136. }
  137. };
  138. Model* modelUnity = createModel<Unity, UnityWidget>("Unity");