use crate::{mod_inc, prelude::*};
pub trait Ring {
type Buf: buf::BufferMut;
fn buffer(&self) -> &Self::Buf;
fn buffer_mut(&mut self) -> &mut Self::Buf;
fn capacity(&self) -> usize {
self.buffer().len()
}
fn clear(&mut self) {
self.buffer_mut().clear();
}
fn push(&mut self, value: <Self::Buf as buf::Buffer>::Item);
fn push_many<S: SignalMut<Sample = <Self::Buf as buf::Buffer>::Item>>(
&mut self,
sgn: &mut S,
count: usize,
) {
for _ in 0..count {
self.push(sgn.next());
}
}
fn get(&self, index: usize) -> <Self::Buf as buf::Buffer>::Item;
fn get_mut(&mut self, index: usize) -> &mut <Self::Buf as buf::Buffer>::Item;
fn fst(&self) -> <Self::Buf as buf::Buffer>::Item {
self.get(0)
}
}
#[derive(Clone, Copy, Debug, Default)]
pub struct Shift<B: buf::BufferMut> {
pub inner: B,
}
impl<B: buf::BufferMut> Shift<B> {
pub const fn new(inner: B) -> Self {
Self { inner }
}
pub const fn inner(&self) -> &B {
&self.inner
}
}
fn shift<R: Ring>(ring: &mut R, index: usize, count: usize) {
let buf = ring.buffer_mut();
buf.as_mut()[index + count] = buf[index];
}
impl<B: buf::BufferMut> Ring for Shift<B> {
type Buf = B;
fn buffer(&self) -> &Self::Buf {
&self.inner
}
fn buffer_mut(&mut self) -> &mut Self::Buf {
&mut self.inner
}
fn get(&self, index: usize) -> <Self::Buf as buf::Buffer>::Item {
self.inner[index]
}
fn get_mut(&mut self, index: usize) -> &mut <Self::Buf as buf::Buffer>::Item {
&mut self.inner[index]
}
fn push(&mut self, value: B::Item) {
for i in (0..(self.capacity() - 1)).rev() {
shift(self, i, 1);
}
self.inner[0] = value;
}
fn push_many<S: SignalMut<Sample = <Self::Buf as buf::Buffer>::Item>>(
&mut self,
sgn: &mut S,
count: usize,
) {
let n = self.capacity();
let new = if count < n {
count
} else {
for _ in 0..(count - n) {
sgn.advance();
}
n
};
for i in (0..(self.capacity() - new)).rev() {
shift(self, i, new);
}
for val in self.inner.as_mut_slice()[..new].iter_mut().rev() {
*val = sgn.next();
}
}
}
#[derive(Clone, Debug, Default)]
pub struct Circ<B: buf::BufferMut> {
pub inner: B,
pos: usize,
}
impl<B: buf::BufferMut> Circ<B> {
pub const fn new(inner: B) -> Self {
Self { inner, pos: 0 }
}
fn index(&self, n: usize) -> usize {
(if self.pos > n {
self.pos - n
} else {
self.pos + self.capacity() - n
}) - 1
}
}
impl<B: buf::BufferMut> Ring for Circ<B> {
type Buf = B;
fn buffer(&self) -> &Self::Buf {
&self.inner
}
fn buffer_mut(&mut self) -> &mut Self::Buf {
&mut self.inner
}
fn get(&self, index: usize) -> <Self::Buf as buf::Buffer>::Item {
self.inner[self.index(index)]
}
fn get_mut(&mut self, index: usize) -> &mut <Self::Buf as buf::Buffer>::Item {
let idx = self.index(index);
&mut self.inner[idx]
}
fn push(&mut self, value: B::Item) {
let pos = self.pos;
self.buffer_mut()[pos] = value;
mod_inc(self.capacity(), &mut self.pos);
}
}
fn zst_mut<'a, T>() -> &'a mut T {
assert_eq!(std::mem::size_of::<T>(), 0);
unsafe { std::ptr::NonNull::dangling().as_mut() }
}
pub struct EmptyRing<A: Audio>(std::marker::PhantomData<A>);
const EMPTY_BUFFER: &str = "can't get an element from an empty buffer";
impl<A: Audio> Ring for EmptyRing<A> {
type Buf = buf::Empty<A>;
fn buffer(&self) -> &Self::Buf {
zst_mut()
}
fn buffer_mut(&mut self) -> &mut Self::Buf {
zst_mut()
}
fn push(&mut self, _: <Self::Buf as buf::Buffer>::Item) {
}
fn get(&self, _: usize) -> <Self::Buf as buf::Buffer>::Item {
panic!("{EMPTY_BUFFER}")
}
fn get_mut(&mut self, _: usize) -> &mut <Self::Buf as buf::Buffer>::Item {
panic!("{EMPTY_BUFFER}")
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn shift() {
let mut shift = Shift::new(buf::Stc::from_data(smp::Mono::array([3.0, 2.0, 1.0])));
shift.push(smp::Mono(4.0));
assert_eq!(shift.buffer().as_ref(), &smp::Mono::array([4.0, 3.0, 2.0]));
assert_eq!(shift.fst(), smp::Mono(4.0));
shift.push_many(
&mut gen::LoopBuf::new(buf::Stc::from_data(smp::Mono::array([5.0, 6.0]))),
2,
);
assert_eq!(shift.buffer().as_ref(), &smp::Mono::array([6.0, 5.0, 4.0]));
assert_eq!(shift.fst(), smp::Mono(6.0));
shift.push_many(
&mut gen::LoopBuf::new(buf::Stc::from_data(smp::Mono::array([7.0, 8.0, 9.0, 10.0]))),
4,
);
assert_eq!(shift.buffer().as_ref(), &smp::Mono::array([10.0, 9.0, 8.0]));
assert_eq!(shift.fst(), smp::Mono(10.0));
}
#[test]
fn ring() {
let mut ring = Circ::new(buf::Stc::from_data(smp::Mono::array([1.0, 2.0, 3.0])));
ring.push(smp::Mono(4.0));
assert_eq!(ring.buffer().as_ref(), &smp::Mono::array([4.0, 2.0, 3.0]));
assert_eq!(ring.fst(), smp::Mono(4.0));
ring.push_many(
&mut gen::LoopBuf::new(buf::Stc::from_data(smp::Mono::array([5.0, 6.0]))),
2,
);
assert_eq!(ring.buffer().as_ref(), &smp::Mono::array([4.0, 5.0, 6.0]));
assert_eq!(ring.fst(), smp::Mono(6.0));
ring.push_many(
&mut gen::LoopBuf::new(buf::Stc::from_data(smp::Mono::array([7.0, 8.0, 9.0, 10.0]))),
4,
);
assert_eq!(ring.buffer().as_ref(), &smp::Mono::array([10.0, 8.0, 9.0]));
assert_eq!(ring.fst(), smp::Mono(10.0));
}
}