rill_core/buffer/
delay.rs1use crate::buffer::{AtomicStats, SignalBuffer, BufferStats};
2use crate::math::Transcendental;
3use core::marker::PhantomData;
4use core::ops::{Index, IndexMut};
5
6#[repr(align(64))]
17pub struct DelayLine<T: Transcendental, const MAX_DELAY: usize> {
18 buffer: [T; MAX_DELAY],
19 write_pos: usize,
20 delay_samples: usize,
21 sample_rate: f32,
22 stats: AtomicStats,
23 _phantom: PhantomData<T>,
24}
25
26impl<T: Transcendental, const MAX_DELAY: usize> DelayLine<T, MAX_DELAY> {
27 pub fn new(sample_rate: f32) -> Self {
32 assert!(MAX_DELAY > 0, "DelayLine must have MAX_DELAY > 0");
33 Self {
34 buffer: [T::ZERO; MAX_DELAY],
35 write_pos: 0,
36 delay_samples: 0,
37 sample_rate,
38 stats: AtomicStats::new(),
39 _phantom: PhantomData,
40 }
41 }
42
43 pub fn set_delay(&mut self, delay_sec: f32) {
45 let samples = (delay_sec * self.sample_rate) as usize;
46 self.delay_samples = samples.min(MAX_DELAY - 1);
47 }
48
49 pub fn set_delay_samples(&mut self, samples: usize) {
51 self.delay_samples = samples.min(MAX_DELAY - 1);
52 }
53
54 pub fn delay_samples(&self) -> usize { self.delay_samples }
56 pub const fn max_delay(&self) -> usize { MAX_DELAY }
58 pub fn sample_rate(&self) -> f32 { self.sample_rate }
60
61 #[inline(always)]
63 pub fn write(&mut self, input: T) -> T {
64 self.buffer[self.write_pos] = input;
65 let read_pos = if self.write_pos >= self.delay_samples {
66 self.write_pos - self.delay_samples
67 } else {
68 MAX_DELAY + self.write_pos - self.delay_samples
69 };
70 let output = self.buffer[read_pos];
71 self.write_pos = (self.write_pos + 1) % MAX_DELAY;
72 self.stats.record_write();
73 self.stats.record_read();
74 self.stats.update_peak(MAX_DELAY);
75 output
76 }
77
78 #[inline(always)]
80 pub fn read(&self) -> T {
81 let read_pos = if self.write_pos >= self.delay_samples {
82 self.write_pos - self.delay_samples
83 } else {
84 MAX_DELAY + self.write_pos - self.delay_samples
85 };
86 self.buffer[read_pos]
87 }
88
89 #[inline(always)]
91 pub fn read_delayed(&self, delay: usize) -> T {
92 debug_assert!(delay < MAX_DELAY, "Delay {} out of range (max {})", delay, MAX_DELAY);
93 let read_pos = if self.write_pos > delay {
94 self.write_pos - 1 - delay
95 } else {
96 MAX_DELAY + self.write_pos - 1 - delay
97 };
98 self.buffer[read_pos]
99 }
100
101 #[inline(always)]
103 pub fn read_interpolated(&self, delay_frac: f32) -> T {
104 let delay_int = delay_frac.floor() as usize;
105 let frac = T::from_f32(delay_frac.fract());
106 let s1 = self.read_delayed(delay_int);
107 if delay_int == MAX_DELAY - 1 {
108 s1
109 } else {
110 let s2 = self.read_delayed(delay_int + 1);
111 s1 + (s2 - s1) * frac
112 }
113 }
114
115 pub fn clear(&mut self) {
117 self.buffer.fill(T::ZERO);
118 self.write_pos = 0;
119 self.stats.reset();
120 }
121
122 pub fn write_position(&self) -> usize { self.write_pos }
124}
125
126impl<T: Transcendental, const MAX_DELAY: usize> Index<usize> for DelayLine<T, MAX_DELAY> {
131 type Output = T;
132 fn index(&self, index: usize) -> &Self::Output {
133 &self.buffer[index]
134 }
135}
136
137impl<T: Transcendental, const MAX_DELAY: usize> IndexMut<usize> for DelayLine<T, MAX_DELAY> {
138 fn index_mut(&mut self, index: usize) -> &mut Self::Output {
139 &mut self.buffer[index]
140 }
141}
142
143impl<T: Transcendental, const MAX_DELAY: usize> SignalBuffer<T> for DelayLine<T, MAX_DELAY> {
148 fn capacity(&self) -> usize { MAX_DELAY }
149 fn len(&self) -> usize { MAX_DELAY }
150 fn is_empty(&self) -> bool { false }
151 fn is_full(&self) -> bool { true }
152 fn clear(&mut self) { self.clear(); }
153 fn stats(&self) -> BufferStats {
154 let mut stats = self.stats.snapshot();
155 stats.fill_level = 1.0;
156 stats
157 }
158 fn reset_stats(&mut self) { self.stats.reset(); }
159}
160
161#[cfg(test)]
166mod tests {
167 use super::*;
168
169 #[test]
170 fn test_delay_line_basic() {
171 let mut delay = DelayLine::<f32, 1024>::new(44100.0);
172 delay.set_delay_samples(100);
173 for i in 0..200 {
174 let out = delay.write(i as f32);
175 if i >= 100 {
176 assert_eq!(out, (i - 100) as f32);
177 }
178 }
179 }
180
181 #[test]
182 fn test_delay_line_read_delayed() {
183 let mut delay = DelayLine::<f32, 1024>::new(44100.0);
184 for i in 0..1024 { delay.write(i as f32); }
185 assert_eq!(delay.read_delayed(0), 1023.0);
186 assert_eq!(delay.read_delayed(100), 923.0);
187 }
188
189 #[test]
190 fn test_delay_line_interpolation() {
191 let mut delay = DelayLine::<f32, 1024>::new(44100.0);
192 for i in 0..1024 { delay.write(i as f32); }
193 let val = delay.read_interpolated(100.5);
194 assert!((val - 922.5).abs() < 0.01);
195 }
196}