use crossbeam_channel::Receiver;
use fundsp::prelude32::*;
const BASE_ID: u64 = 0x1337;
#[derive(Clone)]
pub struct Input<F: Real> {
receiver: Receiver<(F, F)>,
}
impl<F: Real> AudioNode for Input<F> {
const ID: u64 = BASE_ID;
type Inputs = U0;
type Outputs = U2;
#[inline]
fn tick(&mut self, _input: &Frame<f32, Self::Inputs>) -> Frame<f32, Self::Outputs> {
let (left, right) = self
.receiver
.recv()
.inspect_err(|e| {
tracing::error!(error =? e);
})
.unwrap_or_else(|_| (F::zero(), F::zero()));
[convert(left), convert(right)].into()
}
}
pub fn input<F: Real>(receiver: Receiver<(F, F)>) -> An<Input<F>> {
An(Input { receiver })
}
#[derive(Clone)]
pub struct AlphaLpf<F: Real> {
alpha: F,
previous: F,
}
impl<F: Real> AudioNode for AlphaLpf<F> {
const ID: u64 = BASE_ID + 1;
type Inputs = U1;
type Outputs = U1;
#[inline]
fn tick(&mut self, input: &Frame<f32, Self::Inputs>) -> Frame<f32, Self::Outputs> {
let x = convert(input[0]);
let value = (F::one() - self.alpha) * x + self.alpha * self.previous;
self.previous = x;
[convert(value)].into()
}
fn reset(&mut self) {
self.previous = F::zero();
}
}
pub fn alpha_lpf<F: Real>(alpha: F) -> An<AlphaLpf<F>> {
An(AlphaLpf {
alpha,
previous: F::zero(),
})
}
#[derive(Clone)]
pub struct FullWaveRectification<F: Real> {
_marker: std::marker::PhantomData<F>,
}
impl<F: Real> AudioNode for FullWaveRectification<F> {
const ID: u64 = BASE_ID + 2;
type Inputs = U1;
type Outputs = U1;
#[inline]
fn tick(&mut self, input: &Frame<f32, Self::Inputs>) -> Frame<f32, Self::Outputs> {
[convert(input[0].abs())].into()
}
fn process(&mut self, size: usize, input: &BufferRef, output: &mut BufferMut) {
(0..simd_items(size)).for_each(|i| {
let input = input.channel(0)[i];
let output = &mut output.channel_mut(0)[i];
*output = input.abs();
});
}
}
pub fn fwr<F: Real>() -> An<FullWaveRectification<F>> {
An(FullWaveRectification {
_marker: std::marker::PhantomData,
})
}