Skip to main content

rill_core/buffer/
ring.rs

1use crate::math::Transcendental;
2use std::fmt;
3
4/// Fixed-size ring buffer (power-of-two size). Single-threaded.
5///
6/// Used inside the signal graph for delay effects and sample buffering.
7/// Size must be a power of two.
8///
9/// # Example
10/// ```
11/// use rill_core::buffer::RingBuffer;
12///
13/// let mut buffer = RingBuffer::<f32, 4>::new();
14/// buffer.write(1.0);
15/// buffer.write(2.0);
16/// assert_eq!(buffer.read_delayed(0), 2.0);
17/// ```
18#[repr(C, align(64))]
19pub struct RingBuffer<T: Transcendental, const N: usize> {
20    data: [T; N],
21    head: usize,
22    tail: usize,
23    mask: usize,
24    full: bool,
25}
26
27impl<T: Transcendental, const N: usize> RingBuffer<T, N> {
28    /// Create a new ring buffer.
29    ///
30    /// # Panics
31    /// Panics if `N` is not a power of two.
32    pub fn new() -> Self {
33        assert!(N.is_power_of_two(), "RingBuffer size must be power of two");
34        Self {
35            data: [T::ZERO; N],
36            head: 0,
37            tail: 0,
38            mask: N - 1,
39            full: false,
40        }
41    }
42
43    /// Write a single sample, advancing the head cursor.
44    pub fn write(&mut self, sample: T) {
45        self.data[self.head] = sample;
46        let next_head = (self.head + 1) & self.mask;
47        self.head = next_head;
48        if next_head == self.tail {
49            self.full = true;
50        }
51    }
52
53    /// Write multiple samples in sequence.
54    pub fn write_slice(&mut self, samples: &[T])
55    where
56        T: Copy,
57    {
58        for &sample in samples {
59            self.write(sample);
60        }
61    }
62
63    /// Read the oldest sample, or `None` if empty.
64    pub fn read(&mut self) -> Option<T> {
65        if self.tail == self.head && !self.full {
66            return None;
67        }
68        let sample = self.data[self.tail];
69        self.tail = (self.tail + 1) & self.mask;
70        self.full = false;
71        Some(sample)
72    }
73
74    /// Read a sample at `delay` samples behind head (0 = most recent).
75    ///
76    /// # Panics
77    /// Panics if `delay >= len()`.
78    pub fn read_delayed(&self, delay: usize) -> T {
79        assert!(delay < self.len(), "Delay must be less than buffer length");
80        let read_pos = (self.head + self.capacity() - delay - 1) & self.mask;
81        self.data[read_pos]
82    }
83
84    /// Read with linear interpolation between samples at fractional delay.
85    pub fn read_interpolated(&self, delay_frac: f32) -> T
86    where
87        T: From<f32> + Into<f32>,
88    {
89        let delay_int = delay_frac.floor() as usize;
90        let frac = delay_frac.fract();
91        if frac == 0.0 {
92            return self.read_delayed(delay_int);
93        }
94        let s1: f32 = self.read_delayed(delay_int).into();
95        let prev = if delay_int == 0 {
96            self.len() - 1
97        } else {
98            delay_int - 1
99        };
100        let s2: f32 = self.read_delayed(prev).into();
101        T::from(s1 * (1.0 - frac) + s2 * frac)
102    }
103
104    /// Read a sequence of interpolated samples into the output buffer,
105    /// starting at `start_delay` samples behind head.
106    pub fn read_sequence_interpolated(&self, start_delay: f32, output: &mut [T])
107    where
108        T: From<f32> + Into<f32>,
109    {
110        let len = self.len();
111        for (i, out) in output.iter_mut().enumerate() {
112            let delay = start_delay + i as f32;
113            *out = if delay < len as f32 {
114                self.read_interpolated(delay)
115            } else {
116                T::ZERO
117            };
118        }
119    }
120
121    /// Number of samples currently stored.
122    pub fn len(&self) -> usize {
123        if self.full {
124            N
125        } else if self.head >= self.tail {
126            self.head - self.tail
127        } else {
128            N - self.tail + self.head
129        }
130    }
131
132    /// Maximum capacity (const generic parameter).
133    pub const fn capacity(&self) -> usize {
134        N
135    }
136    /// Whether the buffer has no samples.
137    pub fn is_empty(&self) -> bool {
138        self.head == self.tail && !self.full
139    }
140    /// Whether the buffer is completely full.
141    pub fn is_full(&self) -> bool {
142        self.full
143    }
144
145    /// Clear all samples and reset cursors.
146    pub fn clear(&mut self) {
147        self.data.fill(T::ZERO);
148        self.head = 0;
149        self.tail = 0;
150        self.full = false;
151    }
152
153    /// Reset cursors without zeroing the data.
154    pub fn reset(&mut self) {
155        self.head = 0;
156        self.tail = 0;
157        self.full = false;
158    }
159}
160
161impl<T: Transcendental, const N: usize> Default for RingBuffer<T, N> {
162    fn default() -> Self {
163        Self::new()
164    }
165}
166
167impl<T: Transcendental + fmt::Debug, const N: usize> fmt::Debug for RingBuffer<T, N> {
168    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
169        let mut preview = Vec::with_capacity(4);
170        for i in 0..4.min(N) {
171            preview.push(self.data[i]);
172        }
173        f.debug_struct("RingBuffer")
174            .field("head", &self.head)
175            .field("tail", &self.tail)
176            .field("full", &self.full)
177            .field("len", &self.len())
178            .field("capacity", &N)
179            .field("preview", &preview)
180            .finish()
181    }
182}
183
184// =============================================================================
185// Итератор
186// =============================================================================
187
188/// Iterator over the contents of a [`RingBuffer`], from oldest to newest.
189pub struct RingBufferIter<'a, T: Transcendental, const N: usize> {
190    buffer: &'a RingBuffer<T, N>,
191    pos: usize,
192    end: usize,
193}
194
195impl<'a, T: Transcendental, const N: usize> RingBufferIter<'a, T, N> {
196    fn new(buffer: &'a RingBuffer<T, N>) -> Self {
197        let tail = buffer.tail;
198        let head = buffer.head;
199        let len = if buffer.full {
200            N
201        } else if head >= tail {
202            head - tail
203        } else {
204            N - tail + head
205        };
206        Self {
207            buffer,
208            pos: tail,
209            end: tail + len,
210        }
211    }
212}
213
214impl<'a, T: Transcendental, const N: usize> Iterator for RingBufferIter<'a, T, N> {
215    type Item = T;
216    fn next(&mut self) -> Option<Self::Item> {
217        if self.pos >= self.end {
218            None
219        } else {
220            let idx = self.pos & self.buffer.mask;
221            let value = self.buffer.data[idx];
222            self.pos += 1;
223            Some(value)
224        }
225    }
226}
227
228impl<'a, T: Transcendental, const N: usize> ExactSizeIterator for RingBufferIter<'a, T, N> {
229    fn len(&self) -> usize {
230        self.end - self.pos
231    }
232}
233
234impl<T: Transcendental, const N: usize> RingBuffer<T, N> {
235    /// Iterate over buffered samples from oldest to newest.
236    pub fn iter(&self) -> RingBufferIter<'_, T, N> {
237        RingBufferIter::new(self)
238    }
239}
240
241// =============================================================================
242// Тесты
243// =============================================================================
244
245#[cfg(test)]
246mod tests {
247    use super::*;
248
249    #[test]
250    fn test_ring_buffer_basic() {
251        let mut buffer = RingBuffer::<f32, 4>::new();
252        buffer.write(1.0);
253        buffer.write(2.0);
254        buffer.write(3.0);
255        buffer.write(4.0);
256        assert!(buffer.is_full());
257        assert_eq!(buffer.len(), 4);
258        assert_eq!(buffer.read(), Some(1.0));
259        assert_eq!(buffer.read(), Some(2.0));
260        assert_eq!(buffer.read(), Some(3.0));
261        assert_eq!(buffer.read(), Some(4.0));
262        assert_eq!(buffer.read(), None);
263        assert!(buffer.is_empty());
264    }
265
266    #[test]
267    fn test_ring_buffer_wraparound() {
268        let mut buffer = RingBuffer::<f32, 4>::new();
269        for i in 0..10 {
270            buffer.write(i as f32);
271        }
272        assert_eq!(buffer.read_delayed(0), 9.0);
273        assert_eq!(buffer.read_delayed(1), 8.0);
274        assert_eq!(buffer.read_delayed(2), 7.0);
275        assert_eq!(buffer.read_delayed(3), 6.0);
276    }
277
278    #[test]
279    fn test_ring_buffer_interpolated() {
280        let mut buffer = RingBuffer::<f32, 4>::new();
281        buffer.write(1.0);
282        buffer.write(2.0);
283        buffer.write(3.0);
284        buffer.write(4.0);
285        let val = buffer.read_interpolated(1.5);
286        assert!((val - 3.5).abs() < 0.001);
287    }
288
289    #[test]
290    fn test_ring_buffer_clear() {
291        let mut buffer = RingBuffer::<f32, 4>::new();
292        buffer.write(1.0);
293        buffer.write(2.0);
294        assert!(!buffer.is_empty());
295        buffer.clear();
296        assert!(buffer.is_empty());
297    }
298
299    #[test]
300    fn test_ring_buffer_iterator() {
301        let mut buffer = RingBuffer::<f32, 4>::new();
302        buffer.write(1.0);
303        buffer.write(2.0);
304        buffer.write(3.0);
305        buffer.write(4.0);
306        let collected: Vec<f32> = buffer.iter().collect();
307        assert_eq!(collected, vec![1.0, 2.0, 3.0, 4.0]);
308    }
309
310    #[test]
311    fn test_ring_buffer_read_sequence() {
312        let mut buffer = RingBuffer::<f32, 4>::new();
313        buffer.write(1.0);
314        buffer.write(2.0);
315        buffer.write(3.0);
316        buffer.write(4.0);
317        let mut output = [0.0; 4];
318        buffer.read_sequence_interpolated(0.0, &mut output);
319        assert_eq!(output, [4.0, 3.0, 2.0, 1.0]);
320    }
321
322    #[test]
323    #[should_panic(expected = "Delay must be less than buffer length")]
324    fn test_ring_buffer_invalid_delay() {
325        let buffer = RingBuffer::<f32, 4>::new();
326        let _ = buffer.read_delayed(4);
327    }
328
329    #[test]
330    fn test_ring_buffer_write_slice() {
331        let mut buffer = RingBuffer::<f32, 4>::new();
332        buffer.write_slice(&[1.0, 2.0, 3.0, 4.0]);
333        assert_eq!(buffer.read(), Some(1.0));
334        assert_eq!(buffer.read(), Some(2.0));
335        assert_eq!(buffer.read(), Some(3.0));
336        assert_eq!(buffer.read(), Some(4.0));
337    }
338}