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 frame(&self, frame: usize) -> impl Iterator<Item = &S> {
156        assert!(frame < self.num_frames);
157        self.data
158            .iter()
159            .take(self.num_channels as usize)
160            .map(move |channel_data| unsafe { channel_data.as_ref().get_unchecked(frame) })
161    }
162
163    #[nonblocking]
164    fn frames(&self) -> impl Iterator<Item = impl Iterator<Item = &'_ S> + '_> + '_ {
165        let num_channels = self.num_channels as usize;
166        let num_frames = self.num_frames;
167        // `self.data` is the field `&'data [V]`. We get `&'a [V]` from `&'a self`.
168        let data_slice: &[V] = self.data;
169
170        // Assumes the struct/caller guarantees that for all `chan` in `0..num_channels`,
171        // `self.data[chan].as_ref().len() >= num_frames`.
172
173        (0..num_frames).map(move |frame_idx| {
174            // For each frame index, create an iterator over the relevant channel views.
175            data_slice[..num_channels]
176                .iter() // Yields `&'a V`
177                .map(move |channel_view: &V| {
178                    // Get the immutable slice `&[S]` from the view using AsRef.
179                    let channel_slice: &[S] = channel_view.as_ref();
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).as_ref() }
204    }
205}
206
207impl<S: Sample, V: AsMut<[S]> + AsRef<[S]>> AudioBlockMut<S> for StackedViewMut<'_, S, V> {
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                .as_mut()
224                .get_unchecked_mut(frame)
225        }
226    }
227
228    #[nonblocking]
229    fn channel_mut(&mut self, channel: u16) -> impl Iterator<Item = &mut S> {
230        assert!(channel < self.num_channels);
231        unsafe {
232            self.data
233                .get_unchecked_mut(channel as usize)
234                .as_mut()
235                .iter_mut()
236                .take(self.num_frames)
237        }
238    }
239
240    #[nonblocking]
241    fn channels_mut(&mut self) -> impl Iterator<Item = impl Iterator<Item = &mut S> + '_> + '_ {
242        let num_frames = self.num_frames;
243        self.data
244            .iter_mut()
245            .take(self.num_channels as usize)
246            .map(move |channel_data| channel_data.as_mut().iter_mut().take(num_frames))
247    }
248
249    #[nonblocking]
250    fn frame_mut(&mut self, frame: usize) -> impl Iterator<Item = &mut S> {
251        assert!(frame < self.num_frames);
252        self.data
253            .iter_mut()
254            .take(self.num_channels as usize)
255            .map(move |channel_data| unsafe { channel_data.as_mut().get_unchecked_mut(frame) })
256    }
257
258    #[nonblocking]
259    fn frames_mut(&mut self) -> impl Iterator<Item = impl Iterator<Item = &mut S> + '_> + '_ {
260        let num_channels = self.num_channels as usize;
261        let num_frames = self.num_frames;
262        let data_slice: &mut [V] = self.data;
263        let data_ptr: *mut [V] = data_slice;
264
265        (0..num_frames).map(move |frame_idx| {
266            // Re-borrow mutably inside the closure via the raw pointer.
267            // Safety: Safe because the outer iterator executes this sequentially per frame.
268            let current_channel_views: &mut [V] = unsafe { &mut *data_ptr };
269
270            // Iterate over the relevant channel views up to num_channels.
271            current_channel_views[..num_channels]
272                .iter_mut() // Yields `&mut V`
273                .map(move |channel_view: &mut V| {
274                    // Get the mutable slice `&mut [S]` from the view using AsMut.
275                    let channel_slice: &mut [S] = channel_view.as_mut();
276                    // Access the sample for the current channel view at the current frame index.
277                    // Safety: Relies on `frame_idx < channel_slice.len()`.
278                    unsafe { channel_slice.get_unchecked_mut(frame_idx) }
279                })
280        })
281    }
282
283    #[nonblocking]
284    fn view_mut(&mut self) -> impl AudioBlockMut<S> {
285        StackedViewMut::from_slice_limited(self.data, self.num_channels, self.num_frames)
286    }
287
288    #[nonblocking]
289    fn raw_data_mut(&mut self, stacked_ch: Option<u16>) -> &mut [S] {
290        let ch = stacked_ch.expect("For stacked layout channel needs to be provided!");
291        assert!(ch < self.num_channels_allocated);
292        unsafe { self.data.get_unchecked_mut(ch as usize).as_mut() }
293    }
294}
295
296/// Adapter for creating mutable stacked audio block views from raw pointers.
297///
298/// This adapter provides a safe interface to work with mutable audio data stored in external buffers,
299/// which is common when interfacing with audio APIs or hardware.
300///
301/// # Example
302///
303/// ```
304/// use audio_blocks::*;
305///
306/// // Create sample data for two channels with five frames each
307/// let mut ch1 = vec![0.0f32, 1.0, 2.0, 3.0, 4.0];
308/// let mut ch2 = vec![5.0f32, 6.0, 7.0, 8.0, 9.0];
309///
310/// // Create mutable pointers to the channel data
311/// let mut ptrs = [ch1.as_mut_ptr(), ch2.as_mut_ptr()];
312/// let data = ptrs.as_mut_ptr();
313/// let num_channels = 2u16;
314/// let num_frames = 5;
315///
316/// // Create an adapter from raw pointers to audio channel data
317/// let mut adapter = unsafe { StackedPtrAdapterMut::<f32, 16>::from_ptr(data, num_channels, num_frames) };
318///
319/// // Get a safe mutable view of the audio data
320/// let mut block = adapter.stacked_view_mut();
321///
322/// // Verify the data access works and can be modified
323/// assert_eq!(block.sample(0, 2), 2.0);
324/// assert_eq!(block.sample(1, 3), 8.0);
325/// *block.sample_mut(0, 1) = 10.0; // Modify a sample
326/// ```
327///
328/// # Safety
329///
330/// When creating an adapter from raw pointers, you must ensure that:
331/// - The pointers are valid and properly aligned
332/// - The memory they point to remains valid for the lifetime of the adapter
333/// - The data is not accessed through other pointers during the adapter's lifetime
334/// - The channel count doesn't exceed the adapter's `MAX_CHANNELS` capacity
335pub struct StackedPtrAdapterMut<'a, S: Sample, const MAX_CHANNELS: usize> {
336    data: [MaybeUninit<&'a mut [S]>; MAX_CHANNELS],
337    num_channels: u16,
338}
339
340impl<'a, S: Sample, const MAX_CHANNELS: usize> StackedPtrAdapterMut<'a, S, MAX_CHANNELS> {
341    /// Creates new StackedPtrAdapterNew from raw pointers.
342    ///
343    /// # Safety
344    ///
345    /// - `ptr` must be a valid pointer to an array of pointers
346    /// - The array must contain at least `num_channels` valid pointers
347    /// - Each pointer in the array must point to a valid array of samples with `num_frames` length
348    /// - The pointed memory must remain valid for the lifetime of the returned adapter
349    /// - The data must not be modified through other pointers for the lifetime of the returned adapter
350    #[nonblocking]
351    pub unsafe fn from_ptr(ptrs: *mut *mut S, num_channels: u16, num_frames: usize) -> Self {
352        assert!(
353            num_channels as usize <= MAX_CHANNELS,
354            "num_channels exceeds MAX_CHANNELS"
355        );
356
357        let mut data: [MaybeUninit<&'a mut [S]>; MAX_CHANNELS] =
358            unsafe { MaybeUninit::uninit().assume_init() }; // Or other safe initialization
359
360        // SAFETY: Caller guarantees `ptr` is valid for `num_channels` elements.
361        let ptr_slice: &mut [*mut S] =
362            unsafe { core::slice::from_raw_parts_mut(ptrs, num_channels as usize) };
363
364        for ch in 0..num_channels as usize {
365            // SAFETY: See previous explanation
366            data[ch].write(unsafe { core::slice::from_raw_parts_mut(ptr_slice[ch], num_frames) });
367        }
368
369        Self { data, num_channels }
370    }
371
372    /// Returns a mutable slice of references to the initialized channel data buffers.
373    ///
374    /// This method provides access to the underlying audio data as a slice of mutable slices,
375    /// with each inner slice representing one audio channel.
376    #[inline]
377    pub fn data_slice_mut(&mut self) -> &mut [&'a mut [S]] {
378        let initialized_part: &mut [MaybeUninit<&'a mut [S]>] =
379            &mut self.data[..self.num_channels as usize];
380        unsafe {
381            core::slice::from_raw_parts_mut(
382                initialized_part.as_mut_ptr() as *mut &'a mut [S],
383                self.num_channels as usize,
384            )
385        }
386    }
387
388    /// Creates a safe [`StackedViewMut`] for accessing the audio data.
389    ///
390    /// This provides a convenient way to interact with the audio data through
391    /// the full [`AudioBlockMut`] interface, enabling operations like iterating
392    /// through channels or frames and modifying the underlying audio samples.
393    ///
394    /// # Returns
395    ///
396    /// A [`StackedViewMut`] that provides safe, mutable access to the audio data.
397    #[nonblocking]
398    pub fn stacked_view_mut(&mut self) -> StackedViewMut<'a, S, &mut [S]> {
399        StackedViewMut::from_slice(self.data_slice_mut())
400    }
401}
402
403#[cfg(test)]
404mod tests {
405
406    use super::*;
407
408    #[test]
409    fn test_samples() {
410        let mut ch1 = vec![0.0; 5];
411        let mut ch2 = vec![0.0; 5];
412        let mut data = vec![ch1.as_mut_slice(), ch2.as_mut_slice()];
413        let mut block = StackedViewMut::from_slice(&mut data);
414
415        let num_frames = block.num_frames();
416        for ch in 0..block.num_channels() {
417            for f in 0..block.num_frames() {
418                *block.sample_mut(ch, f) = (ch as usize * num_frames + f) as f32;
419            }
420        }
421
422        for ch in 0..block.num_channels() {
423            for f in 0..block.num_frames() {
424                assert_eq!(block.sample(ch, f), (ch as usize * num_frames + f) as f32);
425            }
426        }
427
428        assert_eq!(block.raw_data(Some(0)), &[0.0, 1.0, 2.0, 3.0, 4.0]);
429        assert_eq!(block.raw_data(Some(1)), &[5.0, 6.0, 7.0, 8.0, 9.0]);
430    }
431
432    #[test]
433    fn test_channel() {
434        let mut ch1 = vec![0.0; 5];
435        let mut ch2 = vec![0.0; 5];
436        let mut data = vec![ch1.as_mut_slice(), ch2.as_mut_slice()];
437        let mut block = StackedViewMut::from_slice(&mut data);
438
439        let channel = block.channel(0).copied().collect::<Vec<_>>();
440        assert_eq!(channel, vec![0.0, 0.0, 0.0, 0.0, 0.0]);
441        let channel = block.channel(1).copied().collect::<Vec<_>>();
442        assert_eq!(channel, vec![0.0, 0.0, 0.0, 0.0, 0.0]);
443
444        block
445            .channel_mut(0)
446            .enumerate()
447            .for_each(|(i, v)| *v = i as f32);
448        block
449            .channel_mut(1)
450            .enumerate()
451            .for_each(|(i, v)| *v = i as f32 + 10.0);
452
453        let channel = block.channel(0).copied().collect::<Vec<_>>();
454        assert_eq!(channel, vec![0.0, 1.0, 2.0, 3.0, 4.0]);
455        let channel = block.channel(1).copied().collect::<Vec<_>>();
456        assert_eq!(channel, vec![10.0, 11.0, 12.0, 13.0, 14.0]);
457    }
458
459    #[test]
460    fn test_channels() {
461        let mut ch1 = vec![0.0; 5];
462        let mut ch2 = vec![0.0; 5];
463        let mut data = vec![ch1.as_mut_slice(), ch2.as_mut_slice()];
464        let mut block = StackedViewMut::from_slice(&mut data);
465
466        let mut channels_iter = block.channels();
467        let channel = channels_iter.next().unwrap().copied().collect::<Vec<_>>();
468        assert_eq!(channel, vec![0.0, 0.0, 0.0, 0.0, 0.0]);
469        let channel = channels_iter.next().unwrap().copied().collect::<Vec<_>>();
470        assert_eq!(channel, vec![0.0, 0.0, 0.0, 0.0, 0.0]);
471        assert!(channels_iter.next().is_none());
472        drop(channels_iter);
473
474        let mut channels_iter = block.channels_mut();
475        channels_iter
476            .next()
477            .unwrap()
478            .enumerate()
479            .for_each(|(i, v)| *v = i as f32);
480        channels_iter
481            .next()
482            .unwrap()
483            .enumerate()
484            .for_each(|(i, v)| *v = i as f32 + 10.0);
485        assert!(channels_iter.next().is_none());
486        drop(channels_iter);
487
488        let mut channels_iter = block.channels();
489        let channel = channels_iter.next().unwrap().copied().collect::<Vec<_>>();
490        assert_eq!(channel, vec![0.0, 1.0, 2.0, 3.0, 4.0]);
491        let channel = channels_iter.next().unwrap().copied().collect::<Vec<_>>();
492        assert_eq!(channel, vec![10.0, 11.0, 12.0, 13.0, 14.0]);
493        assert!(channels_iter.next().is_none());
494        drop(channels_iter);
495    }
496
497    #[test]
498    fn test_frame() {
499        let mut ch1 = vec![0.0; 5];
500        let mut ch2 = vec![0.0; 5];
501        let mut data = vec![ch1.as_mut_slice(), ch2.as_mut_slice()];
502        let mut block = StackedViewMut::from_slice(&mut data);
503
504        for i in 0..block.num_frames() {
505            let frame = block.frame(i).copied().collect::<Vec<_>>();
506            assert_eq!(frame, vec![0.0, 0.0]);
507        }
508
509        for i in 0..block.num_frames() {
510            let add = i as f32 * 10.0;
511            block
512                .frame_mut(i)
513                .enumerate()
514                .for_each(|(i, v)| *v = i as f32 + add);
515        }
516
517        let channel = block.frame(0).copied().collect::<Vec<_>>();
518        assert_eq!(channel, vec![0.0, 1.0]);
519        let channel = block.frame(1).copied().collect::<Vec<_>>();
520        assert_eq!(channel, vec![10.0, 11.0]);
521        let channel = block.frame(2).copied().collect::<Vec<_>>();
522        assert_eq!(channel, vec![20.0, 21.0]);
523        let channel = block.frame(3).copied().collect::<Vec<_>>();
524        assert_eq!(channel, vec![30.0, 31.0]);
525        let channel = block.frame(4).copied().collect::<Vec<_>>();
526        assert_eq!(channel, vec![40.0, 41.0]);
527    }
528
529    #[test]
530    fn test_frames() {
531        let mut ch1 = vec![0.0; 10];
532        let mut ch2 = vec![0.0; 10];
533        let mut ch3 = vec![0.0; 10];
534        let mut data = vec![ch1.as_mut_slice(), ch2.as_mut_slice(), ch3.as_mut_slice()];
535        let mut block = StackedViewMut::from_slice(&mut data);
536        block.resize(2, 5);
537
538        let num_frames = block.num_frames;
539        let mut frames_iter = block.frames();
540        for _ in 0..num_frames {
541            let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
542            assert_eq!(frame, vec![0.0, 0.0]);
543        }
544        assert!(frames_iter.next().is_none());
545        drop(frames_iter);
546
547        let mut frames_iter = block.frames_mut();
548        for i in 0..num_frames {
549            let add = i as f32 * 10.0;
550            frames_iter
551                .next()
552                .unwrap()
553                .enumerate()
554                .for_each(|(i, v)| *v = i as f32 + add);
555        }
556        assert!(frames_iter.next().is_none());
557        drop(frames_iter);
558
559        let mut frames_iter = block.frames();
560        let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
561        assert_eq!(frame, vec![0.0, 1.0]);
562        let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
563        assert_eq!(frame, vec![10.0, 11.0]);
564        let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
565        assert_eq!(frame, vec![20.0, 21.0]);
566        let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
567        assert_eq!(frame, vec![30.0, 31.0]);
568        let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
569        assert_eq!(frame, vec![40.0, 41.0]);
570        assert!(frames_iter.next().is_none());
571    }
572
573    #[test]
574    fn test_from_vec() {
575        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]];
576        let block = StackedViewMut::from_slice(&mut vec);
577        assert_eq!(block.num_channels(), 2);
578        assert_eq!(block.num_frames(), 5);
579        assert_eq!(
580            block.channel(0).copied().collect::<Vec<_>>(),
581            vec![0.0, 2.0, 4.0, 6.0, 8.0]
582        );
583        assert_eq!(
584            block.channel(1).copied().collect::<Vec<_>>(),
585            vec![1.0, 3.0, 5.0, 7.0, 9.0]
586        );
587        assert_eq!(block.frame(0).copied().collect::<Vec<_>>(), vec![0.0, 1.0]);
588        assert_eq!(block.frame(1).copied().collect::<Vec<_>>(), vec![2.0, 3.0]);
589        assert_eq!(block.frame(2).copied().collect::<Vec<_>>(), vec![4.0, 5.0]);
590        assert_eq!(block.frame(3).copied().collect::<Vec<_>>(), vec![6.0, 7.0]);
591        assert_eq!(block.frame(4).copied().collect::<Vec<_>>(), vec![8.0, 9.0]);
592    }
593
594    #[test]
595    fn test_view() {
596        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]];
597        let block = StackedViewMut::from_slice(&mut vec);
598        let view = block.view();
599        assert_eq!(
600            view.channel(0).copied().collect::<Vec<_>>(),
601            vec![0.0, 2.0, 4.0, 6.0, 8.0]
602        );
603        assert_eq!(
604            view.channel(1).copied().collect::<Vec<_>>(),
605            vec![1.0, 3.0, 5.0, 7.0, 9.0]
606        );
607    }
608
609    #[test]
610    fn test_view_mut() {
611        let mut data = vec![vec![0.0; 5]; 2];
612        let mut block = StackedViewMut::from_slice(&mut data);
613
614        {
615            let mut view = block.view_mut();
616            view.channel_mut(0)
617                .enumerate()
618                .for_each(|(i, v)| *v = i as f32);
619            view.channel_mut(1)
620                .enumerate()
621                .for_each(|(i, v)| *v = i as f32 + 10.0);
622        }
623
624        assert_eq!(
625            block.channel(0).copied().collect::<Vec<_>>(),
626            vec![0.0, 1.0, 2.0, 3.0, 4.0]
627        );
628        assert_eq!(
629            block.channel(1).copied().collect::<Vec<_>>(),
630            vec![10.0, 11.0, 12.0, 13.0, 14.0]
631        );
632    }
633
634    #[test]
635    fn test_limited() {
636        let mut data = vec![vec![0.0; 4]; 3];
637
638        let mut block = StackedViewMut::from_slice_limited(&mut data, 2, 3);
639
640        assert_eq!(block.num_channels(), 2);
641        assert_eq!(block.num_frames(), 3);
642        assert_eq!(block.num_channels_allocated, 3);
643        assert_eq!(block.num_frames_allocated, 4);
644
645        for i in 0..block.num_channels() {
646            assert_eq!(block.channel(i).count(), 3);
647            assert_eq!(block.channel_mut(i).count(), 3);
648        }
649        for i in 0..block.num_frames() {
650            assert_eq!(block.frame(i).count(), 2);
651            assert_eq!(block.frame_mut(i).count(), 2);
652        }
653    }
654
655    #[test]
656    fn test_pointer() {
657        unsafe {
658            let num_channels = 2;
659            let num_frames = 5;
660            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]];
661
662            let mut ptr_vec: Vec<*mut f32> = data
663                .iter_mut()
664                .map(|inner_vec| inner_vec.as_mut_ptr())
665                .collect();
666            let ptr = ptr_vec.as_mut_ptr();
667
668            let mut adaptor =
669                StackedPtrAdapterMut::<_, 16>::from_ptr(ptr, num_channels, num_frames);
670
671            let stacked = adaptor.stacked_view_mut();
672
673            assert_eq!(
674                stacked.channel(0).copied().collect::<Vec<_>>(),
675                vec![0.0, 2.0, 4.0, 6.0, 8.0]
676            );
677
678            assert_eq!(
679                stacked.channel(1).copied().collect::<Vec<_>>(),
680                vec![1.0, 3.0, 5.0, 7.0, 9.0]
681            );
682        }
683    }
684
685    #[test]
686    fn test_raw_data() {
687        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]];
688        let mut block = StackedViewMut::from_slice(&mut vec);
689
690        assert_eq!(block.layout(), crate::BlockLayout::Stacked);
691
692        assert_eq!(block.raw_data(Some(0)), &[0.0, 2.0, 4.0, 6.0, 8.0]);
693        assert_eq!(block.raw_data(Some(1)), &[1.0, 3.0, 5.0, 7.0, 9.0]);
694
695        assert_eq!(block.raw_data_mut(Some(0)), &[0.0, 2.0, 4.0, 6.0, 8.0]);
696        assert_eq!(block.raw_data_mut(Some(1)), &[1.0, 3.0, 5.0, 7.0, 9.0]);
697    }
698}