using System; namespace FractalVisualizer.Audio; public sealed class AudioSampleRingBuffer { private readonly float[] _buffer; private readonly object _sync = new(); private int _writeIndex; private int _readIndex; private int _count; public AudioSampleRingBuffer(int capacity) { if (capacity <= 0) { throw new ArgumentOutOfRangeException(nameof(capacity)); } _buffer = new float[capacity]; } public int Capacity => _buffer.Length; public int Count { get { lock (_sync) { return _count; } } } public void Clear() { lock (_sync) { _writeIndex = 0; _readIndex = 0; _count = 0; } } public void Write(ReadOnlySpan samples) { lock (_sync) { for (int i = 0; i < samples.Length; i++) { _buffer[_writeIndex] = samples[i]; _writeIndex = (_writeIndex + 1) % _buffer.Length; if (_count == _buffer.Length) { _readIndex = (_readIndex + 1) % _buffer.Length; } else { _count++; } } } } public bool TryRead(Span destination) { lock (_sync) { if (_count < destination.Length) { return false; } for (int i = 0; i < destination.Length; i++) { destination[i] = _buffer[_readIndex]; _readIndex = (_readIndex + 1) % _buffer.Length; } _count -= destination.Length; return true; } } }