mindball/Source/DelayLine.h
2026-08-14 21:14:18 +02:00

59 lines
1.4 KiB
C++

#pragma once
#include <algorithm>
#include <cmath>
#include <vector>
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<std::size_t> (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<std::size_t> (writePos)] = sample;
writePos = (writePos + 1) % static_cast<int> (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<int> (buffer.size());
const float readPos = static_cast<float> (writePos) - d;
const float floorPos = std::floor (readPos);
int i0 = static_cast<int> (floorPos) % size;
if (i0 < 0)
i0 += size;
const int i1 = (i0 + 1) % size;
const float frac = readPos - floorPos;
return buffer[static_cast<std::size_t> (i0)]
+ (buffer[static_cast<std::size_t> (i1)] - buffer[static_cast<std::size_t> (i0)]) * frac;
}
private:
std::vector<float> buffer;
float maxDelay = 1.0f;
int writePos = 0;
};
}