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.

164 lines
4.9KB

  1. #include "plugin.hpp"
  2. #define MAX(a,b) (a>b)?a:b
  3. #define MIN(a,b) (a<b)?a:b
  4. struct Mixer : Module {
  5. enum ParamIds {
  6. CH1_PARAM,
  7. CH2_PARAM,
  8. CH3_PARAM,
  9. CH4_PARAM,
  10. NUM_PARAMS
  11. };
  12. enum InputIds {
  13. IN1_INPUT,
  14. IN2_INPUT,
  15. IN3_INPUT,
  16. IN4_INPUT,
  17. NUM_INPUTS
  18. };
  19. enum OutputIds {
  20. OUT1_OUTPUT,
  21. OUT2_OUTPUT,
  22. NUM_OUTPUTS
  23. };
  24. enum LightIds {
  25. OUT_POS_LIGHT,
  26. OUT_NEG_LIGHT,
  27. NUM_LIGHTS
  28. };
  29. simd::float_4 mask[4];
  30. simd::float_4 minus_one;
  31. Mixer() {
  32. config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS);
  33. configParam(CH1_PARAM, 0.0, 1.0, 0.0, "Ch 1 level", "%", 0, 100);
  34. configParam(CH2_PARAM, 0.0, 1.0, 0.0, "Ch 2 level", "%", 0, 100);
  35. configParam(CH3_PARAM, 0.0, 1.0, 0.0, "Ch 3 level", "%", 0, 100);
  36. configParam(CH4_PARAM, 0.0, 1.0, 0.0, "Ch 4 level", "%", 0, 100);
  37. minus_one = simd::float_4(-1.0f);
  38. __m128i tmp = _mm_cmpeq_epi16(_mm_set_epi32(0,0,0,0),_mm_set_epi32(0,0,0,0));
  39. for(int i=0; i<4; i++) {
  40. mask[3-i] = simd::float_4(_mm_castsi128_ps(tmp));
  41. tmp = _mm_srli_si128(tmp, 4);
  42. }
  43. }
  44. void process(const ProcessArgs &args) override {
  45. int i;
  46. int channels1 = inputs[IN1_INPUT].getChannels();
  47. int channels2 = inputs[IN2_INPUT].getChannels();
  48. int channels3 = inputs[IN3_INPUT].getChannels();
  49. int channels4 = inputs[IN4_INPUT].getChannels();
  50. int out_channels = 1;
  51. out_channels = MAX(out_channels, channels1);
  52. out_channels = MAX(out_channels, channels2);
  53. out_channels = MAX(out_channels, channels3);
  54. out_channels = MAX(out_channels, channels4);
  55. simd::float_4 mult1 = simd::float_4(params[CH1_PARAM].getValue());
  56. simd::float_4 mult2 = simd::float_4(params[CH2_PARAM].getValue());
  57. simd::float_4 mult3 = simd::float_4(params[CH3_PARAM].getValue());
  58. simd::float_4 mult4 = simd::float_4(params[CH4_PARAM].getValue());
  59. simd::float_4 in1[4];
  60. simd::float_4 in2[4];
  61. simd::float_4 in3[4];
  62. simd::float_4 in4[4];
  63. simd::float_4 out[4];
  64. out[0] = simd::float_4(0.f);
  65. out[1] = simd::float_4(0.f);
  66. out[2] = simd::float_4(0.f);
  67. out[3] = simd::float_4(0.f);
  68. if(inputs[IN1_INPUT].isConnected()) {
  69. // this also loads some spurious channels into in1[]
  70. for(int c=0; c<channels1; c+=4) in1[c/4] = simd::float_4::load(inputs[IN1_INPUT].getVoltages(c)) * mult1;
  71. for(i=0; i<channels1/4; i++) out[i] += in1[i]; // add only "real" channels.
  72. out[i] += simd::float_4(_mm_and_ps(in1[i].v, mask[channels1-4*i].v)); // make sure we zero out spurious channels
  73. }
  74. if(inputs[IN2_INPUT].isConnected()) {
  75. for(int c=0; c<channels2; c+=4) in2[c/4] = simd::float_4::load(inputs[IN2_INPUT].getVoltages(c)) * mult2;
  76. for(i=0; i<channels2/4; i++) out[i] += in2[i];
  77. out[i] += simd::float_4(_mm_and_ps(in2[i].v, mask[channels2-4*i].v));
  78. }
  79. if(inputs[IN3_INPUT].isConnected()) {
  80. for(int c=0; c<channels3; c+=4) in3[c/4] = simd::float_4::load(inputs[IN3_INPUT].getVoltages(c)) * mult3;
  81. for(i=0; i<channels3/4; i++) out[i] += in3[i];
  82. out[i] += simd::float_4(_mm_and_ps(in3[i].v, mask[channels3-4*i].v));
  83. }
  84. if(inputs[IN4_INPUT].isConnected()) {
  85. for(int c=0; c<channels4; c+=4) in4[c/4] = simd::float_4::load(inputs[IN4_INPUT].getVoltages(c)) * mult4;
  86. for(i=0; i<channels4/4; i++) out[i] += in4[i];
  87. out[i] += simd::float_4(_mm_and_ps(in4[i].v, mask[channels4-4*i].v));
  88. }
  89. outputs[OUT1_OUTPUT].setChannels(out_channels);
  90. outputs[OUT2_OUTPUT].setChannels(out_channels);
  91. for(int c=0; c<out_channels; c+=4) {
  92. out[c / 4].store(outputs[OUT1_OUTPUT].getVoltages(c));
  93. out[c / 4] *= minus_one;
  94. out[c / 4].store(outputs[OUT2_OUTPUT].getVoltages(c));
  95. }
  96. /*
  97. lights[OUT_POS_LIGHT].setSmoothBrightness(out / 5.f, args.sampleTime);
  98. lights[OUT_NEG_LIGHT].setSmoothBrightness(-out / 5.f, args.sampleTime);
  99. */
  100. }
  101. };
  102. struct MixerWidget : ModuleWidget {
  103. MixerWidget(Mixer *module) {
  104. setModule(module);
  105. setPanel(APP->window->loadSvg(asset::plugin(pluginInstance, "res/Mixer.svg")));
  106. addChild(createWidget<Knurlie>(Vec(15, 0)));
  107. addChild(createWidget<Knurlie>(Vec(15, 365)));
  108. addParam(createParam<Davies1900hWhiteKnob>(Vec(19, 32), module, Mixer::CH1_PARAM));
  109. addParam(createParam<Davies1900hWhiteKnob>(Vec(19, 85), module, Mixer::CH2_PARAM));
  110. addParam(createParam<Davies1900hWhiteKnob>(Vec(19, 137), module, Mixer::CH3_PARAM));
  111. addParam(createParam<Davies1900hWhiteKnob>(Vec(19, 190), module, Mixer::CH4_PARAM));
  112. addInput(createInput<PJ301MPort>(Vec(7, 242), module, Mixer::IN1_INPUT));
  113. addInput(createInput<PJ301MPort>(Vec(43, 242), module, Mixer::IN2_INPUT));
  114. addInput(createInput<PJ301MPort>(Vec(7, 281), module, Mixer::IN3_INPUT));
  115. addInput(createInput<PJ301MPort>(Vec(43, 281), module, Mixer::IN4_INPUT));
  116. addOutput(createOutput<PJ301MPort>(Vec(7, 324), module, Mixer::OUT1_OUTPUT));
  117. addOutput(createOutput<PJ301MPort>(Vec(43, 324), module, Mixer::OUT2_OUTPUT));
  118. addChild(createLight<MediumLight<GreenRedLight>>(Vec(32.7, 310), module, Mixer::OUT_POS_LIGHT));
  119. }
  120. };
  121. Model *modelMixer = createModel<Mixer, MixerWidget>("Mixer");