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::zero(); 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 channel_slice(&self, channel: u16) -> Option<&[S]> {
155        assert!(channel < self.num_channels);
156        Some(&self.data[channel as usize].as_ref()[..self.num_frames])
157    }
158
159    #[nonblocking]
160    fn frame(&self, frame: usize) -> impl Iterator<Item = &S> {
161        assert!(frame < self.num_frames);
162        self.data
163            .iter()
164            .take(self.num_channels as usize)
165            .map(move |channel_data| unsafe { channel_data.get_unchecked(frame) })
166    }
167
168    #[nonblocking]
169    fn frames(&self) -> impl Iterator<Item = impl Iterator<Item = &S> + '_> + '_ {
170        let num_channels = self.num_channels as usize;
171        let num_frames = self.num_frames;
172        // Get an immutable slice of the channel boxes: `&[Box<[S]>]`
173        let data_slice: &[Box<[S]>] = &self.data;
174
175        // Assumes the struct guarantees that for all `chan` in `0..num_channels`,
176        // `self.data[chan].len() >= num_frames`.
177
178        (0..num_frames).map(move |frame_idx| {
179            // For each frame index, create an iterator over the relevant channel boxes.
180            // `data_slice` is captured immutably, which is allowed by nested closures.
181            data_slice[..num_channels]
182                .iter() // Yields `&'a Box<[S]>`
183                .map(move |channel_slice_box| {
184                    // Get the immutable slice `&[S]` from the box.
185                    let channel_slice: &[S] = channel_slice_box;
186                    // Access the sample immutably using safe indexing.
187                    // Assumes frame_idx is valid based on outer loop and struct invariants.
188                    &channel_slice[frame_idx]
189                    // For max performance (if bounds are absolutely guaranteed):
190                    // unsafe { channel_slice.get_unchecked(frame_idx) }
191                })
192        })
193    }
194
195    #[nonblocking]
196    fn view(&self) -> impl AudioBlock<S> {
197        StackedView::from_slice_limited(&self.data, self.num_channels, self.num_frames)
198    }
199
200    #[nonblocking]
201    fn layout(&self) -> crate::BlockLayout {
202        crate::BlockLayout::Stacked
203    }
204
205    #[nonblocking]
206    fn raw_data(&self, stacked_ch: Option<u16>) -> &[S] {
207        let ch = stacked_ch.expect("For stacked layout channel needs to be provided!");
208        assert!(ch < self.num_channels_allocated);
209        unsafe { self.data.get_unchecked(ch as usize) }
210    }
211}
212
213impl<S: Sample> AudioBlockMut<S> for Stacked<S> {
214    #[nonblocking]
215    fn set_active_num_channels(&mut self, num_channels: u16) {
216        assert!(num_channels <= self.num_channels_allocated);
217        self.num_channels = num_channels;
218    }
219
220    #[nonblocking]
221    fn set_active_num_frames(&mut self, num_frames: usize) {
222        assert!(num_frames <= self.num_frames_allocated);
223        self.num_frames = num_frames;
224    }
225
226    #[nonblocking]
227    fn sample_mut(&mut self, channel: u16, frame: usize) -> &mut S {
228        assert!(channel < self.num_channels);
229        assert!(frame < self.num_frames);
230        unsafe {
231            self.data
232                .get_unchecked_mut(channel as usize)
233                .get_unchecked_mut(frame)
234        }
235    }
236
237    #[nonblocking]
238    fn channel_mut(&mut self, channel: u16) -> impl Iterator<Item = &mut S> {
239        assert!(channel < self.num_channels);
240        unsafe {
241            self.data
242                .get_unchecked_mut(channel as usize)
243                .iter_mut()
244                .take(self.num_frames)
245        }
246    }
247
248    #[nonblocking]
249    fn channels_mut(&mut self) -> impl Iterator<Item = impl Iterator<Item = &mut S> + '_> + '_ {
250        let num_frames = self.num_frames;
251        self.data
252            .iter_mut()
253            .take(self.num_channels as usize)
254            .map(move |channel_data| channel_data.as_mut().iter_mut().take(num_frames))
255    }
256
257    #[nonblocking]
258    fn channel_slice_mut(&mut self, channel: u16) -> Option<&mut [S]> {
259        assert!(channel < self.num_channels);
260        Some(&mut self.data[channel as usize].as_mut()[..self.num_frames])
261    }
262
263    #[nonblocking]
264    fn frame_mut(&mut self, frame: usize) -> impl Iterator<Item = &mut S> {
265        assert!(frame < self.num_frames);
266        self.data
267            .iter_mut()
268            .take(self.num_channels as usize)
269            .map(move |channel_data| unsafe { channel_data.get_unchecked_mut(frame) })
270    }
271
272    #[nonblocking]
273    fn frames_mut(&mut self) -> impl Iterator<Item = impl Iterator<Item = &mut S> + '_> + '_ {
274        let num_channels = self.num_channels as usize;
275        let num_frames = self.num_frames;
276        let data_slice: &mut [Box<[S]>] = &mut self.data;
277        let data_ptr: *mut [Box<[S]>] = data_slice;
278
279        (0..num_frames).map(move |frame_idx| {
280            // Re-borrow mutably inside the closure via the raw pointer.
281            // Safety: Safe because the outer iterator executes this sequentially per frame.
282            let current_channel_boxes: &mut [Box<[S]>] = unsafe { &mut *data_ptr };
283
284            // Iterate over the relevant channel boxes up to num_channels
285            current_channel_boxes[..num_channels]
286                .iter_mut() // Yields `&'a mut Box<[S]>`
287                .map(move |channel_slice_box| {
288                    // Get the mutable slice `&mut [S]` from the box.
289                    let channel_slice: &mut [S] = channel_slice_box;
290                    // Access the sample for the current channel at the current frame index.
291                    // Safety: Relies on `frame_idx < channel_slice.len()`.
292                    unsafe { channel_slice.get_unchecked_mut(frame_idx) }
293                })
294        })
295    }
296
297    #[nonblocking]
298    fn view_mut(&mut self) -> impl AudioBlockMut<S> {
299        StackedViewMut::from_slice_limited(&mut self.data, self.num_channels, self.num_frames)
300    }
301
302    #[nonblocking]
303    fn raw_data_mut(&mut self, stacked_ch: Option<u16>) -> &mut [S] {
304        let ch = stacked_ch.expect("For stacked layout channel needs to be provided!");
305        assert!(ch < self.num_channels_allocated);
306        unsafe { self.data.get_unchecked_mut(ch as usize).as_mut() }
307    }
308}
309
310#[cfg(test)]
311mod tests {
312    use rtsan_standalone::no_sanitize_realtime;
313
314    use super::*;
315    use crate::interleaved::InterleavedView;
316
317    #[test]
318    fn test_samples() {
319        let mut block = Stacked::<f32>::new(2, 5);
320
321        let num_frames = block.num_frames();
322        for ch in 0..block.num_channels() {
323            for f in 0..block.num_frames() {
324                *block.sample_mut(ch, f) = (ch as usize * num_frames + f) as f32;
325            }
326        }
327
328        for ch in 0..block.num_channels() {
329            for f in 0..block.num_frames() {
330                assert_eq!(block.sample(ch, f), (ch as usize * num_frames + f) as f32);
331            }
332        }
333
334        assert_eq!(block.raw_data(Some(0)), &[0.0, 1.0, 2.0, 3.0, 4.0]);
335        assert_eq!(block.raw_data(Some(1)), &[5.0, 6.0, 7.0, 8.0, 9.0]);
336    }
337
338    #[test]
339    fn test_channel() {
340        let mut block = Stacked::<f32>::new(2, 5);
341
342        let channel = block.channel(0).copied().collect::<Vec<_>>();
343        assert_eq!(channel, vec![0.0, 0.0, 0.0, 0.0, 0.0]);
344        let channel = block.channel(1).copied().collect::<Vec<_>>();
345        assert_eq!(channel, vec![0.0, 0.0, 0.0, 0.0, 0.0]);
346
347        block
348            .channel_mut(0)
349            .enumerate()
350            .for_each(|(i, v)| *v = i as f32);
351        block
352            .channel_mut(1)
353            .enumerate()
354            .for_each(|(i, v)| *v = i as f32 + 10.0);
355
356        let channel = block.channel(0).copied().collect::<Vec<_>>();
357        assert_eq!(channel, vec![0.0, 1.0, 2.0, 3.0, 4.0]);
358        let channel = block.channel(1).copied().collect::<Vec<_>>();
359        assert_eq!(channel, vec![10.0, 11.0, 12.0, 13.0, 14.0]);
360    }
361
362    #[test]
363    fn test_channels() {
364        let mut block = Stacked::<f32>::new(2, 5);
365
366        let mut channels_iter = block.channels();
367        let channel = channels_iter.next().unwrap().copied().collect::<Vec<_>>();
368        assert_eq!(channel, vec![0.0, 0.0, 0.0, 0.0, 0.0]);
369        let channel = channels_iter.next().unwrap().copied().collect::<Vec<_>>();
370        assert_eq!(channel, vec![0.0, 0.0, 0.0, 0.0, 0.0]);
371        assert!(channels_iter.next().is_none());
372        drop(channels_iter);
373
374        let mut channels_iter = block.channels_mut();
375        channels_iter
376            .next()
377            .unwrap()
378            .enumerate()
379            .for_each(|(i, v)| *v = i as f32);
380        channels_iter
381            .next()
382            .unwrap()
383            .enumerate()
384            .for_each(|(i, v)| *v = i as f32 + 10.0);
385        assert!(channels_iter.next().is_none());
386        drop(channels_iter);
387
388        let mut channels_iter = block.channels();
389        let channel = channels_iter.next().unwrap().copied().collect::<Vec<_>>();
390        assert_eq!(channel, vec![0.0, 1.0, 2.0, 3.0, 4.0]);
391        let channel = channels_iter.next().unwrap().copied().collect::<Vec<_>>();
392        assert_eq!(channel, vec![10.0, 11.0, 12.0, 13.0, 14.0]);
393        assert!(channels_iter.next().is_none());
394        drop(channels_iter);
395    }
396
397    #[test]
398    fn test_frame() {
399        let mut block = Stacked::<f32>::new(2, 5);
400
401        for i in 0..block.num_frames() {
402            let frame = block.frame(i).copied().collect::<Vec<_>>();
403            assert_eq!(frame, vec![0.0, 0.0]);
404        }
405
406        for i in 0..block.num_frames() {
407            let add = i as f32 * 10.0;
408            block
409                .frame_mut(i)
410                .enumerate()
411                .for_each(|(i, v)| *v = i as f32 + add);
412        }
413
414        let channel = block.frame(0).copied().collect::<Vec<_>>();
415        assert_eq!(channel, vec![0.0, 1.0]);
416        let channel = block.frame(1).copied().collect::<Vec<_>>();
417        assert_eq!(channel, vec![10.0, 11.0]);
418        let channel = block.frame(2).copied().collect::<Vec<_>>();
419        assert_eq!(channel, vec![20.0, 21.0]);
420        let channel = block.frame(3).copied().collect::<Vec<_>>();
421        assert_eq!(channel, vec![30.0, 31.0]);
422        let channel = block.frame(4).copied().collect::<Vec<_>>();
423        assert_eq!(channel, vec![40.0, 41.0]);
424    }
425
426    #[test]
427    fn test_frames() {
428        let mut block = Stacked::<f32>::new(3, 6);
429        block.set_active_size(2, 5);
430
431        let num_frames = block.num_frames;
432        let mut frames_iter = block.frames();
433        for _ in 0..num_frames {
434            let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
435            assert_eq!(frame, vec![0.0, 0.0]);
436        }
437        assert!(frames_iter.next().is_none());
438        drop(frames_iter);
439
440        let mut frames_iter = block.frames_mut();
441        for i in 0..num_frames {
442            let add = i as f32 * 10.0;
443            frames_iter
444                .next()
445                .unwrap()
446                .enumerate()
447                .for_each(|(i, v)| *v = i as f32 + add);
448        }
449        assert!(frames_iter.next().is_none());
450        drop(frames_iter);
451
452        let mut frames_iter = block.frames();
453        let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
454        assert_eq!(frame, vec![0.0, 1.0]);
455        let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
456        assert_eq!(frame, vec![10.0, 11.0]);
457        let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
458        assert_eq!(frame, vec![20.0, 21.0]);
459        let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
460        assert_eq!(frame, vec![30.0, 31.0]);
461        let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
462        assert_eq!(frame, vec![40.0, 41.0]);
463        assert!(frames_iter.next().is_none());
464    }
465
466    #[test]
467    fn test_from_block() {
468        let block = Stacked::<f32>::from_block(&InterleavedView::from_slice(
469            &[0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0],
470            2,
471            5,
472        ));
473        assert_eq!(block.num_channels(), 2);
474        assert_eq!(block.num_channels_allocated(), 2);
475        assert_eq!(block.num_frames(), 5);
476        assert_eq!(block.num_frames_allocated(), 5);
477        assert_eq!(
478            block.channel(0).copied().collect::<Vec<_>>(),
479            vec![0.0, 2.0, 4.0, 6.0, 8.0]
480        );
481        assert_eq!(
482            block.channel(1).copied().collect::<Vec<_>>(),
483            vec![1.0, 3.0, 5.0, 7.0, 9.0]
484        );
485        assert_eq!(block.frame(0).copied().collect::<Vec<_>>(), vec![0.0, 1.0]);
486        assert_eq!(block.frame(1).copied().collect::<Vec<_>>(), vec![2.0, 3.0]);
487        assert_eq!(block.frame(2).copied().collect::<Vec<_>>(), vec![4.0, 5.0]);
488        assert_eq!(block.frame(3).copied().collect::<Vec<_>>(), vec![6.0, 7.0]);
489        assert_eq!(block.frame(4).copied().collect::<Vec<_>>(), vec![8.0, 9.0]);
490    }
491
492    #[test]
493    fn test_view() {
494        let block = Stacked::<f32>::from_block(&InterleavedView::from_slice(
495            &[0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0],
496            2,
497            5,
498        ));
499        let view = block.view();
500        assert_eq!(
501            view.channel(0).copied().collect::<Vec<_>>(),
502            vec![0.0, 2.0, 4.0, 6.0, 8.0]
503        );
504        assert_eq!(
505            view.channel(1).copied().collect::<Vec<_>>(),
506            vec![1.0, 3.0, 5.0, 7.0, 9.0]
507        );
508    }
509
510    #[test]
511    fn test_view_mut() {
512        let mut block = Stacked::<f32>::new(2, 5);
513        {
514            let mut view = block.view_mut();
515            view.channel_mut(0)
516                .enumerate()
517                .for_each(|(i, v)| *v = i as f32);
518            view.channel_mut(1)
519                .enumerate()
520                .for_each(|(i, v)| *v = i as f32 + 10.0);
521        }
522
523        assert_eq!(
524            block.channel(0).copied().collect::<Vec<_>>(),
525            vec![0.0, 1.0, 2.0, 3.0, 4.0]
526        );
527        assert_eq!(
528            block.channel(1).copied().collect::<Vec<_>>(),
529            vec![10.0, 11.0, 12.0, 13.0, 14.0]
530        );
531    }
532
533    #[test]
534    fn test_resize() {
535        let mut block = Stacked::<f32>::new(3, 10);
536        assert_eq!(block.num_channels(), 3);
537        assert_eq!(block.num_frames(), 10);
538        assert_eq!(block.num_channels_allocated(), 3);
539        assert_eq!(block.num_frames_allocated(), 10);
540
541        for i in 0..block.num_channels() {
542            assert_eq!(block.channel(i).count(), 10);
543            assert_eq!(block.channel_mut(i).count(), 10);
544        }
545        for i in 0..block.num_frames() {
546            assert_eq!(block.frame(i).count(), 3);
547            assert_eq!(block.frame_mut(i).count(), 3);
548        }
549
550        block.set_active_size(3, 10);
551        block.set_active_size(2, 5);
552
553        assert_eq!(block.num_channels(), 2);
554        assert_eq!(block.num_frames(), 5);
555        assert_eq!(block.num_channels_allocated(), 3);
556        assert_eq!(block.num_frames_allocated(), 10);
557
558        for i in 0..block.num_channels() {
559            assert_eq!(block.channel(i).count(), 5);
560            assert_eq!(block.channel_mut(i).count(), 5);
561        }
562        for i in 0..block.num_frames() {
563            assert_eq!(block.frame(i).count(), 2);
564            assert_eq!(block.frame_mut(i).count(), 2);
565        }
566    }
567
568    #[test]
569    #[should_panic]
570    #[no_sanitize_realtime]
571    fn test_wrong_resize_channels() {
572        let mut block = Stacked::<f32>::new(2, 10);
573        block.set_active_size(3, 10);
574    }
575
576    #[test]
577    #[should_panic]
578    #[no_sanitize_realtime]
579    fn test_wrong_resize_frames() {
580        let mut block = Stacked::<f32>::new(2, 10);
581        block.set_active_size(2, 11);
582    }
583
584    #[test]
585    #[should_panic]
586    #[no_sanitize_realtime]
587    fn test_wrong_channel() {
588        let mut block = Stacked::<f32>::new(2, 10);
589        block.set_active_size(1, 10);
590        let _ = block.channel(1);
591    }
592
593    #[test]
594    #[should_panic]
595    #[no_sanitize_realtime]
596    fn test_wrong_frame() {
597        let mut block = Stacked::<f32>::new(2, 10);
598        block.set_active_size(2, 5);
599        let _ = block.frame(5);
600    }
601
602    #[test]
603    #[should_panic]
604    #[no_sanitize_realtime]
605    fn test_wrong_channel_mut() {
606        let mut block = Stacked::<f32>::new(2, 10);
607        block.set_active_size(1, 10);
608        let _ = block.channel_mut(1);
609    }
610
611    #[test]
612    #[should_panic]
613    #[no_sanitize_realtime]
614    fn test_wrong_frame_mut() {
615        let mut block = Stacked::<f32>::new(2, 10);
616        block.set_active_size(2, 5);
617        let _ = block.frame_mut(5);
618    }
619
620    #[test]
621    fn test_slice() {
622        let mut block = Stacked::<f32>::new(3, 4);
623        block.set_active_size(2, 3);
624
625        assert!(block.frame_slice(0).is_none());
626
627        block.channel_slice_mut(0).unwrap().fill(1.0);
628        block.channel_slice_mut(1).unwrap().fill(2.0);
629        assert_eq!(block.channel_slice(0).unwrap(), &[1.0; 3]);
630        assert_eq!(block.channel_slice(1).unwrap(), &[2.0; 3]);
631    }
632
633    #[test]
634    #[should_panic]
635    #[no_sanitize_realtime]
636    fn test_slice_out_of_bounds() {
637        let mut block = Stacked::<f32>::new(3, 4);
638        block.set_active_size(2, 3);
639
640        block.channel_slice(2);
641    }
642
643    #[test]
644    #[should_panic]
645    #[no_sanitize_realtime]
646    fn test_slice_out_of_bounds_mut() {
647        let mut block = Stacked::<f32>::new(3, 4);
648        block.set_active_size(2, 3);
649
650        block.channel_slice_mut(2);
651    }
652
653    #[test]
654    fn test_raw_data() {
655        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]];
656        let mut block = Stacked::from_block(&StackedViewMut::from_slice(&mut vec));
657
658        assert_eq!(block.layout(), crate::BlockLayout::Stacked);
659
660        assert_eq!(block.raw_data(Some(0)), &[0.0, 2.0, 4.0, 6.0, 8.0]);
661        assert_eq!(block.raw_data(Some(1)), &[1.0, 3.0, 5.0, 7.0, 9.0]);
662
663        assert_eq!(block.raw_data_mut(Some(0)), &[0.0, 2.0, 4.0, 6.0, 8.0]);
664        assert_eq!(block.raw_data_mut(Some(1)), &[1.0, 3.0, 5.0, 7.0, 9.0]);
665    }
666}