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.

139 lines
5.6KB

  1. #include "plugin.hpp"
  2. using simd::float_4;
  3. struct STMix : Module {
  4. // NOTE: not including auxiliary channel
  5. static const int numMixerChannels = 4;
  6. enum ParamIds {
  7. ENUMS(GAIN_PARAM, numMixerChannels),
  8. NUM_PARAMS
  9. };
  10. enum InputIds {
  11. // +1 for aux
  12. ENUMS(LEFT_INPUT, numMixerChannels + 1),
  13. ENUMS(RIGHT_INPUT, numMixerChannels + 1),
  14. NUM_INPUTS
  15. };
  16. enum OutputIds {
  17. LEFT_OUTPUT,
  18. RIGHT_OUTPUT,
  19. NUM_OUTPUTS
  20. };
  21. enum LightIds {
  22. ENUMS(LEFT_LED, 3),
  23. ENUMS(RIGHT_LED, 3),
  24. NUM_LIGHTS
  25. };
  26. STMix() {
  27. config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS);
  28. for (int i = 0; i < numMixerChannels; ++i) {
  29. configParam(GAIN_PARAM + i, 0.f, 1.f, 0.f, string::f("Gain %d", i + 1));
  30. configInput(LEFT_INPUT + i, string::f("Channel %d left", i + 1));
  31. configInput(RIGHT_INPUT + i, string::f("Channel %d right", i + 1));
  32. }
  33. configInput(LEFT_INPUT + numMixerChannels, "Channel left (aux)");
  34. configInput(RIGHT_INPUT + numMixerChannels, "Channel right (aux)");
  35. configOutput(LEFT_OUTPUT, "Left");
  36. configOutput(RIGHT_OUTPUT, "Right");
  37. }
  38. void process(const ProcessArgs& args) override {
  39. float_4 out_left[4] = {};
  40. float_4 out_right[4] = {};
  41. int numActivePolyphonyEngines = 1;
  42. for (int i = 0; i < numMixerChannels + 1; ++i) {
  43. const int stereoPolyChannels = std::max(inputs[LEFT_INPUT + i].getChannels(),
  44. inputs[RIGHT_INPUT + i].getChannels());
  45. numActivePolyphonyEngines = std::max(numActivePolyphonyEngines, stereoPolyChannels);
  46. }
  47. for (int i = 0; i < numMixerChannels + 1; ++i) {
  48. const float gain = (i < numMixerChannels) ? exponentialBipolar80Pade_5_4(params[GAIN_PARAM + i].getValue()) : 1.f;
  49. for (int c = 0; c < numActivePolyphonyEngines; c += 4) {
  50. const float_4 in_left = inputs[LEFT_INPUT + i].getNormalVoltageSimd<float_4>(0.f, c);
  51. const float_4 in_right = inputs[RIGHT_INPUT + i].getNormalVoltageSimd<float_4>(in_left, c);
  52. out_left[c / 4] += in_left * gain;
  53. out_right[c / 4] += in_right * gain;
  54. }
  55. }
  56. outputs[LEFT_OUTPUT].setChannels(numActivePolyphonyEngines);
  57. outputs[RIGHT_OUTPUT].setChannels(numActivePolyphonyEngines);
  58. for (int c = 0; c < numActivePolyphonyEngines; c += 4) {
  59. outputs[LEFT_OUTPUT].setVoltageSimd(out_left[c / 4], c);
  60. outputs[RIGHT_OUTPUT].setVoltageSimd(out_right[c / 4], c);
  61. }
  62. if (numActivePolyphonyEngines == 1) {
  63. lights[LEFT_LED + 0].setSmoothBrightness(outputs[LEFT_OUTPUT].getVoltage() / 5.f, args.sampleTime);
  64. lights[RIGHT_LED + 0].setSmoothBrightness(outputs[RIGHT_OUTPUT].getVoltage() / 5.f, args.sampleTime);
  65. lights[LEFT_LED + 1].setBrightness(0.f);
  66. lights[RIGHT_LED + 1].setBrightness(0.f);
  67. lights[LEFT_LED + 2].setBrightness(0.f);
  68. lights[RIGHT_LED + 2].setBrightness(0.f);
  69. }
  70. else {
  71. lights[LEFT_LED + 0].setBrightness(0.f);
  72. lights[RIGHT_LED + 0].setBrightness(0.f);
  73. lights[LEFT_LED + 1].setBrightness(0.f);
  74. lights[RIGHT_LED + 1].setBrightness(0.f);
  75. float b_left = 0.f;
  76. float b_right = 0.f;
  77. for (int c = 0; c < numActivePolyphonyEngines; c++) {
  78. b_left += std::pow(out_left[c / 4][c % 4], 2);
  79. b_right += std::pow(out_right[c / 4][c % 4], 2);
  80. }
  81. b_left = std::sqrt(b_left) / 5.f;
  82. b_right = std::sqrt(b_right) / 5.f;
  83. lights[LEFT_LED + 2].setSmoothBrightness(b_left, args.sampleTime);
  84. lights[RIGHT_LED + 2].setSmoothBrightness(b_right, args.sampleTime);
  85. }
  86. }
  87. };
  88. struct STMixWidget : ModuleWidget {
  89. STMixWidget(STMix* module) {
  90. setModule(module);
  91. setPanel(APP->window->loadSvg(asset::plugin(pluginInstance, "res/panels/STMix.svg")));
  92. addChild(createWidget<Knurlie>(Vec(RACK_GRID_WIDTH, 0)));
  93. addChild(createWidget<Knurlie>(Vec(RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH)));
  94. addParam(createParamCentered<Davies1900hWhiteKnob>(mm2px(Vec(21.0, 18.141)), module, STMix::GAIN_PARAM + 0));
  95. addParam(createParamCentered<Davies1900hLightGreyKnob>(mm2px(Vec(21.0, 41.451)), module, STMix::GAIN_PARAM + 1));
  96. addParam(createParamCentered<Davies1900hDarkGreyKnob>(mm2px(Vec(21.0, 64.318)), module, STMix::GAIN_PARAM + 2));
  97. addParam(createParamCentered<Davies1900hDarkBlackAlt>(mm2px(Vec(21.0, 87.124)), module, STMix::GAIN_PARAM + 3));
  98. addInput(createInputCentered<BefacoInputPort>(mm2px(Vec(6.3, 13.108)), module, STMix::LEFT_INPUT + 0));
  99. addInput(createInputCentered<BefacoInputPort>(mm2px(Vec(6.3, 36.175)), module, STMix::LEFT_INPUT + 1));
  100. addInput(createInputCentered<BefacoInputPort>(mm2px(Vec(6.3, 59.243)), module, STMix::LEFT_INPUT + 2));
  101. addInput(createInputCentered<BefacoInputPort>(mm2px(Vec(6.3, 82.311)), module, STMix::LEFT_INPUT + 3));
  102. addInput(createInputCentered<BefacoInputPort>(mm2px(Vec(6.3, 105.378)), module, STMix::LEFT_INPUT + 4));
  103. addInput(createInputCentered<BefacoInputPort>(mm2px(Vec(6.3, 23.108)), module, STMix::RIGHT_INPUT + 0));
  104. addInput(createInputCentered<BefacoInputPort>(mm2px(Vec(6.3, 46.354)), module, STMix::RIGHT_INPUT + 1));
  105. addInput(createInputCentered<BefacoInputPort>(mm2px(Vec(6.3, 69.237)), module, STMix::RIGHT_INPUT + 2));
  106. addInput(createInputCentered<BefacoInputPort>(mm2px(Vec(6.3, 92.132)), module, STMix::RIGHT_INPUT + 3));
  107. addInput(createInputCentered<BefacoInputPort>(mm2px(Vec(6.3, 115.379)), module, STMix::RIGHT_INPUT + 4));
  108. addOutput(createOutputCentered<BefacoOutputPort>(mm2px(Vec(23.8, 105.422)), module, STMix::LEFT_OUTPUT));
  109. addOutput(createOutputCentered<BefacoOutputPort>(mm2px(Vec(23.8, 115.392)), module, STMix::RIGHT_OUTPUT));
  110. addChild(createLightCentered<MediumLight<RedGreenBlueLight>>(mm2px(Vec(16.8, 103.0)), module, STMix::LEFT_LED));
  111. addChild(createLightCentered<MediumLight<RedGreenBlueLight>>(mm2px(Vec(16.8, 113.0)), module, STMix::RIGHT_LED));
  112. }
  113. };
  114. Model* modelSTMix = createModel<STMix, STMixWidget>("STMix");