audio_channel_buffer/
const_buffer_ref.rs

1use core::ops::{Index, IndexMut, Range};
2
3/// An immutable memory-efficient buffer of samples with a fixed compile-time number
4/// of channels each with a fixed runtime number of frames (samples in a single channel
5/// of audio).
6///
7/// This version uses a reference to a slice as its data source.
8#[derive(Debug, Clone, Copy)]
9pub struct ChannelBufferRef<'a, T: Clone + Copy + Default + Sized, const CHANNELS: usize> {
10    data: &'a [T],
11    offsets: [*const T; CHANNELS],
12    frames: usize,
13}
14
15impl<'a, T: Clone + Copy + Default + Sized, const CHANNELS: usize>
16    ChannelBufferRef<'a, T, CHANNELS>
17{
18    const _COMPILE_TIME_ASSERTS: () = {
19        assert!(CHANNELS > 0);
20    };
21
22    #[inline(always)]
23    pub(crate) unsafe fn from_raw(
24        data: &'a [T],
25        offsets: [*const T; CHANNELS],
26        frames: usize,
27    ) -> Self {
28        let _ = Self::_COMPILE_TIME_ASSERTS;
29
30        Self {
31            data,
32            offsets,
33            frames,
34        }
35    }
36
37    /// Create an empty [`ChannelBufferRef`] with no data.
38    pub fn empty() -> Self {
39        let _ = Self::_COMPILE_TIME_ASSERTS;
40
41        let data = &[];
42        let offsets = core::array::from_fn(|_| data.as_ptr());
43
44        Self {
45            data,
46            offsets,
47            frames: 0,
48        }
49    }
50
51    /// Create a new [`ChannelBufferRef`] using the given slice as the data.
52    pub fn new(data: &'a [T]) -> Self {
53        let _ = Self::_COMPILE_TIME_ASSERTS;
54
55        let frames = data.len() / CHANNELS;
56
57        Self {
58            data,
59            // SAFETY:
60            // * All of these pointers point to valid memory in the slice.
61            // * We have asserted at compile-time that `CHANNELS` is non-zero.
62            offsets: unsafe { core::array::from_fn(|ch_i| data.as_ptr().add(ch_i * frames)) },
63            frames,
64        }
65    }
66
67    /// Create a new [`ChannelBufferRef`] using the given slice as the data.
68    ///
69    /// # Safety
70    /// The caller must uphold that `data.len() >= frames * CHANNELS`.
71    pub unsafe fn new_unchecked(data: &'a [T], frames: usize) -> Self {
72        let _ = Self::_COMPILE_TIME_ASSERTS;
73
74        Self {
75            data,
76            // SAFETY:
77            // * All of these pointers point to valid memory in the slice.
78            // * We have asserted at compile-time that `CHANNELS` is non-zero.
79            offsets: core::array::from_fn(|ch_i| data.as_ptr().add(ch_i * frames)),
80            frames,
81        }
82    }
83
84    /// The number of frames (samples in a single channel of audio) that are allocated
85    /// in this buffer.
86    pub fn frames(&self) -> usize {
87        self.frames
88    }
89
90    /// The number of channels in this buffer.
91    pub fn channels(&self) -> usize {
92        CHANNELS
93    }
94
95    #[inline(always)]
96    /// Get an immutable reference to the channel at `index`. The slice will have a length
97    /// of `self.frames()`.
98    ///
99    /// Returns `None` if `index` is out of bounds.
100    pub fn channel(&self, index: usize) -> Option<&[T]> {
101        if index < CHANNELS {
102            // SAFETY: We haved checked that `index` is within bounds.
103            unsafe { Some(self.channel_unchecked(index)) }
104        } else {
105            None
106        }
107    }
108
109    #[inline(always)]
110    /// Get an immutable reference to the channel at `index`. The slice will have a length
111    /// of `self.frames()`.
112    ///
113    /// # Safety
114    /// `index` must be less than `self.channels()`
115    pub unsafe fn channel_unchecked(&self, index: usize) -> &[T] {
116        // SAFETY:
117        //
118        // * The constructors ensure that the pointed-to data slice has a length of at
119        // least `frames * CHANNELS`.
120        // * The caller upholds that `index` is within bounds.
121        // * The data slice cannot be moved, so the pointers are valid for the lifetime
122        // of the slice.
123        // * We have asserted at compile-time that `CHANNELS` is non-zero.
124        core::slice::from_raw_parts(*self.offsets.get_unchecked(index), self.frames)
125    }
126
127    /// Get all channels as immutable slices. Each slice will have a length of `self.frames()`.
128    #[inline]
129    pub fn as_slices(&self) -> [&[T]; CHANNELS] {
130        // SAFETY:
131        //
132        // * The constructors ensure that the pointed-to data slice has a length of at
133        // least `frames * CHANNELS`.
134        // * The data slice cannot be moved, so the pointers are valid for the lifetime
135        // of the slice.
136        // * We have asserted at compile-time that `CHANNELS` is non-zero.
137        unsafe {
138            core::array::from_fn(|ch_i| {
139                core::slice::from_raw_parts(*self.offsets.get_unchecked(ch_i), self.frames)
140            })
141        }
142    }
143
144    /// Get all channels as immutable slices with the given length in frames.
145    ///
146    /// If `frames > self.frames()`, then each slice will have a length of `self.frames()`
147    /// instead.
148    #[inline]
149    pub fn as_slices_with_length(&self, frames: usize) -> [&[T]; CHANNELS] {
150        let frames = frames.min(self.frames);
151
152        // SAFETY:
153        //
154        // * The constructors ensure that the pointed-to data slice has a length of at
155        // least `frames * CHANNELS`.
156        // * The data slice cannot be moved, so the pointers are valid for the lifetime
157        // of the slice.
158        // * We have constrained `frames` above.
159        // * We have asserted at compile-time that `CHANNELS` is non-zero.
160        unsafe {
161            core::array::from_fn(|ch_i| {
162                core::slice::from_raw_parts(*self.offsets.get_unchecked(ch_i), frames)
163            })
164        }
165    }
166
167    /// Get all channels as immutable slices in the given range.
168    ///
169    /// If all or part of the range falls out of bounds, then only the part that falls
170    /// within range will be returned.
171    #[inline]
172    pub fn as_slices_with_range(&self, range: Range<usize>) -> [&[T]; CHANNELS] {
173        let start_frame = range.start.min(self.frames);
174        let frames = range.end.min(self.frames) - start_frame;
175
176        // SAFETY:
177        //
178        // * The constructors ensure that the pointed-to data slice has a length of at
179        // least `frames * CHANNELS`.
180        // * The data slice cannot be moved, so the pointers are valid for the lifetime
181        // of the slice.
182        // * We have constrained the given range above.
183        // * We have asserted at compile-time that `CHANNELS` is non-zero.
184        unsafe {
185            core::array::from_fn(|ch_i| {
186                core::slice::from_raw_parts(
187                    self.offsets.get_unchecked(ch_i).add(start_frame),
188                    frames,
189                )
190            })
191        }
192    }
193
194    /// Get the entire contents of the buffer as a single immutable slice.
195    pub fn raw(&self) -> &[T] {
196        self.data
197    }
198}
199
200impl<'a, T: Clone + Copy + Default + Sized, const CHANNELS: usize> Index<usize>
201    for ChannelBufferRef<'a, T, CHANNELS>
202{
203    type Output = [T];
204
205    #[inline(always)]
206    fn index(&self, index: usize) -> &Self::Output {
207        self.channel(index).unwrap()
208    }
209}
210
211impl<'a, T: Clone + Copy + Default + Sized, const CHANNELS: usize> Default
212    for ChannelBufferRef<'a, T, CHANNELS>
213{
214    fn default() -> Self {
215        Self::empty()
216    }
217}
218
219impl<'a, T: Clone + Copy + Default + Sized, const CHANNELS: usize> Into<&'a [T]>
220    for ChannelBufferRefMut<'a, T, CHANNELS>
221{
222    fn into(self) -> &'a [T] {
223        self.data
224    }
225}
226
227// # SAFETY: All the stored pointers are valid for the lifetime of the struct, and
228// the public API prevents misuse of the pointers.
229unsafe impl<'a, T: Clone + Copy + Default + Sized, const CHANNELS: usize> Send
230    for ChannelBufferRef<'a, T, CHANNELS>
231{
232}
233// # SAFETY: All the stored pointers are valid for the lifetime of the struct, and
234// the public API prevents misuse of the pointers.
235unsafe impl<'a, T: Clone + Copy + Default + Sized, const CHANNELS: usize> Sync
236    for ChannelBufferRef<'a, T, CHANNELS>
237{
238}
239
240/// A mutable memory-efficient buffer of samples with a fixed compile-time number of
241/// channels each with a fixed runtime number of frames (samples in a single channel
242/// of audio).
243///
244/// This version uses a reference to a slice as its data source.
245#[derive(Debug)]
246pub struct ChannelBufferRefMut<'a, T: Clone + Copy + Default + Sized, const CHANNELS: usize> {
247    data: &'a mut [T],
248    offsets: [*mut T; CHANNELS],
249    frames: usize,
250}
251
252impl<'a, T: Clone + Copy + Default + Sized, const CHANNELS: usize>
253    ChannelBufferRefMut<'a, T, CHANNELS>
254{
255    const _COMPILE_TIME_ASSERTS: () = {
256        assert!(CHANNELS > 0);
257    };
258
259    #[inline(always)]
260    pub(crate) unsafe fn from_raw(
261        data: &'a mut [T],
262        offsets: [*mut T; CHANNELS],
263        frames: usize,
264    ) -> Self {
265        let _ = Self::_COMPILE_TIME_ASSERTS;
266
267        Self {
268            data,
269            offsets,
270            frames,
271        }
272    }
273
274    /// Create an empty [`ChannelBufferRefMut`] with no data.
275    pub fn empty() -> Self {
276        let _ = Self::_COMPILE_TIME_ASSERTS;
277
278        let data = &mut [];
279        let offsets = core::array::from_fn(|_| data.as_mut_ptr());
280
281        Self {
282            data,
283            offsets,
284            frames: 0,
285        }
286    }
287
288    /// Create a new [`ChannelBufferRefMut`] using the given slice as the data.
289    pub fn new(data: &'a mut [T]) -> Self {
290        let _ = Self::_COMPILE_TIME_ASSERTS;
291
292        let frames = data.len() / CHANNELS;
293
294        // SAFETY:
295        // * All of these pointers point to valid memory in the slice.
296        // * We have asserted at compile-time that `CHANNELS` is non-zero.
297        let offsets = unsafe { core::array::from_fn(|ch_i| data.as_mut_ptr().add(ch_i * frames)) };
298
299        Self {
300            data,
301            offsets,
302            frames,
303        }
304    }
305
306    /// Create a new [`ChannelBufferRefMut`] using the given slice as the data.
307    ///
308    /// # Safety
309    /// The caller must uphold that `data.len() >= frames * CHANNELS`.
310    pub unsafe fn new_unchecked(data: &'a mut [T], frames: usize) -> Self {
311        let _ = Self::_COMPILE_TIME_ASSERTS;
312
313        // SAFETY:
314        // * All of these pointers point to valid memory in the slice.
315        // * We have asserted at compile-time that `CHANNELS` is non-zero.
316        let offsets = core::array::from_fn(|ch_i| data.as_mut_ptr().add(ch_i * frames));
317
318        Self {
319            data,
320            offsets,
321            frames,
322        }
323    }
324
325    /// The number of frames (samples in a single channel of audio) that are allocated
326    /// in this buffer.
327    pub fn frames(&self) -> usize {
328        self.frames
329    }
330
331    /// The number of channels in this buffer.
332    pub fn channels(&self) -> usize {
333        CHANNELS
334    }
335
336    #[inline(always)]
337    /// Get an immutable reference to the channel at `index`. The slice will have a length
338    /// of `self.frames()`.
339    ///
340    /// Returns `None` if `index` is out of bounds.
341    pub fn channel(&self, index: usize) -> Option<&[T]> {
342        if index < CHANNELS {
343            // SAFETY: We haved checked that `index` is within bounds.
344            unsafe { Some(self.channel_unchecked(index)) }
345        } else {
346            None
347        }
348    }
349
350    #[inline(always)]
351    /// Get an immutable reference to the channel at `index`. The slice will have a length
352    /// of `self.frames()`.
353    ///
354    /// # Safety
355    /// `index` must be less than `self.channels()`
356    pub unsafe fn channel_unchecked(&self, index: usize) -> &[T] {
357        // SAFETY:
358        //
359        // * The constructors ensure that the pointed-to data slice has a length of at
360        // least `frames * CHANNELS`.
361        // * The caller upholds that `index` is within bounds.
362        // * The data slice cannot be moved, so the pointers are valid for the lifetime
363        // of the slice.
364        // * We have asserted at compile-time that `CHANNELS` is non-zero.
365        core::slice::from_raw_parts(*self.offsets.get_unchecked(index), self.frames)
366    }
367
368    #[inline(always)]
369    /// Get a mutable reference to the channel at `index`. The slice will have a length
370    /// of `self.frames()`.
371    ///
372    /// Returns `None` if `index` is out of bounds.
373    pub fn channel_mut(&mut self, index: usize) -> Option<&mut [T]> {
374        if index < CHANNELS {
375            // SAFETY: We haved checked that `index` is within bounds.
376            unsafe { Some(self.channel_unchecked_mut(index)) }
377        } else {
378            None
379        }
380    }
381
382    #[inline(always)]
383    /// Get a mutable reference to the channel at `index`. The slice will have a length
384    /// of `self.frames()`.
385    ///
386    /// # Safety
387    /// `index` must be less than `self.channels()`
388    pub unsafe fn channel_unchecked_mut(&mut self, index: usize) -> &mut [T] {
389        // SAFETY:
390        //
391        // * The constructors ensure that the pointed-to data slice has a length of at
392        // least `frames * CHANNELS`.
393        // * The caller upholds that `index` is within bounds.
394        // * The data slice cannot be moved, so the pointers are valid for the lifetime
395        // of the slice.
396        // * `self` is borrowed as mutable, ensuring that no other references to the
397        // data slice can exist.
398        // * We have asserted at compile-time that `CHANNELS` is non-zero.
399        core::slice::from_raw_parts_mut(*self.offsets.get_unchecked(index), self.frames)
400    }
401
402    /// Get all channels as immutable slices. Each slice will have a length of `self.frames()`.
403    #[inline]
404    pub fn as_slices(&self) -> [&[T]; CHANNELS] {
405        // SAFETY:
406        //
407        // * The constructors ensure that the pointed-to data slice has a length of at
408        // least `frames * CHANNELS`.
409        // * The data slice cannot be moved, so the pointers are valid for the lifetime
410        // of the slice.
411        // * We have asserted at compile-time that `CHANNELS` is non-zero.
412        unsafe {
413            core::array::from_fn(|ch_i| {
414                core::slice::from_raw_parts(*self.offsets.get_unchecked(ch_i), self.frames)
415            })
416        }
417    }
418
419    /// Get all channels as mutable slices. Each slice will have a length of `self.frames()`.
420    #[inline]
421    pub fn as_mut_slices(&mut self) -> [&mut [T]; CHANNELS] {
422        // SAFETY:
423        //
424        // * The constructors ensure that the pointed-to data slice has a length of at
425        // least `frames * CHANNELS`.
426        // * The data slice cannot be moved, so the pointers are valid for the lifetime
427        // of the slice.
428        // * `self` is borrowed as mutable, and none of these slices overlap, so all
429        // mutability rules are being upheld.
430        // * We have asserted at compile-time that `CHANNELS` is non-zero.
431        unsafe {
432            core::array::from_fn(|ch_i| {
433                core::slice::from_raw_parts_mut(*self.offsets.get_unchecked(ch_i), self.frames)
434            })
435        }
436    }
437
438    /// Get all channels as immutable slices with the given length in frames.
439    ///
440    /// If `frames > self.frames()`, then each slice will have a length of `self.frames()`
441    /// instead.
442    #[inline]
443    pub fn as_slices_with_length(&self, frames: usize) -> [&[T]; CHANNELS] {
444        let frames = frames.min(self.frames);
445
446        // SAFETY:
447        //
448        // * The constructors ensure that the pointed-to data slice has a length of at
449        // least `frames * CHANNELS`.
450        // * The data slice cannot be moved, so the pointers are valid for the lifetime
451        // of the slice.
452        // * We have constrained `frames` above.
453        // * We have asserted at compile-time that `CHANNELS` is non-zero.
454        unsafe {
455            core::array::from_fn(|ch_i| {
456                core::slice::from_raw_parts(*self.offsets.get_unchecked(ch_i), frames)
457            })
458        }
459    }
460
461    /// Get all channels as immutable slices with the given length in frames.
462    ///
463    /// If `frames > self.frames()`, then each slice will have a length of `self.frames()`
464    /// instead.
465    #[inline]
466    pub fn as_mut_slices_with_length(&mut self, frames: usize) -> [&mut [T]; CHANNELS] {
467        let frames = frames.min(self.frames);
468
469        // SAFETY:
470        //
471        // * The constructors ensure that the pointed-to data slice has a length of at
472        // least `frames * CHANNELS`.
473        // * The data slice cannot be moved, so the pointers are valid for the lifetime
474        // of the slice.
475        // * We have constrained `frames` above.
476        // * `self` is borrowed as mutable, and none of these slices overlap, so all
477        // mutability rules are being upheld.
478        // * We have asserted at compile-time that `CHANNELS` is non-zero.
479        unsafe {
480            core::array::from_fn(|ch_i| {
481                core::slice::from_raw_parts_mut(*self.offsets.get_unchecked(ch_i), frames)
482            })
483        }
484    }
485
486    /// Get all channels as immutable slices in the given range.
487    ///
488    /// If all or part of the range falls out of bounds, then only the part that falls
489    /// within range will be returned.
490    #[inline]
491    pub fn as_slices_with_range(&self, range: Range<usize>) -> [&[T]; CHANNELS] {
492        let start_frame = range.start.min(self.frames);
493        let frames = range.end.min(self.frames) - start_frame;
494
495        // SAFETY:
496        //
497        // * The constructors ensure that the pointed-to data slice has a length of at
498        // least `frames * CHANNELS`.
499        // * The data slice cannot be moved, so the pointers are valid for the lifetime
500        // of the slice.
501        // * We have constrained the given range above.
502        // * We have asserted at compile-time that `CHANNELS` is non-zero.
503        unsafe {
504            core::array::from_fn(|ch_i| {
505                core::slice::from_raw_parts(
506                    self.offsets.get_unchecked(ch_i).add(start_frame),
507                    frames,
508                )
509            })
510        }
511    }
512
513    /// Get all channels as immutable slices in the given range.
514    ///
515    /// If all or part of the range falls out of bounds, then only the part that falls
516    /// within range will be returned.
517    #[inline]
518    pub fn as_mut_slices_with_range(&mut self, range: Range<usize>) -> [&mut [T]; CHANNELS] {
519        let start_frame = range.start.min(self.frames);
520        let frames = range.end.min(self.frames) - start_frame;
521
522        // SAFETY:
523        //
524        // * The constructors ensure that the pointed-to data slice has a length of at
525        // least `frames * CHANNELS`.
526        // * The data slice cannot be moved, so the pointers are valid for the lifetime
527        // of the slice.
528        // * We have constrained the given range above.
529        // * `self` is borrowed as mutable, and none of these slices overlap, so all
530        // mutability rules are being upheld.
531        // * We have asserted at compile-time that `CHANNELS` is non-zero.
532        unsafe {
533            core::array::from_fn(|ch_i| {
534                core::slice::from_raw_parts_mut(
535                    self.offsets.get_unchecked(ch_i).add(start_frame),
536                    frames,
537                )
538            })
539        }
540    }
541
542    /// Get the entire contents of the buffer as a single immutable slice.
543    pub fn raw(&self) -> &[T] {
544        self.data
545    }
546
547    /// Get the entire contents of the buffer as a single mutable slice.
548    pub fn raw_mut(&mut self) -> &mut [T] {
549        &mut self.data[..]
550    }
551
552    /// Clear all data with the default value.
553    pub fn clear(&mut self) {
554        self.raw_mut().fill(T::default());
555    }
556
557    /// Clear all data in each channel up to `frames` with the default value.
558    pub fn clear_frames(&mut self, frames: usize) {
559        for ch in self.as_mut_slices_with_length(frames) {
560            ch.fill(T::default());
561        }
562    }
563}
564
565impl<'a, T: Clone + Copy + Default + Sized, const CHANNELS: usize> Index<usize>
566    for ChannelBufferRefMut<'a, T, CHANNELS>
567{
568    type Output = [T];
569
570    #[inline(always)]
571    fn index(&self, index: usize) -> &Self::Output {
572        self.channel(index).unwrap()
573    }
574}
575
576impl<'a, T: Clone + Copy + Default + Sized, const CHANNELS: usize> IndexMut<usize>
577    for ChannelBufferRefMut<'a, T, CHANNELS>
578{
579    #[inline(always)]
580    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
581        self.channel_mut(index).unwrap()
582    }
583}
584
585impl<'a, T: Clone + Copy + Default + Sized, const CHANNELS: usize> Default
586    for ChannelBufferRefMut<'a, T, CHANNELS>
587{
588    fn default() -> Self {
589        Self::empty()
590    }
591}
592
593impl<'a, T: Clone + Copy + Default + Sized, const CHANNELS: usize>
594    Into<ChannelBufferRef<'a, T, CHANNELS>> for ChannelBufferRefMut<'a, T, CHANNELS>
595{
596    #[inline(always)]
597    fn into(self) -> ChannelBufferRef<'a, T, CHANNELS> {
598        ChannelBufferRef {
599            data: self.data,
600            // SAFETY: `[*const T; CHANNELS]` and `[*mut T; CHANNELS]` are interchangeable bit-for-bit.
601            offsets: unsafe { core::mem::transmute_copy(&self.offsets) },
602            frames: self.frames,
603        }
604    }
605}
606
607impl<'a, T: Clone + Copy + Default + Sized, const CHANNELS: usize> Into<&'a mut [T]>
608    for ChannelBufferRefMut<'a, T, CHANNELS>
609{
610    fn into(self) -> &'a mut [T] {
611        self.data
612    }
613}
614
615// # SAFETY: All the stored pointers are valid for the lifetime of the struct, and
616// the public API prevents misuse of the pointers.
617unsafe impl<'a, T: Clone + Copy + Default + Sized, const CHANNELS: usize> Send
618    for ChannelBufferRefMut<'a, T, CHANNELS>
619{
620}
621// # SAFETY: All the stored pointers are valid for the lifetime of the struct, and
622// the public API prevents misuse of the pointers.
623unsafe impl<'a, T: Clone + Copy + Default + Sized, const CHANNELS: usize> Sync
624    for ChannelBufferRefMut<'a, T, CHANNELS>
625{
626}