audio_channel_buffer/
const_buffer.rs

1use alloc::vec::Vec;
2use core::ops::{Index, IndexMut, Range};
3use core::pin::Pin;
4
5use crate::{ChannelBufferRef, ChannelBufferRefMut};
6
7/// A memory-efficient buffer of samples with a fixed compile-time number of channels
8/// each with a fixed runtime number of frames (samples in a single channel of audio).
9///
10/// This version uses an owned `Vec` as its data source.
11#[derive(Debug)]
12pub struct ChannelBuffer<T: Clone + Copy + Default + Sized + Unpin, const CHANNELS: usize> {
13    data: Pin<Vec<T>>,
14    offsets: [*mut T; CHANNELS],
15    frames: usize,
16}
17
18impl<T: Clone + Copy + Default + Sized + Unpin, const CHANNELS: usize> ChannelBuffer<T, CHANNELS> {
19    const _COMPILE_TIME_ASSERTS: () = {
20        assert!(CHANNELS > 0);
21    };
22
23    /// Create an empty [`ChannelBuffer`] with no allocated capacity.
24    pub fn empty() -> Self {
25        let _ = Self::_COMPILE_TIME_ASSERTS;
26
27        let mut data = Pin::new(Vec::<T>::new());
28
29        let offsets = core::array::from_fn(|_| data.as_mut_ptr());
30
31        Self {
32            data,
33            offsets,
34            frames: 0,
35        }
36    }
37
38    /// Create a new [`ChannelBuffer`] allocated with the given number of channels
39    /// each allocated with the given number of frames (samples in a single channel
40    /// of audio).
41    ///
42    /// All data will be initialized with the default value.
43    pub fn new(frames: usize) -> Self {
44        let _ = Self::_COMPILE_TIME_ASSERTS;
45
46        let buffer_len = CHANNELS * frames;
47
48        let mut data = Vec::<T>::new();
49        data.reserve_exact(buffer_len);
50        data.resize(buffer_len, Default::default());
51
52        let mut data = Pin::new(data);
53
54        // SAFETY:
55        // * All of these pointers point to valid memory in the vec.
56        // * We have asserted at compile-time that `CHANNELS` is non-zero.
57        let offsets = unsafe { core::array::from_fn(|ch_i| data.as_mut_ptr().add(ch_i * frames)) };
58
59        Self {
60            data,
61            offsets,
62            frames,
63        }
64    }
65
66    /// Create a new [`ChannelBuffer`] allocated with the given number of channels
67    /// each allocated with the given number of frames (samples in a single channel
68    /// of audio).
69    ///
70    /// No data will be initialized.
71    ///
72    /// # Safety
73    /// Any data must be initialized before reading.
74    pub unsafe fn new_uninit(frames: usize) -> Self {
75        let _ = Self::_COMPILE_TIME_ASSERTS;
76
77        let buffer_len = CHANNELS * frames;
78
79        let mut data = Vec::<T>::new();
80        data.reserve_exact(buffer_len);
81        data.set_len(buffer_len);
82
83        let mut data = Pin::new(data);
84
85        // SAFETY:
86        // * All of these pointers point to valid memory in the vec.
87        // * We have asserted at compile-time that `CHANNELS` is non-zero.
88        let offsets = unsafe { core::array::from_fn(|ch_i| data.as_mut_ptr().add(ch_i * frames)) };
89
90        Self {
91            data,
92            offsets,
93            frames,
94        }
95    }
96
97    /// The number of channels in this buffer.
98    pub fn channels(&self) -> usize {
99        CHANNELS
100    }
101
102    /// The number of frames (samples in a single channel of audio) that are allocated
103    /// in this buffer.
104    pub fn frames(&self) -> usize {
105        self.frames
106    }
107
108    #[inline(always)]
109    /// Get an immutable reference to the channel at `index`. The slice will have a length
110    /// of `self.frames()`.
111    ///
112    /// Returns `None` if `index` is out of bounds.
113    pub fn channel(&self, index: usize) -> Option<&[T]> {
114        if index < CHANNELS {
115            // SAFETY:
116            // We haved checked that `index` is within bounds.
117            unsafe { Some(self.channel_unchecked(index)) }
118        } else {
119            None
120        }
121    }
122
123    #[inline(always)]
124    /// Get an immutable reference to the channel at `index`. The slice will have a length
125    /// of `self.frames()`.
126    ///
127    /// # Safety
128    /// `index` must be less than `self.channels()`
129    pub unsafe fn channel_unchecked(&self, index: usize) -> &[T] {
130        // SAFETY:
131        //
132        // * The constructors ensure that the pointed-to data vec has a length of at
133        // least `frames * CHANNELS`.
134        // * The caller upholds that `index` is within bounds.
135        // * The Vec is pinned and cannot be moved, so the pointers are valid for the lifetime
136        // of the struct.
137        // * We have asserted at compile-time that `CHANNELS` is non-zero.
138        core::slice::from_raw_parts(*self.offsets.get_unchecked(index), self.frames)
139    }
140
141    #[inline(always)]
142    /// Get a mutable reference to the channel at `index`. The slice will have a length
143    /// of `self.frames()`.
144    ///
145    /// Returns `None` if `index` is out of bounds.
146    pub fn channel_mut(&mut self, index: usize) -> Option<&mut [T]> {
147        if index < CHANNELS {
148            // SAFETY:
149            // We haved checked that `index` is within bounds.
150            unsafe { Some(self.channel_unchecked_mut(index)) }
151        } else {
152            None
153        }
154    }
155
156    #[inline(always)]
157    /// Get a mutable reference to the channel at `index`. The slice will have a length
158    /// of `self.frames()`.
159    ///
160    /// # Safety
161    /// `index` must be less than `self.channels()`
162    pub unsafe fn channel_unchecked_mut(&mut self, index: usize) -> &mut [T] {
163        // SAFETY:
164        //
165        // * The constructors ensure that the pointed-to data vec has a length of at
166        // least `frames * CHANNELS`.
167        // * The caller upholds that `index` is within bounds.
168        // * The Vec is pinned and cannot be moved, so the pointers are valid for the lifetime
169        // of the struct.
170        // * `self` is borrowed as mutable, ensuring that no other references to the
171        // data Vec can exist.
172        // * We have asserted at compile-time that `CHANNELS` is non-zero.
173        core::slice::from_raw_parts_mut(*self.offsets.get_unchecked(index), self.frames)
174    }
175
176    /// Get all channels as immutable slices. Each slice will have a length of `self.frames()`.
177    #[inline]
178    pub fn as_slices(&self) -> [&[T]; CHANNELS] {
179        // SAFETY:
180        //
181        // * The constructors ensure that the pointed-to data vec has a length of at
182        // least `frames * CHANNELS`.
183        // * The Vec is pinned and cannot be moved, so the pointers are valid for the lifetime
184        // of the struct.
185        // * We have asserted at compile-time that `CHANNELS` is non-zero.
186        unsafe {
187            core::array::from_fn(|ch_i| {
188                core::slice::from_raw_parts(*self.offsets.get_unchecked(ch_i), self.frames)
189            })
190        }
191    }
192
193    /// Get all channels as mutable slices. Each slice will have a length of `self.frames()`.
194    #[inline]
195    pub fn as_mut_slices(&mut self) -> [&mut [T]; CHANNELS] {
196        // SAFETY:
197        //
198        // * The constructors ensure that the pointed-to data vec has a length of at
199        // least `frames * CHANNELS`.
200        // * The Vec is pinned and cannot be moved, so the pointers are valid for the lifetime
201        // of the struct.
202        // * `self` is borrowed as mutable, and none of these slices overlap, so all
203        // mutability rules are being upheld.
204        // * We have asserted at compile-time that `CHANNELS` is non-zero.
205        unsafe {
206            core::array::from_fn(|ch_i| {
207                core::slice::from_raw_parts_mut(*self.offsets.get_unchecked(ch_i), self.frames)
208            })
209        }
210    }
211
212    /// Get all channels as immutable slices with the given length in frames.
213    ///
214    /// If `frames > self.frames()`, then each slice will have a length of `self.frames()`
215    /// instead.
216    #[inline]
217    pub fn as_slices_with_length(&self, frames: usize) -> [&[T]; CHANNELS] {
218        let frames = frames.min(self.frames);
219
220        // SAFETY:
221        //
222        // * The constructors ensure that the pointed-to data vec has a length of at
223        // least `frames * CHANNELS`.
224        // * The Vec is pinned and cannot be moved, so the pointers are valid for the lifetime
225        // of the struct.
226        // * We have constrained `frames` above.
227        // * We have asserted at compile-time that `CHANNELS` is non-zero.
228        unsafe {
229            core::array::from_fn(|ch_i| {
230                core::slice::from_raw_parts(*self.offsets.get_unchecked(ch_i), frames)
231            })
232        }
233    }
234
235    /// Get all channels as mutable slices with the given length in frames.
236    ///
237    /// If `frames > self.frames()`, then each slice will have a length of `self.frames()`
238    /// instead.
239    #[inline]
240    pub fn as_mut_slices_with_length(&mut self, frames: usize) -> [&mut [T]; CHANNELS] {
241        let frames = frames.min(self.frames);
242
243        // SAFETY:
244        //
245        // * The constructors ensure that the pointed-to data vec has a length of at
246        // least `frames * CHANNELS`.
247        // * The Vec is pinned and cannot be moved, so the pointers are valid for the lifetime
248        // of the struct.
249        // * We have constrained `frames` above.
250        // * `self` is borrowed as mutable, and none of these slices overlap, so all
251        // mutability rules are being upheld.
252        // * We have asserted at compile-time that `CHANNELS` is non-zero.
253        unsafe {
254            core::array::from_fn(|ch_i| {
255                core::slice::from_raw_parts_mut(*self.offsets.get_unchecked(ch_i), frames)
256            })
257        }
258    }
259
260    /// Get all channels as immutable slices in the given range.
261    ///
262    /// If all or part of the range falls out of bounds, then only the part that falls
263    /// within range will be returned.
264    #[inline]
265    pub fn as_slices_with_range(&self, range: Range<usize>) -> [&[T]; CHANNELS] {
266        let start_frame = range.start.min(self.frames);
267        let frames = range.end.min(self.frames) - start_frame;
268
269        // SAFETY:
270        //
271        // * The constructors ensure that the pointed-to data vec has a length of at
272        // least `frames * CHANNELS`.
273        // * The Vec is pinned and cannot be moved, so the pointers are valid for the lifetime
274        // of the struct.
275        // * We have constrained the given range above.
276        // * We have asserted at compile-time that `CHANNELS` is non-zero.
277        unsafe {
278            core::array::from_fn(|ch_i| {
279                core::slice::from_raw_parts(
280                    self.offsets.get_unchecked(ch_i).add(start_frame),
281                    frames,
282                )
283            })
284        }
285    }
286
287    /// Get all channels as mutable slices in the given range.
288    ///
289    /// If all or part of the range falls out of bounds, then only the part that falls
290    /// within range will be returned.
291    #[inline]
292    pub fn as_mut_slices_with_range(&mut self, range: Range<usize>) -> [&mut [T]; CHANNELS] {
293        let start_frame = range.start.min(self.frames);
294        let frames = range.end.min(self.frames) - start_frame;
295
296        // SAFETY:
297        //
298        // * The constructors ensure that the pointed-to data vec has a length of at
299        // least `frames * CHANNELS`.
300        // * The Vec is pinned and cannot be moved, so the pointers are valid for the lifetime
301        // of the struct.
302        // * We have constrained the given range above.
303        // * `self` is borrowed as mutable, and none of these slices overlap, so all
304        // mutability rules are being upheld.
305        // * We have asserted at compile-time that `CHANNELS` is non-zero.
306        unsafe {
307            core::array::from_fn(|ch_i| {
308                core::slice::from_raw_parts_mut(
309                    self.offsets.get_unchecked(ch_i).add(start_frame),
310                    frames,
311                )
312            })
313        }
314    }
315
316    /// Get the entire contents of the buffer as a single immutable slice.
317    pub fn raw(&self) -> &[T] {
318        &self.data
319    }
320
321    /// Get the entire contents of the buffer as a single mutable slice.
322    pub fn raw_mut(&mut self) -> &mut [T] {
323        &mut self.data
324    }
325
326    /// Clear all data with the default value.
327    pub fn clear(&mut self) {
328        self.raw_mut().fill(T::default());
329    }
330
331    /// Clear all data in each channel up to `frames` with the default value.
332    pub fn clear_frames(&mut self, frames: usize) {
333        for ch in self.as_mut_slices_with_length(frames) {
334            ch.fill(T::default());
335        }
336    }
337
338    #[inline(always)]
339    pub fn as_ref<'a>(&'a self) -> ChannelBufferRef<'a, T, CHANNELS> {
340        // SAFETY:
341        // * The constructors have the same invariants as `ChannelBufferRef`.
342        // * `[*const T; CHANNELS]` and `[*mut T; CHANNELS]` are interchangeable bit-for-bit.
343        unsafe {
344            ChannelBufferRef::from_raw(
345                &self.data,
346                core::mem::transmute_copy(&self.offsets),
347                self.frames,
348            )
349        }
350    }
351
352    #[inline(always)]
353    pub fn as_mut<'a>(&'a mut self) -> ChannelBufferRefMut<'a, T, CHANNELS> {
354        // SAFETY: The constructors have the same invariants as `ChannelBufferRefMut`.
355        unsafe { ChannelBufferRefMut::from_raw(&mut self.data, self.offsets, self.frames) }
356    }
357}
358
359impl<T: Clone + Copy + Default + Sized + Unpin, const CHANNELS: usize> Index<usize>
360    for ChannelBuffer<T, CHANNELS>
361{
362    type Output = [T];
363
364    #[inline(always)]
365    fn index(&self, index: usize) -> &Self::Output {
366        self.channel(index).unwrap()
367    }
368}
369
370impl<T: Clone + Copy + Default + Sized + Unpin, const CHANNELS: usize> IndexMut<usize>
371    for ChannelBuffer<T, CHANNELS>
372{
373    #[inline(always)]
374    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
375        self.channel_mut(index).unwrap()
376    }
377}
378
379impl<T: Clone + Copy + Default + Sized + Unpin, const CHANNELS: usize> Default
380    for ChannelBuffer<T, CHANNELS>
381{
382    fn default() -> Self {
383        Self::empty()
384    }
385}
386
387impl<'a, T: Clone + Copy + Default + Sized + Unpin, const CHANNELS: usize>
388    Into<ChannelBufferRef<'a, T, CHANNELS>> for &'a ChannelBuffer<T, CHANNELS>
389{
390    #[inline(always)]
391    fn into(self) -> ChannelBufferRef<'a, T, CHANNELS> {
392        self.as_ref()
393    }
394}
395
396impl<'a, T: Clone + Copy + Default + Sized + Unpin, const CHANNELS: usize>
397    Into<ChannelBufferRefMut<'a, T, CHANNELS>> for &'a mut ChannelBuffer<T, CHANNELS>
398{
399    #[inline(always)]
400    fn into(self) -> ChannelBufferRefMut<'a, T, CHANNELS> {
401        self.as_mut()
402    }
403}
404
405impl<T: Clone + Copy + Default + Sized + Unpin, const CHANNELS: usize> Into<Vec<T>>
406    for ChannelBuffer<T, CHANNELS>
407{
408    fn into(self) -> Vec<T> {
409        Pin::<Vec<T>>::into_inner(self.data)
410    }
411}
412
413impl<T: Clone + Copy + Default + Sized + Unpin, const CHANNELS: usize> Clone
414    for ChannelBuffer<T, CHANNELS>
415{
416    fn clone(&self) -> Self {
417        // SAFETY: We initialize all the data below.
418        let mut new_self = unsafe { Self::new_uninit(self.frames) };
419
420        new_self.raw_mut().copy_from_slice(self.raw());
421
422        new_self
423    }
424}
425
426// # SAFETY: All the stored pointers are valid for the lifetime of the struct, and
427// the public API prevents misuse of the pointers.
428unsafe impl<T: Clone + Copy + Default + Sized + Unpin, const CHANNELS: usize> Send
429    for ChannelBuffer<T, CHANNELS>
430{
431}
432// # SAFETY: All the stored pointers are valid for the lifetime of the struct, and
433// the public API prevents misuse of the pointers.
434unsafe impl<T: Clone + Copy + Default + Sized + Unpin, const CHANNELS: usize> Sync
435    for ChannelBuffer<T, CHANNELS>
436{
437}