#pragma once #include #include #include class Delay { public: void prepare(double sr) { sampleRate = sr; int maxSamples = static_cast(sr * 2.0); bufferL.resize(maxSamples, 0.0f); bufferR.resize(maxSamples, 0.0f); writePos = 0; } void setParameters(float timeMs, float fb, float mx, bool pingpong = false) { timeSamplesF = timeMs * 0.001f * static_cast(sampleRate); float bufMax = static_cast(bufferL.size()) - 1.0f; timeSamplesF = std::clamp(timeSamplesF, 1.0f, bufMax); feedback = std::clamp(fb, 0.0f, 0.95f); mix = std::clamp(mx, 0.0f, 1.0f); pingPong = pingpong; } void process(float& left, float& right) { int bufSize = static_cast(bufferL.size()); float readPosF = static_cast(writePos) - timeSamplesF; while (readPosF < 0.0f) readPosF += static_cast(bufSize); int i0 = static_cast(readPosF) % bufSize; int i1 = (i0 + 1) % bufSize; float frac = readPosF - std::floor(readPosF); float outL = bufferL[i0] * (1.0f - frac) + bufferL[i1] * frac; float outR = bufferR[i0] * (1.0f - frac) + bufferR[i1] * frac; if (pingPong) { // Classic ping-pong: each channel's echo bounces to the opposite // channel on the next repeat, so the taps alternate L/R. bufferL[writePos] = left + outR * feedback; bufferR[writePos] = right + outL * feedback; } else { bufferL[writePos] = left + outL * feedback; bufferR[writePos] = right + outR * feedback; } writePos = (writePos + 1) % bufSize; left = left * (1.0f - mix) + outL * mix; right = right * (1.0f - mix) + outR * mix; } private: std::vector bufferL, bufferR; int writePos = 0; double sampleRate = 44100; float timeSamplesF = 8820.0f; float feedback = 0.3f; float mix = 0.25f; bool pingPong = false; };