diff --git a/src/signal.rs b/src/signal.rs index 52359fa7..72ac7d0d 100644 --- a/src/signal.rs +++ b/src/signal.rs @@ -523,6 +523,23 @@ pub struct GenMut { frame: core::marker::PhantomData, } +/// A signal that maps from one signal to another +#[derive(Clone)] +pub struct Map { + map: M, + signal: S, + frames: core::marker::PhantomData, +} + +/// A signal that iterates two signals in parallel and combines them with a function +#[derive(Clone)] +pub struct ZipMap { + map: M, + this: S, + other: O, + frame: core::marker::PhantomData +} + /// A type that wraps an Iterator and provides a `Signal` implementation for it. #[derive(Clone)] pub struct FromIterator { @@ -824,6 +841,69 @@ pub fn gen_mut(gen_mut: G) -> GenMut } +/// A signal that maps one set of frames to another +/// +/// # Example +/// +/// ```rust +/// extern crate sample; +/// +/// use sample::{signal, Signal}; +/// +/// fn main() { +/// let frames = signal::gen(|| [0.5]); +/// let mut mapper = signal::map(frames, |f| [f[0], 0.25]); +/// assert_eq!(mapper.next(), [0.5, 0.25]); +/// assert_eq!(mapper.next(), [0.5, 0.25]); +/// assert_eq!(mapper.next(), [0.5, 0.25]); +/// } +/// ``` +pub fn map(signal: S, map: M) -> Map + where M: FnMut(S::Frame) -> F, + S: Signal, + F: Frame, +{ + Map { + map: map, + signal: signal, + frames: core::marker::PhantomData, + } +} + + +/// A signal that maps one set of frames to another +/// +/// # Example +/// +/// ```rust +/// extern crate sample; +/// +/// use sample::{signal, Signal}; +/// +/// fn main() { +/// let frames = signal::gen(|| [0.5]); +/// let more_frames = signal::gen(|| [0.25]); +/// let mut mapper = signal::zip_map(frames, more_frames, |f, o| [f[0], o[0]]); +/// assert_eq!(mapper.next(), [0.5, 0.25]); +/// assert_eq!(mapper.next(), [0.5, 0.25]); +/// assert_eq!(mapper.next(), [0.5, 0.25]); +/// } +/// ``` +pub fn zip_map(this: S, other: O, map: M) -> ZipMap + where M: FnMut(S::Frame, O::Frame) -> F, + S: Signal, + O: Signal, + F: Frame, +{ + ZipMap { + map: map, + this: this, + other: other, + frame: core::marker::PhantomData, + } +} + + /// Create a new `Signal` from the given `Frame`-yielding `Iterator`. /// /// When the `Iterator` is exhausted, the new `Signal` will yield `F::equilibrium`. @@ -1118,6 +1198,33 @@ impl Signal for GenMut } +impl Signal for Map + where M: FnMut(S::Frame) -> F, + S: Signal, + F: Frame, +{ + type Frame = F; + #[inline] + fn next(&mut self) -> Self::Frame { + (self.map)(self.signal.next()) + } +} + + +impl Signal for ZipMap + where M: FnMut(S::Frame, O::Frame) -> F, + S: Signal, + O: Signal, + F: Frame, +{ + type Frame = F; + #[inline] + fn next(&mut self) -> Self::Frame { + (self.map)(self.this.next(), self.other.next()) + } +} + + impl Signal for Hz where S: Signal, {