#include "Template.hpp" namespace rack_plugin_PG_Instruments { #define HALF_BUFFER_SIZE 65536 #define BUFFER_SIZE HALF_BUFFER_SIZE * 2 #define BUFFER_MASK (BUFFER_SIZE - 1) struct PGStereoPingPongEcho : Module { enum ParamIds { TIME_PARAM, FEEDBACK_PARAM, NUM_PARAMS }; enum InputIds { INPUT, NUM_INPUTS }; enum OutputIds { LEFT_OUTPUT, RIGHT_OUTPUT, NUM_OUTPUTS }; int reader; int writer; int writer2; int offset; float buffer[BUFFER_SIZE]; PGStereoPingPongEcho() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, 0) { reader = 0; offset = BUFFER_SIZE >> 1; writer = offset; writer2 = BUFFER_SIZE - 1; for(int i = 0; i < BUFFER_SIZE; i++) { buffer[i] = 0.0f; } } void step() override { int timeParam = (int)(params[TIME_PARAM].value * BUFFER_SIZE); if (timeParam != offset) { offset = timeParam; writer = (reader - offset) & BUFFER_MASK; writer2 = (reader - offset * 2 - 1) & BUFFER_MASK; } float input; input = inputs[INPUT].value; outputs[LEFT_OUTPUT].value = input * 0.7f + buffer[reader] + buffer[writer]; outputs[RIGHT_OUTPUT].value = input * 0.7f + buffer[reader] + buffer[writer2]; buffer[writer] = input + buffer[writer] * params[FEEDBACK_PARAM].value; buffer[writer2] = input + buffer[writer2] * params[FEEDBACK_PARAM].value / 2.0f; reader++; writer++; writer2++; reader &= BUFFER_MASK; writer &= BUFFER_MASK; writer2 &= BUFFER_MASK; } }; struct PGStereoPingPongEchoWidget : ModuleWidget { PGStereoPingPongEchoWidget(PGStereoPingPongEcho *module) : ModuleWidget(module) { setPanel(SVG::load(assetPlugin(plugin, "res/PGStereoPingPongEcho.svg"))); addChild(Widget::create(Vec(15, 0))); addChild(Widget::create(Vec(box.size.x-30, 0))); addChild(Widget::create(Vec(15, 365))); addChild(Widget::create(Vec(box.size.x-30, 365))); addInput(Port::create(Vec(30, 100), Port::INPUT, module, PGStereoPingPongEcho::INPUT)); addParam(ParamWidget::create(Vec(70, 100), module, PGStereoPingPongEcho::TIME_PARAM, 0.0f, 1.0f, 0.5f)); addParam(ParamWidget::create(Vec(110, 100), module, PGStereoPingPongEcho::FEEDBACK_PARAM, 0.0f, 1.0f, 0.5f)); addOutput(Port::create(Vec(150, 100), Port::OUTPUT, module, PGStereoPingPongEcho::LEFT_OUTPUT)); addOutput(Port::create(Vec(150, 140), Port::OUTPUT, module, PGStereoPingPongEcho::RIGHT_OUTPUT)); } }; } // namespace rack_plugin_PG_Instruments using namespace rack_plugin_PG_Instruments; RACK_PLUGIN_MODEL_INIT(PG_Instruments, PGStereoPingPongEcho) { Model *modelPGStereoPingPongEcho = Model::create("PG-Instruments", "PGStereoPingPongEcho", "PG Stereo Ping Pong Echo", DELAY_TAG); return modelPGStereoPingPongEcho; }