use std::ptr::slice_from_raw_parts_mut;
use super::RawVal;
#[repr(C)]
pub(super) struct Ringbuffer<'a> {
read_idx: &'a mut u64,
write_idx: &'a mut u64,
data: &'a mut [u64],
}
impl<'a> Ringbuffer<'a> {
pub fn new(head: *mut u64, size_in_samples: u64) -> Self {
let (read_idx, write_idx, data) = unsafe {
let read_idx = head.as_mut().unwrap_unchecked();
let write_ptr = head.offset(1);
let write_idx = write_ptr.as_mut().unwrap_unchecked();
let data_head = head.offset(2);
let data = slice_from_raw_parts_mut(data_head, size_in_samples as usize);
(read_idx, write_idx, data.as_mut().unwrap())
};
Self {
read_idx,
write_idx,
data,
}
}
pub fn process(&mut self, input: RawVal, time_raw: u64) -> RawVal {
let len = self.data.len() as u64;
if len == 0 {
return 0;
}
unsafe {
let delay_time = f64::from_bits(time_raw);
let max_delay = (len - 1) as f64;
let delay_samples = delay_time.clamp(0.0, max_delay) as u64;
let write_idx = *self.write_idx % len;
let read_idx = (write_idx + len - delay_samples) % len;
let res = *self.data.get_unchecked(read_idx as usize);
*self.data.get_unchecked_mut(write_idx as usize) = input;
*self.read_idx = read_idx;
*self.write_idx = (write_idx + 1) % len;
res
}
}
}