audio/frame/
interleaved.rs

1use core::marker;
2use core::ptr;
3use core::slice;
4
5use audio_core::Frame;
6
7use crate::channel::linear::Iter;
8
9/// An unsafe wrapper around a raw sequential buffer.
10pub(crate) struct RawInterleaved<T> {
11    ptr: ptr::NonNull<T>,
12    len: usize,
13    channels: usize,
14    frames: usize,
15}
16
17impl<T> Clone for RawInterleaved<T> {
18    #[inline]
19    fn clone(&self) -> Self {
20        *self
21    }
22}
23
24impl<T> Copy for RawInterleaved<T> {}
25
26impl<T> RawInterleaved<T> {
27    /// Construct a new raw sequential buffer.
28    ///
29    /// # Safety
30    ///
31    /// Caller must ensure that the provided buffer is within bounds of the
32    /// given specification.
33    pub(crate) unsafe fn new(data: &[T], channels: usize, frames: usize) -> Self {
34        let len = data.len();
35
36        debug_assert!(
37            len % channels == 0,
38            "data provided is not aligned with the number of channels; len={}, frames={}",
39            len,
40            channels,
41        );
42
43        debug_assert!(
44            len % frames == 0,
45            "data provided is not aligned with the number of frames; len={}, frames={}",
46            len,
47            frames,
48        );
49
50        Self {
51            ptr: ptr::NonNull::new_unchecked(data.as_ptr() as *mut T),
52            len,
53            channels,
54            frames,
55        }
56    }
57
58    /// Access number of frames in the buffer.
59    #[inline]
60    pub(crate) fn frames(&self) -> usize {
61        self.frames
62    }
63
64    /// Get the given sample inside of the specified frame.
65    ///
66    /// This checks that the given channel `n` is in bounds.
67    ///
68    /// # Safety
69    ///
70    /// The caller must ensure that the specified `frame` is in bounds.
71    pub(crate) unsafe fn get_sample(&self, frame: usize, channel: usize) -> Option<T>
72    where
73        T: Copy,
74    {
75        let index = channel.checked_add(self.channels.checked_mul(frame)?)?;
76
77        debug_assert!(
78            index < self.len,
79            "index `{index}` out-of-bounds",
80            index = index
81        );
82
83        if index >= self.len {
84            return None;
85        }
86
87        Some(*self.ptr.as_ptr().add(index))
88    }
89
90    /// Construct a sequential iterator from the specified frame.
91    ///
92    /// # Safety
93    ///
94    /// The caller is responsible for ensuring that the lifetime of the produced
95    /// iterator is valid.
96    pub(crate) unsafe fn iter_from_frame<'a>(self, frame: usize) -> Iter<'a, T> {
97        let data = slice::from_raw_parts(self.ptr.as_ptr() as *const _, self.len);
98        let data = self
99            .channels
100            .checked_mul(frame)
101            .and_then(|start| data.get(start..)?.get(..self.channels))
102            .unwrap_or_default();
103        Iter::new(data)
104    }
105}
106
107/// The frame of a interleaved buffer.
108pub struct InterleavedFrame<'a, T> {
109    frame: usize,
110    raw: RawInterleaved<T>,
111    _marker: marker::PhantomData<&'a ()>,
112}
113
114impl<T> InterleavedFrame<'_, T> {
115    #[inline]
116    pub(crate) fn new(frame: usize, raw: RawInterleaved<T>) -> Self {
117        Self {
118            frame,
119            raw,
120            _marker: marker::PhantomData,
121        }
122    }
123}
124
125impl<T> Frame for InterleavedFrame<'_, T>
126where
127    T: Copy,
128{
129    type Sample = T;
130
131    type Frame<'this>
132        = InterleavedFrame<'this, T>
133    where
134        Self: 'this;
135
136    type Iter<'this>
137        = Iter<'this, T>
138    where
139        Self: 'this;
140
141    #[inline]
142    fn as_frame(&self) -> Self::Frame<'_> {
143        Self {
144            frame: self.frame,
145            raw: self.raw,
146            _marker: marker::PhantomData,
147        }
148    }
149
150    #[inline]
151    fn len(&self) -> usize {
152        self.raw.frames()
153    }
154
155    #[inline]
156    fn get(&self, channel: usize) -> Option<Self::Sample> {
157        // SAFETY: the constructor of this wrapper is unsafe and requires the
158        // caller to guarantee its boundaries.
159        unsafe { self.raw.get_sample(self.frame, channel) }
160    }
161
162    #[inline]
163    fn iter(&self) -> Self::Iter<'_> {
164        // SAFETY: The construction of this buffer ensures that the iterator is
165        // in line and the lifetime is bounded to the current object.
166        unsafe { self.raw.iter_from_frame(self.frame) }
167    }
168}
169
170/// An iterator over all frames.
171pub struct InterleavedFramesIter<'a, T> {
172    frame: usize,
173    raw: RawInterleaved<T>,
174    _marker: marker::PhantomData<&'a [T]>,
175}
176
177impl<T> InterleavedFramesIter<'_, T> {
178    #[inline]
179    pub(crate) fn new(frame: usize, raw: RawInterleaved<T>) -> Self {
180        Self {
181            frame,
182            raw,
183            _marker: marker::PhantomData,
184        }
185    }
186}
187
188impl<'a, T> Iterator for InterleavedFramesIter<'a, T> {
189    type Item = InterleavedFrame<'a, T>;
190
191    #[inline]
192    fn next(&mut self) -> Option<Self::Item> {
193        if self.frame >= self.raw.frames() {
194            return None;
195        }
196
197        let frame = self.frame;
198        self.frame = self.frame.checked_add(1)?;
199
200        Some(InterleavedFrame {
201            frame,
202            raw: self.raw,
203            _marker: marker::PhantomData,
204        })
205    }
206}