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}