audio_blocks/stacked/
view_mut.rs

1use core::mem::MaybeUninit;
2use rtsan_standalone::nonblocking;
3use std::marker::PhantomData;
4
5use crate::{AudioBlock, AudioBlockMut, Sample};
6
7use super::StackedView;
8
9/// A mutable view of stacked / separate-channel audio data.
10///
11/// * **Layout:** `[[ch0, ch0, ch0], [ch1, ch1, ch1]]`
12/// * **Interpretation:** Each channel has its own separate buffer or array.
13/// * **Terminology:** Also described as “planar” or “channels first” though more specifically it’s channel-isolated buffers.
14/// * **Usage:** Very common in real-time DSP, as it simplifies memory access and can improve SIMD/vectorization efficiency.
15///
16/// # Example
17///
18/// ```
19/// use audio_blocks::*;
20///
21/// let mut data = vec![[0.0, 0.0, 0.0], [1.0, 1.0, 1.0]];
22///
23/// let block = StackedViewMut::from_slice(&mut data);
24///
25/// block.channel(0).for_each(|&v| assert_eq!(v, 0.0));
26/// block.channel(1).for_each(|&v| assert_eq!(v, 1.0));
27/// ```
28pub struct StackedViewMut<'a, S: Sample, V: AsMut<[S]> + AsRef<[S]>> {
29    data: &'a mut [V],
30    num_channels: u16,
31    num_frames: usize,
32    num_channels_allocated: u16,
33    num_frames_allocated: usize,
34    _phantom: PhantomData<S>,
35}
36
37impl<'a, S: Sample, V: AsMut<[S]> + AsRef<[S]>> StackedViewMut<'a, S, V> {
38    /// Creates a new [`StackedViewMut`] from a mutable slice of stacked audio data.
39    ///
40    /// # Parameters
41    /// * `data` - The mutable slice containing stacked audio samples (one slice per channel)
42    ///
43    /// # Panics
44    /// Panics if the channel slices have different lengths.
45    #[nonblocking]
46    pub fn from_slice(data: &'a mut [V]) -> Self {
47        let num_frames_available = if data.is_empty() {
48            0
49        } else {
50            data[0].as_ref().len()
51        };
52        Self::from_slice_limited(data, data.len() as u16, num_frames_available)
53    }
54
55    /// Creates a new [`StackedViewMut`] from a mutable slice with limited visibility.
56    ///
57    /// This function allows creating a view that exposes only a subset of the allocated channels
58    /// and frames, which is useful for working with a logical section of a larger buffer.
59    ///
60    /// # Parameters
61    /// * `data` - The mutable slice containing stacked audio samples (one slice per channel)
62    /// * `num_channels_visible` - Number of audio channels to expose in the view
63    /// * `num_frames_visible` - Number of audio frames to expose in the view
64    ///
65    /// # Panics
66    /// * Panics if `num_channels_visible` exceeds the number of channels in `data`
67    /// * Panics if `num_frames_visible` exceeds the length of any channel buffer
68    /// * Panics if channel slices have different lengths
69    #[nonblocking]
70    pub fn from_slice_limited(
71        data: &'a mut [V],
72        num_channels_visible: u16,
73        num_frames_visible: usize,
74    ) -> Self {
75        let num_channels_available = data.len();
76        let num_frames_available = if num_channels_available == 0 {
77            0
78        } else {
79            data[0].as_ref().len()
80        };
81        assert!(num_channels_visible <= num_channels_available as u16);
82        assert!(num_frames_visible <= num_frames_available);
83        data.iter()
84            .for_each(|v| assert_eq!(v.as_ref().len(), num_frames_available));
85
86        Self {
87            data,
88            num_channels: num_channels_visible,
89            num_frames: num_frames_visible,
90            num_channels_allocated: num_channels_available as u16,
91            num_frames_allocated: num_frames_available,
92            _phantom: PhantomData,
93        }
94    }
95}
96
97impl<S: Sample, V: AsMut<[S]> + AsRef<[S]>> AudioBlock<S> for StackedViewMut<'_, S, V> {
98    #[nonblocking]
99    fn num_channels(&self) -> u16 {
100        self.num_channels
101    }
102
103    #[nonblocking]
104    fn num_frames(&self) -> usize {
105        self.num_frames
106    }
107
108    #[nonblocking]
109    fn num_channels_allocated(&self) -> u16 {
110        self.num_channels_allocated
111    }
112
113    #[nonblocking]
114    fn num_frames_allocated(&self) -> usize {
115        self.num_frames_allocated
116    }
117
118    #[nonblocking]
119    fn sample(&self, channel: u16, frame: usize) -> S {
120        assert!(channel < self.num_channels);
121        assert!(frame < self.num_frames);
122        unsafe {
123            *self
124                .data
125                .get_unchecked(channel as usize)
126                .as_ref()
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                .as_ref()
138                .iter()
139                .take(self.num_frames)
140        }
141    }
142
143    #[nonblocking]
144    fn channels(&self) -> impl Iterator<Item = impl Iterator<Item = &S> + '_> + '_ {
145        let num_frames = self.num_frames; // Capture num_frames for the closure
146        self.data
147            .iter()
148            // Limit to the active number of channels
149            .take(self.num_channels as usize)
150            // For each channel slice, create an iterator over its samples
151            .map(move |channel_data| channel_data.as_ref().iter().take(num_frames))
152    }
153
154    #[nonblocking]
155    fn channel_slice(&self, channel: u16) -> Option<&[S]> {
156        assert!(channel < self.num_channels);
157        Some(&self.data[channel as usize].as_ref()[..self.num_frames])
158    }
159
160    #[nonblocking]
161    fn frame(&self, frame: usize) -> impl Iterator<Item = &S> {
162        assert!(frame < self.num_frames);
163        self.data
164            .iter()
165            .take(self.num_channels as usize)
166            .map(move |channel_data| unsafe { channel_data.as_ref().get_unchecked(frame) })
167    }
168
169    #[nonblocking]
170    fn frames(&self) -> impl Iterator<Item = impl Iterator<Item = &'_ S> + '_> + '_ {
171        let num_channels = self.num_channels as usize;
172        let num_frames = self.num_frames;
173        // `self.data` is the field `&'data [V]`. We get `&'a [V]` from `&'a self`.
174        let data_slice: &[V] = self.data;
175
176        // Assumes the struct/caller guarantees that for all `chan` in `0..num_channels`,
177        // `self.data[chan].as_ref().len() >= num_frames`.
178
179        (0..num_frames).map(move |frame_idx| {
180            // For each frame index, create an iterator over the relevant channel views.
181            data_slice[..num_channels]
182                .iter() // Yields `&'a V`
183                .map(move |channel_view: &V| {
184                    // Get the immutable slice `&[S]` from the view using AsRef.
185                    let channel_slice: &[S] = channel_view.as_ref();
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).as_ref() }
210    }
211}
212
213impl<S: Sample, V: AsMut<[S]> + AsRef<[S]>> AudioBlockMut<S> for StackedViewMut<'_, S, V> {
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                .as_mut()
234                .get_unchecked_mut(frame)
235        }
236    }
237
238    #[nonblocking]
239    fn channel_mut(&mut self, channel: u16) -> impl Iterator<Item = &mut S> {
240        assert!(channel < self.num_channels);
241        unsafe {
242            self.data
243                .get_unchecked_mut(channel as usize)
244                .as_mut()
245                .iter_mut()
246                .take(self.num_frames)
247        }
248    }
249
250    #[nonblocking]
251    fn channels_mut(&mut self) -> impl Iterator<Item = impl Iterator<Item = &mut S> + '_> + '_ {
252        let num_frames = self.num_frames;
253        self.data
254            .iter_mut()
255            .take(self.num_channels as usize)
256            .map(move |channel_data| channel_data.as_mut().iter_mut().take(num_frames))
257    }
258
259    #[nonblocking]
260    fn channel_slice_mut(&mut self, channel: u16) -> Option<&mut [S]> {
261        assert!(channel < self.num_channels);
262        Some(&mut self.data[channel as usize].as_mut()[..self.num_frames])
263    }
264
265    #[nonblocking]
266    fn frame_mut(&mut self, frame: usize) -> impl Iterator<Item = &mut S> {
267        assert!(frame < self.num_frames);
268        self.data
269            .iter_mut()
270            .take(self.num_channels as usize)
271            .map(move |channel_data| unsafe { channel_data.as_mut().get_unchecked_mut(frame) })
272    }
273
274    #[nonblocking]
275    fn frames_mut(&mut self) -> impl Iterator<Item = impl Iterator<Item = &mut S> + '_> + '_ {
276        let num_channels = self.num_channels as usize;
277        let num_frames = self.num_frames;
278        let data_slice: &mut [V] = self.data;
279        let data_ptr: *mut [V] = data_slice;
280
281        (0..num_frames).map(move |frame_idx| {
282            // Re-borrow mutably inside the closure via the raw pointer.
283            // Safety: Safe because the outer iterator executes this sequentially per frame.
284            let current_channel_views: &mut [V] = unsafe { &mut *data_ptr };
285
286            // Iterate over the relevant channel views up to num_channels.
287            current_channel_views[..num_channels]
288                .iter_mut() // Yields `&mut V`
289                .map(move |channel_view: &mut V| {
290                    // Get the mutable slice `&mut [S]` from the view using AsMut.
291                    let channel_slice: &mut [S] = channel_view.as_mut();
292                    // Access the sample for the current channel view at the current frame index.
293                    // Safety: Relies on `frame_idx < channel_slice.len()`.
294                    unsafe { channel_slice.get_unchecked_mut(frame_idx) }
295                })
296        })
297    }
298
299    #[nonblocking]
300    fn view_mut(&mut self) -> impl AudioBlockMut<S> {
301        StackedViewMut::from_slice_limited(self.data, self.num_channels, self.num_frames)
302    }
303
304    #[nonblocking]
305    fn raw_data_mut(&mut self, stacked_ch: Option<u16>) -> &mut [S] {
306        let ch = stacked_ch.expect("For stacked layout channel needs to be provided!");
307        assert!(ch < self.num_channels_allocated);
308        unsafe { self.data.get_unchecked_mut(ch as usize).as_mut() }
309    }
310}
311
312/// Adapter for creating mutable stacked audio block views from raw pointers.
313///
314/// This adapter provides a safe interface to work with mutable audio data stored in external buffers,
315/// which is common when interfacing with audio APIs or hardware.
316///
317/// # Example
318///
319/// ```
320/// use audio_blocks::*;
321///
322/// // Create sample data for two channels with five frames each
323/// let mut ch1 = vec![0.0f32, 1.0, 2.0, 3.0, 4.0];
324/// let mut ch2 = vec![5.0f32, 6.0, 7.0, 8.0, 9.0];
325///
326/// // Create mutable pointers to the channel data
327/// let mut ptrs = [ch1.as_mut_ptr(), ch2.as_mut_ptr()];
328/// let data = ptrs.as_mut_ptr();
329/// let num_channels = 2u16;
330/// let num_frames = 5;
331///
332/// // Create an adapter from raw pointers to audio channel data
333/// let mut adapter = unsafe { StackedPtrAdapterMut::<f32, 16>::from_ptr(data, num_channels, num_frames) };
334///
335/// // Get a safe mutable view of the audio data
336/// let mut block = adapter.stacked_view_mut();
337///
338/// // Verify the data access works and can be modified
339/// assert_eq!(block.sample(0, 2), 2.0);
340/// assert_eq!(block.sample(1, 3), 8.0);
341/// *block.sample_mut(0, 1) = 10.0; // Modify a sample
342/// ```
343///
344/// # Safety
345///
346/// When creating an adapter from raw pointers, you must ensure that:
347/// - The pointers are valid and properly aligned
348/// - The memory they point to remains valid for the lifetime of the adapter
349/// - The data is not accessed through other pointers during the adapter's lifetime
350/// - The channel count doesn't exceed the adapter's `MAX_CHANNELS` capacity
351pub struct StackedPtrAdapterMut<'a, S: Sample, const MAX_CHANNELS: usize> {
352    data: [MaybeUninit<&'a mut [S]>; MAX_CHANNELS],
353    num_channels: u16,
354}
355
356impl<'a, S: Sample, const MAX_CHANNELS: usize> StackedPtrAdapterMut<'a, S, MAX_CHANNELS> {
357    /// Creates new StackedPtrAdapterNew from raw pointers.
358    ///
359    /// # Safety
360    ///
361    /// - `ptr` must be a valid pointer to an array of pointers
362    /// - The array must contain at least `num_channels` valid pointers
363    /// - Each pointer in the array must point to a valid array of samples with `num_frames` length
364    /// - The pointed memory must remain valid for the lifetime of the returned adapter
365    /// - The data must not be modified through other pointers for the lifetime of the returned adapter
366    #[nonblocking]
367    pub unsafe fn from_ptr(ptrs: *mut *mut S, num_channels: u16, num_frames: usize) -> Self {
368        assert!(
369            num_channels as usize <= MAX_CHANNELS,
370            "num_channels exceeds MAX_CHANNELS"
371        );
372
373        let mut data: [MaybeUninit<&'a mut [S]>; MAX_CHANNELS] =
374            unsafe { MaybeUninit::uninit().assume_init() }; // Or other safe initialization
375
376        // SAFETY: Caller guarantees `ptr` is valid for `num_channels` elements.
377        let ptr_slice: &mut [*mut S] =
378            unsafe { core::slice::from_raw_parts_mut(ptrs, num_channels as usize) };
379
380        for ch in 0..num_channels as usize {
381            // SAFETY: See previous explanation
382            data[ch].write(unsafe { core::slice::from_raw_parts_mut(ptr_slice[ch], num_frames) });
383        }
384
385        Self { data, num_channels }
386    }
387
388    /// Returns a mutable slice of references to the initialized channel data buffers.
389    ///
390    /// This method provides access to the underlying audio data as a slice of mutable slices,
391    /// with each inner slice representing one audio channel.
392    #[inline]
393    pub fn data_slice_mut(&mut self) -> &mut [&'a mut [S]] {
394        let initialized_part: &mut [MaybeUninit<&'a mut [S]>] =
395            &mut self.data[..self.num_channels as usize];
396        unsafe {
397            core::slice::from_raw_parts_mut(
398                initialized_part.as_mut_ptr() as *mut &'a mut [S],
399                self.num_channels as usize,
400            )
401        }
402    }
403
404    /// Creates a safe [`StackedViewMut`] for accessing the audio data.
405    ///
406    /// This provides a convenient way to interact with the audio data through
407    /// the full [`AudioBlockMut`] interface, enabling operations like iterating
408    /// through channels or frames and modifying the underlying audio samples.
409    ///
410    /// # Returns
411    ///
412    /// A [`StackedViewMut`] that provides safe, mutable access to the audio data.
413    #[nonblocking]
414    pub fn stacked_view_mut(&mut self) -> StackedViewMut<'a, S, &mut [S]> {
415        StackedViewMut::from_slice(self.data_slice_mut())
416    }
417}
418
419#[cfg(test)]
420mod tests {
421
422    use rtsan_standalone::no_sanitize_realtime;
423
424    use super::*;
425
426    #[test]
427    fn test_samples() {
428        let mut ch1 = vec![0.0; 5];
429        let mut ch2 = vec![0.0; 5];
430        let mut data = vec![ch1.as_mut_slice(), ch2.as_mut_slice()];
431        let mut block = StackedViewMut::from_slice(&mut data);
432
433        let num_frames = block.num_frames();
434        for ch in 0..block.num_channels() {
435            for f in 0..block.num_frames() {
436                *block.sample_mut(ch, f) = (ch as usize * num_frames + f) as f32;
437            }
438        }
439
440        for ch in 0..block.num_channels() {
441            for f in 0..block.num_frames() {
442                assert_eq!(block.sample(ch, f), (ch as usize * num_frames + f) as f32);
443            }
444        }
445
446        assert_eq!(block.channel_slice(0).unwrap(), &[0.0, 1.0, 2.0, 3.0, 4.0]);
447        assert_eq!(block.channel_slice(1).unwrap(), &[5.0, 6.0, 7.0, 8.0, 9.0]);
448    }
449
450    #[test]
451    fn test_channel() {
452        let mut ch1 = vec![0.0; 5];
453        let mut ch2 = vec![0.0; 5];
454        let mut data = vec![ch1.as_mut_slice(), ch2.as_mut_slice()];
455        let mut block = StackedViewMut::from_slice(&mut data);
456
457        let channel = block.channel(0).copied().collect::<Vec<_>>();
458        assert_eq!(channel, vec![0.0, 0.0, 0.0, 0.0, 0.0]);
459        let channel = block.channel(1).copied().collect::<Vec<_>>();
460        assert_eq!(channel, vec![0.0, 0.0, 0.0, 0.0, 0.0]);
461
462        block
463            .channel_mut(0)
464            .enumerate()
465            .for_each(|(i, v)| *v = i as f32);
466        block
467            .channel_mut(1)
468            .enumerate()
469            .for_each(|(i, v)| *v = i as f32 + 10.0);
470
471        let channel = block.channel(0).copied().collect::<Vec<_>>();
472        assert_eq!(channel, vec![0.0, 1.0, 2.0, 3.0, 4.0]);
473        let channel = block.channel(1).copied().collect::<Vec<_>>();
474        assert_eq!(channel, vec![10.0, 11.0, 12.0, 13.0, 14.0]);
475    }
476
477    #[test]
478    fn test_channels() {
479        let mut ch1 = vec![0.0; 5];
480        let mut ch2 = vec![0.0; 5];
481        let mut data = vec![ch1.as_mut_slice(), ch2.as_mut_slice()];
482        let mut block = StackedViewMut::from_slice(&mut data);
483
484        let mut channels_iter = block.channels();
485        let channel = channels_iter.next().unwrap().copied().collect::<Vec<_>>();
486        assert_eq!(channel, vec![0.0, 0.0, 0.0, 0.0, 0.0]);
487        let channel = channels_iter.next().unwrap().copied().collect::<Vec<_>>();
488        assert_eq!(channel, vec![0.0, 0.0, 0.0, 0.0, 0.0]);
489        assert!(channels_iter.next().is_none());
490        drop(channels_iter);
491
492        let mut channels_iter = block.channels_mut();
493        channels_iter
494            .next()
495            .unwrap()
496            .enumerate()
497            .for_each(|(i, v)| *v = i as f32);
498        channels_iter
499            .next()
500            .unwrap()
501            .enumerate()
502            .for_each(|(i, v)| *v = i as f32 + 10.0);
503        assert!(channels_iter.next().is_none());
504        drop(channels_iter);
505
506        let mut channels_iter = block.channels();
507        let channel = channels_iter.next().unwrap().copied().collect::<Vec<_>>();
508        assert_eq!(channel, vec![0.0, 1.0, 2.0, 3.0, 4.0]);
509        let channel = channels_iter.next().unwrap().copied().collect::<Vec<_>>();
510        assert_eq!(channel, vec![10.0, 11.0, 12.0, 13.0, 14.0]);
511        assert!(channels_iter.next().is_none());
512        drop(channels_iter);
513    }
514
515    #[test]
516    fn test_frame() {
517        let mut ch1 = vec![0.0; 5];
518        let mut ch2 = vec![0.0; 5];
519        let mut data = vec![ch1.as_mut_slice(), ch2.as_mut_slice()];
520        let mut block = StackedViewMut::from_slice(&mut data);
521
522        for i in 0..block.num_frames() {
523            let frame = block.frame(i).copied().collect::<Vec<_>>();
524            assert_eq!(frame, vec![0.0, 0.0]);
525        }
526
527        for i in 0..block.num_frames() {
528            let add = i as f32 * 10.0;
529            block
530                .frame_mut(i)
531                .enumerate()
532                .for_each(|(i, v)| *v = i as f32 + add);
533        }
534
535        let channel = block.frame(0).copied().collect::<Vec<_>>();
536        assert_eq!(channel, vec![0.0, 1.0]);
537        let channel = block.frame(1).copied().collect::<Vec<_>>();
538        assert_eq!(channel, vec![10.0, 11.0]);
539        let channel = block.frame(2).copied().collect::<Vec<_>>();
540        assert_eq!(channel, vec![20.0, 21.0]);
541        let channel = block.frame(3).copied().collect::<Vec<_>>();
542        assert_eq!(channel, vec![30.0, 31.0]);
543        let channel = block.frame(4).copied().collect::<Vec<_>>();
544        assert_eq!(channel, vec![40.0, 41.0]);
545    }
546
547    #[test]
548    fn test_frames() {
549        let mut ch1 = vec![0.0; 10];
550        let mut ch2 = vec![0.0; 10];
551        let mut ch3 = vec![0.0; 10];
552        let mut data = vec![ch1.as_mut_slice(), ch2.as_mut_slice(), ch3.as_mut_slice()];
553        let mut block = StackedViewMut::from_slice(&mut data);
554        block.set_active_size(2, 5);
555
556        let num_frames = block.num_frames;
557        let mut frames_iter = block.frames();
558        for _ in 0..num_frames {
559            let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
560            assert_eq!(frame, vec![0.0, 0.0]);
561        }
562        assert!(frames_iter.next().is_none());
563        drop(frames_iter);
564
565        let mut frames_iter = block.frames_mut();
566        for i in 0..num_frames {
567            let add = i as f32 * 10.0;
568            frames_iter
569                .next()
570                .unwrap()
571                .enumerate()
572                .for_each(|(i, v)| *v = i as f32 + add);
573        }
574        assert!(frames_iter.next().is_none());
575        drop(frames_iter);
576
577        let mut frames_iter = block.frames();
578        let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
579        assert_eq!(frame, vec![0.0, 1.0]);
580        let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
581        assert_eq!(frame, vec![10.0, 11.0]);
582        let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
583        assert_eq!(frame, vec![20.0, 21.0]);
584        let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
585        assert_eq!(frame, vec![30.0, 31.0]);
586        let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
587        assert_eq!(frame, vec![40.0, 41.0]);
588        assert!(frames_iter.next().is_none());
589    }
590
591    #[test]
592    fn test_from_vec() {
593        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]];
594        let block = StackedViewMut::from_slice(&mut vec);
595        assert_eq!(block.num_channels(), 2);
596        assert_eq!(block.num_frames(), 5);
597        assert_eq!(
598            block.channel(0).copied().collect::<Vec<_>>(),
599            vec![0.0, 2.0, 4.0, 6.0, 8.0]
600        );
601        assert_eq!(
602            block.channel(1).copied().collect::<Vec<_>>(),
603            vec![1.0, 3.0, 5.0, 7.0, 9.0]
604        );
605        assert_eq!(block.frame(0).copied().collect::<Vec<_>>(), vec![0.0, 1.0]);
606        assert_eq!(block.frame(1).copied().collect::<Vec<_>>(), vec![2.0, 3.0]);
607        assert_eq!(block.frame(2).copied().collect::<Vec<_>>(), vec![4.0, 5.0]);
608        assert_eq!(block.frame(3).copied().collect::<Vec<_>>(), vec![6.0, 7.0]);
609        assert_eq!(block.frame(4).copied().collect::<Vec<_>>(), vec![8.0, 9.0]);
610    }
611
612    #[test]
613    fn test_view() {
614        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]];
615        let block = StackedViewMut::from_slice(&mut vec);
616        let view = block.view();
617        assert_eq!(
618            view.channel(0).copied().collect::<Vec<_>>(),
619            vec![0.0, 2.0, 4.0, 6.0, 8.0]
620        );
621        assert_eq!(
622            view.channel(1).copied().collect::<Vec<_>>(),
623            vec![1.0, 3.0, 5.0, 7.0, 9.0]
624        );
625    }
626
627    #[test]
628    fn test_view_mut() {
629        let mut data = vec![vec![0.0; 5]; 2];
630        let mut block = StackedViewMut::from_slice(&mut data);
631
632        {
633            let mut view = block.view_mut();
634            view.channel_mut(0)
635                .enumerate()
636                .for_each(|(i, v)| *v = i as f32);
637            view.channel_mut(1)
638                .enumerate()
639                .for_each(|(i, v)| *v = i as f32 + 10.0);
640        }
641
642        assert_eq!(
643            block.channel(0).copied().collect::<Vec<_>>(),
644            vec![0.0, 1.0, 2.0, 3.0, 4.0]
645        );
646        assert_eq!(
647            block.channel(1).copied().collect::<Vec<_>>(),
648            vec![10.0, 11.0, 12.0, 13.0, 14.0]
649        );
650    }
651
652    #[test]
653    fn test_limited() {
654        let mut data = vec![vec![0.0; 4]; 3];
655
656        let mut block = StackedViewMut::from_slice_limited(&mut data, 2, 3);
657
658        assert_eq!(block.num_channels(), 2);
659        assert_eq!(block.num_frames(), 3);
660        assert_eq!(block.num_channels_allocated, 3);
661        assert_eq!(block.num_frames_allocated, 4);
662
663        for i in 0..block.num_channels() {
664            assert_eq!(block.channel(i).count(), 3);
665            assert_eq!(block.channel_mut(i).count(), 3);
666        }
667        for i in 0..block.num_frames() {
668            assert_eq!(block.frame(i).count(), 2);
669            assert_eq!(block.frame_mut(i).count(), 2);
670        }
671    }
672
673    #[test]
674    fn test_pointer() {
675        unsafe {
676            let num_channels = 2;
677            let num_frames = 5;
678            let mut data = [vec![0.0, 2.0, 4.0, 6.0, 8.0], vec![1.0, 3.0, 5.0, 7.0, 9.0]];
679
680            let mut ptr_vec: Vec<*mut f32> = data
681                .iter_mut()
682                .map(|inner_vec| inner_vec.as_mut_ptr())
683                .collect();
684            let ptr = ptr_vec.as_mut_ptr();
685
686            let mut adaptor =
687                StackedPtrAdapterMut::<_, 16>::from_ptr(ptr, num_channels, num_frames);
688
689            let stacked = adaptor.stacked_view_mut();
690
691            assert_eq!(
692                stacked.channel(0).copied().collect::<Vec<_>>(),
693                vec![0.0, 2.0, 4.0, 6.0, 8.0]
694            );
695
696            assert_eq!(
697                stacked.channel(1).copied().collect::<Vec<_>>(),
698                vec![1.0, 3.0, 5.0, 7.0, 9.0]
699            );
700        }
701    }
702
703    #[test]
704    fn test_slice() {
705        let mut data = [[0.0; 4]; 3];
706        let mut block = StackedViewMut::from_slice_limited(&mut data, 2, 3);
707
708        assert!(block.frame_slice(0).is_none());
709
710        block.channel_slice_mut(0).unwrap().fill(1.0);
711        block.channel_slice_mut(1).unwrap().fill(2.0);
712        assert_eq!(block.channel_slice(0).unwrap(), &[1.0; 3]);
713        assert_eq!(block.channel_slice(1).unwrap(), &[2.0; 3]);
714    }
715
716    #[test]
717    #[should_panic]
718    #[no_sanitize_realtime]
719    fn test_slice_out_of_bounds() {
720        let mut data = [[0.0; 4]; 3];
721        let block = StackedViewMut::from_slice_limited(&mut data, 2, 3);
722
723        block.channel_slice(2);
724    }
725
726    #[test]
727    #[should_panic]
728    #[no_sanitize_realtime]
729    fn test_slice_out_of_bounds_mut() {
730        let mut data = [[0.0; 4]; 3];
731        let mut block = StackedViewMut::from_slice_limited(&mut data, 2, 3);
732
733        block.channel_slice_mut(2);
734    }
735
736    #[test]
737    fn test_raw_data() {
738        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]];
739        let mut block = StackedViewMut::from_slice(&mut vec);
740
741        assert_eq!(block.layout(), crate::BlockLayout::Stacked);
742
743        assert_eq!(block.raw_data(Some(0)), &[0.0, 2.0, 4.0, 6.0, 8.0]);
744        assert_eq!(block.raw_data(Some(1)), &[1.0, 3.0, 5.0, 7.0, 9.0]);
745
746        assert_eq!(block.raw_data_mut(Some(0)), &[0.0, 2.0, 4.0, 6.0, 8.0]);
747        assert_eq!(block.raw_data_mut(Some(1)), &[1.0, 3.0, 5.0, 7.0, 9.0]);
748    }
749}