audio_blocks/stacked/
owned.rs

1use rtsan_standalone::{blocking, nonblocking};
2
3#[cfg(all(feature = "alloc", not(feature = "std")))]
4use alloc::{boxed::Box, vec, vec::Vec};
5#[cfg(all(feature = "std", not(feature = "alloc")))]
6use std::{boxed::Box, vec, vec::Vec};
7#[cfg(all(feature = "std", feature = "alloc"))]
8use std::{boxed::Box, vec, vec::Vec};
9
10use crate::{AudioBlock, AudioBlockMut, Sample};
11
12use super::{view::StackedView, view_mut::StackedViewMut};
13
14/// A stacked / seperate-channel audio block that owns its data.
15///
16/// * **Layout:** `[[ch0, ch0, ch0], [ch1, ch1, ch1]]`
17/// * **Interpretation:** Each channel has its own separate buffer or array.
18/// * **Terminology:** Also described as “planar” or “channels first” though more specifically it’s channel-isolated buffers.
19/// * **Usage:** Very common in real-time DSP, as it simplifies memory access and can improve SIMD/vectorization efficiency.
20///
21/// # Example
22///
23/// ```
24/// use audio_blocks::*;
25///
26/// let block = Stacked::new(2, 3);
27/// let mut block = Stacked::from_block(&block);
28///
29/// block.channel_mut(0).for_each(|v| *v = 0.0);
30/// block.channel_mut(1).for_each(|v| *v = 1.0);
31///
32/// assert_eq!(block.raw_data(Some(0)), &[0.0, 0.0, 0.0]);
33/// assert_eq!(block.raw_data(Some(1)), &[1.0, 1.0, 1.0]);
34/// ```
35pub struct Stacked<S: Sample> {
36    data: Box<[Box<[S]>]>,
37    num_channels: u16,
38    num_frames: usize,
39    num_channels_allocated: u16,
40    num_frames_allocated: usize,
41}
42
43impl<S: Sample> Stacked<S> {
44    /// Creates a new [`Stacked`] audio block with the specified dimensions.
45    ///
46    /// Allocates memory for a new stacked audio block with exactly the specified
47    /// number of channels and frames. The block is initialized with the default value
48    /// for the sample type.
49    ///
50    /// Do not use in real-time processes!
51    ///
52    /// # Arguments
53    ///
54    /// * `num_channels` - The number of audio channels
55    /// * `num_frames` - The number of frames per channel
56    ///
57    /// # Panics
58    ///
59    /// Panics if the multiplication of `num_channels` and `num_frames` would overflow a usize.
60    #[blocking]
61    pub fn new(num_channels: u16, num_frames: usize) -> Self {
62        Self {
63            data: vec![vec![S::default(); num_frames].into_boxed_slice(); num_channels as usize]
64                .into_boxed_slice(),
65            num_channels,
66            num_frames,
67            num_channels_allocated: num_channels,
68            num_frames_allocated: num_frames,
69        }
70    }
71
72    /// Creates a new [`Stacked`] audio block by copying data from another [`AudioBlock`].
73    ///
74    /// Converts any [`AudioBlock`] implementation to a stacked format by iterating
75    /// through each channel of the source block and copying its samples. The new block
76    /// will have the same dimensions as the source block.
77    ///
78    /// # Warning
79    ///
80    /// This function allocates memory and should not be used in real-time audio processing contexts.
81    ///
82    /// # Arguments
83    ///
84    /// * `block` - The source audio block to copy data from
85    #[blocking]
86    pub fn from_block(block: &impl AudioBlock<S>) -> Self {
87        let data: Vec<Box<[S]>> = block.channels().map(|c| c.copied().collect()).collect();
88        Self {
89            data: data.into_boxed_slice(),
90            num_channels: block.num_channels(),
91            num_frames: block.num_frames(),
92            num_channels_allocated: block.num_channels(),
93            num_frames_allocated: block.num_frames(),
94        }
95    }
96}
97
98impl<S: Sample> AudioBlock<S> for Stacked<S> {
99    #[nonblocking]
100    fn num_channels(&self) -> u16 {
101        self.num_channels
102    }
103
104    #[nonblocking]
105    fn num_frames(&self) -> usize {
106        self.num_frames
107    }
108
109    #[nonblocking]
110    fn num_channels_allocated(&self) -> u16 {
111        self.num_channels_allocated
112    }
113
114    #[nonblocking]
115    fn num_frames_allocated(&self) -> usize {
116        self.num_frames_allocated
117    }
118
119    #[nonblocking]
120    fn sample(&self, channel: u16, frame: usize) -> S {
121        assert!(channel < self.num_channels);
122        assert!(frame < self.num_frames);
123        unsafe {
124            *self
125                .data
126                .get_unchecked(channel as usize)
127                .get_unchecked(frame)
128        }
129    }
130
131    #[nonblocking]
132    fn channel(&self, channel: u16) -> impl Iterator<Item = &S> {
133        assert!(channel < self.num_channels);
134        unsafe {
135            self.data
136                .get_unchecked(channel as usize)
137                .iter()
138                .take(self.num_frames)
139        }
140    }
141
142    #[nonblocking]
143    fn channels(&self) -> impl Iterator<Item = impl Iterator<Item = &S> + '_> + '_ {
144        let num_frames = self.num_frames; // Capture num_frames for the closure
145        self.data
146            .iter()
147            // Limit to the active number of channels
148            .take(self.num_channels as usize)
149            // For each channel slice, create an iterator over its samples
150            .map(move |channel_data| channel_data.as_ref().iter().take(num_frames))
151    }
152
153    #[nonblocking]
154    fn frame(&self, frame: usize) -> impl Iterator<Item = &S> {
155        assert!(frame < self.num_frames);
156        self.data
157            .iter()
158            .take(self.num_channels as usize)
159            .map(move |channel_data| unsafe { channel_data.get_unchecked(frame) })
160    }
161
162    #[nonblocking]
163    fn frames(&self) -> impl Iterator<Item = impl Iterator<Item = &S> + '_> + '_ {
164        let num_channels = self.num_channels as usize;
165        let num_frames = self.num_frames;
166        // Get an immutable slice of the channel boxes: `&[Box<[S]>]`
167        let data_slice: &[Box<[S]>] = &self.data;
168
169        // Assumes the struct guarantees that for all `chan` in `0..num_channels`,
170        // `self.data[chan].len() >= num_frames`.
171
172        (0..num_frames).map(move |frame_idx| {
173            // For each frame index, create an iterator over the relevant channel boxes.
174            // `data_slice` is captured immutably, which is allowed by nested closures.
175            data_slice[..num_channels]
176                .iter() // Yields `&'a Box<[S]>`
177                .map(move |channel_slice_box| {
178                    // Get the immutable slice `&[S]` from the box.
179                    let channel_slice: &[S] = channel_slice_box;
180                    // Access the sample immutably using safe indexing.
181                    // Assumes frame_idx is valid based on outer loop and struct invariants.
182                    &channel_slice[frame_idx]
183                    // For max performance (if bounds are absolutely guaranteed):
184                    // unsafe { channel_slice.get_unchecked(frame_idx) }
185                })
186        })
187    }
188
189    #[nonblocking]
190    fn view(&self) -> impl AudioBlock<S> {
191        StackedView::from_slice_limited(&self.data, self.num_channels, self.num_frames)
192    }
193
194    #[nonblocking]
195    fn layout(&self) -> crate::BlockLayout {
196        crate::BlockLayout::Stacked
197    }
198
199    #[nonblocking]
200    fn raw_data(&self, stacked_ch: Option<u16>) -> &[S] {
201        let ch = stacked_ch.expect("For stacked layout channel needs to be provided!");
202        assert!(ch < self.num_channels_allocated);
203        unsafe { self.data.get_unchecked(ch as usize) }
204    }
205}
206
207impl<S: Sample> AudioBlockMut<S> for Stacked<S> {
208    #[nonblocking]
209    fn resize(&mut self, num_channels: u16, num_frames: usize) {
210        assert!(num_channels <= self.num_channels_allocated);
211        assert!(num_frames <= self.num_frames_allocated);
212        self.num_channels = num_channels;
213        self.num_frames = num_frames;
214    }
215
216    #[nonblocking]
217    fn sample_mut(&mut self, channel: u16, frame: usize) -> &mut S {
218        assert!(channel < self.num_channels);
219        assert!(frame < self.num_frames);
220        unsafe {
221            self.data
222                .get_unchecked_mut(channel as usize)
223                .get_unchecked_mut(frame)
224        }
225    }
226
227    #[nonblocking]
228    fn channel_mut(&mut self, channel: u16) -> impl Iterator<Item = &mut S> {
229        assert!(channel < self.num_channels);
230        unsafe {
231            self.data
232                .get_unchecked_mut(channel as usize)
233                .iter_mut()
234                .take(self.num_frames)
235        }
236    }
237
238    #[nonblocking]
239    fn channels_mut(&mut self) -> impl Iterator<Item = impl Iterator<Item = &mut S> + '_> + '_ {
240        let num_frames = self.num_frames;
241        self.data
242            .iter_mut()
243            .take(self.num_channels as usize)
244            .map(move |channel_data| channel_data.as_mut().iter_mut().take(num_frames))
245    }
246
247    #[nonblocking]
248    fn frame_mut(&mut self, frame: usize) -> impl Iterator<Item = &mut S> {
249        assert!(frame < self.num_frames);
250        self.data
251            .iter_mut()
252            .take(self.num_channels as usize)
253            .map(move |channel_data| unsafe { channel_data.get_unchecked_mut(frame) })
254    }
255
256    #[nonblocking]
257    fn frames_mut(&mut self) -> impl Iterator<Item = impl Iterator<Item = &mut S> + '_> + '_ {
258        let num_channels = self.num_channels as usize;
259        let num_frames = self.num_frames;
260        let data_slice: &mut [Box<[S]>] = &mut self.data;
261        let data_ptr: *mut [Box<[S]>] = data_slice;
262
263        (0..num_frames).map(move |frame_idx| {
264            // Re-borrow mutably inside the closure via the raw pointer.
265            // Safety: Safe because the outer iterator executes this sequentially per frame.
266            let current_channel_boxes: &mut [Box<[S]>] = unsafe { &mut *data_ptr };
267
268            // Iterate over the relevant channel boxes up to num_channels
269            current_channel_boxes[..num_channels]
270                .iter_mut() // Yields `&'a mut Box<[S]>`
271                .map(move |channel_slice_box| {
272                    // Get the mutable slice `&mut [S]` from the box.
273                    let channel_slice: &mut [S] = channel_slice_box;
274                    // Access the sample for the current channel at the current frame index.
275                    // Safety: Relies on `frame_idx < channel_slice.len()`.
276                    unsafe { channel_slice.get_unchecked_mut(frame_idx) }
277                })
278        })
279    }
280
281    #[nonblocking]
282    fn view_mut(&mut self) -> impl AudioBlockMut<S> {
283        StackedViewMut::from_slice_limited(&mut self.data, self.num_channels, self.num_frames)
284    }
285
286    #[nonblocking]
287    fn raw_data_mut(&mut self, stacked_ch: Option<u16>) -> &mut [S] {
288        let ch = stacked_ch.expect("For stacked layout channel needs to be provided!");
289        assert!(ch < self.num_channels_allocated);
290        unsafe { self.data.get_unchecked_mut(ch as usize).as_mut() }
291    }
292}
293
294#[cfg(test)]
295mod tests {
296    use rtsan_standalone::no_sanitize_realtime;
297
298    use super::*;
299    use crate::interleaved::InterleavedView;
300
301    #[test]
302    fn test_samples() {
303        let mut block = Stacked::<f32>::new(2, 5);
304
305        let num_frames = block.num_frames();
306        for ch in 0..block.num_channels() {
307            for f in 0..block.num_frames() {
308                *block.sample_mut(ch, f) = (ch as usize * num_frames + f) as f32;
309            }
310        }
311
312        for ch in 0..block.num_channels() {
313            for f in 0..block.num_frames() {
314                assert_eq!(block.sample(ch, f), (ch as usize * num_frames + f) as f32);
315            }
316        }
317
318        assert_eq!(block.raw_data(Some(0)), &[0.0, 1.0, 2.0, 3.0, 4.0]);
319        assert_eq!(block.raw_data(Some(1)), &[5.0, 6.0, 7.0, 8.0, 9.0]);
320    }
321
322    #[test]
323    fn test_channel() {
324        let mut block = Stacked::<f32>::new(2, 5);
325
326        let channel = block.channel(0).copied().collect::<Vec<_>>();
327        assert_eq!(channel, vec![0.0, 0.0, 0.0, 0.0, 0.0]);
328        let channel = block.channel(1).copied().collect::<Vec<_>>();
329        assert_eq!(channel, vec![0.0, 0.0, 0.0, 0.0, 0.0]);
330
331        block
332            .channel_mut(0)
333            .enumerate()
334            .for_each(|(i, v)| *v = i as f32);
335        block
336            .channel_mut(1)
337            .enumerate()
338            .for_each(|(i, v)| *v = i as f32 + 10.0);
339
340        let channel = block.channel(0).copied().collect::<Vec<_>>();
341        assert_eq!(channel, vec![0.0, 1.0, 2.0, 3.0, 4.0]);
342        let channel = block.channel(1).copied().collect::<Vec<_>>();
343        assert_eq!(channel, vec![10.0, 11.0, 12.0, 13.0, 14.0]);
344    }
345
346    #[test]
347    fn test_channels() {
348        let mut block = Stacked::<f32>::new(2, 5);
349
350        let mut channels_iter = block.channels();
351        let channel = channels_iter.next().unwrap().copied().collect::<Vec<_>>();
352        assert_eq!(channel, vec![0.0, 0.0, 0.0, 0.0, 0.0]);
353        let channel = channels_iter.next().unwrap().copied().collect::<Vec<_>>();
354        assert_eq!(channel, vec![0.0, 0.0, 0.0, 0.0, 0.0]);
355        assert!(channels_iter.next().is_none());
356        drop(channels_iter);
357
358        let mut channels_iter = block.channels_mut();
359        channels_iter
360            .next()
361            .unwrap()
362            .enumerate()
363            .for_each(|(i, v)| *v = i as f32);
364        channels_iter
365            .next()
366            .unwrap()
367            .enumerate()
368            .for_each(|(i, v)| *v = i as f32 + 10.0);
369        assert!(channels_iter.next().is_none());
370        drop(channels_iter);
371
372        let mut channels_iter = block.channels();
373        let channel = channels_iter.next().unwrap().copied().collect::<Vec<_>>();
374        assert_eq!(channel, vec![0.0, 1.0, 2.0, 3.0, 4.0]);
375        let channel = channels_iter.next().unwrap().copied().collect::<Vec<_>>();
376        assert_eq!(channel, vec![10.0, 11.0, 12.0, 13.0, 14.0]);
377        assert!(channels_iter.next().is_none());
378        drop(channels_iter);
379    }
380
381    #[test]
382    fn test_frame() {
383        let mut block = Stacked::<f32>::new(2, 5);
384
385        for i in 0..block.num_frames() {
386            let frame = block.frame(i).copied().collect::<Vec<_>>();
387            assert_eq!(frame, vec![0.0, 0.0]);
388        }
389
390        for i in 0..block.num_frames() {
391            let add = i as f32 * 10.0;
392            block
393                .frame_mut(i)
394                .enumerate()
395                .for_each(|(i, v)| *v = i as f32 + add);
396        }
397
398        let channel = block.frame(0).copied().collect::<Vec<_>>();
399        assert_eq!(channel, vec![0.0, 1.0]);
400        let channel = block.frame(1).copied().collect::<Vec<_>>();
401        assert_eq!(channel, vec![10.0, 11.0]);
402        let channel = block.frame(2).copied().collect::<Vec<_>>();
403        assert_eq!(channel, vec![20.0, 21.0]);
404        let channel = block.frame(3).copied().collect::<Vec<_>>();
405        assert_eq!(channel, vec![30.0, 31.0]);
406        let channel = block.frame(4).copied().collect::<Vec<_>>();
407        assert_eq!(channel, vec![40.0, 41.0]);
408    }
409
410    #[test]
411    fn test_frames() {
412        let mut block = Stacked::<f32>::new(3, 6);
413        block.resize(2, 5);
414
415        let num_frames = block.num_frames;
416        let mut frames_iter = block.frames();
417        for _ in 0..num_frames {
418            let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
419            assert_eq!(frame, vec![0.0, 0.0]);
420        }
421        assert!(frames_iter.next().is_none());
422        drop(frames_iter);
423
424        let mut frames_iter = block.frames_mut();
425        for i in 0..num_frames {
426            let add = i as f32 * 10.0;
427            frames_iter
428                .next()
429                .unwrap()
430                .enumerate()
431                .for_each(|(i, v)| *v = i as f32 + add);
432        }
433        assert!(frames_iter.next().is_none());
434        drop(frames_iter);
435
436        let mut frames_iter = block.frames();
437        let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
438        assert_eq!(frame, vec![0.0, 1.0]);
439        let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
440        assert_eq!(frame, vec![10.0, 11.0]);
441        let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
442        assert_eq!(frame, vec![20.0, 21.0]);
443        let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
444        assert_eq!(frame, vec![30.0, 31.0]);
445        let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
446        assert_eq!(frame, vec![40.0, 41.0]);
447        assert!(frames_iter.next().is_none());
448    }
449
450    #[test]
451    fn test_from_block() {
452        let block = Stacked::<f32>::from_block(&InterleavedView::from_slice(
453            &[0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0],
454            2,
455            5,
456        ));
457        assert_eq!(block.num_channels(), 2);
458        assert_eq!(block.num_channels_allocated(), 2);
459        assert_eq!(block.num_frames(), 5);
460        assert_eq!(block.num_frames_allocated(), 5);
461        assert_eq!(
462            block.channel(0).copied().collect::<Vec<_>>(),
463            vec![0.0, 2.0, 4.0, 6.0, 8.0]
464        );
465        assert_eq!(
466            block.channel(1).copied().collect::<Vec<_>>(),
467            vec![1.0, 3.0, 5.0, 7.0, 9.0]
468        );
469        assert_eq!(block.frame(0).copied().collect::<Vec<_>>(), vec![0.0, 1.0]);
470        assert_eq!(block.frame(1).copied().collect::<Vec<_>>(), vec![2.0, 3.0]);
471        assert_eq!(block.frame(2).copied().collect::<Vec<_>>(), vec![4.0, 5.0]);
472        assert_eq!(block.frame(3).copied().collect::<Vec<_>>(), vec![6.0, 7.0]);
473        assert_eq!(block.frame(4).copied().collect::<Vec<_>>(), vec![8.0, 9.0]);
474    }
475
476    #[test]
477    fn test_view() {
478        let block = Stacked::<f32>::from_block(&InterleavedView::from_slice(
479            &[0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0],
480            2,
481            5,
482        ));
483        let view = block.view();
484        assert_eq!(
485            view.channel(0).copied().collect::<Vec<_>>(),
486            vec![0.0, 2.0, 4.0, 6.0, 8.0]
487        );
488        assert_eq!(
489            view.channel(1).copied().collect::<Vec<_>>(),
490            vec![1.0, 3.0, 5.0, 7.0, 9.0]
491        );
492    }
493
494    #[test]
495    fn test_view_mut() {
496        let mut block = Stacked::<f32>::new(2, 5);
497        {
498            let mut view = block.view_mut();
499            view.channel_mut(0)
500                .enumerate()
501                .for_each(|(i, v)| *v = i as f32);
502            view.channel_mut(1)
503                .enumerate()
504                .for_each(|(i, v)| *v = i as f32 + 10.0);
505        }
506
507        assert_eq!(
508            block.channel(0).copied().collect::<Vec<_>>(),
509            vec![0.0, 1.0, 2.0, 3.0, 4.0]
510        );
511        assert_eq!(
512            block.channel(1).copied().collect::<Vec<_>>(),
513            vec![10.0, 11.0, 12.0, 13.0, 14.0]
514        );
515    }
516
517    #[test]
518    fn test_resize() {
519        let mut block = Stacked::<f32>::new(3, 10);
520        assert_eq!(block.num_channels(), 3);
521        assert_eq!(block.num_frames(), 10);
522        assert_eq!(block.num_channels_allocated(), 3);
523        assert_eq!(block.num_frames_allocated(), 10);
524
525        for i in 0..block.num_channels() {
526            assert_eq!(block.channel(i).count(), 10);
527            assert_eq!(block.channel_mut(i).count(), 10);
528        }
529        for i in 0..block.num_frames() {
530            assert_eq!(block.frame(i).count(), 3);
531            assert_eq!(block.frame_mut(i).count(), 3);
532        }
533
534        block.resize(3, 10);
535        block.resize(2, 5);
536
537        assert_eq!(block.num_channels(), 2);
538        assert_eq!(block.num_frames(), 5);
539        assert_eq!(block.num_channels_allocated(), 3);
540        assert_eq!(block.num_frames_allocated(), 10);
541
542        for i in 0..block.num_channels() {
543            assert_eq!(block.channel(i).count(), 5);
544            assert_eq!(block.channel_mut(i).count(), 5);
545        }
546        for i in 0..block.num_frames() {
547            assert_eq!(block.frame(i).count(), 2);
548            assert_eq!(block.frame_mut(i).count(), 2);
549        }
550    }
551
552    #[test]
553    #[should_panic]
554    #[no_sanitize_realtime]
555    fn test_wrong_resize_channels() {
556        let mut block = Stacked::<f32>::new(2, 10);
557        block.resize(3, 10);
558    }
559
560    #[test]
561    #[should_panic]
562    #[no_sanitize_realtime]
563    fn test_wrong_resize_frames() {
564        let mut block = Stacked::<f32>::new(2, 10);
565        block.resize(2, 11);
566    }
567
568    #[test]
569    #[should_panic]
570    #[no_sanitize_realtime]
571    fn test_wrong_channel() {
572        let mut block = Stacked::<f32>::new(2, 10);
573        block.resize(1, 10);
574        let _ = block.channel(1);
575    }
576
577    #[test]
578    #[should_panic]
579    #[no_sanitize_realtime]
580    fn test_wrong_frame() {
581        let mut block = Stacked::<f32>::new(2, 10);
582        block.resize(2, 5);
583        let _ = block.frame(5);
584    }
585
586    #[test]
587    #[should_panic]
588    #[no_sanitize_realtime]
589    fn test_wrong_channel_mut() {
590        let mut block = Stacked::<f32>::new(2, 10);
591        block.resize(1, 10);
592        let _ = block.channel_mut(1);
593    }
594
595    #[test]
596    #[should_panic]
597    #[no_sanitize_realtime]
598    fn test_wrong_frame_mut() {
599        let mut block = Stacked::<f32>::new(2, 10);
600        block.resize(2, 5);
601        let _ = block.frame_mut(5);
602    }
603
604    #[test]
605    fn test_raw_data() {
606        let mut vec = vec![vec![0.0, 2.0, 4.0, 6.0, 8.0], vec![1.0, 3.0, 5.0, 7.0, 9.0]];
607        let mut block = Stacked::from_block(&StackedViewMut::from_slice(&mut vec));
608
609        assert_eq!(block.layout(), crate::BlockLayout::Stacked);
610
611        assert_eq!(block.raw_data(Some(0)), &[0.0, 2.0, 4.0, 6.0, 8.0]);
612        assert_eq!(block.raw_data(Some(1)), &[1.0, 3.0, 5.0, 7.0, 9.0]);
613
614        assert_eq!(block.raw_data_mut(Some(0)), &[0.0, 2.0, 4.0, 6.0, 8.0]);
615        assert_eq!(block.raw_data_mut(Some(1)), &[1.0, 3.0, 5.0, 7.0, 9.0]);
616    }
617}