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.

114 lines
4.0KB

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