use std::{cell::RefCell, fmt::Debug, iter, marker::PhantomData, rc::Rc};
use crate::arith::signed_to_01;
#[derive(Clone, Copy)]
pub struct SigCtx {
pub sample_rate_hz: f32,
pub batch_index: u64,
pub num_samples: usize,
}
impl SigCtx {
pub fn sample_period_s(&self) -> f32 {
self.num_samples as f32 / self.sample_rate_hz
}
}
pub trait Buf<T>
where
T: Clone,
{
fn iter(&self) -> impl Iterator<Item = T>;
fn clone_to_vec(&self, out: &mut Vec<T>) {
out.clear();
for x in self.iter() {
out.push(x.clone());
}
}
}
impl<T> Buf<T> for &Vec<T>
where
T: Clone,
{
fn iter(&self) -> impl Iterator<Item = T> {
(self as &[T]).iter().cloned()
}
fn clone_to_vec(&self, out: &mut Vec<T>) {
if let Some(first) = self.first() {
out.resize_with(self.len(), || first.clone());
out.clone_from_slice(self);
} else {
out.clear();
}
}
}
pub struct ConstBuf<T> {
pub value: T,
pub count: usize,
}
impl<T> Buf<T> for ConstBuf<T>
where
T: Clone,
{
fn iter(&self) -> impl Iterator<Item = T> {
iter::repeat_n(&self.value, self.count).cloned()
}
fn clone_to_vec(&self, out: &mut Vec<T>) {
out.resize_with(self.count, || self.value.clone());
out.fill(self.value.clone());
}
}
pub struct MapBuf<B, F, I, O>
where
I: Clone,
O: Clone,
B: Buf<I>,
F: Fn(I) -> O,
{
buf: B,
f: F,
phantom: PhantomData<(I, O)>,
}
impl<B, F, I, O> MapBuf<B, F, I, O>
where
I: Clone,
O: Clone,
B: Buf<I>,
F: Fn(I) -> O,
{
pub fn new(buf: B, f: F) -> Self {
Self {
buf,
f,
phantom: PhantomData,
}
}
}
impl<B, F, I, O> Buf<O> for MapBuf<B, F, I, O>
where
I: Clone,
O: Clone,
B: Buf<I>,
F: Fn(I) -> O,
{
fn iter(&self) -> impl Iterator<Item = O> {
self.buf.iter().map(&self.f)
}
}
pub struct MapBuf2<BL, BR, F, L, R, O>
where
L: Clone,
R: Clone,
O: Clone,
BL: Buf<L>,
BR: Buf<R>,
F: Fn(L, R) -> O,
{
buf_left: BL,
buf_right: BR,
f: F,
phantom: PhantomData<(L, R, O)>,
}
impl<BL, BR, F, L, R, O> MapBuf2<BL, BR, F, L, R, O>
where
L: Clone,
R: Clone,
O: Clone,
BL: Buf<L>,
BR: Buf<R>,
F: Fn(L, R) -> O,
{
pub fn new(buf_left: BL, buf_right: BR, f: F) -> Self {
Self {
buf_left,
buf_right,
f,
phantom: PhantomData,
}
}
}
impl<BL, BR, F, L, R, O> Buf<O> for MapBuf2<BL, BR, F, L, R, O>
where
L: Clone,
R: Clone,
O: Clone,
BL: Buf<L>,
BR: Buf<R>,
F: Fn(L, R) -> O,
{
fn iter(&self) -> impl Iterator<Item = O> {
self.buf_left
.iter()
.zip(self.buf_right.iter())
.map(|(l, r)| (self.f)(l, r))
}
}
pub struct ZipBuf<BL, BR, L, R>
where
L: Clone,
R: Clone,
BL: Buf<L>,
BR: Buf<R>,
{
buf_left: BL,
buf_right: BR,
phantom: PhantomData<(L, R)>,
}
impl<BL, BR, L, R> ZipBuf<BL, BR, L, R>
where
L: Clone,
R: Clone,
BL: Buf<L>,
BR: Buf<R>,
{
pub fn new(buf_left: BL, buf_right: BR) -> Self {
Self {
buf_left,
buf_right,
phantom: PhantomData,
}
}
}
impl<BL, BR, L, R> Buf<(L, R)> for ZipBuf<BL, BR, L, R>
where
L: Clone,
R: Clone,
BL: Buf<L>,
BR: Buf<R>,
{
fn iter(&self) -> impl Iterator<Item = (L, R)> {
self.buf_left.iter().zip(self.buf_right.iter())
}
}
pub trait SigT {
type Item: Clone;
fn sample(&mut self, ctx: &SigCtx) -> impl Buf<Self::Item>;
fn filter<F>(self, filter: F) -> Sig<F::Out<Self>>
where
F: Filter<ItemIn = Self::Item>,
Self: Sized,
{
Sig(filter.into_sig(self))
}
}
pub trait SigSampleIntoBufT {
type Item: Clone;
fn sample_into_buf(&mut self, ctx: &SigCtx, buf: &mut Vec<Self::Item>);
}
impl SigT for f32 {
type Item = f32;
fn sample(&mut self, ctx: &SigCtx) -> impl Buf<Self::Item> {
ConstBuf {
value: *self,
count: ctx.num_samples,
}
}
}
impl SigT for bool {
type Item = bool;
fn sample(&mut self, ctx: &SigCtx) -> impl Buf<Self::Item> {
ConstBuf {
value: *self,
count: ctx.num_samples,
}
}
}
pub struct SigConst<T: Clone>(T);
impl<T: Clone> SigT for SigConst<T> {
type Item = T;
fn sample(&mut self, ctx: &SigCtx) -> impl Buf<Self::Item> {
ConstBuf {
value: self.0.clone(),
count: ctx.num_samples,
}
}
}
#[derive(Clone)]
pub struct Sig<S>(pub S)
where
S: SigT;
impl<S: SigT> SigT for Sig<S> {
type Item = S::Item;
fn sample(&mut self, ctx: &SigCtx) -> impl Buf<Self::Item> {
self.0.sample(ctx)
}
}
impl<S: SigT> SigSampleIntoBufT for Sig<S> {
type Item = S::Item;
fn sample_into_buf(&mut self, ctx: &SigCtx, buf: &mut Vec<Self::Item>) {
let buf_internal = self.0.sample(ctx);
buf_internal.clone_to_vec(buf);
}
}
pub struct SigBoxed<T>(Box<dyn SigSampleIntoBufT<Item = T>>)
where
T: Clone;
impl<T> SigSampleIntoBufT for SigBoxed<T>
where
T: Clone,
{
type Item = T;
fn sample_into_buf(&mut self, ctx: &SigCtx, buf: &mut Vec<Self::Item>) {
self.0.sample_into_buf(ctx, buf);
}
}
impl<S> Sig<S>
where
S: SigT<Item: Clone>,
{
pub fn map_mut<T, F>(self, f: F) -> Sig<MapMut<S, T, F>>
where
T: Clone,
F: FnMut(S::Item) -> T,
{
Sig(MapMut {
sig: self.0,
f,
buf: Vec::new(),
})
}
pub fn map_mut_ctx<T, F>(self, f: F) -> Sig<MapMutCtx<S, T, F>>
where
T: Clone,
F: FnMut(S::Item, &SigCtx) -> T,
{
Sig(MapMutCtx {
sig: self.0,
f,
buf: Vec::new(),
})
}
pub fn map<T, F>(self, f: F) -> Sig<Map<S, T, F>>
where
T: Clone,
F: Fn(S::Item) -> T,
{
Sig(Map { sig: self.0, f })
}
pub fn map_ctx<T, F>(self, f: F) -> Sig<MapCtx<S, T, F>>
where
T: Clone,
F: Fn(S::Item, &SigCtx) -> T,
{
Sig(MapCtx { sig: self.0, f })
}
pub fn zip<O>(self, other: O) -> Sig<Zip<S, O>>
where
O: SigT,
{
Sig(Zip {
a: self.0,
b: other,
})
}
pub fn shared(self) -> Sig<SigShared<S>> {
sig_shared(self.0)
}
pub fn debug<F: FnMut(&S::Item)>(
self,
mut f: F,
) -> Sig<impl SigT<Item = S::Item>> {
self.map_mut(move |x| {
f(&x);
x
})
}
}
impl<S> Sig<S>
where
S: SigT + 'static,
{
pub fn boxed(self) -> SigBoxed<S::Item> {
SigBoxed(Box::new(self))
}
}
impl<S> Sig<S>
where
S: SigT<Item: Debug>,
{
pub fn debug_print(self) -> Sig<impl SigT<Item = S::Item>> {
self.debug(|x| println!("{:?}", x))
}
}
impl<S> Sig<S>
where
S: SigT<Item = f32>,
{
pub fn clamp_symetric<C>(
self,
max_unsigned: C,
) -> Sig<impl SigT<Item = f32>>
where
C: SigT<Item = f32>,
{
self.zip(max_unsigned).map(|(s, max_unsigned)| {
crate::arith::clamp_symetric(s, max_unsigned)
})
}
pub fn exp_01<K>(self, k: K) -> Sig<impl SigT<Item = f32>>
where
K: SigT<Item = f32>,
{
self.zip(k).map(|(x, k)| crate::arith::exp_01(x, k))
}
pub fn inv_01(self) -> Sig<impl SigT<Item = f32>> {
1.0 - self
}
pub fn signed_to_01(self) -> Sig<SignedTo01<S>> {
Sig(SignedTo01(self.0))
}
pub fn abs(self) -> Sig<SigAbs<S>> {
Sig(SigAbs(self.0))
}
}
pub struct GateToTrigRisingEdge<S>
where
S: SigT<Item = bool>,
{
sig: S,
prev: bool,
buf: Vec<bool>,
}
impl<S> SigT for GateToTrigRisingEdge<S>
where
S: SigT<Item = bool>,
{
type Item = bool;
fn sample(&mut self, ctx: &SigCtx) -> impl Buf<Self::Item> {
self.buf.resize(ctx.num_samples, false);
for (out, sample) in
self.buf.iter_mut().zip(self.sig.sample(ctx).iter())
{
*out = sample && !self.prev;
self.prev = sample;
}
&self.buf
}
}
impl<S> Sig<S>
where
S: SigT<Item = bool>,
{
pub fn gate_to_trig_rising_edge(self) -> Sig<GateToTrigRisingEdge<S>> {
Sig(GateToTrigRisingEdge {
sig: self.0,
prev: false,
buf: Vec::new(),
})
}
pub fn trig_to_gate<P>(self, period_s: P) -> Sig<impl SigT<Item = bool>>
where
P: SigT<Item = f32>,
{
let mut remaining_s = 0.0;
self.zip(period_s).map_mut_ctx(move |(x, period_s), ctx| {
if x {
remaining_s = period_s;
}
remaining_s -= 1.0 / ctx.sample_rate_hz;
remaining_s > 0.0
})
}
}
pub struct MapMut<S, T, F>
where
S: SigT,
F: FnMut(S::Item) -> T,
{
sig: S,
f: F,
buf: Vec<T>,
}
impl<S, T, F> SigT for MapMut<S, T, F>
where
T: Clone,
S: SigT,
F: FnMut(S::Item) -> T,
{
type Item = T;
fn sample(&mut self, ctx: &SigCtx) -> impl Buf<Self::Item> {
let buf = self.sig.sample(ctx);
self.buf.clear();
self.buf.extend(buf.iter().map(&mut self.f));
&self.buf
}
}
pub struct MapMutCtx<S, T, F>
where
S: SigT,
F: FnMut(S::Item, &SigCtx) -> T,
{
sig: S,
f: F,
buf: Vec<T>,
}
impl<S, T, F> SigT for MapMutCtx<S, T, F>
where
T: Clone,
S: SigT,
F: FnMut(S::Item, &SigCtx) -> T,
{
type Item = T;
fn sample(&mut self, ctx: &SigCtx) -> impl Buf<Self::Item> {
let buf = self.sig.sample(ctx);
self.buf.clear();
self.buf.extend(buf.iter().map(|x| (self.f)(x, ctx)));
&self.buf
}
}
pub struct Map<S, T, F>
where
S: SigT,
F: Fn(S::Item) -> T,
{
sig: S,
f: F,
}
impl<S, T, F> SigT for Map<S, T, F>
where
T: Clone,
S: SigT,
F: Fn(S::Item) -> T,
{
type Item = T;
fn sample(&mut self, ctx: &SigCtx) -> impl Buf<Self::Item> {
MapBuf::new(self.sig.sample(ctx), &self.f)
}
}
pub struct MapCtx<S, T, F>
where
S: SigT,
F: Fn(S::Item, &SigCtx) -> T,
{
sig: S,
f: F,
}
impl<S, T, F> SigT for MapCtx<S, T, F>
where
T: Clone,
S: SigT,
F: Fn(S::Item, &SigCtx) -> T,
{
type Item = T;
fn sample(&mut self, ctx: &SigCtx) -> impl Buf<Self::Item> {
MapBuf::new(self.sig.sample(ctx), |x| (self.f)(x, ctx))
}
}
pub struct Zip<A, B>
where
A: SigT,
B: SigT,
{
a: A,
b: B,
}
impl<A, B> SigT for Zip<A, B>
where
A: SigT,
B: SigT,
{
type Item = (A::Item, B::Item);
fn sample(&mut self, ctx: &SigCtx) -> impl Buf<Self::Item> {
ZipBuf::new(self.a.sample(ctx), self.b.sample(ctx))
}
}
pub struct SigAbs<S>(S)
where
S: SigT<Item = f32>;
impl<S> SigT for SigAbs<S>
where
S: SigT<Item = f32>,
{
type Item = f32;
fn sample(&mut self, ctx: &SigCtx) -> impl Buf<Self::Item> {
MapBuf::new(self.0.sample(ctx), |x| x.abs())
}
}
pub struct SignedTo01<S>(S)
where
S: SigT<Item = f32>;
impl<S> SigT for SignedTo01<S>
where
S: SigT<Item = f32>,
{
type Item = f32;
fn sample(&mut self, ctx: &SigCtx) -> impl Buf<Self::Item> {
MapBuf::new(self.0.sample(ctx), signed_to_01)
}
}
pub trait Filter {
type ItemIn;
type Out<S>: SigT
where
S: SigT<Item = Self::ItemIn>;
fn into_sig<S>(self, sig: S) -> Self::Out<S>
where
S: SigT<Item = Self::ItemIn>;
}
struct SigCached<S>
where
S: SigT,
{
sig: S,
cache: Vec<S::Item>,
next_batch_index: u64,
}
impl<S> SigCached<S>
where
S: SigT,
{
fn new(sig: S) -> Self {
Self {
sig,
cache: Vec::new(),
next_batch_index: 0,
}
}
}
impl<S> SigT for SigCached<S>
where
S: SigT,
{
type Item = S::Item;
fn sample(&mut self, ctx: &SigCtx) -> impl Buf<Self::Item> {
if ctx.batch_index >= self.next_batch_index {
self.next_batch_index = ctx.batch_index + 1;
let buf = self.sig.sample(ctx);
buf.clone_to_vec(&mut self.cache);
}
&self.cache
}
}
pub struct SigShared<S>
where
S: SigT,
{
shared_cached_sig: Rc<RefCell<SigCached<S>>>,
buf: Vec<S::Item>,
}
impl<S> Clone for SigShared<S>
where
S: SigT,
{
fn clone(&self) -> Self {
SigShared {
shared_cached_sig: Rc::clone(&self.shared_cached_sig),
buf: self.buf.clone(),
}
}
}
impl<S> SigT for SigShared<S>
where
S: SigT,
{
type Item = S::Item;
fn sample(&mut self, ctx: &SigCtx) -> impl Buf<Self::Item> {
let mut shared_cached_sig = self.shared_cached_sig.borrow_mut();
let buf = shared_cached_sig.sample(ctx);
buf.clone_to_vec(&mut self.buf);
&self.buf
}
}
pub fn sig_shared<S>(sig: S) -> Sig<SigShared<S>>
where
S: SigT,
{
Sig(SigShared {
shared_cached_sig: Rc::new(RefCell::new(SigCached::new(sig))),
buf: Vec::new(),
})
}
pub struct SigFn<F, T>
where
F: FnMut(&SigCtx) -> T,
T: Clone + Default,
{
f: F,
buf: Vec<T>,
}
impl<F, T> SigT for SigFn<F, T>
where
F: FnMut(&SigCtx) -> T,
T: Clone + Default,
{
type Item = T;
fn sample(&mut self, ctx: &SigCtx) -> impl Buf<Self::Item> {
self.buf.resize_with(ctx.num_samples, Default::default);
for out in self.buf.iter_mut() {
*out = (self.f)(ctx);
}
&self.buf
}
}
impl<F, T> Sig<SigFn<F, T>>
where
F: FnMut(&SigCtx) -> T,
T: Clone + Default,
{
pub fn from_fn(f: F) -> Self {
Self(SigFn { f, buf: Vec::new() })
}
}
pub struct SigBufFn<F, T>
where
F: FnMut(&SigCtx, &mut Vec<T>),
T: Clone + Default,
{
f: F,
buf: Vec<T>,
}
impl<F, T> SigT for SigBufFn<F, T>
where
F: FnMut(&SigCtx, &mut Vec<T>),
T: Clone + Default,
{
type Item = T;
fn sample(&mut self, ctx: &SigCtx) -> impl Buf<Self::Item> {
self.buf.resize_with(ctx.num_samples, Default::default);
(self.f)(ctx, &mut self.buf);
&self.buf
}
}
impl<F, T> Sig<SigBufFn<F, T>>
where
F: FnMut(&SigCtx, &mut Vec<T>),
T: Clone + Default,
{
pub fn from_buf_fn(f: F) -> Self {
Self(SigBufFn { f, buf: Vec::new() })
}
}