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.

162 lines
5.7KB

  1. #include "plugin.hpp"
  2. struct VCMixer : Module {
  3. enum ParamIds {
  4. MIX_LVL_PARAM,
  5. ENUMS(LVL_PARAMS, 4),
  6. NUM_PARAMS
  7. };
  8. enum InputIds {
  9. MIX_CV_INPUT,
  10. ENUMS(CH_INPUTS, 4),
  11. ENUMS(CV_INPUTS, 4),
  12. NUM_INPUTS
  13. };
  14. enum OutputIds {
  15. MIX_OUTPUT,
  16. ENUMS(CH_OUTPUTS, 4),
  17. NUM_OUTPUTS
  18. };
  19. enum LightIds {
  20. ENUMS(LVL_LIGHTS, 4),
  21. NUM_LIGHTS
  22. };
  23. dsp::VuMeter2 chMeters[4];
  24. dsp::ClockDivider lightDivider;
  25. VCMixer() {
  26. config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS);
  27. // x^1 scaling up to 6 dB
  28. configParam(MIX_LVL_PARAM, 0.0, 2.0, 1.0, "Master level", " dB", -10, 20);
  29. // x^2 scaling up to 6 dB
  30. configParam(LVL_PARAMS + 0, 0.0, M_SQRT2, 1.0, "Ch 1 level", " dB", -10, 40);
  31. configParam(LVL_PARAMS + 1, 0.0, M_SQRT2, 1.0, "Ch 2 level", " dB", -10, 40);
  32. configParam(LVL_PARAMS + 2, 0.0, M_SQRT2, 1.0, "Ch 3 level", " dB", -10, 40);
  33. configParam(LVL_PARAMS + 3, 0.0, M_SQRT2, 1.0, "Ch 4 level", " dB", -10, 40);
  34. lightDivider.setDivision(512);
  35. }
  36. void process(const ProcessArgs& args) override {
  37. float mix[16] = {};
  38. int maxChannels = 1;
  39. // Channels
  40. for (int i = 0; i < 4; i++) {
  41. int channels = 1;
  42. float in[16] = {};
  43. float sum = 0.f;
  44. if (inputs[CH_INPUTS + i].isConnected()) {
  45. channels = inputs[CH_INPUTS + i].getChannels();
  46. maxChannels = std::max(maxChannels, channels);
  47. // Get input
  48. inputs[CH_INPUTS + i].readVoltages(in);
  49. // Apply fader gain
  50. float gain = std::pow(params[LVL_PARAMS + i].getValue(), 2.f);
  51. for (int c = 0; c < channels; c++) {
  52. in[c] *= gain;
  53. }
  54. // Apply CV gain
  55. if (inputs[CV_INPUTS + i].isConnected()) {
  56. for (int c = 0; c < channels; c++) {
  57. float cv = clamp(inputs[CV_INPUTS + i].getPolyVoltage(c) / 10.f, 0.f, 1.f);
  58. in[c] *= cv;
  59. }
  60. }
  61. // Add to mix
  62. for (int c = 0; c < channels; c++) {
  63. mix[c] += in[c];
  64. }
  65. // Sum channel for VU meter
  66. for (int c = 0; c < channels; c++) {
  67. sum += in[c];
  68. }
  69. }
  70. chMeters[i].process(args.sampleTime, sum / 5.f);
  71. // Set channel output
  72. if (outputs[CH_OUTPUTS + i].isConnected()) {
  73. outputs[CH_OUTPUTS + i].setChannels(channels);
  74. outputs[CH_OUTPUTS + i].writeVoltages(in);
  75. }
  76. }
  77. // Mix output
  78. if (outputs[MIX_OUTPUT].isConnected()) {
  79. // Apply mix knob gain
  80. float gain = params[MIX_LVL_PARAM].getValue();
  81. for (int c = 0; c < maxChannels; c++) {
  82. mix[c] *= gain;
  83. }
  84. // Apply mix CV gain
  85. if (inputs[MIX_CV_INPUT].isConnected()) {
  86. for (int c = 0; c < maxChannels; c++) {
  87. float cv = clamp(inputs[MIX_CV_INPUT].getPolyVoltage(c) / 10.f, 0.f, 1.f);
  88. mix[c] *= cv;
  89. }
  90. }
  91. // Set mix output
  92. outputs[MIX_OUTPUT].setChannels(maxChannels);
  93. outputs[MIX_OUTPUT].writeVoltages(mix);
  94. }
  95. // VU lights
  96. if (lightDivider.process()) {
  97. for (int i = 0; i < 4; i++) {
  98. float b = chMeters[i].getBrightness(-24.f, 0.f);
  99. lights[LVL_LIGHTS + i].setBrightness(b);
  100. }
  101. }
  102. }
  103. };
  104. struct VCMixerWidget : ModuleWidget {
  105. VCMixerWidget(VCMixer* module) {
  106. setModule(module);
  107. setPanel(APP->window->loadSvg(asset::plugin(pluginInstance, "res/VCMixer.svg")));
  108. addChild(createWidget<ScrewSilver>(Vec(RACK_GRID_WIDTH, 0)));
  109. addChild(createWidget<ScrewSilver>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, 0)));
  110. addChild(createWidget<ScrewSilver>(Vec(RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH)));
  111. addChild(createWidget<ScrewSilver>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH)));
  112. addParam(createParam<RoundLargeBlackKnob>(mm2px(Vec(19.049999, 21.161154)), module, VCMixer::MIX_LVL_PARAM));
  113. addParam(createLightParam<LEDLightSliderFixed<GreenLight>>(mm2px(Vec(5.8993969, 44.33149).plus(Vec(-2, 0))), module, VCMixer::LVL_PARAMS + 0, VCMixer::LVL_LIGHTS + 0));
  114. addParam(createLightParam<LEDLightSliderFixed<GreenLight>>(mm2px(Vec(17.899343, 44.331486).plus(Vec(-2, 0))), module, VCMixer::LVL_PARAMS + 1, VCMixer::LVL_LIGHTS + 1));
  115. addParam(createLightParam<LEDLightSliderFixed<GreenLight>>(mm2px(Vec(29.899292, 44.331486).plus(Vec(-2, 0))), module, VCMixer::LVL_PARAMS + 2, VCMixer::LVL_LIGHTS + 2));
  116. addParam(createLightParam<LEDLightSliderFixed<GreenLight>>(mm2px(Vec(41.90065, 44.331486).plus(Vec(-2, 0))), module, VCMixer::LVL_PARAMS + 3, VCMixer::LVL_LIGHTS + 3));
  117. // Use old interleaved order for backward compatibility with <0.6
  118. addInput(createInput<PJ301MPort>(mm2px(Vec(3.2935331, 23.404598)), module, VCMixer::MIX_CV_INPUT));
  119. addInput(createInput<PJ301MPort>(mm2px(Vec(3.2935331, 78.531639)), module, VCMixer::CH_INPUTS + 0));
  120. addInput(createInput<PJ301MPort>(mm2px(Vec(3.2935331, 93.531586)), module, VCMixer::CV_INPUTS + 0));
  121. addInput(createInput<PJ301MPort>(mm2px(Vec(15.29348, 78.531639)), module, VCMixer::CH_INPUTS + 1));
  122. addInput(createInput<PJ301MPort>(mm2px(Vec(15.29348, 93.531586)), module, VCMixer::CV_INPUTS + 1));
  123. addInput(createInput<PJ301MPort>(mm2px(Vec(27.293465, 78.531639)), module, VCMixer::CH_INPUTS + 2));
  124. addInput(createInput<PJ301MPort>(mm2px(Vec(27.293465, 93.531586)), module, VCMixer::CV_INPUTS + 2));
  125. addInput(createInput<PJ301MPort>(mm2px(Vec(39.293411, 78.531639)), module, VCMixer::CH_INPUTS + 3));
  126. addInput(createInput<PJ301MPort>(mm2px(Vec(39.293411, 93.531586)), module, VCMixer::CV_INPUTS + 3));
  127. addOutput(createOutput<PJ301MPort>(mm2px(Vec(39.293411, 23.4046)), module, VCMixer::MIX_OUTPUT));
  128. addOutput(createOutput<PJ301MPort>(mm2px(Vec(3.2935331, 108.53153)), module, VCMixer::CH_OUTPUTS + 0));
  129. addOutput(createOutput<PJ301MPort>(mm2px(Vec(15.29348, 108.53153)), module, VCMixer::CH_OUTPUTS + 1));
  130. addOutput(createOutput<PJ301MPort>(mm2px(Vec(27.293465, 108.53153)), module, VCMixer::CH_OUTPUTS + 2));
  131. addOutput(createOutput<PJ301MPort>(mm2px(Vec(39.293411, 108.53153)), module, VCMixer::CH_OUTPUTS + 3));
  132. }
  133. };
  134. Model* modelVCMixer = createModel<VCMixer, VCMixerWidget>("VCMixer");