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_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 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_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    /// 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 Iterator<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 Iterator<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 active 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 active 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 Iterator<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 Iterator<Item = impl Iterator<Item = &S> + '_> + '_ {
224        let num_frames = self.num_frames; // Capture num_frames for the closure
225        self.data
226            .iter()
227            // Limit to the active 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 Iterator<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 frame_iters(&self) -> impl Iterator<Item = impl Iterator<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_active_num_channels(&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_active_num_frames(&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 Iterator<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 Iterator<Item = impl Iterator<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 Iterator<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(&mut self) -> impl Iterator<Item = impl Iterator<Item = &mut S> + '_> + '_ {
340        let num_channels = self.num_channels as usize;
341        let num_frames = self.num_frames;
342        let data_slice: &mut [V] = self.data;
343        let data_ptr: *mut [V] = data_slice;
344
345        (0..num_frames).map(move |frame_idx| {
346            // Re-borrow mutably inside the closure via the raw pointer.
347            // Safety: Safe because the outer iterator executes this sequentially per frame.
348            let current_channel_views: &mut [V] = unsafe { &mut *data_ptr };
349
350            // Iterate over the relevant channel views up to num_channels.
351            current_channel_views[..num_channels]
352                .iter_mut() // Yields `&mut V`
353                .map(move |channel_view: &mut V| {
354                    // Get the mutable slice `&mut [S]` from the view using AsMut.
355                    let channel_slice: &mut [S] = channel_view.as_mut();
356                    // Access the sample for the current channel view at the current frame index.
357                    // Safety: Relies on `frame_idx < channel_slice.len()`.
358                    unsafe { channel_slice.get_unchecked_mut(frame_idx) }
359                })
360        })
361    }
362
363    #[nonblocking]
364    fn as_view_mut(&mut self) -> impl AudioBlockMut<S> {
365        self.view_mut()
366    }
367
368    #[nonblocking]
369    fn as_planar_view_mut(
370        &mut self,
371    ) -> Option<AudioBlockPlanarViewMut<'_, S, Self::PlanarViewMut>> {
372        Some(self.view_mut())
373    }
374}
375
376impl<S: Sample + core::fmt::Debug, V: AsMut<[S]> + AsRef<[S]> + core::fmt::Debug> core::fmt::Debug
377    for AudioBlockPlanarViewMut<'_, S, V>
378{
379    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
380        writeln!(f, "AudioBlockPlanarViewMut {{")?;
381        writeln!(f, "  num_channels: {}", self.num_channels)?;
382        writeln!(f, "  num_frames: {}", self.num_frames)?;
383        writeln!(
384            f,
385            "  num_channels_allocated: {}",
386            self.num_channels_allocated
387        )?;
388        writeln!(f, "  num_frames_allocated: {}", self.num_frames_allocated)?;
389        writeln!(f, "  channels:")?;
390
391        for (i, channel) in self.channels().enumerate() {
392            writeln!(f, "    {}: {:?}", i, channel)?;
393        }
394
395        writeln!(f, "  raw_data: {:?}", self.raw_data())?;
396        writeln!(f, "}}")?;
397
398        Ok(())
399    }
400}
401
402/// Adapter for creating mutable planar audio block views from raw pointers.
403///
404/// This adapter provides a safe interface to work with mutable audio data stored in external buffers,
405/// which is common when interfacing with audio APIs or hardware.
406///
407/// # Example
408///
409/// ```
410/// use audio_blocks::*;
411///
412/// // Create sample data for two channels with five frames each
413/// let mut ch1 = vec![0.0f32, 1.0, 2.0, 3.0, 4.0];
414/// let mut ch2 = vec![5.0f32, 6.0, 7.0, 8.0, 9.0];
415///
416/// // Create mutable pointers to the channel data
417/// let mut ptrs = [ch1.as_mut_ptr(), ch2.as_mut_ptr()];
418/// let data = ptrs.as_mut_ptr();
419/// let num_channels = 2u16;
420/// let num_frames = 5;
421///
422/// // Create an adapter from raw pointers to audio channel data
423/// let mut adapter = unsafe { PlanarPtrAdapterMut::<f32, 16>::from_ptr(data, num_channels, num_frames) };
424///
425/// // Get a safe mutable view of the audio data
426/// let mut block = adapter.planar_view_mut();
427///
428/// // Verify the data access works and can be modified
429/// assert_eq!(block.sample(0, 2), 2.0);
430/// assert_eq!(block.sample(1, 3), 8.0);
431/// *block.sample_mut(0, 1) = 10.0; // Modify a sample
432/// ```
433///
434/// # Safety
435///
436/// When creating an adapter from raw pointers, you must ensure that:
437/// - The pointers are valid and properly aligned
438/// - The memory they point to remains valid for the lifetime of the adapter
439/// - The data is not accessed through other pointers during the adapter's lifetime
440/// - The channel count doesn't exceed the adapter's `MAX_CHANNELS` capacity
441pub struct PlanarPtrAdapterMut<'a, S: Sample, const MAX_CHANNELS: usize> {
442    data: [MaybeUninit<&'a mut [S]>; MAX_CHANNELS],
443    num_channels: u16,
444}
445
446impl<'a, S: Sample, const MAX_CHANNELS: usize> PlanarPtrAdapterMut<'a, S, MAX_CHANNELS> {
447    /// Creates new pointer adapter to create an audio block from raw pointers.
448    ///
449    /// # Safety
450    ///
451    /// - `ptr` must be a valid pointer to an array of pointers
452    /// - The array must contain at least `num_channels` valid pointers
453    /// - Each pointer in the array must point to a valid array of samples with `num_frames` length
454    /// - The pointed memory must remain valid for the lifetime of the returned adapter
455    /// - The data must not be modified through other pointers for the lifetime of the returned adapter
456    #[nonblocking]
457    pub unsafe fn from_ptr(ptrs: *mut *mut S, num_channels: u16, num_frames: usize) -> Self {
458        assert!(
459            num_channels as usize <= MAX_CHANNELS,
460            "num_channels exceeds MAX_CHANNELS"
461        );
462
463        let mut data: [MaybeUninit<&'a mut [S]>; MAX_CHANNELS] =
464            unsafe { MaybeUninit::uninit().assume_init() }; // Or other safe initialization
465
466        // SAFETY: Caller guarantees `ptr` is valid for `num_channels` elements.
467        let ptr_slice: &mut [*mut S] =
468            unsafe { core::slice::from_raw_parts_mut(ptrs, num_channels as usize) };
469
470        for ch in 0..num_channels as usize {
471            // SAFETY: See previous explanation
472            data[ch].write(unsafe { core::slice::from_raw_parts_mut(ptr_slice[ch], num_frames) });
473        }
474
475        Self { data, num_channels }
476    }
477
478    /// Returns a mutable slice of references to the initialized channel data buffers.
479    ///
480    /// This method provides access to the underlying audio data as a slice of mutable slices,
481    /// with each inner slice representing one audio channel.
482    #[inline]
483    pub fn data_slice_mut(&mut self) -> &mut [&'a mut [S]] {
484        let initialized_part: &mut [MaybeUninit<&'a mut [S]>] =
485            &mut self.data[..self.num_channels as usize];
486        unsafe {
487            core::slice::from_raw_parts_mut(
488                initialized_part.as_mut_ptr() as *mut &'a mut [S],
489                self.num_channels as usize,
490            )
491        }
492    }
493
494    /// Creates a safe [`AudioBlockPlanarViewMut`] for accessing the audio data.
495    ///
496    /// This provides a convenient way to interact with the audio data through
497    /// the full [`AudioBlockMut`] interface, enabling operations like iterating
498    /// through channels or frames and modifying the underlying audio samples.
499    ///
500    /// # Returns
501    ///
502    /// An [`AudioBlockPlanarViewMut`] that provides safe, mutable access to the audio data.
503    #[nonblocking]
504    pub fn planar_view_mut(&mut self) -> AudioBlockPlanarViewMut<'a, S, &mut [S]> {
505        AudioBlockPlanarViewMut::from_slice(self.data_slice_mut())
506    }
507}
508
509#[cfg(test)]
510mod tests {
511    use super::*;
512    use rtsan_standalone::no_sanitize_realtime;
513
514    #[test]
515    fn test_member_functions() {
516        let mut data = [
517            [0.0, 1.0, 2.0, 3.0],
518            [4.0, 5.0, 6.0, 7.0],
519            [0.0, 0.0, 0.0, 0.0],
520        ];
521        let mut block = AudioBlockPlanarViewMut::from_slice_limited(&mut data, 2, 3);
522
523        // single frame
524        assert_eq!(block.channel(0), &[0.0, 1.0, 2.0]);
525        assert_eq!(block.channel(1), &[4.0, 5.0, 6.0]);
526
527        assert_eq!(block.channel_mut(0), &[0.0, 1.0, 2.0]);
528        assert_eq!(block.channel_mut(1), &[4.0, 5.0, 6.0]);
529
530        // all frames
531        let mut channels = block.channels();
532        assert_eq!(channels.next().unwrap(), &[0.0, 1.0, 2.0]);
533        assert_eq!(channels.next().unwrap(), &[4.0, 5.0, 6.0]);
534        assert_eq!(channels.next(), None);
535        drop(channels);
536
537        let mut channels = block.channels_mut();
538        assert_eq!(channels.next().unwrap(), &[0.0, 1.0, 2.0]);
539        assert_eq!(channels.next().unwrap(), &[4.0, 5.0, 6.0]);
540        assert_eq!(channels.next(), None);
541        drop(channels);
542
543        // raw data
544        assert_eq!(block.raw_data()[0].as_ref(), &[0.0, 1.0, 2.0, 3.0]);
545        assert_eq!(block.raw_data()[1].as_ref(), &[4.0, 5.0, 6.0, 7.0]);
546        assert_eq!(block.raw_data()[2].as_ref(), &[0.0, 0.0, 0.0, 0.0]);
547
548        assert_eq!(block.raw_data_mut()[0].as_ref(), &[0.0, 1.0, 2.0, 3.0]);
549        assert_eq!(block.raw_data_mut()[1].as_ref(), &[4.0, 5.0, 6.0, 7.0]);
550        assert_eq!(block.raw_data_mut()[2].as_ref(), &[0.0, 0.0, 0.0, 0.0]);
551
552        // views
553        let view = block.view();
554        assert_eq!(view.num_channels(), block.num_channels());
555        assert_eq!(view.num_frames(), block.num_frames());
556        assert_eq!(
557            view.num_channels_allocated(),
558            block.num_channels_allocated()
559        );
560        assert_eq!(view.num_frames_allocated(), block.num_frames_allocated());
561        assert_eq!(view.raw_data(), block.raw_data());
562
563        let num_channels = block.num_channels();
564        let num_frames = block.num_frames();
565        let num_channels_allocated = block.num_channels_allocated();
566        let num_frames_allocated = block.num_frames_allocated();
567        let data = block.raw_data().to_vec();
568        let view = block.view_mut();
569        assert_eq!(view.num_channels(), num_channels);
570        assert_eq!(view.num_frames(), num_frames);
571        assert_eq!(view.num_channels_allocated(), num_channels_allocated);
572        assert_eq!(view.num_frames_allocated(), num_frames_allocated);
573        assert_eq!(view.raw_data(), &data);
574    }
575
576    #[test]
577    fn test_samples() {
578        let mut ch1 = vec![0.0; 5];
579        let mut ch2 = vec![0.0; 5];
580        let mut data = vec![ch1.as_mut_slice(), ch2.as_mut_slice()];
581        let mut block = AudioBlockPlanarViewMut::from_slice(&mut data);
582
583        let num_frames = block.num_frames();
584        for ch in 0..block.num_channels() {
585            for f in 0..block.num_frames() {
586                *block.sample_mut(ch, f) = (ch as usize * num_frames + f) as f32;
587            }
588        }
589
590        for ch in 0..block.num_channels() {
591            for f in 0..block.num_frames() {
592                assert_eq!(block.sample(ch, f), (ch as usize * num_frames + f) as f32);
593            }
594        }
595
596        assert_eq!(block.channel(0), &[0.0, 1.0, 2.0, 3.0, 4.0]);
597        assert_eq!(block.channel(1), &[5.0, 6.0, 7.0, 8.0, 9.0]);
598    }
599
600    #[test]
601    fn test_channel_iter() {
602        let mut ch1 = vec![0.0; 5];
603        let mut ch2 = vec![0.0; 5];
604        let mut data = vec![ch1.as_mut_slice(), ch2.as_mut_slice()];
605        let mut block = AudioBlockPlanarViewMut::from_slice(&mut data);
606
607        let channel = block.channel_iter(0).copied().collect::<Vec<_>>();
608        assert_eq!(channel, vec![0.0, 0.0, 0.0, 0.0, 0.0]);
609        let channel = block.channel_iter(1).copied().collect::<Vec<_>>();
610        assert_eq!(channel, vec![0.0, 0.0, 0.0, 0.0, 0.0]);
611
612        block
613            .channel_iter_mut(0)
614            .enumerate()
615            .for_each(|(i, v)| *v = i as f32);
616        block
617            .channel_iter_mut(1)
618            .enumerate()
619            .for_each(|(i, v)| *v = i as f32 + 10.0);
620
621        let channel = block.channel_iter(0).copied().collect::<Vec<_>>();
622        assert_eq!(channel, vec![0.0, 1.0, 2.0, 3.0, 4.0]);
623        let channel = block.channel_iter(1).copied().collect::<Vec<_>>();
624        assert_eq!(channel, vec![10.0, 11.0, 12.0, 13.0, 14.0]);
625    }
626
627    #[test]
628    fn test_channel_iters() {
629        let mut ch1 = vec![0.0; 5];
630        let mut ch2 = vec![0.0; 5];
631        let mut data = vec![ch1.as_mut_slice(), ch2.as_mut_slice()];
632        let mut block = AudioBlockPlanarViewMut::from_slice(&mut data);
633
634        let mut channels_iter = block.channels_iter();
635        let channel = channels_iter.next().unwrap().copied().collect::<Vec<_>>();
636        assert_eq!(channel, vec![0.0, 0.0, 0.0, 0.0, 0.0]);
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        assert!(channels_iter.next().is_none());
640        drop(channels_iter);
641
642        let mut channels_iter = block.channels_iter_mut();
643        channels_iter
644            .next()
645            .unwrap()
646            .enumerate()
647            .for_each(|(i, v)| *v = i as f32);
648        channels_iter
649            .next()
650            .unwrap()
651            .enumerate()
652            .for_each(|(i, v)| *v = i as f32 + 10.0);
653        assert!(channels_iter.next().is_none());
654        drop(channels_iter);
655
656        let mut channels_iter = block.channels_iter();
657        let channel = channels_iter.next().unwrap().copied().collect::<Vec<_>>();
658        assert_eq!(channel, vec![0.0, 1.0, 2.0, 3.0, 4.0]);
659        let channel = channels_iter.next().unwrap().copied().collect::<Vec<_>>();
660        assert_eq!(channel, vec![10.0, 11.0, 12.0, 13.0, 14.0]);
661        assert!(channels_iter.next().is_none());
662        drop(channels_iter);
663    }
664
665    #[test]
666    fn test_frame_iter() {
667        let mut ch1 = vec![0.0; 5];
668        let mut ch2 = vec![0.0; 5];
669        let mut data = vec![ch1.as_mut_slice(), ch2.as_mut_slice()];
670        let mut block = AudioBlockPlanarViewMut::from_slice(&mut data);
671
672        for i in 0..block.num_frames() {
673            let frame = block.frame_iter(i).copied().collect::<Vec<_>>();
674            assert_eq!(frame, vec![0.0, 0.0]);
675        }
676
677        for i in 0..block.num_frames() {
678            let add = i as f32 * 10.0;
679            block
680                .frame_iter_mut(i)
681                .enumerate()
682                .for_each(|(i, v)| *v = i as f32 + add);
683        }
684
685        let channel = block.frame_iter(0).copied().collect::<Vec<_>>();
686        assert_eq!(channel, vec![0.0, 1.0]);
687        let channel = block.frame_iter(1).copied().collect::<Vec<_>>();
688        assert_eq!(channel, vec![10.0, 11.0]);
689        let channel = block.frame_iter(2).copied().collect::<Vec<_>>();
690        assert_eq!(channel, vec![20.0, 21.0]);
691        let channel = block.frame_iter(3).copied().collect::<Vec<_>>();
692        assert_eq!(channel, vec![30.0, 31.0]);
693        let channel = block.frame_iter(4).copied().collect::<Vec<_>>();
694        assert_eq!(channel, vec![40.0, 41.0]);
695    }
696
697    #[test]
698    fn test_frame_iters() {
699        let mut ch1 = vec![0.0; 10];
700        let mut ch2 = vec![0.0; 10];
701        let mut ch3 = vec![0.0; 10];
702        let mut data = vec![ch1.as_mut_slice(), ch2.as_mut_slice(), ch3.as_mut_slice()];
703        let mut block = AudioBlockPlanarViewMut::from_slice(&mut data);
704        block.set_active_size(2, 5);
705
706        let num_frames = block.num_frames;
707        let mut frames_iter = block.frame_iters();
708        for _ in 0..num_frames {
709            let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
710            assert_eq!(frame, vec![0.0, 0.0]);
711        }
712        assert!(frames_iter.next().is_none());
713        drop(frames_iter);
714
715        let mut frames_iter = block.frames_iter_mut();
716        for i in 0..num_frames {
717            let add = i as f32 * 10.0;
718            frames_iter
719                .next()
720                .unwrap()
721                .enumerate()
722                .for_each(|(i, v)| *v = i as f32 + add);
723        }
724        assert!(frames_iter.next().is_none());
725        drop(frames_iter);
726
727        let mut frames_iter = block.frame_iters();
728        let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
729        assert_eq!(frame, vec![0.0, 1.0]);
730        let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
731        assert_eq!(frame, vec![10.0, 11.0]);
732        let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
733        assert_eq!(frame, vec![20.0, 21.0]);
734        let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
735        assert_eq!(frame, vec![30.0, 31.0]);
736        let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
737        assert_eq!(frame, vec![40.0, 41.0]);
738        assert!(frames_iter.next().is_none());
739    }
740
741    #[test]
742    fn test_from_vec() {
743        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]];
744        let block = AudioBlockPlanarViewMut::from_slice(&mut vec);
745        assert_eq!(block.num_channels(), 2);
746        assert_eq!(block.num_frames(), 5);
747        assert_eq!(
748            block.channel_iter(0).copied().collect::<Vec<_>>(),
749            vec![0.0, 2.0, 4.0, 6.0, 8.0]
750        );
751        assert_eq!(
752            block.channel_iter(1).copied().collect::<Vec<_>>(),
753            vec![1.0, 3.0, 5.0, 7.0, 9.0]
754        );
755        assert_eq!(
756            block.frame_iter(0).copied().collect::<Vec<_>>(),
757            vec![0.0, 1.0]
758        );
759        assert_eq!(
760            block.frame_iter(1).copied().collect::<Vec<_>>(),
761            vec![2.0, 3.0]
762        );
763        assert_eq!(
764            block.frame_iter(2).copied().collect::<Vec<_>>(),
765            vec![4.0, 5.0]
766        );
767        assert_eq!(
768            block.frame_iter(3).copied().collect::<Vec<_>>(),
769            vec![6.0, 7.0]
770        );
771        assert_eq!(
772            block.frame_iter(4).copied().collect::<Vec<_>>(),
773            vec![8.0, 9.0]
774        );
775    }
776
777    #[test]
778    fn test_view() {
779        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]];
780        let block = AudioBlockPlanarViewMut::from_slice(&mut vec);
781
782        assert!(block.as_interleaved_view().is_none());
783        assert!(block.as_planar_view().is_some());
784        assert!(block.as_sequential_view().is_none());
785
786        let view = block.as_view();
787        assert_eq!(
788            view.channel_iter(0).copied().collect::<Vec<_>>(),
789            vec![0.0, 2.0, 4.0, 6.0, 8.0]
790        );
791        assert_eq!(
792            view.channel_iter(1).copied().collect::<Vec<_>>(),
793            vec![1.0, 3.0, 5.0, 7.0, 9.0]
794        );
795    }
796
797    #[test]
798    fn test_view_mut() {
799        let mut data = vec![vec![0.0; 5]; 2];
800        let mut block = AudioBlockPlanarViewMut::from_slice(&mut data);
801        assert!(block.as_interleaved_view().is_none());
802        assert!(block.as_planar_view().is_some());
803        assert!(block.as_sequential_view().is_none());
804        {
805            let mut view = block.as_view_mut();
806            view.channel_iter_mut(0)
807                .enumerate()
808                .for_each(|(i, v)| *v = i as f32);
809            view.channel_iter_mut(1)
810                .enumerate()
811                .for_each(|(i, v)| *v = i as f32 + 10.0);
812        }
813
814        assert_eq!(
815            block.channel_iter(0).copied().collect::<Vec<_>>(),
816            vec![0.0, 1.0, 2.0, 3.0, 4.0]
817        );
818        assert_eq!(
819            block.channel_iter(1).copied().collect::<Vec<_>>(),
820            vec![10.0, 11.0, 12.0, 13.0, 14.0]
821        );
822    }
823
824    #[test]
825    fn test_limited() {
826        let mut data = vec![vec![0.0; 4]; 3];
827
828        let mut block = AudioBlockPlanarViewMut::from_slice_limited(&mut data, 2, 3);
829
830        assert_eq!(block.num_channels(), 2);
831        assert_eq!(block.num_frames(), 3);
832        assert_eq!(block.num_channels_allocated, 3);
833        assert_eq!(block.num_frames_allocated, 4);
834
835        for i in 0..block.num_channels() {
836            assert_eq!(block.channel_iter(i).count(), 3);
837            assert_eq!(block.channel_iter_mut(i).count(), 3);
838        }
839        for i in 0..block.num_frames() {
840            assert_eq!(block.frame_iter(i).count(), 2);
841            assert_eq!(block.frame_iter_mut(i).count(), 2);
842        }
843    }
844
845    #[test]
846    fn test_pointer() {
847        unsafe {
848            let num_channels = 2;
849            let num_frames = 5;
850            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]];
851
852            let mut ptr_vec: Vec<*mut f32> = data
853                .iter_mut()
854                .map(|inner_vec| inner_vec.as_mut_ptr())
855                .collect();
856            let ptr = ptr_vec.as_mut_ptr();
857
858            let mut adaptor = PlanarPtrAdapterMut::<_, 16>::from_ptr(ptr, num_channels, num_frames);
859
860            let planar = adaptor.planar_view_mut();
861
862            assert_eq!(
863                planar.channel_iter(0).copied().collect::<Vec<_>>(),
864                vec![0.0, 2.0, 4.0, 6.0, 8.0]
865            );
866
867            assert_eq!(
868                planar.channel_iter(1).copied().collect::<Vec<_>>(),
869                vec![1.0, 3.0, 5.0, 7.0, 9.0]
870            );
871        }
872    }
873
874    #[test]
875    #[should_panic]
876    #[no_sanitize_realtime]
877    fn test_slice_out_of_bounds() {
878        let mut data = [[0.0; 4]; 3];
879        let block = AudioBlockPlanarViewMut::from_slice_limited(&mut data, 2, 3);
880
881        block.channel(2);
882    }
883
884    #[test]
885    #[should_panic]
886    #[no_sanitize_realtime]
887    fn test_slice_out_of_bounds_mut() {
888        let mut data = [[0.0; 4]; 3];
889        let mut block = AudioBlockPlanarViewMut::from_slice_limited(&mut data, 2, 3);
890
891        block.channel_mut(2);
892    }
893}