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.

109 lines
3.5KB

  1. #include "plugin.hpp"
  2. static float clip(float x) {
  3. x = clamp(x, -2.f, 2.f);
  4. return x / std::pow(1.f + std::pow(x, 24.f), 1/24.f);
  5. }
  6. struct ABC : Module {
  7. enum ParamIds {
  8. B1_LEVEL_PARAM,
  9. C1_LEVEL_PARAM,
  10. B2_LEVEL_PARAM,
  11. C2_LEVEL_PARAM,
  12. NUM_PARAMS
  13. };
  14. enum InputIds {
  15. A1_INPUT,
  16. B1_INPUT,
  17. C1_INPUT,
  18. A2_INPUT,
  19. B2_INPUT,
  20. C2_INPUT,
  21. NUM_INPUTS
  22. };
  23. enum OutputIds {
  24. OUT1_OUTPUT,
  25. OUT2_OUTPUT,
  26. NUM_OUTPUTS
  27. };
  28. enum LightIds {
  29. OUT1_POS_LIGHT,
  30. OUT1_NEG_LIGHT,
  31. OUT2_POS_LIGHT,
  32. OUT2_NEG_LIGHT,
  33. NUM_LIGHTS
  34. };
  35. ABC() {
  36. config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS);
  37. params[B1_LEVEL_PARAM].config(-1.0, 1.0, 0.0, "B1 Level");
  38. params[C1_LEVEL_PARAM].config(-1.0, 1.0, 0.0, "C1 Level");
  39. params[B2_LEVEL_PARAM].config(-1.0, 1.0, 0.0, "B2 Level");
  40. params[C2_LEVEL_PARAM].config(-1.0, 1.0, 0.0, "C2 Level");
  41. }
  42. void process(const ProcessArgs &args) override {
  43. float a1 = inputs[A1_INPUT].value;
  44. float b1 = inputs[B1_INPUT].getNormalVoltage(5.f) * 2.f*dsp::exponentialBipolar(80.f, params[B1_LEVEL_PARAM].value);
  45. float c1 = inputs[C1_INPUT].getNormalVoltage(10.f) * dsp::exponentialBipolar(80.f, params[C1_LEVEL_PARAM].value);
  46. float out1 = a1 * b1 / 5.f + c1;
  47. float a2 = inputs[A2_INPUT].value;
  48. float b2 = inputs[B2_INPUT].getNormalVoltage(5.f) * 2.f*dsp::exponentialBipolar(80.f, params[B2_LEVEL_PARAM].value);
  49. float c2 = inputs[C2_INPUT].getNormalVoltage(10.f) * dsp::exponentialBipolar(80.f, params[C2_LEVEL_PARAM].value);
  50. float out2 = a2 * b2 / 5.f + c2;
  51. // Set outputs
  52. if (outputs[OUT1_OUTPUT].active) {
  53. outputs[OUT1_OUTPUT].value = clip(out1 / 10.f) * 10.f;
  54. }
  55. else {
  56. out2 += out1;
  57. }
  58. if (outputs[OUT2_OUTPUT].active) {
  59. outputs[OUT2_OUTPUT].value = clip(out2 / 10.f) * 10.f;
  60. }
  61. // Lights
  62. lights[OUT1_POS_LIGHT].setSmoothBrightness(out1 / 5.f, args.sampleTime);
  63. lights[OUT1_NEG_LIGHT].setSmoothBrightness(-out1 / 5.f, args.sampleTime);
  64. lights[OUT2_POS_LIGHT].setSmoothBrightness(out2 / 5.f, args.sampleTime);
  65. lights[OUT2_NEG_LIGHT].setSmoothBrightness(-out2 / 5.f, args.sampleTime);
  66. }
  67. };
  68. struct ABCWidget : ModuleWidget {
  69. ABCWidget(ABC *module) {
  70. setModule(module);
  71. setPanel(APP->window->loadSvg(asset::plugin(pluginInstance, "res/ABC.svg")));
  72. addChild(createWidget<Knurlie>(Vec(15, 0)));
  73. addChild(createWidget<Knurlie>(Vec(15, 365)));
  74. addParam(createParam<Davies1900hRedKnob>(Vec(45, 37), module, ABC::B1_LEVEL_PARAM));
  75. addParam(createParam<Davies1900hWhiteKnob>(Vec(45, 107), module, ABC::C1_LEVEL_PARAM));
  76. addParam(createParam<Davies1900hRedKnob>(Vec(45, 204), module, ABC::B2_LEVEL_PARAM));
  77. addParam(createParam<Davies1900hWhiteKnob>(Vec(45, 274), module, ABC::C2_LEVEL_PARAM));
  78. addInput(createInput<PJ301MPort>(Vec(7, 28), module, ABC::A1_INPUT));
  79. addInput(createInput<PJ301MPort>(Vec(7, 70), module, ABC::B1_INPUT));
  80. addInput(createInput<PJ301MPort>(Vec(7, 112), module, ABC::C1_INPUT));
  81. addOutput(createOutput<PJ301MPort>(Vec(7, 154), module, ABC::OUT1_OUTPUT));
  82. addInput(createInput<PJ301MPort>(Vec(7, 195), module, ABC::A2_INPUT));
  83. addInput(createInput<PJ301MPort>(Vec(7, 237), module, ABC::B2_INPUT));
  84. addInput(createInput<PJ301MPort>(Vec(7, 279), module, ABC::C2_INPUT));
  85. addOutput(createOutput<PJ301MPort>(Vec(7, 321), module, ABC::OUT2_OUTPUT));
  86. addChild(createLight<MediumLight<GreenRedLight>>(Vec(37, 162), module, ABC::OUT1_POS_LIGHT));
  87. addChild(createLight<MediumLight<GreenRedLight>>(Vec(37, 329), module, ABC::OUT2_POS_LIGHT));
  88. }
  89. };
  90. Model *modelABC = createModel<ABC, ABCWidget>("ABC");