unnieversal/crates/utils/src/delay.rs

89 lines
2.2 KiB
Rust

pub struct DelayLine<const LEN: usize> {
buffer: [f32; LEN],
index: usize,
}
impl<const LEN: usize> DelayLine<LEN> {
pub fn new() -> Self {
Self {
buffer: [0.0; LEN],
index: 0,
}
}
pub fn read_slice(&self, slice: &mut [f32]) {
// Copy values in order
for i in 0..LEN {
slice[i] = self.wrapped_index(self.index + i);
}
}
pub fn write_and_advance(&mut self, value: f32) {
self.buffer[self.index] = value;
if self.index == LEN - 1 {
self.index = 0;
} else {
self.index += 1;
}
}
/// Returns the sample at idx after taking modulo LEN
pub fn wrapped_index(&self, idx: usize) -> f32 {
self.buffer[idx % LEN]
}
/// Indexes the buffer but interpolates between the current and the next sample
pub fn floating_index(&self, val: f32) -> f32 {
let idx = val.trunc() as usize;
let frac = val.fract();
// TODO uhm idk what this should be, but we don't want an underflow so yeah,
let xm1 = if idx == 0 {
0.0
} else {
self.wrapped_index(idx - 1)
};
let x0 = self.wrapped_index(idx);
let x1 = self.wrapped_index(idx + 1);
let x2 = self.wrapped_index(idx + 2);
// linear interpolation
// return (1.0 - frac) * x0 + frac * x1;
crate::hermite(frac, xm1, x0, x1, x2)
}
/// Get a reference to the delay line's index.
pub fn idx(&self) -> &usize {
&self.index
}
/// Get a reference to the delay line's buffer.
pub fn buffer(&self) -> &[f32; LEN] {
&self.buffer
}
}
pub struct DelayLines<const LEN: usize> {
pub l: DelayLine<LEN>,
pub r: DelayLine<LEN>,
}
impl<const LEN: usize> DelayLines<LEN> {
pub fn new() -> Self {
Self {
l: DelayLine::<LEN>::new(),
r: DelayLine::<LEN>::new(),
}
}
pub fn read_slices(&self, l: &mut [f32], r: &mut [f32]) {
self.l.read_slice(l);
self.r.read_slice(r);
}
pub fn write_and_advance(&mut self, l: f32, r: f32) {
self.l.write_and_advance(l);
self.r.write_and_advance(r);
}
}