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.

149 lines
5.5KB

  1. #include "plugin.hpp"
  2. struct Compare : Module {
  3. enum ParamId {
  4. B_PARAM,
  5. PARAMS_LEN
  6. };
  7. enum InputId {
  8. A_INPUT,
  9. B_INPUT,
  10. INPUTS_LEN
  11. };
  12. enum OutputId {
  13. MAX_OUTPUT,
  14. MIN_OUTPUT,
  15. CLIP_OUTPUT,
  16. LIM_OUTPUT,
  17. CLIPGATE_OUTPUT,
  18. LIMGATE_OUTPUT,
  19. GREATER_OUTPUT,
  20. LESS_OUTPUT,
  21. OUTPUTS_LEN
  22. };
  23. enum LightId {
  24. ENUMS(CLIP_LIGHT, 2),
  25. ENUMS(LIM_LIGHT, 2),
  26. ENUMS(GREATER_LIGHT, 2),
  27. ENUMS(LESS_LIGHT, 2),
  28. LIGHTS_LEN
  29. };
  30. dsp::ClockDivider lightDivider;
  31. Compare() {
  32. config(PARAMS_LEN, INPUTS_LEN, OUTPUTS_LEN, LIGHTS_LEN);
  33. configParam(B_PARAM, -10.f, 10.f, 0.f, "B offset", " V");
  34. configInput(A_INPUT, "A");
  35. configInput(B_INPUT, "B");
  36. configOutput(MAX_OUTPUT, "Maximum");
  37. configOutput(MIN_OUTPUT, "Minimum");
  38. configOutput(CLIP_OUTPUT, "Clip");
  39. configOutput(LIM_OUTPUT, "Limit");
  40. configOutput(CLIPGATE_OUTPUT, "Clip gate");
  41. configOutput(LIMGATE_OUTPUT, "Limit gate");
  42. configOutput(GREATER_OUTPUT, "A>B");
  43. configOutput(LESS_OUTPUT, "A<B");
  44. lightDivider.setDivision(32);
  45. }
  46. void process(const ProcessArgs& args) override {
  47. int channels = std::max({1, inputs[A_INPUT].getChannels(), inputs[B_INPUT].getChannels()});
  48. float bOffset = params[B_PARAM].getValue();
  49. bool anyClipped = false;
  50. bool anyLimmed = false;
  51. bool anyGreater = false;
  52. bool anyLess = false;
  53. for (int c = 0; c < channels; c++) {
  54. float a = inputs[A_INPUT].getVoltage(c);
  55. float b = inputs[B_INPUT].getVoltage(c) + bOffset;
  56. float bAbs = std::fabs(b);
  57. outputs[MAX_OUTPUT].setVoltage(std::max(a, b), c);
  58. outputs[MIN_OUTPUT].setVoltage(std::min(a, b), c);
  59. float clip = a;
  60. bool clipped = false;
  61. if (bAbs < a) {
  62. clip = bAbs;
  63. clipped = true;
  64. }
  65. else if (a < -bAbs) {
  66. clip = -bAbs;
  67. clipped = true;
  68. }
  69. outputs[CLIP_OUTPUT].setVoltage(clip, c);
  70. outputs[LIM_OUTPUT].setVoltage(a - clip, c);
  71. outputs[CLIPGATE_OUTPUT].setVoltage(clipped ? 10.f : 0.f, c);
  72. anyClipped = anyClipped || clipped;
  73. anyLimmed = anyLimmed || !clipped;
  74. outputs[LIMGATE_OUTPUT].setVoltage(!clipped ? 10.f : 0.f, c);
  75. outputs[GREATER_OUTPUT].setVoltage(a > b ? 10.f : 0.f, c);
  76. anyGreater = anyGreater || (a > b);
  77. outputs[LESS_OUTPUT].setVoltage(a < b ? 10.f : 0.f, c);
  78. anyLess = anyLess || (a < b);
  79. }
  80. outputs[MAX_OUTPUT].setChannels(channels);
  81. outputs[MIN_OUTPUT].setChannels(channels);
  82. outputs[CLIP_OUTPUT].setChannels(channels);
  83. outputs[LIM_OUTPUT].setChannels(channels);
  84. outputs[CLIPGATE_OUTPUT].setChannels(channels);
  85. outputs[LIMGATE_OUTPUT].setChannels(channels);
  86. outputs[GREATER_OUTPUT].setChannels(channels);
  87. outputs[LESS_OUTPUT].setChannels(channels);
  88. if (lightDivider.process()) {
  89. float lightTime = args.sampleTime * lightDivider.getDivision();
  90. lights[CLIP_LIGHT + 0].setBrightnessSmooth(anyClipped && channels <= 1, lightTime);
  91. lights[CLIP_LIGHT + 1].setBrightnessSmooth(anyClipped && channels > 1, lightTime);
  92. lights[LIM_LIGHT + 0].setBrightnessSmooth(anyLimmed && channels <= 1, lightTime);
  93. lights[LIM_LIGHT + 1].setBrightnessSmooth(anyLimmed && channels > 1, lightTime);
  94. lights[GREATER_LIGHT + 0].setBrightnessSmooth(anyGreater && channels <= 1, lightTime);
  95. lights[GREATER_LIGHT + 1].setBrightnessSmooth(anyGreater && channels > 1, lightTime);
  96. lights[LESS_LIGHT + 0].setBrightnessSmooth(anyLess && channels <= 1, lightTime);
  97. lights[LESS_LIGHT + 1].setBrightnessSmooth(anyLess && channels > 1, lightTime);
  98. }
  99. }
  100. };
  101. struct CompareWidget : ModuleWidget {
  102. CompareWidget(Compare* module) {
  103. setModule(module);
  104. setPanel(createPanel(asset::plugin(pluginInstance, "res/Compare.svg")));
  105. addChild(createWidget<ScrewSilver>(Vec(RACK_GRID_WIDTH, 0)));
  106. addChild(createWidget<ScrewSilver>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, 0)));
  107. addChild(createWidget<ScrewSilver>(Vec(RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH)));
  108. addChild(createWidget<ScrewSilver>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH)));
  109. addParam(createParamCentered<RoundLargeBlackKnob>(mm2px(Vec(12.646, 26.755)), module, Compare::B_PARAM));
  110. addInput(createInputCentered<PJ301MPort>(mm2px(Vec(7.299, 52.31)), module, Compare::A_INPUT));
  111. addInput(createInputCentered<PJ301MPort>(mm2px(Vec(18.136, 52.31)), module, Compare::B_INPUT));
  112. addOutput(createOutputCentered<PJ301MPort>(mm2px(Vec(7.297, 67.53)), module, Compare::MAX_OUTPUT));
  113. addOutput(createOutputCentered<PJ301MPort>(mm2px(Vec(18.134, 67.53)), module, Compare::MIN_OUTPUT));
  114. addOutput(createOutputCentered<PJ301MPort>(mm2px(Vec(7.297, 82.732)), module, Compare::CLIP_OUTPUT));
  115. addOutput(createOutputCentered<PJ301MPort>(mm2px(Vec(18.134, 82.732)), module, Compare::LIM_OUTPUT));
  116. addOutput(createOutputCentered<PJ301MPort>(mm2px(Vec(7.297, 97.958)), module, Compare::CLIPGATE_OUTPUT));
  117. addOutput(createOutputCentered<PJ301MPort>(mm2px(Vec(18.134, 97.958)), module, Compare::LIMGATE_OUTPUT));
  118. addOutput(createOutputCentered<PJ301MPort>(mm2px(Vec(7.297, 113.115)), module, Compare::GREATER_OUTPUT));
  119. addOutput(createOutputCentered<PJ301MPort>(mm2px(Vec(18.134, 113.115)), module, Compare::LESS_OUTPUT));
  120. addChild(createLightCentered<TinyLight<YellowBlueLight<>>>(mm2px(Vec(11.027, 94.233)), module, Compare::CLIP_LIGHT));
  121. addChild(createLightCentered<TinyLight<YellowBlueLight<>>>(mm2px(Vec(21.864, 94.233)), module, Compare::LIM_LIGHT));
  122. addChild(createLightCentered<TinyLight<YellowBlueLight<>>>(mm2px(Vec(11.027, 109.393)), module, Compare::GREATER_LIGHT));
  123. addChild(createLightCentered<TinyLight<YellowBlueLight<>>>(mm2px(Vec(21.864, 109.393)), module, Compare::LESS_LIGHT));
  124. }
  125. };
  126. Model* modelCompare = createModel<Compare, CompareWidget>("Compare");