siraph 0.1.2

A node-based digital signal processing crate
Documentation
#[cfg(feature = "math")]
pub mod math;

#[cfg(feature = "random")]
pub mod random;

use crate::{Input, Node, Output, Register};

/// The `Const` node returns a constant value.
///
/// # Outputs
/// * **output**: The output of the node.
pub struct Const<T> {
    val: T,
    output: Output<T>,
}

impl<T: Default> Default for Const<T> {
    fn default() -> Self {
        Self {
            val: T::default(),
            output: Output::default(),
        }
    }
}

impl<T> Const<T> {
    /// Creates a new `Const` node.
    pub fn new(val: T) -> Self {
        Self {
            val,
            output: Output::default(),
        }
    }
}

impl<T: 'static + Clone> Node for Const<T> {
    fn register(&self, r: &mut Register) {
        r.output("output", &self.output);
    }

    fn process(&mut self) {}

    fn reset(&mut self) {
        self.output.set(self.val.clone());
    }
}

/// A node that maps its input to its output using a function.
///
/// # Inputs
/// * **input**: The value that will be provided to the given function.
///
/// # Outputs
/// * **output**: The value returned by the function.
pub struct Map<T, U, F> {
    map: F,
    input: Input<T>,
    output: Output<U>,
}

impl<T, U, F> Map<T, U, F> {
    /// Creates a new `Map` node.
    pub fn new(map: F) -> Self
    where
        F: FnMut(T) -> U,
    {
        Self {
            map,
            input: Input::default(),
            output: Output::default(),
        }
    }
}

impl<T, U, F> Node for Map<T, U, F>
where
    T: 'static + Clone,
    U: 'static,
    F: FnMut(T) -> U,
{
    fn register(&self, r: &mut Register) {
        r.output("output", &self.output);
        r.input("input", &self.input);
    }

    fn process(&mut self) {
        if let Some(val) = self.input.get() {
            self.output.set((self.map)(val))
        }
    }

    fn reset(&mut self) {}
}

/// A node that outputs the content of an iterator.
///
/// # Outputs
/// * **output**: The values returned by the iterator.
pub struct FromIter<I: Iterator> {
    iter: I,
    output: Output<I::Item>,
}

impl<I: Iterator> FromIter<I> {
    /// Creates a new `FromIter` node.
    pub fn new(iter: impl IntoIterator<Item = I::Item, IntoIter = I>) -> Self {
        Self {
            iter: iter.into_iter(),
            output: Output::default(),
        }
    }
}

impl<I> Node for FromIter<I>
where
    I: Iterator,
    I::Item: 'static + Clone,
{
    fn register(&self, r: &mut Register) {
        r.output("output", &self.output);
    }

    fn process(&mut self) {
        self.output.set(self.iter.next());
    }

    fn reset(&mut self) {
        // Not every iterator can be reseted and I don't
        // want to constrain iterators to be Clone.
    }
}

/// # Inputs
/// * **input**: The signal that will be held when `true` is received .
/// * **resample**: Hold the value received in the `input` input when `true` is received.
///
/// # Outputs
/// * **output**: The output signal.
pub struct Hold<T> {
    input: Input<T>,
    resample: Input<bool>,
    output: Output<T>,
}

impl<T> Default for Hold<T> {
    fn default() -> Self {
        Self {
            input: Input::default(),
            resample: Input::default(),
            output: Output::default(),
        }
    }
}

impl<T> Hold<T> {
    /// Creates a new `Hold` node.
    pub fn new() -> Self {
        Self::default()
    }
}

impl<T: 'static + Clone> Node for Hold<T> {
    fn register(&self, r: &mut Register) {
        r.input("input", &self.input);
        r.input("resample", &self.resample);
        r.output("output", &self.output);
    }

    fn process(&mut self) {
        if self.resample.get().unwrap_or_default() {
            if let Some(val) = self.input.get() {
                self.output.set(val);
            }
        }
    }

    fn reset(&mut self) {}
}

/// An node that offsets its received values by `n` calls to `process`.
pub struct Offset<T> {
    input: Input<T>,
    output: Output<T>,
    buffer: Box<[Option<T>]>,
    idx: usize,
}

impl<T> Offset<T> {
    /// Creates a new `Offset` node.
    ///
    /// # Panics
    /// This function panics if it could not allocate for the inner buffer.
    pub fn new(offset: usize) -> Self {
        let vec: Vec<Option<T>> = (0..offset).map(|_| None).collect();

        Self {
            input: Input::default(),
            output: Output::default(),
            buffer: vec.into_boxed_slice(),
            idx: 0,
        }
    }
}

impl<T: 'static + Clone> Node for Offset<T> {
    fn register(&self, r: &mut Register) {
        r.input("input", &self.input);
        r.output("output", &self.output);
    }

    fn process(&mut self) {
        let val = unsafe { self.buffer.get_unchecked_mut(self.idx) };
        self.output.set(val.take());
        *val = self.input.get();
        self.idx = (self.idx + 1) % self.buffer.len();
    }

    fn reset(&mut self) {
        for val in self.buffer.as_mut() {
            *val = None;
        }
    }
}

/// A node that replaces the `None` values of its input with
/// a default value.
pub struct ReplaceNone<T> {
    default: T,
    input: Input<T>,
    output: Output<T>,
}

impl<T: Default> Default for ReplaceNone<T> {
    fn default() -> Self {
        Self::new(T::default())
    }
}

impl<T> ReplaceNone<T> {
    /// Creates a new `ReplaceNone` node.
    pub fn new(default: T) -> Self {
        Self {
            default,
            input: Input::default(),
            output: Output::default(),
        }
    }
}

impl<T: 'static + Clone> Node for ReplaceNone<T> {
    fn register(&self, r: &mut Register) {
        r.input("input", &self.input);
        r.output("output", &self.output);
    }

    fn process(&mut self) {
        self.output
            .set(self.input.get().unwrap_or_else(|| self.default.clone()))
    }

    fn reset(&mut self) {}
}

/// A simple node that infinitly outputs `n` `false` then one `true`.
pub struct Pulse {
    n: usize,
    current: usize,
    output: Output<bool>,
}

impl Pulse {
    /// Creates a new `Pulse` node.
    pub fn new(n: usize) -> Self {
        Self {
            n,
            current: 0,
            output: Output::default(),
        }
    }
}

impl Node for Pulse {
    fn register(&self, r: &mut Register) {
        r.output("output", &self.output);
    }

    fn process(&mut self) {
        if self.current == 0 {
            self.output.set(true);
            self.current = self.n;
        } else {
            self.output.set(false);
            self.current -= 1;
        }
    }

    fn reset(&mut self) {
        self.current = 0;
    }
}