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.2KB

  1. #include "Template.hpp"
  2. namespace rack_plugin_PG_Instruments {
  3. #define HALF_BUFFER_SIZE 65536
  4. #define BUFFER_SIZE HALF_BUFFER_SIZE * 2
  5. #define BUFFER_MASK (BUFFER_SIZE - 1)
  6. struct PGStereoPingPongEcho : Module
  7. {
  8. enum ParamIds
  9. {
  10. TIME_PARAM,
  11. FEEDBACK_PARAM,
  12. NUM_PARAMS
  13. };
  14. enum InputIds
  15. {
  16. INPUT,
  17. NUM_INPUTS
  18. };
  19. enum OutputIds
  20. {
  21. LEFT_OUTPUT,
  22. RIGHT_OUTPUT,
  23. NUM_OUTPUTS
  24. };
  25. int reader;
  26. int writer;
  27. int writer2;
  28. int offset;
  29. float buffer[BUFFER_SIZE];
  30. PGStereoPingPongEcho() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, 0)
  31. {
  32. reader = 0;
  33. offset = BUFFER_SIZE >> 1;
  34. writer = offset;
  35. writer2 = BUFFER_SIZE - 1;
  36. for(int i = 0; i < BUFFER_SIZE; i++)
  37. {
  38. buffer[i] = 0.0f;
  39. }
  40. }
  41. void step() override
  42. {
  43. int timeParam = (int)(params[TIME_PARAM].value * BUFFER_SIZE);
  44. if (timeParam != offset)
  45. {
  46. offset = timeParam;
  47. writer = (reader - offset) & BUFFER_MASK;
  48. writer2 = (reader - offset * 2 - 1) & BUFFER_MASK;
  49. }
  50. float input;
  51. input = inputs[INPUT].value;
  52. outputs[LEFT_OUTPUT].value = input * 0.7f + buffer[reader] + buffer[writer];
  53. outputs[RIGHT_OUTPUT].value = input * 0.7f + buffer[reader] + buffer[writer2];
  54. buffer[writer] = input + buffer[writer] * params[FEEDBACK_PARAM].value;
  55. buffer[writer2] = input + buffer[writer2] * params[FEEDBACK_PARAM].value / 2.0f;
  56. reader++;
  57. writer++;
  58. writer2++;
  59. reader &= BUFFER_MASK;
  60. writer &= BUFFER_MASK;
  61. writer2 &= BUFFER_MASK;
  62. }
  63. };
  64. struct PGStereoPingPongEchoWidget : ModuleWidget
  65. {
  66. PGStereoPingPongEchoWidget(PGStereoPingPongEcho *module) : ModuleWidget(module)
  67. {
  68. setPanel(SVG::load(assetPlugin(plugin, "res/PGStereoPingPongEcho.svg")));
  69. addChild(Widget::create<ScrewSilver>(Vec(15, 0)));
  70. addChild(Widget::create<ScrewSilver>(Vec(box.size.x-30, 0)));
  71. addChild(Widget::create<ScrewSilver>(Vec(15, 365)));
  72. addChild(Widget::create<ScrewSilver>(Vec(box.size.x-30, 365)));
  73. addInput(Port::create<PJ301MPort>(Vec(30, 100), Port::INPUT, module, PGStereoPingPongEcho::INPUT));
  74. addParam(ParamWidget::create<RoundBlackKnob>(Vec(70, 100), module, PGStereoPingPongEcho::TIME_PARAM, 0.0f, 1.0f, 0.5f));
  75. addParam(ParamWidget::create<RoundBlackKnob>(Vec(110, 100), module, PGStereoPingPongEcho::FEEDBACK_PARAM, 0.0f, 1.0f, 0.5f));
  76. addOutput(Port::create<PJ301MPort>(Vec(150, 100), Port::OUTPUT, module, PGStereoPingPongEcho::LEFT_OUTPUT));
  77. addOutput(Port::create<PJ301MPort>(Vec(150, 140), Port::OUTPUT, module, PGStereoPingPongEcho::RIGHT_OUTPUT));
  78. }
  79. };
  80. } // namespace rack_plugin_PG_Instruments
  81. using namespace rack_plugin_PG_Instruments;
  82. RACK_PLUGIN_MODEL_INIT(PG_Instruments, PGStereoPingPongEcho) {
  83. Model *modelPGStereoPingPongEcho = Model::create<PGStereoPingPongEcho, PGStereoPingPongEchoWidget>("PG-Instruments", "PGStereoPingPongEcho", "PG Stereo Ping Pong Echo", DELAY_TAG);
  84. return modelPGStereoPingPongEcho;
  85. }