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.

120 lines
3.7KB

  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 PGStereoEcho : Module
  7. {
  8. enum ParamIds
  9. {
  10. TIME_PARAM,
  11. OFFSET_PARAM,
  12. FEEDBACK_PARAM,
  13. NUM_PARAMS
  14. };
  15. enum InputIds
  16. {
  17. LEFT_INPUT,
  18. RIGHT_INPUT,
  19. NUM_INPUTS
  20. };
  21. enum OutputIds
  22. {
  23. LEFT_OUTPUT,
  24. RIGHT_OUTPUT,
  25. NUM_OUTPUTS
  26. };
  27. int reader;
  28. int leftWriter;
  29. int rightWriter;
  30. int offset;
  31. int rightOffset;
  32. float leftBuffer[BUFFER_SIZE];
  33. float rightBuffer[BUFFER_SIZE];
  34. PGStereoEcho() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, 0)
  35. {
  36. reader = 0;
  37. offset = BUFFER_SIZE >> 1;
  38. rightOffset = 0;
  39. leftWriter = offset;
  40. rightWriter = offset;
  41. for(int i = 0; i < BUFFER_SIZE; i++)
  42. {
  43. leftBuffer[i] = 0.0f;
  44. rightBuffer[i] = 0.0f;
  45. }
  46. }
  47. void step() override
  48. {
  49. int timeParam = (int)(params[TIME_PARAM].value * BUFFER_SIZE);
  50. int offsetParam = (int)(params[OFFSET_PARAM].value * HALF_BUFFER_SIZE);
  51. if (timeParam != offset || offsetParam != rightOffset)
  52. {
  53. offset = timeParam;
  54. rightOffset = offsetParam;
  55. leftWriter = (reader - offset) & BUFFER_MASK;
  56. rightWriter = (reader - offset - rightOffset) & BUFFER_MASK;
  57. }
  58. float input;
  59. input = inputs[LEFT_INPUT].value;
  60. outputs[LEFT_OUTPUT].value = input + leftBuffer[reader];
  61. leftBuffer[leftWriter] = input + leftBuffer[leftWriter] * params[FEEDBACK_PARAM].value;
  62. input = inputs[RIGHT_INPUT].value;
  63. outputs[RIGHT_OUTPUT].value = input + rightBuffer[reader];
  64. rightBuffer[rightWriter] = input + rightBuffer[rightWriter] * params[FEEDBACK_PARAM].value;
  65. reader++;
  66. leftWriter++;
  67. rightWriter++;
  68. reader &= BUFFER_MASK;
  69. leftWriter &= BUFFER_MASK;
  70. rightWriter &= BUFFER_MASK;
  71. }
  72. };
  73. struct PGStereoEchoWidget : ModuleWidget
  74. {
  75. PGStereoEchoWidget(PGStereoEcho *module) : ModuleWidget(module)
  76. {
  77. setPanel(SVG::load(assetPlugin(plugin, "res/PGStereoEcho.svg")));
  78. addChild(Widget::create<ScrewSilver>(Vec(15, 0)));
  79. addChild(Widget::create<ScrewSilver>(Vec(box.size.x-30, 0)));
  80. addChild(Widget::create<ScrewSilver>(Vec(15, 365)));
  81. addChild(Widget::create<ScrewSilver>(Vec(box.size.x-30, 365)));
  82. addInput(Port::create<PJ301MPort>(Vec(30, 100), Port::INPUT, module, PGStereoEcho::LEFT_INPUT));
  83. addInput(Port::create<PJ301MPort>(Vec(30, 140), Port::INPUT, module, PGStereoEcho::RIGHT_INPUT));
  84. addParam(ParamWidget::create<RoundBlackKnob>(Vec(70, 100), module, PGStereoEcho::TIME_PARAM, 0.0f, 1.0f, 0.5f));
  85. addParam(ParamWidget::create<RoundBlackKnob>(Vec(110, 100), module, PGStereoEcho::FEEDBACK_PARAM, 0.0f, 1.0f, 0.5f));
  86. addParam(ParamWidget::create<RoundBlackKnob>(Vec(70, 140), module, PGStereoEcho::OFFSET_PARAM, 0.0f, 1.0f, 0.0f));
  87. addOutput(Port::create<PJ301MPort>(Vec(150, 100), Port::OUTPUT, module, PGStereoEcho::LEFT_OUTPUT));
  88. addOutput(Port::create<PJ301MPort>(Vec(150, 140), Port::OUTPUT, module, PGStereoEcho::RIGHT_OUTPUT));
  89. }
  90. };
  91. } // namespace rack_plugin_PG_Instruments
  92. using namespace rack_plugin_PG_Instruments;
  93. RACK_PLUGIN_MODEL_INIT(PG_Instruments, PGStereoEcho) {
  94. Model *modelPGStereoEcho = Model::create<PGStereoEcho, PGStereoEchoWidget>("PG-Instruments", "PGStereoEcho", "PG Stereo Echo", DELAY_TAG);
  95. return modelPGStereoEcho;
  96. }