1use crate::buffer::Buffer;
2use crate::math::Transcendental;
3use std::cell::UnsafeCell;
4use std::rc::Rc;
5
6#[derive(Debug)]
28pub struct TapeLoop<T> {
29 buffer: Box<[T]>,
30 capacity: usize,
31 write_pos: usize,
32}
33
34impl<T: Transcendental> TapeLoop<T> {
35 pub fn new(capacity: usize) -> Option<Self> {
37 if capacity == 0 {
38 return None;
39 }
40 let mut vec = Vec::with_capacity(capacity);
41 for _ in 0..capacity {
42 vec.push(T::ZERO);
43 }
44 Some(Self {
45 buffer: vec.into_boxed_slice(),
46 capacity,
47 write_pos: 0,
48 })
49 }
50
51 pub fn capacity(&self) -> usize {
53 self.capacity
54 }
55 pub fn write_pos(&self) -> usize {
57 self.write_pos
58 }
59
60 #[inline(always)]
62 pub fn write(&mut self, sample: T) {
63 self.buffer[self.write_pos] = sample;
64 self.write_pos = (self.write_pos + 1) % self.capacity;
65 }
66
67 #[inline(always)]
69 pub fn read(&self, delay: usize) -> T {
70 let d = delay.min(self.capacity - 1);
71 let read_pos = if self.write_pos > d {
72 self.write_pos - 1 - d
73 } else {
74 self.capacity + self.write_pos - 1 - d
75 };
76 self.buffer[read_pos]
77 }
78
79 #[inline(always)]
81 pub fn read_interpolated(&self, delay: f64) -> T {
82 let d = delay as usize;
83 let frac = T::from_f64(delay.fract());
84 let s1 = self.read(d);
85 let s2 = self.read(d + 1);
86 s1 + (s2 - s1) * frac
87 }
88
89 #[inline(always)]
91 pub fn write_block(&mut self, block: &[T]) {
92 let len = block.len().min(self.capacity);
93 for (i, &b) in block.iter().enumerate().take(len) {
94 self.buffer[(self.write_pos + i) % self.capacity] = b;
95 }
96 self.write_pos = (self.write_pos + len) % self.capacity;
97 }
98
99 #[inline(always)]
101 pub fn read_block(&self, delay: usize, output: &mut [T]) {
102 let len = output.len().min(self.capacity);
103 let d = delay.min(self.capacity - 1);
104 for (i, out) in output.iter_mut().enumerate().take(len) {
105 *out = self.read(d + len - 1 - i);
106 }
107 }
108
109 pub fn fill(&mut self, value: T) {
111 for slot in self.buffer.iter_mut() {
112 *slot = value;
113 }
114 }
115
116 pub fn clear(&mut self) {
118 for slot in self.buffer.iter_mut() {
119 *slot = T::ZERO;
120 }
121 self.write_pos = 0;
122 }
123}
124
125impl<T: Transcendental> Buffer<T> for TapeLoop<T> {
128 fn capacity(&self) -> usize {
129 self.capacity
130 }
131
132 fn len(&self) -> usize {
133 self.capacity
134 }
135
136 fn as_slice(&self) -> &[T] {
137 &self.buffer
138 }
139
140 fn as_mut_slice(&mut self) -> &mut [T] {
141 &mut self.buffer
142 }
143
144 fn fill(&mut self, value: T) {
145 for slot in self.buffer.iter_mut() {
146 *slot = value;
147 }
148 }
149
150 fn copy_from(&mut self, src: &[T]) {
151 let len = src.len().min(self.capacity);
152 self.buffer[..len].copy_from_slice(&src[..len]);
153 }
154
155 fn clear(&mut self) {
156 for slot in self.buffer.iter_mut() {
157 *slot = T::ZERO;
158 }
159 self.write_pos = 0;
160 }
161}
162
163struct TapeCell<T> {
173 inner: Rc<UnsafeCell<TapeLoop<T>>>,
174}
175
176impl<T> Clone for TapeCell<T> {
177 fn clone(&self) -> Self {
178 Self {
179 inner: Rc::clone(&self.inner),
180 }
181 }
182}
183
184impl<T> TapeCell<T> {
185 fn new(tape: TapeLoop<T>) -> Self {
186 Self {
187 inner: Rc::new(UnsafeCell::new(tape)),
188 }
189 }
190}
191
192pub struct TapeWriter<T> {
197 cell: TapeCell<T>,
198}
199
200pub struct TapeReader<T> {
205 cell: TapeCell<T>,
206}
207
208impl<T> Clone for TapeReader<T> {
209 fn clone(&self) -> Self {
210 Self {
211 cell: self.cell.clone(),
212 }
213 }
214}
215
216pub fn tape_handles<T>(tape: TapeLoop<T>) -> (TapeWriter<T>, TapeReader<T>) {
221 let cell = TapeCell::new(tape);
222 (TapeWriter { cell: cell.clone() }, TapeReader { cell })
223}
224
225impl<T: Transcendental> TapeWriter<T> {
226 #[allow(unsafe_code)]
231 #[inline(always)]
232 fn tape_mut(&mut self) -> &mut TapeLoop<T> {
233 unsafe { &mut *self.cell.inner.get() }
234 }
235
236 #[inline(always)]
238 pub fn write(&mut self, sample: T) {
239 self.tape_mut().write(sample);
240 }
241
242 #[inline(always)]
244 pub fn write_block(&mut self, block: &[T]) {
245 self.tape_mut().write_block(block);
246 }
247
248 pub fn fill(&mut self, value: T) {
250 self.tape_mut().fill(value);
251 }
252
253 pub fn clear(&mut self) {
255 self.tape_mut().clear();
256 }
257
258 pub fn capacity(&self) -> usize {
260 #[allow(unsafe_code)]
262 unsafe {
263 (*self.cell.inner.get()).capacity()
264 }
265 }
266}
267
268impl<T: Transcendental> TapeReader<T> {
269 #[allow(unsafe_code)]
273 #[inline(always)]
274 fn tape(&self) -> &TapeLoop<T> {
275 unsafe { &*self.cell.inner.get() }
276 }
277
278 #[inline(always)]
280 pub fn read(&self, delay: usize) -> T {
281 self.tape().read(delay)
282 }
283
284 #[inline(always)]
286 pub fn read_interpolated(&self, delay: f64) -> T {
287 self.tape().read_interpolated(delay)
288 }
289
290 #[inline(always)]
292 pub fn read_block(&self, delay: usize, output: &mut [T]) {
293 self.tape().read_block(delay, output);
294 }
295
296 pub fn capacity(&self) -> usize {
298 self.tape().capacity()
299 }
300}
301
302#[cfg(test)]
303mod tests {
304 use super::*;
305
306 #[test]
307 fn test_tape_basic_write_read() {
308 let mut tape = TapeLoop::<f32>::new(1024).unwrap();
309 tape.write(1.0);
310 tape.write(2.0);
311 tape.write(3.0);
312 assert_eq!(tape.read(0), 3.0);
313 assert_eq!(tape.read(1), 2.0);
314 assert_eq!(tape.read(2), 1.0);
315 }
316
317 #[test]
318 fn test_tape_wraparound() {
319 let mut tape = TapeLoop::<f32>::new(4).unwrap();
320 for i in 0..10 {
321 tape.write(i as f32);
322 }
323 assert_eq!(tape.read(0), 9.0);
324 assert_eq!(tape.read(1), 8.0);
325 assert_eq!(tape.read(2), 7.0);
326 assert_eq!(tape.read(3), 6.0);
327 }
328
329 #[test]
330 fn test_tape_block_ops() {
331 let mut tape = TapeLoop::<f32>::new(64).unwrap();
332 let block = [1.0f32; 64];
333 tape.write_block(&block);
334 let mut out = [0.0f32; 64];
335 tape.read_block(63, &mut out);
336 assert_eq!(out[0], 1.0);
337 }
338
339 #[test]
340 fn test_tape_large_capacity() {
341 let tape = TapeLoop::<f32>::new(1_000_000).unwrap();
342 assert_eq!(tape.capacity(), 1_000_000);
343 }
344
345 #[test]
346 fn test_tape_zero_capacity() {
347 assert!(TapeLoop::<f32>::new(0).is_none());
348 }
349
350 #[test]
351 fn test_read_interpolated() {
352 let mut tape = TapeLoop::<f32>::new(1024).unwrap();
353 tape.write(0.0);
354 tape.write(1.0);
355 let v = tape.read_interpolated(0.5);
356 assert!((v - 0.5).abs() < 0.01);
357 }
358}