Skip to main content

audio_blocks/planar/
view_mut.rs

1use core::mem::MaybeUninit;
2use rtsan_standalone::nonblocking;
3use std::marker::PhantomData;
4
5use crate::{AudioBlock, AudioBlockMut, Sample};
6
7use super::AudioBlockPlanarView;
8
9/// A mutable view of planar / 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 = AudioBlockPlanarViewMut::from_slice(&mut data);
24///
25/// assert_eq!(block.channel(0), &[0.0, 0.0, 0.0]);
26/// assert_eq!(block.channel(1), &[1.0, 1.0, 1.0]);
27/// ```
28pub struct AudioBlockPlanarViewMut<'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]>> AudioBlockPlanarViewMut<'a, S, V> {
38    /// Creates a new audio block from a mutable slice of planar audio data.
39    ///
40    /// # Parameters
41    /// * `data` - The mutable slice containing planar 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_allocated = 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_allocated)
53    }
54
55    /// Creates a new audio block 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 planar 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_allocated = data.len();
76        let num_frames_allocated = if num_channels_allocated == 0 {
77            0
78        } else {
79            data[0].as_ref().len()
80        };
81        assert!(num_channels_visible <= num_channels_allocated as u16);
82        assert!(num_frames_visible <= num_frames_allocated);
83        data.iter()
84            .for_each(|v| assert_eq!(v.as_ref().len(), num_frames_allocated));
85
86        Self {
87            data,
88            num_channels: num_channels_visible,
89            num_frames: num_frames_visible,
90            num_channels_allocated: num_channels_allocated as u16,
91            num_frames_allocated,
92            _phantom: PhantomData,
93        }
94    }
95
96    /// Returns a slice for a single channel.
97    ///
98    /// # Panics
99    ///
100    /// Panics if channel index is out of bounds.
101    #[nonblocking]
102    pub fn channel(&self, channel: u16) -> &[S] {
103        assert!(channel < self.num_channels);
104        &self.data[channel as usize].as_ref()[..self.num_frames]
105    }
106
107    /// Returns a mutable slice for a single channel.
108    ///
109    /// # Panics
110    ///
111    /// Panics if channel index is out of bounds.
112    #[nonblocking]
113    pub fn channel_mut(&mut self, channel: u16) -> &mut [S] {
114        assert!(channel < self.num_channels);
115        &mut self.data[channel as usize].as_mut()[..self.num_frames]
116    }
117
118    /// Returns an iterator over all channels in the block.
119    ///
120    /// Each channel is represented as a slice of samples.
121    #[nonblocking]
122    pub fn channels(&self) -> impl ExactSizeIterator<Item = &[S]> {
123        self.data
124            .iter()
125            .take(self.num_channels as usize)
126            .map(|channel_data| &channel_data.as_ref()[..self.num_frames])
127    }
128
129    /// Returns a mutable iterator over all channels in the block.
130    ///
131    /// Each channel is represented as a mutable slice of samples.
132    #[nonblocking]
133    pub fn channels_mut(&mut self) -> impl ExactSizeIterator<Item = &mut [S]> {
134        self.data
135            .iter_mut()
136            .take(self.num_channels as usize)
137            .map(|channel_data| &mut channel_data.as_mut()[..self.num_frames])
138    }
139
140    /// Provides direct access to the underlying memory.
141    ///
142    /// This function gives access to all allocated data, including any reserved capacity
143    /// beyond the visible range.
144    #[nonblocking]
145    pub fn raw_data(&self) -> &[V] {
146        self.data
147    }
148
149    /// Provides direct access to the underlying memory.
150    ///
151    /// This function gives access to all allocated data, including any reserved capacity
152    /// beyond the visible range.
153    #[nonblocking]
154    pub fn raw_data_mut(&mut self) -> &mut [V] {
155        self.data
156    }
157
158    #[nonblocking]
159    pub fn view(&self) -> AudioBlockPlanarView<'_, S, V> {
160        AudioBlockPlanarView::from_slice_limited(self.data, self.num_channels, self.num_frames)
161    }
162
163    #[nonblocking]
164    pub fn view_mut(&mut self) -> AudioBlockPlanarViewMut<'_, S, V> {
165        AudioBlockPlanarViewMut::from_slice_limited(self.data, self.num_channels, self.num_frames)
166    }
167}
168
169impl<S: Sample, V: AsMut<[S]> + AsRef<[S]>> AudioBlock<S> for AudioBlockPlanarViewMut<'_, S, V> {
170    type PlanarView = V;
171
172    #[nonblocking]
173    fn num_channels(&self) -> u16 {
174        self.num_channels
175    }
176
177    #[nonblocking]
178    fn num_frames(&self) -> usize {
179        self.num_frames
180    }
181
182    #[nonblocking]
183    fn num_channels_allocated(&self) -> u16 {
184        self.num_channels_allocated
185    }
186
187    #[nonblocking]
188    fn num_frames_allocated(&self) -> usize {
189        self.num_frames_allocated
190    }
191
192    #[nonblocking]
193    fn layout(&self) -> crate::BlockLayout {
194        crate::BlockLayout::Planar
195    }
196
197    #[nonblocking]
198    fn sample(&self, channel: u16, frame: usize) -> S {
199        assert!(channel < self.num_channels);
200        assert!(frame < self.num_frames);
201        unsafe {
202            *self
203                .data
204                .get_unchecked(channel as usize)
205                .as_ref()
206                .get_unchecked(frame)
207        }
208    }
209
210    #[nonblocking]
211    fn channel_iter(&self, channel: u16) -> impl ExactSizeIterator<Item = &S> {
212        assert!(channel < self.num_channels);
213        unsafe {
214            self.data
215                .get_unchecked(channel as usize)
216                .as_ref()
217                .iter()
218                .take(self.num_frames)
219        }
220    }
221
222    #[nonblocking]
223    fn channels_iter(&self) -> impl ExactSizeIterator<Item = impl ExactSizeIterator<Item = &S>> {
224        let num_frames = self.num_frames; // Capture num_frames for the closure
225        self.data
226            .iter()
227            // Limit to the visible number of channels
228            .take(self.num_channels as usize)
229            // For each channel slice, create an iterator over its samples
230            .map(move |channel_data| channel_data.as_ref().iter().take(num_frames))
231    }
232
233    #[nonblocking]
234    fn frame_iter(&self, frame: usize) -> impl ExactSizeIterator<Item = &S> {
235        assert!(frame < self.num_frames);
236        self.data
237            .iter()
238            .take(self.num_channels as usize)
239            .map(move |channel_data| unsafe { channel_data.as_ref().get_unchecked(frame) })
240    }
241
242    #[nonblocking]
243    fn frames_iter(&self) -> impl ExactSizeIterator<Item = impl ExactSizeIterator<Item = &'_ S>> {
244        let num_channels = self.num_channels as usize;
245        let num_frames = self.num_frames;
246        // `self.data` is the field `&'data [V]`. We get `&'a [V]` from `&'a self`.
247        let data_slice: &[V] = self.data;
248
249        // Assumes the struct/caller guarantees that for all `chan` in `0..num_channels`,
250        // `self.data[chan].as_ref().len() >= num_frames`.
251
252        (0..num_frames).map(move |frame_idx| {
253            // For each frame index, create an iterator over the relevant channel views.
254            data_slice[..num_channels]
255                .iter() // Yields `&'a V`
256                .map(move |channel_view: &V| {
257                    // Get the immutable slice `&[S]` from the view using AsRef.
258                    let channel_slice: &[S] = channel_view.as_ref();
259                    // Access the sample immutably using safe indexing.
260                    // Assumes frame_idx is valid based on outer loop and struct invariants.
261                    &channel_slice[frame_idx]
262                    // For max performance (if bounds are absolutely guaranteed):
263                    // unsafe { channel_slice.get_unchecked(frame_idx) }
264                })
265        })
266    }
267
268    #[nonblocking]
269    fn as_view(&self) -> impl AudioBlock<S> {
270        AudioBlockPlanarView::from_slice_limited(self.data, self.num_channels, self.num_frames)
271    }
272
273    #[nonblocking]
274    fn as_planar_view(&self) -> Option<AudioBlockPlanarView<'_, S, Self::PlanarView>> {
275        Some(self.view())
276    }
277}
278
279impl<S: Sample, V: AsMut<[S]> + AsRef<[S]>> AudioBlockMut<S> for AudioBlockPlanarViewMut<'_, S, V> {
280    type PlanarViewMut = V;
281
282    #[nonblocking]
283    fn set_num_channels_visible(&mut self, num_channels: u16) {
284        assert!(num_channels <= self.num_channels_allocated);
285        self.num_channels = num_channels;
286    }
287
288    #[nonblocking]
289    fn set_num_frames_visible(&mut self, num_frames: usize) {
290        assert!(num_frames <= self.num_frames_allocated);
291        self.num_frames = num_frames;
292    }
293
294    #[nonblocking]
295    fn sample_mut(&mut self, channel: u16, frame: usize) -> &mut S {
296        assert!(channel < self.num_channels);
297        assert!(frame < self.num_frames);
298        unsafe {
299            self.data
300                .get_unchecked_mut(channel as usize)
301                .as_mut()
302                .get_unchecked_mut(frame)
303        }
304    }
305
306    #[nonblocking]
307    fn channel_iter_mut(&mut self, channel: u16) -> impl ExactSizeIterator<Item = &mut S> {
308        assert!(channel < self.num_channels);
309        unsafe {
310            self.data
311                .get_unchecked_mut(channel as usize)
312                .as_mut()
313                .iter_mut()
314                .take(self.num_frames)
315        }
316    }
317
318    #[nonblocking]
319    fn channels_iter_mut(
320        &mut self,
321    ) -> impl ExactSizeIterator<Item = impl ExactSizeIterator<Item = &mut S>> {
322        let num_frames = self.num_frames;
323        self.data
324            .iter_mut()
325            .take(self.num_channels as usize)
326            .map(move |channel_data| channel_data.as_mut().iter_mut().take(num_frames))
327    }
328
329    #[nonblocking]
330    fn frame_iter_mut(&mut self, frame: usize) -> impl ExactSizeIterator<Item = &mut S> {
331        assert!(frame < self.num_frames);
332        self.data
333            .iter_mut()
334            .take(self.num_channels as usize)
335            .map(move |channel_data| unsafe { channel_data.as_mut().get_unchecked_mut(frame) })
336    }
337
338    #[nonblocking]
339    fn frames_iter_mut(
340        &mut self,
341    ) -> impl ExactSizeIterator<Item = impl ExactSizeIterator<Item = &mut S>> {
342        let num_channels = self.num_channels as usize;
343        let num_frames = self.num_frames;
344        let data_slice: &mut [V] = self.data;
345        let data_ptr: *mut [V] = data_slice;
346
347        (0..num_frames).map(move |frame_idx| {
348            // Re-borrow mutably inside the closure via the raw pointer.
349            // Safety: Safe because the outer iterator executes this sequentially per frame.
350            let current_channel_views: &mut [V] = unsafe { &mut *data_ptr };
351
352            // Iterate over the relevant channel views up to num_channels.
353            current_channel_views[..num_channels]
354                .iter_mut() // Yields `&mut V`
355                .map(move |channel_view: &mut V| {
356                    // Get the mutable slice `&mut [S]` from the view using AsMut.
357                    let channel_slice: &mut [S] = channel_view.as_mut();
358                    // Access the sample for the current channel view at the current frame index.
359                    // Safety: Relies on `frame_idx < channel_slice.len()`.
360                    unsafe { channel_slice.get_unchecked_mut(frame_idx) }
361                })
362        })
363    }
364
365    #[nonblocking]
366    fn as_view_mut(&mut self) -> impl AudioBlockMut<S> {
367        self.view_mut()
368    }
369
370    #[nonblocking]
371    fn as_planar_view_mut(
372        &mut self,
373    ) -> Option<AudioBlockPlanarViewMut<'_, S, Self::PlanarViewMut>> {
374        Some(self.view_mut())
375    }
376}
377
378impl<S: Sample + core::fmt::Debug, V: AsMut<[S]> + AsRef<[S]> + core::fmt::Debug> core::fmt::Debug
379    for AudioBlockPlanarViewMut<'_, S, V>
380{
381    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
382        writeln!(f, "AudioBlockPlanarViewMut {{")?;
383        writeln!(f, "  num_channels: {}", self.num_channels)?;
384        writeln!(f, "  num_frames: {}", self.num_frames)?;
385        writeln!(
386            f,
387            "  num_channels_allocated: {}",
388            self.num_channels_allocated
389        )?;
390        writeln!(f, "  num_frames_allocated: {}", self.num_frames_allocated)?;
391        writeln!(f, "  channels:")?;
392
393        for (i, channel) in self.channels().enumerate() {
394            writeln!(f, "    {}: {:?}", i, channel)?;
395        }
396
397        writeln!(f, "  raw_data: {:?}", self.raw_data())?;
398        writeln!(f, "}}")?;
399
400        Ok(())
401    }
402}
403
404/// Adapter for creating mutable planar audio block views from raw pointers.
405///
406/// This adapter provides a safe interface to work with mutable audio data stored in external buffers,
407/// which is common when interfacing with audio APIs or hardware.
408///
409/// # Example
410///
411/// ```
412/// use audio_blocks::*;
413///
414/// // Create sample data for two channels with five frames each
415/// let mut ch1 = vec![0.0f32, 1.0, 2.0, 3.0, 4.0];
416/// let mut ch2 = vec![5.0f32, 6.0, 7.0, 8.0, 9.0];
417///
418/// // Create mutable pointers to the channel data
419/// let mut ptrs = [ch1.as_mut_ptr(), ch2.as_mut_ptr()];
420/// let data = ptrs.as_mut_ptr();
421/// let num_channels = 2u16;
422/// let num_frames = 5;
423///
424/// // Create an adapter from raw pointers to audio channel data
425/// let mut adapter = unsafe { PlanarPtrAdapterMut::<f32, 16>::from_ptr(data, num_channels, num_frames) };
426///
427/// // Get a safe mutable view of the audio data
428/// let mut block = adapter.planar_view_mut();
429///
430/// // Verify the data access works and can be modified
431/// assert_eq!(block.sample(0, 2), 2.0);
432/// assert_eq!(block.sample(1, 3), 8.0);
433/// *block.sample_mut(0, 1) = 10.0; // Modify a sample
434/// ```
435///
436/// # Safety
437///
438/// When creating an adapter from raw pointers, you must ensure that:
439/// - The pointers are valid and properly aligned
440/// - The memory they point to remains valid for the lifetime of the adapter
441/// - The data is not accessed through other pointers during the adapter's lifetime
442/// - The channel count doesn't exceed the adapter's `MAX_CHANNELS` capacity
443pub struct PlanarPtrAdapterMut<'a, S: Sample, const MAX_CHANNELS: usize> {
444    data: [MaybeUninit<&'a mut [S]>; MAX_CHANNELS],
445    num_channels: u16,
446}
447
448impl<'a, S: Sample, const MAX_CHANNELS: usize> PlanarPtrAdapterMut<'a, S, MAX_CHANNELS> {
449    /// Creates new pointer adapter to create an audio block from raw pointers.
450    ///
451    /// # Safety
452    ///
453    /// - `ptr` must be a valid pointer to an array of pointers
454    /// - The array must contain at least `num_channels` valid pointers
455    /// - Each pointer in the array must point to a valid array of samples with `num_frames` length
456    /// - The pointed memory must remain valid for the lifetime of the returned adapter
457    /// - The data must not be modified through other pointers for the lifetime of the returned adapter
458    #[nonblocking]
459    pub unsafe fn from_ptr(ptrs: *mut *mut S, num_channels: u16, num_frames: usize) -> Self {
460        assert!(
461            num_channels as usize <= MAX_CHANNELS,
462            "num_channels exceeds MAX_CHANNELS"
463        );
464
465        let mut data: [MaybeUninit<&'a mut [S]>; MAX_CHANNELS] =
466            unsafe { MaybeUninit::uninit().assume_init() }; // Or other safe initialization
467
468        // SAFETY: Caller guarantees `ptr` is valid for `num_channels` elements.
469        let ptr_slice: &mut [*mut S] =
470            unsafe { core::slice::from_raw_parts_mut(ptrs, num_channels as usize) };
471
472        for ch in 0..num_channels as usize {
473            // SAFETY: See previous explanation
474            data[ch].write(unsafe { core::slice::from_raw_parts_mut(ptr_slice[ch], num_frames) });
475        }
476
477        Self { data, num_channels }
478    }
479
480    /// Returns a mutable slice of references to the initialized channel data buffers.
481    ///
482    /// This method provides access to the underlying audio data as a slice of mutable slices,
483    /// with each inner slice representing one audio channel.
484    #[inline]
485    pub fn data_slice_mut(&mut self) -> &mut [&'a mut [S]] {
486        let initialized_part: &mut [MaybeUninit<&'a mut [S]>] =
487            &mut self.data[..self.num_channels as usize];
488        unsafe {
489            core::slice::from_raw_parts_mut(
490                initialized_part.as_mut_ptr() as *mut &'a mut [S],
491                self.num_channels as usize,
492            )
493        }
494    }
495
496    /// Creates a safe [`AudioBlockPlanarViewMut`] for accessing the audio data.
497    ///
498    /// This provides a convenient way to interact with the audio data through
499    /// the full [`AudioBlockMut`] interface, enabling operations like iterating
500    /// through channels or frames and modifying the underlying audio samples.
501    ///
502    /// # Returns
503    ///
504    /// An [`AudioBlockPlanarViewMut`] that provides safe, mutable access to the audio data.
505    #[nonblocking]
506    pub fn planar_view_mut(&mut self) -> AudioBlockPlanarViewMut<'a, S, &mut [S]> {
507        AudioBlockPlanarViewMut::from_slice(self.data_slice_mut())
508    }
509}
510
511#[cfg(test)]
512mod tests {
513    use super::*;
514    use rtsan_standalone::no_sanitize_realtime;
515
516    #[test]
517    fn test_member_functions() {
518        let mut data = [
519            [0.0, 1.0, 2.0, 3.0],
520            [4.0, 5.0, 6.0, 7.0],
521            [0.0, 0.0, 0.0, 0.0],
522        ];
523        let mut block = AudioBlockPlanarViewMut::from_slice_limited(&mut data, 2, 3);
524
525        // single frame
526        assert_eq!(block.channel(0), &[0.0, 1.0, 2.0]);
527        assert_eq!(block.channel(1), &[4.0, 5.0, 6.0]);
528
529        assert_eq!(block.channel_mut(0), &[0.0, 1.0, 2.0]);
530        assert_eq!(block.channel_mut(1), &[4.0, 5.0, 6.0]);
531
532        // all frames
533        let mut channels = block.channels();
534        assert_eq!(channels.next().unwrap(), &[0.0, 1.0, 2.0]);
535        assert_eq!(channels.next().unwrap(), &[4.0, 5.0, 6.0]);
536        assert_eq!(channels.next(), None);
537        drop(channels);
538
539        let mut channels = block.channels_mut();
540        assert_eq!(channels.next().unwrap(), &[0.0, 1.0, 2.0]);
541        assert_eq!(channels.next().unwrap(), &[4.0, 5.0, 6.0]);
542        assert_eq!(channels.next(), None);
543        drop(channels);
544
545        // raw data
546        assert_eq!(block.raw_data()[0].as_ref(), &[0.0, 1.0, 2.0, 3.0]);
547        assert_eq!(block.raw_data()[1].as_ref(), &[4.0, 5.0, 6.0, 7.0]);
548        assert_eq!(block.raw_data()[2].as_ref(), &[0.0, 0.0, 0.0, 0.0]);
549
550        assert_eq!(block.raw_data_mut()[0].as_ref(), &[0.0, 1.0, 2.0, 3.0]);
551        assert_eq!(block.raw_data_mut()[1].as_ref(), &[4.0, 5.0, 6.0, 7.0]);
552        assert_eq!(block.raw_data_mut()[2].as_ref(), &[0.0, 0.0, 0.0, 0.0]);
553
554        // views
555        let view = block.view();
556        assert_eq!(view.num_channels(), block.num_channels());
557        assert_eq!(view.num_frames(), block.num_frames());
558        assert_eq!(
559            view.num_channels_allocated(),
560            block.num_channels_allocated()
561        );
562        assert_eq!(view.num_frames_allocated(), block.num_frames_allocated());
563        assert_eq!(view.raw_data(), block.raw_data());
564
565        let num_channels = block.num_channels();
566        let num_frames = block.num_frames();
567        let num_channels_allocated = block.num_channels_allocated();
568        let num_frames_allocated = block.num_frames_allocated();
569        let data = block.raw_data().to_vec();
570        let view = block.view_mut();
571        assert_eq!(view.num_channels(), num_channels);
572        assert_eq!(view.num_frames(), num_frames);
573        assert_eq!(view.num_channels_allocated(), num_channels_allocated);
574        assert_eq!(view.num_frames_allocated(), num_frames_allocated);
575        assert_eq!(view.raw_data(), &data);
576    }
577
578    #[test]
579    fn test_samples() {
580        let mut ch1 = vec![0.0; 5];
581        let mut ch2 = vec![0.0; 5];
582        let mut data = vec![ch1.as_mut_slice(), ch2.as_mut_slice()];
583        let mut block = AudioBlockPlanarViewMut::from_slice(&mut data);
584
585        let num_frames = block.num_frames();
586        for ch in 0..block.num_channels() {
587            for f in 0..block.num_frames() {
588                *block.sample_mut(ch, f) = (ch as usize * num_frames + f) as f32;
589            }
590        }
591
592        for ch in 0..block.num_channels() {
593            for f in 0..block.num_frames() {
594                assert_eq!(block.sample(ch, f), (ch as usize * num_frames + f) as f32);
595            }
596        }
597
598        assert_eq!(block.channel(0), &[0.0, 1.0, 2.0, 3.0, 4.0]);
599        assert_eq!(block.channel(1), &[5.0, 6.0, 7.0, 8.0, 9.0]);
600    }
601
602    #[test]
603    fn test_channel_iter() {
604        let mut ch1 = vec![0.0; 5];
605        let mut ch2 = vec![0.0; 5];
606        let mut data = vec![ch1.as_mut_slice(), ch2.as_mut_slice()];
607        let mut block = AudioBlockPlanarViewMut::from_slice(&mut data);
608
609        let channel = block.channel_iter(0).copied().collect::<Vec<_>>();
610        assert_eq!(channel, vec![0.0, 0.0, 0.0, 0.0, 0.0]);
611        let channel = block.channel_iter(1).copied().collect::<Vec<_>>();
612        assert_eq!(channel, vec![0.0, 0.0, 0.0, 0.0, 0.0]);
613
614        block
615            .channel_iter_mut(0)
616            .enumerate()
617            .for_each(|(i, v)| *v = i as f32);
618        block
619            .channel_iter_mut(1)
620            .enumerate()
621            .for_each(|(i, v)| *v = i as f32 + 10.0);
622
623        let channel = block.channel_iter(0).copied().collect::<Vec<_>>();
624        assert_eq!(channel, vec![0.0, 1.0, 2.0, 3.0, 4.0]);
625        let channel = block.channel_iter(1).copied().collect::<Vec<_>>();
626        assert_eq!(channel, vec![10.0, 11.0, 12.0, 13.0, 14.0]);
627    }
628
629    #[test]
630    fn test_channel_iters() {
631        let mut ch1 = vec![0.0; 5];
632        let mut ch2 = vec![0.0; 5];
633        let mut data = vec![ch1.as_mut_slice(), ch2.as_mut_slice()];
634        let mut block = AudioBlockPlanarViewMut::from_slice(&mut data);
635
636        let mut channels_iter = block.channels_iter();
637        let channel = channels_iter.next().unwrap().copied().collect::<Vec<_>>();
638        assert_eq!(channel, vec![0.0, 0.0, 0.0, 0.0, 0.0]);
639        let channel = channels_iter.next().unwrap().copied().collect::<Vec<_>>();
640        assert_eq!(channel, vec![0.0, 0.0, 0.0, 0.0, 0.0]);
641        assert!(channels_iter.next().is_none());
642        drop(channels_iter);
643
644        let mut channels_iter = block.channels_iter_mut();
645        channels_iter
646            .next()
647            .unwrap()
648            .enumerate()
649            .for_each(|(i, v)| *v = i as f32);
650        channels_iter
651            .next()
652            .unwrap()
653            .enumerate()
654            .for_each(|(i, v)| *v = i as f32 + 10.0);
655        assert!(channels_iter.next().is_none());
656        drop(channels_iter);
657
658        let mut channels_iter = block.channels_iter();
659        let channel = channels_iter.next().unwrap().copied().collect::<Vec<_>>();
660        assert_eq!(channel, vec![0.0, 1.0, 2.0, 3.0, 4.0]);
661        let channel = channels_iter.next().unwrap().copied().collect::<Vec<_>>();
662        assert_eq!(channel, vec![10.0, 11.0, 12.0, 13.0, 14.0]);
663        assert!(channels_iter.next().is_none());
664        drop(channels_iter);
665    }
666
667    #[test]
668    fn test_frame_iter() {
669        let mut ch1 = vec![0.0; 5];
670        let mut ch2 = vec![0.0; 5];
671        let mut data = vec![ch1.as_mut_slice(), ch2.as_mut_slice()];
672        let mut block = AudioBlockPlanarViewMut::from_slice(&mut data);
673
674        for i in 0..block.num_frames() {
675            let frame = block.frame_iter(i).copied().collect::<Vec<_>>();
676            assert_eq!(frame, vec![0.0, 0.0]);
677        }
678
679        for i in 0..block.num_frames() {
680            let add = i as f32 * 10.0;
681            block
682                .frame_iter_mut(i)
683                .enumerate()
684                .for_each(|(i, v)| *v = i as f32 + add);
685        }
686
687        let channel = block.frame_iter(0).copied().collect::<Vec<_>>();
688        assert_eq!(channel, vec![0.0, 1.0]);
689        let channel = block.frame_iter(1).copied().collect::<Vec<_>>();
690        assert_eq!(channel, vec![10.0, 11.0]);
691        let channel = block.frame_iter(2).copied().collect::<Vec<_>>();
692        assert_eq!(channel, vec![20.0, 21.0]);
693        let channel = block.frame_iter(3).copied().collect::<Vec<_>>();
694        assert_eq!(channel, vec![30.0, 31.0]);
695        let channel = block.frame_iter(4).copied().collect::<Vec<_>>();
696        assert_eq!(channel, vec![40.0, 41.0]);
697    }
698
699    #[test]
700    fn test_frame_iters() {
701        let mut ch1 = vec![0.0; 10];
702        let mut ch2 = vec![0.0; 10];
703        let mut ch3 = vec![0.0; 10];
704        let mut data = vec![ch1.as_mut_slice(), ch2.as_mut_slice(), ch3.as_mut_slice()];
705        let mut block = AudioBlockPlanarViewMut::from_slice(&mut data);
706        block.set_visible(2, 5);
707
708        let num_frames = block.num_frames;
709        let mut frames_iter = block.frames_iter();
710        for _ in 0..num_frames {
711            let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
712            assert_eq!(frame, vec![0.0, 0.0]);
713        }
714        assert!(frames_iter.next().is_none());
715        drop(frames_iter);
716
717        let mut frames_iter = block.frames_iter_mut();
718        for i in 0..num_frames {
719            let add = i as f32 * 10.0;
720            frames_iter
721                .next()
722                .unwrap()
723                .enumerate()
724                .for_each(|(i, v)| *v = i as f32 + add);
725        }
726        assert!(frames_iter.next().is_none());
727        drop(frames_iter);
728
729        let mut frames_iter = block.frames_iter();
730        let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
731        assert_eq!(frame, vec![0.0, 1.0]);
732        let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
733        assert_eq!(frame, vec![10.0, 11.0]);
734        let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
735        assert_eq!(frame, vec![20.0, 21.0]);
736        let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
737        assert_eq!(frame, vec![30.0, 31.0]);
738        let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
739        assert_eq!(frame, vec![40.0, 41.0]);
740        assert!(frames_iter.next().is_none());
741    }
742
743    #[test]
744    fn test_from_vec() {
745        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]];
746        let block = AudioBlockPlanarViewMut::from_slice(&mut vec);
747        assert_eq!(block.num_channels(), 2);
748        assert_eq!(block.num_frames(), 5);
749        assert_eq!(
750            block.channel_iter(0).copied().collect::<Vec<_>>(),
751            vec![0.0, 2.0, 4.0, 6.0, 8.0]
752        );
753        assert_eq!(
754            block.channel_iter(1).copied().collect::<Vec<_>>(),
755            vec![1.0, 3.0, 5.0, 7.0, 9.0]
756        );
757        assert_eq!(
758            block.frame_iter(0).copied().collect::<Vec<_>>(),
759            vec![0.0, 1.0]
760        );
761        assert_eq!(
762            block.frame_iter(1).copied().collect::<Vec<_>>(),
763            vec![2.0, 3.0]
764        );
765        assert_eq!(
766            block.frame_iter(2).copied().collect::<Vec<_>>(),
767            vec![4.0, 5.0]
768        );
769        assert_eq!(
770            block.frame_iter(3).copied().collect::<Vec<_>>(),
771            vec![6.0, 7.0]
772        );
773        assert_eq!(
774            block.frame_iter(4).copied().collect::<Vec<_>>(),
775            vec![8.0, 9.0]
776        );
777    }
778
779    #[test]
780    fn test_view() {
781        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]];
782        let block = AudioBlockPlanarViewMut::from_slice(&mut vec);
783
784        assert!(block.as_interleaved_view().is_none());
785        assert!(block.as_planar_view().is_some());
786        assert!(block.as_sequential_view().is_none());
787
788        let view = block.as_view();
789        assert_eq!(
790            view.channel_iter(0).copied().collect::<Vec<_>>(),
791            vec![0.0, 2.0, 4.0, 6.0, 8.0]
792        );
793        assert_eq!(
794            view.channel_iter(1).copied().collect::<Vec<_>>(),
795            vec![1.0, 3.0, 5.0, 7.0, 9.0]
796        );
797    }
798
799    #[test]
800    fn test_view_mut() {
801        let mut data = vec![vec![0.0; 5]; 2];
802        let mut block = AudioBlockPlanarViewMut::from_slice(&mut data);
803        assert!(block.as_interleaved_view().is_none());
804        assert!(block.as_planar_view().is_some());
805        assert!(block.as_sequential_view().is_none());
806        {
807            let mut view = block.as_view_mut();
808            view.channel_iter_mut(0)
809                .enumerate()
810                .for_each(|(i, v)| *v = i as f32);
811            view.channel_iter_mut(1)
812                .enumerate()
813                .for_each(|(i, v)| *v = i as f32 + 10.0);
814        }
815
816        assert_eq!(
817            block.channel_iter(0).copied().collect::<Vec<_>>(),
818            vec![0.0, 1.0, 2.0, 3.0, 4.0]
819        );
820        assert_eq!(
821            block.channel_iter(1).copied().collect::<Vec<_>>(),
822            vec![10.0, 11.0, 12.0, 13.0, 14.0]
823        );
824    }
825
826    #[test]
827    fn test_limited() {
828        let mut data = vec![vec![0.0; 4]; 3];
829
830        let mut block = AudioBlockPlanarViewMut::from_slice_limited(&mut data, 2, 3);
831
832        assert_eq!(block.num_channels(), 2);
833        assert_eq!(block.num_frames(), 3);
834        assert_eq!(block.num_channels_allocated, 3);
835        assert_eq!(block.num_frames_allocated, 4);
836
837        for i in 0..block.num_channels() {
838            assert_eq!(block.channel_iter(i).count(), 3);
839            assert_eq!(block.channel_iter_mut(i).count(), 3);
840        }
841        for i in 0..block.num_frames() {
842            assert_eq!(block.frame_iter(i).count(), 2);
843            assert_eq!(block.frame_iter_mut(i).count(), 2);
844        }
845    }
846
847    #[test]
848    fn test_pointer() {
849        unsafe {
850            let num_channels = 2;
851            let num_frames = 5;
852            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]];
853
854            let mut ptr_vec: Vec<*mut f32> = data
855                .iter_mut()
856                .map(|inner_vec| inner_vec.as_mut_ptr())
857                .collect();
858            let ptr = ptr_vec.as_mut_ptr();
859
860            let mut adaptor = PlanarPtrAdapterMut::<_, 16>::from_ptr(ptr, num_channels, num_frames);
861
862            let planar = adaptor.planar_view_mut();
863
864            assert_eq!(
865                planar.channel_iter(0).copied().collect::<Vec<_>>(),
866                vec![0.0, 2.0, 4.0, 6.0, 8.0]
867            );
868
869            assert_eq!(
870                planar.channel_iter(1).copied().collect::<Vec<_>>(),
871                vec![1.0, 3.0, 5.0, 7.0, 9.0]
872            );
873        }
874    }
875
876    #[test]
877    #[should_panic]
878    #[no_sanitize_realtime]
879    fn test_slice_out_of_bounds() {
880        let mut data = [[0.0; 4]; 3];
881        let block = AudioBlockPlanarViewMut::from_slice_limited(&mut data, 2, 3);
882
883        block.channel(2);
884    }
885
886    #[test]
887    #[should_panic]
888    #[no_sanitize_realtime]
889    fn test_slice_out_of_bounds_mut() {
890        let mut data = [[0.0; 4]; 3];
891        let mut block = AudioBlockPlanarViewMut::from_slice_limited(&mut data, 2, 3);
892
893        block.channel_mut(2);
894    }
895}