#pragma once #include #include #include namespace mindball { // Simple fractional-delay ring buffer with linear interpolation. class DelayLine { public: void prepare (float maxDelaySamples) { maxDelay = std::max (1.0f, maxDelaySamples); buffer.assign (static_cast (maxDelay) + 2, 0.0f); writePos = 0; } void clear() { std::fill (buffer.begin(), buffer.end(), 0.0f); writePos = 0; } void write (float sample) { buffer[static_cast (writePos)] = sample; writePos = (writePos + 1) % static_cast (buffer.size()); } float read (float delaySamples) const { if (buffer.empty()) return 0.0f; const float d = std::max (1.0f, std::min (delaySamples, maxDelay - 1.0f)); const int size = static_cast (buffer.size()); const float readPos = static_cast (writePos) - d; const float floorPos = std::floor (readPos); int i0 = static_cast (floorPos) % size; if (i0 < 0) i0 += size; const int i1 = (i0 + 1) % size; const float frac = readPos - floorPos; return buffer[static_cast (i0)] + (buffer[static_cast (i1)] - buffer[static_cast (i0)]) * frac; } private: std::vector buffer; float maxDelay = 1.0f; int writePos = 0; }; }