use crate::prelude::*;
pub fn linear<S: smp::SampleBase>(x0: S, x1: S, t: unt::Val) -> S {
let t = t.inner();
x0 * (1.0 - t) + x1 * t
}
pub fn cubic<S: smp::SampleBase>(x0: S, x1: S, x2: S, x3: S, t: unt::Val) -> S {
let t = t.inner();
let a0 = x3 - x2 - x0 + x1;
let a1 = x0 - x1 - a0;
let a2 = x2 - x0;
let a3 = x1;
((a0 * t + a1) * t + a2) * t + a3
}
pub fn hermite<S: smp::SampleBase>(x0: S, x1: S, x2: S, x3: S, t: unt::Val) -> S {
let t = t.inner();
let diff = x1 - x2;
let c1 = x2 - x0;
let c3 = x3 - x0 + diff * 3.0;
let c2 = -(diff * 2.0 + c1 + c3);
((c3 * t + c2) * t + c1) * t * 0.5 + x1
}
pub trait Interpolate:
Map<Input = unt::Val, Output = <Self::Buf as buf::Buffer>::Item> + Ring + Sized
{
const LOOK_AHEAD: u8;
const SIZE: usize;
const EMPTY: Self;
fn init<S: SignalMut<Sample = <Self::Buf as buf::Buffer>::Item>>(sgn: &mut S) -> Self {
let mut inter = Self::EMPTY;
inter.push_many(sgn, Self::LOOK_AHEAD as usize + 1);
inter
}
}
macro_rules! ring_boilerplate {
() => {
fn buffer(&self) -> &Self::Buf {
self.0.buffer()
}
fn buffer_mut(&mut self) -> &mut Self::Buf {
self.0.buffer_mut()
}
fn get(&self, index: usize) -> <Self::Buf as Buffer>::Item {
self.0.get(index)
}
fn get_mut(&mut self, index: usize) -> &mut <Self::Buf as Buffer>::Item {
self.0.get_mut(index)
}
fn push(&mut self, sample: A) {
self.0.push(sample)
}
fn push_many<T: SignalMut<Sample = A>>(&mut self, sgn: &mut T, count: usize) {
self.0.push_many(sgn, count)
}
};
}
const fn shift_from<A: Audio, const N: usize>(array: [A; N]) -> buf::Shift<buf::Stc<A, N>> {
buf::Shift::new(buf::Stc::from_data(array))
}
#[derive(Clone, Copy, Debug, Default)]
pub struct Drop<A: Audio>(pub buf::ring::Shift<buf::Stc<A, 1>>);
impl<A: Audio> Drop<A> {
pub const fn new(sample: A) -> Self {
Self(shift_from([sample]))
}
pub const fn zero() -> Self {
Self::new(A::ZERO)
}
pub const fn array(&self) -> [A; 1] {
self.0.inner().data
}
pub const fn sample(&self) -> A {
self.array()[0]
}
}
impl<A: Audio> Map for Drop<A> {
type Input = unt::Val;
type Output = A;
fn eval(&self, _: unt::Val) -> A {
self.0.fst()
}
}
impl<A: Audio> Ring for Drop<A> {
type Buf = buf::Stc<A, 1>;
ring_boilerplate!();
}
impl<A: Audio> Interpolate for Drop<A> {
const LOOK_AHEAD: u8 = 0;
const SIZE: usize = 1;
const EMPTY: Self = Self::zero();
}
#[derive(Clone, Copy, Debug, Default)]
pub struct Linear<A: Audio>(pub buf::ring::Shift<buf::Stc<A, 2>>);
impl<A: Audio> Linear<A> {
pub const fn new(cur: A, next: A) -> Self {
Self(shift_from([cur, next]))
}
pub const fn zero() -> Self {
Self::new(A::ZERO, A::ZERO)
}
pub const fn array(&self) -> [A; 2] {
self.0.inner().data
}
}
impl<A: Audio> Map for Linear<A> {
type Input = unt::Val;
type Output = A;
fn eval(&self, t: unt::Val) -> A {
let arr = self.array();
linear(arr[0], arr[1], t)
}
}
impl<A: Audio> Ring for Linear<A> {
type Buf = buf::Stc<A, 2>;
ring_boilerplate!();
}
impl<A: Audio> Interpolate for Linear<A> {
const LOOK_AHEAD: u8 = 1;
const SIZE: usize = 2;
const EMPTY: Self = Self::zero();
}
pub struct Cubic<A: Audio>(pub buf::ring::Shift<buf::Stc<A, 4>>);
impl<A: Audio> Cubic<A> {
pub const fn new(x0: A, x1: A, x2: A, x3: A) -> Self {
Self(shift_from([x0, x1, x2, x3]))
}
pub const fn zero() -> Self {
Self::new(A::ZERO, A::ZERO, A::ZERO, A::ZERO)
}
pub const fn array(&self) -> [A; 4] {
self.0.inner().data
}
}
impl<A: Audio> Map for Cubic<A> {
type Input = unt::Val;
type Output = A;
fn eval(&self, t: unt::Val) -> A {
let arr = self.array();
cubic(arr[0], arr[1], arr[2], arr[3], t)
}
}
impl<A: Audio> Ring for Cubic<A> {
type Buf = buf::Stc<A, 4>;
ring_boilerplate!();
}
impl<A: Audio> Interpolate for Cubic<A> {
const LOOK_AHEAD: u8 = 2;
const SIZE: usize = 4;
const EMPTY: Self = Self::zero();
}
pub struct Hermite<A: Audio>(pub buf::ring::Shift<buf::Stc<A, 4>>);
impl<A: Audio> Hermite<A> {
pub const fn new(x0: A, x1: A, x2: A, x3: A) -> Self {
Self(shift_from([x0, x1, x2, x3]))
}
pub const fn zero() -> Self {
Self::new(A::ZERO, A::ZERO, A::ZERO, A::ZERO)
}
pub const fn array(&self) -> [A; 4] {
self.0.inner().data
}
}
impl<A: Audio> Map for Hermite<A> {
type Input = unt::Val;
type Output = A;
fn eval(&self, t: unt::Val) -> A {
let arr = self.array();
hermite(arr[0], arr[1], arr[2], arr[3], t)
}
}
impl<A: Audio> Ring for Hermite<A> {
type Buf = buf::Stc<A, 4>;
ring_boilerplate!();
}
impl<A: Audio> Interpolate for Hermite<A> {
const LOOK_AHEAD: u8 = 2;
const SIZE: usize = 4;
const EMPTY: Self = Self::zero();
}
pub struct Stretch<S: SignalMut, I: Interpolate>
where
I::Buf: buf::BufferMut<Item = S::Sample>,
{
sgn: S,
factor: f64,
inter: I,
val: unt::Val,
}
impl<S: SignalMut, I: Interpolate> Stretch<S, I>
where
I::Buf: buf::BufferMut<Item = S::Sample>,
{
pub fn new(mut sgn: S, factor: f64) -> Self {
Self {
inter: I::init(&mut sgn),
sgn,
factor,
val: unt::Val::ZERO,
}
}
pub const fn sgn(&self) -> &S {
&self.sgn
}
pub fn sgn_mut(&mut self) -> &mut S {
&mut self.sgn
}
pub fn factor(&self) -> f64 {
self.factor
}
pub const fn val(&self) -> unt::Val {
self.val
}
}
pub type DropStretch<S> = Stretch<S, Drop<<S as Signal>::Sample>>;
impl<S: SignalMut> DropStretch<S>
where
S::Sample: Audio,
{
pub fn new_drop(sgn: S, factor: f64) -> Self {
Self::new(sgn, factor)
}
}
pub type LinearStretch<S> = Stretch<S, Linear<<S as Signal>::Sample>>;
impl<S: SignalMut> LinearStretch<S>
where
S::Sample: Audio,
{
pub fn new_linear(sgn: S, factor: f64) -> Self {
Self::new(sgn, factor)
}
}
pub type CubicStretch<S> = Stretch<S, Cubic<<S as Signal>::Sample>>;
impl<S: SignalMut> CubicStretch<S>
where
S::Sample: Audio,
{
pub fn new_cubic(sgn: S, factor: f64) -> Self {
Self::new(sgn, factor)
}
}
pub type HermiteStretch<S> = Stretch<S, Hermite<<S as Signal>::Sample>>;
impl<S: SignalMut> HermiteStretch<S>
where
S::Sample: Audio,
{
pub fn new_hermite(sgn: S, factor: f64) -> Self {
Self::new(sgn, factor)
}
}
impl<S: SignalMut, I: Interpolate> Signal for Stretch<S, I>
where
I::Buf: buf::BufferMut<Item = S::Sample>,
{
type Sample = S::Sample;
fn get(&self) -> S::Sample {
self.inter.eval(self.val)
}
}
impl<S: SignalMut, I: Interpolate> SignalMut for Stretch<S, I>
where
I::Buf: buf::BufferMut<Item = S::Sample>,
{
fn advance(&mut self) {
let pos = self.val.inner() + self.factor;
#[allow(clippy::cast_sign_loss)]
#[allow(clippy::cast_possible_truncation)]
let count = pos.floor() as usize;
let val = unt::Val::fract(pos);
self.inter.push_many(&mut self.sgn, count);
self.val = val;
}
fn retrigger(&mut self) {
self.sgn.retrigger();
self.inter = I::init(self.sgn_mut());
}
}