audio_buffer_interface 0.1.0

Traits for iterating through scalar and SIMD audio data.
#![cfg_attr(feature="simd", feature(portable_simd))]
#![cfg_attr(doc, feature(doc_cfg))]
#![no_std]

//! # Audio Buffer Interface
//!
//! `audio_buffer_interface` is a collection of traits for iterating over audio data, both with
//! scalars and SIMD.



//Captures is not a public trait and shou;dn't be exposed because it's only purpose is to
//constrain the lifetime of the references being returned from the iterators.
//Because it doesn't provide any functionality, it shouldn't need to be used outside of this crate.
//and so should be kept private.
//This causes warnings, which are silenced by allowing private bounds.
#![allow(private_bounds)]

//Ensures that lifetime of hidden type is correct. 
//See https://www.youtube.com/watch?v=CWiz_RtA1Hw&t=550
trait Captures<U> {}
impl<T: ?Sized, U> Captures<U> for T {}



///A trait for iterating over some audio data. Iterators contain channels or frames of scalars.
pub trait AudioBufferIterator {
    type Item;

    ///Iterate through some audio data by channel
    /// ```rust
    /// # use audio_buffer_interface::AudioBufferIterator;
    /// 
    /// fn update_peak_levels(peak_levels: &mut [f32], buf: &impl AudioBufferIterator::<Item = f32>) {
    ///     for (chan, peak) in buf.chans().zip(peak_levels.iter_mut()) {
    ///         *peak = chan.fold(0.0, |samp, max| samp.abs().max(*max));
    ///     }
    /// }
    /// ```
    fn chans<'a>(&'a self) -> impl Iterator<Item = impl Iterator<Item = &'a Self::Item>>
        where Self::Item: 'a+Captures<&'a Self::Item>;

    ///Iterate mutably through some audio data by channel
    /// ```rust
    /// # use audio_buffer_interface::AudioBufferIterator;
    /// 
    /// fn mute_chan(buf: &mut impl AudioBufferIterator::<Item = f32>, chan_idx: usize) {
    ///   if let Some(chan) = buf.chans_mut().nth(chan_idx) {
    ///       for samp in chan {
    ///           *samp=0.0;
    ///       }
    ///   }
    /// }
    /// ```
    fn chans_mut<'a>(&'a mut self) -> impl Iterator<Item = impl Iterator<Item = &'a mut Self::Item>>
        where Self::Item: 'a+Captures<&'a mut Self::Item>;


    ///Iterate through some audio data by frame
    /// ```rust
    /// # use audio_buffer_interface::AudioBufferIterator;
    /// 
    /// fn lowpass_buf(in_buf: &impl AudioBufferIterator::<Item = f32>,
    ///                out_buf: &mut impl AudioBufferIterator::<Item = f32>) {
    ///   let mut state = 0.0;
    ///   let mut lowpass = move |input| {
    ///       let cf = 0.0035;
    ///       let out = input*cf+state*(1.0-cf);
    ///       state = out;
    ///       out
    ///   };
    /// 
    ///   for (in_frame, out_frame) in in_buf.frames().zip(out_buf.frames_mut()) {
    ///       let input = in_frame.map(|f| *f).sum::<f32>();
    ///       let output = lowpass(input);
    ///       for samp in out_frame {
    ///           *samp = output;
    ///       }
    ///   }
    /// }
    /// ```
    fn frames<'a>(&'a self) -> impl Iterator<Item = impl Iterator<Item = &'a Self::Item>>
        where Self::Item: 'a+Captures<&'a Self::Item>;

    ///Iterate mutably through some audio data by frame
    /// ```rust
    /// # use audio_buffer_interface::AudioBufferIterator;
    /// 
    /// fn sin_out(buf: &mut impl AudioBufferIterator::<Item = f32>, phase: &mut f32, incr: f32) {
    ///   for frame in buf.frames_mut() {
    ///       let val = (*phase*2.0*core::f32::consts::PI).sin();
    ///       *phase=(*phase+incr).fract();
    ///       for samp in frame {
    ///           *samp = val;
    ///       }
    ///   }
    /// }
    /// ```
    fn frames_mut<'a>(&'a mut self) -> impl Iterator<Item = impl Iterator<Item = &'a mut Self::Item>>
        where Self::Item: 'a+Captures<&'a mut Self::Item>;
}

#[cfg(feature="simd")]
mod simd {
    use core::{ops::{Deref, DerefMut}, 
               simd::{LaneCount, Simd, SimdElement, SupportedLaneCount}};

    ///A trait for iterating over some audio data. Iterators contain channels or frames of SIMD data.
    pub trait AudioBufferSimdIterator:
    {
        type Item: SimdElement;

        ///Iterate through some audio data via channels of SIMD vectors
        /// ```rust
        /// # use audio_buffer_interface::AudioBufferSimdIterator;
        /// 
        /// use core::simd::{LaneCount, Simd, SupportedLaneCount};
        /// use std::simd::num::SimdFloat;
        /// use std::simd::StdFloat;
        /// 
        /// 
        /// fn update_peak_levels<const N: usize>(peak_levels: &mut [f32], buf: &impl AudioBufferSimdIterator::<Item = f32>)
        ///     where LaneCount<N>: SupportedLaneCount
        /// {
        ///     for (chan, peak) in buf.simd_chans::<N>().zip(peak_levels.iter_mut()) {
        ///         *peak = chan.fold(core::simd::Simd::splat(0.0), 
        ///                           |max, samp| samp.as_ref().abs().simd_max(max))
        ///                     .reduce_max();
        ///     }
        /// }
        /// ```
        fn simd_chans<const N: usize>(&self) -> impl Iterator<Item = impl Iterator<Item = impl Deref<Target = Simd<Self::Item, N>>>>
            where LaneCount<N>: SupportedLaneCount;

        ///Iterate mutably through some audio data via channels of SIMD vectors
        /// ```rust
        /// # use audio_buffer_interface::AudioBufferSimdIterator;
        /// 
        /// use core::simd::{LaneCount, Simd, SupportedLaneCount};
        /// use std::simd::num::SimdFloat;
        /// use std::simd::StdFloat;
        /// 
        /// 
        /// fn mute_chan<const N: usize>(buf: &mut impl AudioBufferSimdIterator::<Item = f32>, chan_idx: usize)
        ///     where LaneCount<N>: SupportedLaneCount
        /// {
        ///     if let Some(chan) = buf.simd_chans_mut::<N>().nth(chan_idx) {
        ///         for mut samp in chan {
        ///             *samp.as_mut()=core::simd::Simd::splat(0.0);
        ///         }
        ///     }
        /// }
        /// ```
        fn simd_chans_mut<const N: usize>(&mut self) -> impl Iterator<Item = impl Iterator<Item = impl DerefMut<Target = Simd<Self::Item, N>>>>
            where LaneCount<N>: SupportedLaneCount;


        ///Iterate through some audio data via frames of SIMD vectors
        /// ```rust
        /// # use audio_buffer_interface::AudioBufferSimdIterator;
        /// 
        /// use core::simd::{LaneCount, Simd, SupportedLaneCount};
        /// use std::simd::num::SimdFloat;
        /// use std::simd::StdFloat;
        /// 
        /// 
        /// fn lowpass_buf<const N: usize>(in_buf: &impl AudioBufferSimdIterator::<Item = f32>,
        ///                                out_buf: &mut impl AudioBufferSimdIterator::<Item = f32>) 
        ///     where LaneCount<N>: SupportedLaneCount
        /// {
        ///     let mut state = core::simd::Simd::splat(0.0);
        ///     let mut lowpass = move |input: Simd<f32, N>| {
        ///         let cf = core::simd::Simd::splat(0.0035);
        ///         let out = input*cf+state*Simd::splat(1.0)-cf;
        ///         state = out;
        ///         out
        ///     };
        /// 
        ///     for (in_frame, out_frame) in in_buf.simd_frames::<N>().zip(out_buf.simd_frames_mut::<N>()) {
        ///         for (in_samps, mut out_samps) in in_frame.zip(out_frame) {
        ///             *out_samps.as_mut() = lowpass(*in_samps.as_ref());
        ///         }
        ///     }
        /// }
        /// ```
        fn simd_frames<const N: usize>(&self) -> impl Iterator<Item = impl Iterator<Item = impl Deref<Target = Simd<Self::Item, N>>>>
            where LaneCount<N>: SupportedLaneCount;

        ///Iterate mutably through some audio data via frames of SIMD vectors
        /// ```rust
        /// # use audio_buffer_interface::AudioBufferSimdIterator;
        /// 
        /// use core::simd::{LaneCount, Simd, SupportedLaneCount};
        /// use std::simd::num::SimdFloat;
        /// use std::simd::StdFloat;
        /// 
        /// 
        /// fn sin_out<const N: usize>(buf: &mut impl AudioBufferSimdIterator::<Item = f32>, phase: &mut f32, incr: f32) 
        ///     where LaneCount<N>: SupportedLaneCount
        /// {
        ///     let phase = Simd::splat(*phase);
        ///     let incr = Simd::splat(incr)*Simd::from_array((0..N).map(|i| i as f32).collect::<Vec<_>>().try_into().unwrap());
        ///     let mut phase = (phase+incr).fract();
        ///     for frame in buf.simd_frames_mut::<N>() {
        ///         let val = sin(phase*Simd::splat(2.0*core::f32::consts::PI));
        ///         phase=(phase+incr).fract();
        ///         for mut samp in frame {
        ///             *samp.as_mut() = val;
        ///         }
        ///     }
        /// }
        /// ```
        fn simd_frames_mut<const N: usize>(&mut self) -> impl Iterator<Item = impl Iterator<Item = impl DerefMut<Target = Simd<Self::Item, N>>>>
            where LaneCount<N>: SupportedLaneCount;
    }
}

#[cfg(any(feature="simd", doc))]
#[cfg_attr(doc, doc(cfg(simd)))]
pub use crate::simd::AudioBufferSimdIterator;