1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
use rotary_core::{Buf, Channel, ChannelMut, Channels, ChannelsMut, ExactSizeBuf};

/// A wrapper for a sequential audio buffer.
///
/// See [wrap::sequential][super::sequential()].
pub struct Sequential<T> {
    value: T,
    channels: usize,
}

impl<T> Sequential<T> {
    pub(super) fn new(value: T, channels: usize) -> Self {
        Self { value, channels }
    }

    /// Convert back into the wrapped value.
    ///
    /// # Examples
    ///
    /// ```rust
    /// let buffer = rotary::wrap::sequential(&[1, 2, 3, 4], 2);
    /// assert_eq!(buffer.into_inner(), &[1, 2, 3, 4]);
    /// ```
    pub fn into_inner(self) -> T {
        self.value
    }
}

macro_rules! impl_buf {
    ([$($p:tt)*] , $ty:ty $(, $len:ident)?) => {
        impl<$($p)*> Buf for Sequential<$ty> {
            fn frames_hint(&self) -> Option<usize> {
                Some(self.frames())
            }

            fn channels(&self) -> usize {
                self.channels
            }
        }

        impl<$($p)*> ExactSizeBuf for Sequential<$ty> {
            fn frames(&self) -> usize {
                impl_buf!(@frames self, $($len)*) / self.channels
            }
        }

        impl<$($p)*> Channels<T> for Sequential<$ty> {
            fn channel(&self, channel: usize) -> Channel<'_, T> {
                let frames = self.frames();
                let value = self.value.get(channel * frames..).unwrap_or_default();
                let value = value.get(..frames).unwrap_or_default();
                Channel::linear(value)
            }
        }
    };

    (@frames $s:ident,) => { $s.value.len() };
    (@frames $_:ident, $n:ident) => { $n };
}

impl_buf!([T], &'_ [T]);
impl_buf!([T], &'_ mut [T]);
impl_buf!([T, const N: usize], [T; N], N);
impl_buf!([T, const N: usize], &'_ [T; N], N);
impl_buf!([T, const N: usize], &'_ mut [T; N], N);

macro_rules! impl_buf_mut {
    ([$($p:tt)*], $ty:ty) => {
        impl<$($p)*> ChannelsMut<T> for Sequential<$ty> where T: Copy {
            fn channel_mut(&mut self, channel: usize) -> ChannelMut<'_, T> {
                let frames = self.frames();
                let value = self.value.get_mut(channel * frames..).unwrap_or_default();
                let value = value.get_mut(..frames).unwrap_or_default();
                ChannelMut::linear(value)
            }

            fn copy_channels(&mut self, from: usize, to: usize) {
                let frames = self.frames();

                // Safety: We're calling the copy function with internal
                // parameters which are guaranteed to be correct. `channels` is
                // guaranteed to reflect a valid subset of the buffer based on
                // frames, because it uses the trusted length of the provided
                // slice.
                unsafe {
                    crate::utils::copy_channels_sequential(
                        self.value.as_mut_ptr(),
                        self.channels,
                        frames,
                        from,
                        to,
                    );
                }
            }
        }
    };
}

impl_buf_mut!([T], &'_ mut [T]);
impl_buf_mut!([T, const N: usize], &'_ mut [T; N]);