Skip to main content

audio_blocks/sequential/
view_mut.rs

1use rtsan_standalone::nonblocking;
2
3use core::{marker::PhantomData, ptr::NonNull};
4
5use super::view::AudioBlockSequentialView;
6use crate::{
7    AudioBlock, AudioBlockMut, Sample,
8    iter::{StridedSampleIter, StridedSampleIterMut},
9};
10
11///  A mutable view of sequential audio data.
12///
13/// * **Layout:** `[ch0, ch0, ch0, ch1, ch1, ch1]`
14/// * **Interpretation:** All samples from `ch0` are stored first, followed by all from `ch1`, etc.
15/// * **Terminology:** Described as “channels first” in the sense that all data for one channel appears before any data for the next.
16/// * **Usage:** Used in DSP pipelines where per-channel processing is easier and more efficient.
17///
18/// # Example
19///
20/// ```
21/// use audio_blocks::*;
22///
23/// let mut data = vec![0.0, 0.0, 0.0, 1.0, 1.0, 1.0];
24///
25/// let block = AudioBlockSequentialViewMut::from_slice(&mut data, 2);
26///
27/// assert_eq!(block.channel(0), &[0.0, 0.0, 0.0]);
28/// assert_eq!(block.channel(1), &[1.0, 1.0, 1.0]);
29/// ```
30pub struct AudioBlockSequentialViewMut<'a, S: Sample> {
31    data: &'a mut [S],
32    num_channels: u16,
33    num_frames: usize,
34    num_channels_allocated: u16,
35    num_frames_allocated: usize,
36}
37
38impl<'a, S: Sample> AudioBlockSequentialViewMut<'a, S> {
39    /// Creates a new audio block from a mutable slice of sequential audio data.
40    ///
41    /// # Parameters
42    /// * `data` - The mutable slice containing sequential audio samples
43    /// * `num_channels` - Number of audio channels in the data
44    ///
45    /// # Panics
46    /// Panics if the length of `data` is not evenly divisible by `num_channels`.
47    #[nonblocking]
48    pub fn from_slice(data: &'a mut [S], num_channels: u16) -> Self {
49        assert!(
50            num_channels > 0 && data.len() % num_channels as usize == 0,
51            "data length {} must be divisible by num_channels {}",
52            data.len(),
53            num_channels
54        );
55        let num_frames = data.len() / num_channels as usize;
56        Self {
57            data,
58            num_channels,
59            num_frames,
60            num_channels_allocated: num_channels,
61            num_frames_allocated: num_frames,
62        }
63    }
64
65    /// Creates a new audio block from a mutable slice with limited visibility.
66    ///
67    /// This function allows creating a view that exposes only a subset of the allocated channels
68    /// and frames, which is useful for working with a logical section of a larger buffer.
69    ///
70    /// # Parameters
71    /// * `data` - The mutable slice containing sequential audio samples
72    /// * `num_channels_visible` - Number of audio channels to expose in the view
73    /// * `num_frames_visible` - Number of audio frames to expose in the view
74    /// * `num_channels_allocated` - Total number of channels allocated in the data buffer
75    /// * `num_frames_allocated` - Total number of frames allocated in the data buffer
76    ///
77    /// # Panics
78    /// * Panics if the length of `data` doesn't equal `num_channels_allocated * num_frames_allocated`
79    /// * Panics if `num_channels_visible` exceeds `num_channels_allocated`
80    /// * Panics if `num_frames_visible` exceeds `num_frames_allocated`
81    #[nonblocking]
82    pub fn from_slice_limited(
83        data: &'a mut [S],
84        num_channels_visible: u16,
85        num_frames_visible: usize,
86        num_channels_allocated: u16,
87        num_frames_allocated: usize,
88    ) -> Self {
89        assert!(num_channels_visible <= num_channels_allocated);
90        assert!(num_frames_visible <= num_frames_allocated);
91        assert_eq!(
92            data.len(),
93            num_channels_allocated as usize * num_frames_allocated
94        );
95        Self {
96            data,
97            num_channels: num_channels_visible,
98            num_frames: num_frames_visible,
99            num_channels_allocated,
100            num_frames_allocated,
101        }
102    }
103
104    /// Creates a new audio block from a pointer.
105    ///
106    /// # Safety
107    ///
108    /// The caller must ensure that:
109    /// - `ptr` points to valid memory containing at least `num_channels_allocated * num_frames_allocated` elements
110    /// - The memory referenced by `ptr` must be valid for the lifetime of the returned `SequentialView`
111    /// - The memory must not be mutated through other pointers while this view exists
112    #[nonblocking]
113    pub unsafe fn from_ptr(ptr: *mut S, num_channels: u16, num_frames: usize) -> Self {
114        Self {
115            data: unsafe {
116                std::slice::from_raw_parts_mut(ptr, num_channels as usize * num_frames)
117            },
118            num_channels,
119            num_frames,
120            num_channels_allocated: num_channels,
121            num_frames_allocated: num_frames,
122        }
123    }
124
125    /// Creates a new audio block from a pointer with a limited amount of channels and/or frames.
126    ///
127    /// # Safety
128    ///
129    /// The caller must ensure that:
130    /// - `ptr` points to valid memory containing at least `num_channels_allocated * num_frames_allocated` elements
131    /// - The memory referenced by `ptr` must be valid for the lifetime of the returned `SequentialView`
132    /// - The memory must not be mutated through other pointers while this view exists
133    #[nonblocking]
134    pub unsafe fn from_ptr_limited(
135        ptr: *mut S,
136        num_channels_visible: u16,
137        num_frames_visible: usize,
138        num_channels_allocated: u16,
139        num_frames_allocated: usize,
140    ) -> Self {
141        assert!(num_channels_visible <= num_channels_allocated);
142        assert!(num_frames_visible <= num_frames_allocated);
143        Self {
144            data: unsafe {
145                std::slice::from_raw_parts_mut(
146                    ptr,
147                    num_channels_allocated as usize * num_frames_allocated,
148                )
149            },
150            num_channels: num_channels_visible,
151            num_frames: num_frames_visible,
152            num_channels_allocated,
153            num_frames_allocated,
154        }
155    }
156
157    /// Returns a slice for a single channel.
158    ///
159    /// # Panics
160    ///
161    /// Panics if channel index is out of bounds.
162    #[nonblocking]
163    pub fn channel(&self, channel: u16) -> &[S] {
164        assert!(channel < self.num_channels);
165        let start = channel as usize * self.num_frames_allocated;
166        let end = start + self.num_frames;
167        &self.data[start..end]
168    }
169
170    /// Returns a mutable slice for a single channel.
171    ///
172    /// # Panics
173    ///
174    /// Panics if channel index is out of bounds.
175    #[nonblocking]
176    pub fn channel_mut(&mut self, channel: u16) -> &mut [S] {
177        assert!(channel < self.num_channels);
178        let start = channel as usize * self.num_frames_allocated;
179        let end = start + self.num_frames;
180        &mut self.data[start..end]
181    }
182
183    /// Returns an iterator over all channels in the block.
184    ///
185    /// Each channel is represented as a slice of samples.
186    #[nonblocking]
187    pub fn channels(&self) -> impl Iterator<Item = &[S]> {
188        self.data
189            .chunks(self.num_frames_allocated)
190            .take(self.num_channels as usize)
191            .map(|frame| &frame[..self.num_frames])
192    }
193
194    /// Returns a mutable iterator over all channels in the block.
195    ///
196    /// Each channel is represented as a mutable slice of samples.
197    #[nonblocking]
198    pub fn channels_mut(&mut self) -> impl Iterator<Item = &mut [S]> {
199        self.data
200            .chunks_mut(self.num_frames_allocated)
201            .take(self.num_channels as usize)
202            .map(|frame| &mut frame[..self.num_frames])
203    }
204
205    /// Provides direct access to the underlying memory as a sequential slice.
206    ///
207    /// This function gives access to all allocated data, including any reserved capacity
208    /// beyond the visible range.
209    #[nonblocking]
210    pub fn raw_data(&self) -> &[S] {
211        &self.data
212    }
213
214    /// Provides direct mutable access to the underlying memory as a sequential slice.
215    ///
216    /// This function gives mutable access to all allocated data, including any reserved capacity
217    /// beyond the visible range.
218    #[nonblocking]
219    pub fn raw_data_mut(&mut self) -> &mut [S] {
220        &mut self.data
221    }
222
223    #[nonblocking]
224    pub fn view(&self) -> AudioBlockSequentialView<'_, S> {
225        AudioBlockSequentialView::from_slice_limited(
226            self.data,
227            self.num_channels,
228            self.num_frames,
229            self.num_channels_allocated,
230            self.num_frames_allocated,
231        )
232    }
233
234    #[nonblocking]
235    pub fn view_mut(&mut self) -> AudioBlockSequentialViewMut<'_, S> {
236        AudioBlockSequentialViewMut::from_slice_limited(
237            self.data,
238            self.num_channels,
239            self.num_frames,
240            self.num_channels_allocated,
241            self.num_frames_allocated,
242        )
243    }
244}
245
246impl<S: Sample> AudioBlock<S> for AudioBlockSequentialViewMut<'_, S> {
247    type PlanarView = [S; 0];
248
249    #[nonblocking]
250    fn num_channels(&self) -> u16 {
251        self.num_channels
252    }
253
254    #[nonblocking]
255    fn num_frames(&self) -> usize {
256        self.num_frames
257    }
258
259    #[nonblocking]
260    fn num_channels_allocated(&self) -> u16 {
261        self.num_channels_allocated
262    }
263
264    #[nonblocking]
265    fn num_frames_allocated(&self) -> usize {
266        self.num_frames_allocated
267    }
268
269    #[nonblocking]
270    fn layout(&self) -> crate::BlockLayout {
271        crate::BlockLayout::Sequential
272    }
273
274    #[nonblocking]
275    fn sample(&self, channel: u16, frame: usize) -> S {
276        assert!(channel < self.num_channels);
277        assert!(frame < self.num_frames);
278        unsafe {
279            *self
280                .data
281                .get_unchecked(channel as usize * self.num_frames_allocated + frame)
282        }
283    }
284
285    #[nonblocking]
286    fn channel_iter(&self, channel: u16) -> impl Iterator<Item = &S> {
287        assert!(channel < self.num_channels);
288        self.data
289            .iter()
290            .skip(channel as usize * self.num_frames_allocated)
291            .take(self.num_frames)
292    }
293
294    #[nonblocking]
295    fn channels_iter(&self) -> impl Iterator<Item = impl Iterator<Item = &S> + '_> + '_ {
296        let num_frames = self.num_frames; // Visible frames per channel
297        let num_frames_allocated = self.num_frames_allocated; // Allocated frames per channel (chunk size)
298
299        self.data
300            .chunks(num_frames_allocated)
301            .take(self.num_channels as usize)
302            .map(move |channel_chunk| channel_chunk.iter().take(num_frames))
303    }
304
305    #[nonblocking]
306    fn frame_iter(&self, frame: usize) -> impl Iterator<Item = &S> {
307        assert!(frame < self.num_frames);
308        self.data
309            .iter()
310            .skip(frame)
311            .step_by(self.num_frames_allocated)
312            .take(self.num_channels as usize)
313    }
314
315    #[nonblocking]
316    fn frames_iter(&self) -> impl Iterator<Item = impl Iterator<Item = &S> + '_> + '_ {
317        let num_channels = self.num_channels as usize;
318        let num_frames = self.num_frames;
319        let stride = self.num_frames_allocated;
320        let data_ptr = self.data.as_ptr();
321
322        (0..num_frames).map(move |frame_idx| {
323            // Safety check: Ensure data isn't empty if we calculate a start_ptr.
324            // If num_frames or num_channels is 0, remaining will be 0, iterator is safe.
325            // If data is empty, ptr is dangling, but add(0) is okay. add(>0) is UB.
326            // But if data is empty, num_channels or num_frames must be 0.
327            let start_ptr = if self.data.is_empty() {
328                NonNull::dangling().as_ptr() // Use dangling pointer if slice is empty
329            } else {
330                // Safety: channel_idx is < num_channels <= num_channels_allocated.
331                // Adding it to a valid data_ptr is safe within slice bounds.
332                unsafe { data_ptr.add(frame_idx) }
333            };
334
335            StridedSampleIter::<'_, S> {
336                // Note: '_ lifetime from &self borrow
337                // Safety: Pointer is either dangling (if empty) or valid start pointer.
338                // NonNull::new is safe if start_ptr is non-null (i.e., data not empty).
339                ptr: NonNull::new(start_ptr as *mut S).unwrap_or(NonNull::dangling()), // Use dangling on null/empty
340                stride,
341                remaining: num_channels, // If 0, iterator yields None immediately
342                _marker: PhantomData,
343            }
344        })
345    }
346
347    #[nonblocking]
348    fn as_view(&self) -> impl AudioBlock<S> {
349        self.view()
350    }
351
352    #[nonblocking]
353    fn as_sequential_view(&self) -> Option<AudioBlockSequentialView<'_, S>> {
354        Some(self.view())
355    }
356}
357
358impl<S: Sample> AudioBlockMut<S> for AudioBlockSequentialViewMut<'_, S> {
359    type PlanarViewMut = [S; 0];
360
361    #[nonblocking]
362    fn set_num_channels_visible(&mut self, num_channels: u16) {
363        assert!(num_channels <= self.num_channels_allocated);
364        self.num_channels = num_channels;
365    }
366
367    #[nonblocking]
368    fn set_num_frames_visible(&mut self, num_frames: usize) {
369        assert!(num_frames <= self.num_frames_allocated);
370        self.num_frames = num_frames;
371    }
372
373    #[nonblocking]
374    fn sample_mut(&mut self, channel: u16, frame: usize) -> &mut S {
375        assert!(channel < self.num_channels);
376        assert!(frame < self.num_frames);
377        unsafe {
378            self.data
379                .get_unchecked_mut(channel as usize * self.num_frames_allocated + frame)
380        }
381    }
382
383    #[nonblocking]
384    fn channel_iter_mut(&mut self, channel: u16) -> impl Iterator<Item = &mut S> {
385        assert!(channel < self.num_channels);
386        self.data
387            .iter_mut()
388            .skip(channel as usize * self.num_frames_allocated)
389            .take(self.num_frames)
390    }
391
392    #[nonblocking]
393    fn channels_iter_mut(
394        &mut self,
395    ) -> impl Iterator<Item = impl Iterator<Item = &mut S> + '_> + '_ {
396        let num_frames = self.num_frames;
397        let num_frames_allocated = self.num_frames_allocated;
398        self.data
399            .chunks_mut(num_frames_allocated)
400            .take(self.num_channels as usize)
401            .map(move |channel_chunk| channel_chunk.iter_mut().take(num_frames))
402    }
403
404    #[nonblocking]
405    fn frame_iter_mut(&mut self, frame: usize) -> impl Iterator<Item = &mut S> {
406        assert!(frame < self.num_frames);
407        self.data
408            .iter_mut()
409            .skip(frame)
410            .step_by(self.num_frames_allocated)
411            .take(self.num_channels as usize)
412    }
413
414    #[nonblocking]
415    fn frames_iter_mut(&mut self) -> impl Iterator<Item = impl Iterator<Item = &mut S> + '_> + '_ {
416        let num_channels = self.num_channels as usize;
417        let num_frames = self.num_frames;
418        let stride = self.num_frames_allocated;
419        let data_ptr = self.data.as_mut_ptr();
420
421        (0..num_frames).map(move |frame_idx| {
422            // Safety check: Ensure data isn't empty if we calculate a start_ptr.
423            // If num_frames or num_channels is 0, remaining will be 0, iterator is safe.
424            // If data is empty, ptr is dangling, but add(0) is okay. add(>0) is UB.
425            // But if data is empty, num_channels or num_frames must be 0.
426            let start_ptr = if self.data.is_empty() {
427                NonNull::dangling().as_ptr() // Use dangling pointer if slice is empty
428            } else {
429                // Safety: channel_idx is < num_channels <= num_channels_allocated.
430                // Adding it to a valid data_ptr is safe within slice bounds.
431                unsafe { data_ptr.add(frame_idx) }
432            };
433
434            StridedSampleIterMut::<'_, S> {
435                // Note: '_ lifetime from &self borrow
436                // Safety: Pointer is either dangling (if empty) or valid start pointer.
437                // NonNull::new is safe if start_ptr is non-null (i.e., data not empty).
438                ptr: NonNull::new(start_ptr).unwrap_or(NonNull::dangling()), // Use dangling on null/empty
439                stride,
440                remaining: num_channels, // If 0, iterator yields None immediately
441                _marker: PhantomData,
442            }
443        })
444    }
445
446    #[nonblocking]
447    fn as_view_mut(&mut self) -> impl AudioBlockMut<S> {
448        self.view_mut()
449    }
450
451    #[nonblocking]
452    fn as_sequential_view_mut(&mut self) -> Option<AudioBlockSequentialViewMut<'_, S>> {
453        Some(self.view_mut())
454    }
455}
456
457impl<S: Sample + core::fmt::Debug> core::fmt::Debug for AudioBlockSequentialViewMut<'_, S> {
458    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
459        writeln!(f, "AudioBlockSequentialViewMut {{")?;
460        writeln!(f, "  num_channels: {}", self.num_channels)?;
461        writeln!(f, "  num_frames: {}", self.num_frames)?;
462        writeln!(
463            f,
464            "  num_channels_allocated: {}",
465            self.num_channels_allocated
466        )?;
467        writeln!(f, "  num_frames_allocated: {}", self.num_frames_allocated)?;
468        writeln!(f, "  channels:")?;
469
470        for (i, channel) in self.channels().enumerate() {
471            writeln!(f, "    {}: {:?}", i, channel)?;
472        }
473
474        writeln!(f, "  raw_data: {:?}", self.raw_data())?;
475        writeln!(f, "}}")?;
476
477        Ok(())
478    }
479}
480
481#[cfg(test)]
482mod tests {
483    use super::*;
484    use rtsan_standalone::no_sanitize_realtime;
485
486    #[test]
487    fn test_member_functions() {
488        let mut data = [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 0.0, 0.0, 0.0, 0.0];
489        let mut block =
490            AudioBlockSequentialViewMut::<f32>::from_slice_limited(&mut data, 2, 3, 3, 4);
491
492        // single frame
493        assert_eq!(block.channel(0), &[0.0, 1.0, 2.0]);
494        assert_eq!(block.channel(1), &[4.0, 5.0, 6.0]);
495
496        assert_eq!(block.channel_mut(0), &[0.0, 1.0, 2.0]);
497        assert_eq!(block.channel_mut(1), &[4.0, 5.0, 6.0]);
498
499        // all frames
500        let mut channels = block.channels();
501        assert_eq!(channels.next().unwrap(), &[0.0, 1.0, 2.0]);
502        assert_eq!(channels.next().unwrap(), &[4.0, 5.0, 6.0]);
503        assert_eq!(channels.next(), None);
504        drop(channels);
505
506        let mut channels = block.channels_mut();
507        assert_eq!(channels.next().unwrap(), &[0.0, 1.0, 2.0]);
508        assert_eq!(channels.next().unwrap(), &[4.0, 5.0, 6.0]);
509        assert_eq!(channels.next(), None);
510        drop(channels);
511
512        // raw data
513        assert_eq!(
514            block.raw_data(),
515            &[0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 0.0, 0.0, 0.0, 0.0]
516        );
517
518        // views
519        let view = block.view();
520        assert_eq!(view.num_channels(), block.num_channels());
521        assert_eq!(view.num_frames(), block.num_frames());
522        assert_eq!(
523            view.num_channels_allocated(),
524            block.num_channels_allocated()
525        );
526        assert_eq!(view.num_frames_allocated(), block.num_frames_allocated());
527        assert_eq!(view.raw_data(), block.raw_data());
528
529        let num_channels = block.num_channels();
530        let num_frames = block.num_frames();
531        let num_channels_allocated = block.num_channels_allocated();
532        let num_frames_allocated = block.num_frames_allocated();
533        let data = block.raw_data().to_vec();
534        let view = block.view_mut();
535        assert_eq!(view.num_channels(), num_channels);
536        assert_eq!(view.num_frames(), num_frames);
537        assert_eq!(view.num_channels_allocated(), num_channels_allocated);
538        assert_eq!(view.num_frames_allocated(), num_frames_allocated);
539        assert_eq!(view.raw_data(), &data);
540    }
541
542    #[test]
543    fn test_samples() {
544        let mut data = vec![0.0; 10];
545        let mut block = AudioBlockSequentialViewMut::<f32>::from_slice(&mut data, 2);
546
547        let num_frames = block.num_frames();
548        for ch in 0..block.num_channels() {
549            for f in 0..block.num_frames() {
550                *block.sample_mut(ch, f) = (ch as usize * num_frames + f) as f32;
551            }
552        }
553
554        for ch in 0..block.num_channels() {
555            for f in 0..block.num_frames() {
556                assert_eq!(block.sample(ch, f), (ch as usize * num_frames + f) as f32);
557            }
558        }
559
560        assert_eq!(
561            block.raw_data(),
562            &[0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0]
563        );
564    }
565
566    #[test]
567    fn test_channels() {
568        let mut data = [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 0.0, 0.0, 0.0, 0.0];
569        let mut block = AudioBlockSequentialViewMut::from_slice_limited(&mut data, 2, 3, 3, 4);
570
571        let mut channels = block.channels();
572        assert_eq!(channels.next().unwrap(), &[0.0, 1.0, 2.0]);
573        assert_eq!(channels.next().unwrap(), &[4.0, 5.0, 6.0]);
574        assert_eq!(channels.next(), None);
575        drop(channels);
576
577        let mut channels = block.channels_mut();
578        assert_eq!(channels.next().unwrap(), &[0.0, 1.0, 2.0]);
579        assert_eq!(channels.next().unwrap(), &[4.0, 5.0, 6.0]);
580        assert_eq!(channels.next(), None);
581    }
582
583    #[test]
584    fn test_channel_iter() {
585        let mut data = vec![0.0; 10];
586        let mut block = AudioBlockSequentialViewMut::<f32>::from_slice(&mut data, 2);
587
588        let channel = block.channel_iter(0).copied().collect::<Vec<_>>();
589        assert_eq!(channel, vec![0.0, 0.0, 0.0, 0.0, 0.0]);
590        let channel = block.channel_iter(1).copied().collect::<Vec<_>>();
591        assert_eq!(channel, vec![0.0, 0.0, 0.0, 0.0, 0.0]);
592
593        block
594            .channel_iter_mut(0)
595            .enumerate()
596            .for_each(|(i, v)| *v = i as f32);
597        block
598            .channel_iter_mut(1)
599            .enumerate()
600            .for_each(|(i, v)| *v = i as f32 + 10.0);
601
602        let channel = block.channel_iter(0).copied().collect::<Vec<_>>();
603        assert_eq!(channel, vec![0.0, 1.0, 2.0, 3.0, 4.0]);
604        let channel = block.channel_iter(1).copied().collect::<Vec<_>>();
605        assert_eq!(channel, vec![10.0, 11.0, 12.0, 13.0, 14.0]);
606    }
607
608    #[test]
609    fn test_channel_iters() {
610        let mut data = vec![0.0; 10];
611        let mut block = AudioBlockSequentialViewMut::<f32>::from_slice(&mut data, 2);
612
613        let mut channels_iter = block.channels_iter();
614        let channel = channels_iter.next().unwrap().copied().collect::<Vec<_>>();
615        assert_eq!(channel, vec![0.0, 0.0, 0.0, 0.0, 0.0]);
616        let channel = channels_iter.next().unwrap().copied().collect::<Vec<_>>();
617        assert_eq!(channel, vec![0.0, 0.0, 0.0, 0.0, 0.0]);
618        assert!(channels_iter.next().is_none());
619        drop(channels_iter);
620
621        let mut channels_iter = block.channels_iter_mut();
622        channels_iter
623            .next()
624            .unwrap()
625            .enumerate()
626            .for_each(|(i, v)| *v = i as f32);
627        channels_iter
628            .next()
629            .unwrap()
630            .enumerate()
631            .for_each(|(i, v)| *v = i as f32 + 10.0);
632        assert!(channels_iter.next().is_none());
633        drop(channels_iter);
634
635        let mut channels_iter = block.channels_iter();
636        let channel = channels_iter.next().unwrap().copied().collect::<Vec<_>>();
637        assert_eq!(channel, vec![0.0, 1.0, 2.0, 3.0, 4.0]);
638        let channel = channels_iter.next().unwrap().copied().collect::<Vec<_>>();
639        assert_eq!(channel, vec![10.0, 11.0, 12.0, 13.0, 14.0]);
640        assert!(channels_iter.next().is_none());
641        drop(channels_iter);
642    }
643
644    #[test]
645    fn test_frame_iter() {
646        let mut data = vec![0.0; 12];
647        let mut block = AudioBlockSequentialViewMut::<f32>::from_slice(&mut data, 2);
648        block.set_visible(2, 5);
649
650        for i in 0..block.num_frames() {
651            let frame = block.frame_iter(i).copied().collect::<Vec<_>>();
652            assert_eq!(frame, vec![0.0, 0.0]);
653        }
654
655        for i in 0..block.num_frames() {
656            let add = i as f32 * 10.0;
657            block
658                .frame_iter_mut(i)
659                .enumerate()
660                .for_each(|(i, v)| *v = i as f32 + add);
661        }
662
663        let channel = block.frame_iter(0).copied().collect::<Vec<_>>();
664        assert_eq!(channel, vec![0.0, 1.0]);
665        let channel = block.frame_iter(1).copied().collect::<Vec<_>>();
666        assert_eq!(channel, vec![10.0, 11.0]);
667        let channel = block.frame_iter(2).copied().collect::<Vec<_>>();
668        assert_eq!(channel, vec![20.0, 21.0]);
669        let channel = block.frame_iter(3).copied().collect::<Vec<_>>();
670        assert_eq!(channel, vec![30.0, 31.0]);
671        let channel = block.frame_iter(4).copied().collect::<Vec<_>>();
672        assert_eq!(channel, vec![40.0, 41.0]);
673    }
674
675    #[test]
676    fn test_frame_iters() {
677        let mut data = vec![0.0; 12];
678        let mut block = AudioBlockSequentialViewMut::<f32>::from_slice(&mut data, 2);
679        block.set_visible(2, 5);
680
681        let num_frames = block.num_frames;
682        let mut frames_iter = block.frames_iter();
683        for _ in 0..num_frames {
684            let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
685            assert_eq!(frame, vec![0.0, 0.0]);
686        }
687        assert!(frames_iter.next().is_none());
688        drop(frames_iter);
689
690        let mut frames_iter = block.frames_iter_mut();
691        for i in 0..num_frames {
692            let add = i as f32 * 10.0;
693            frames_iter
694                .next()
695                .unwrap()
696                .enumerate()
697                .for_each(|(i, v)| *v = i as f32 + add);
698        }
699        assert!(frames_iter.next().is_none());
700        drop(frames_iter);
701
702        let mut frames_iter = block.frames_iter();
703        let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
704        assert_eq!(frame, vec![0.0, 1.0]);
705        let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
706        assert_eq!(frame, vec![10.0, 11.0]);
707        let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
708        assert_eq!(frame, vec![20.0, 21.0]);
709        let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
710        assert_eq!(frame, vec![30.0, 31.0]);
711        let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
712        assert_eq!(frame, vec![40.0, 41.0]);
713        assert!(frames_iter.next().is_none());
714    }
715
716    #[test]
717    fn test_from_slice() {
718        let mut data = [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0];
719        let block = AudioBlockSequentialViewMut::<f32>::from_slice(&mut data, 2);
720        assert_eq!(block.num_channels(), 2);
721        assert_eq!(block.num_channels_allocated, 2);
722        assert_eq!(block.num_frames(), 5);
723        assert_eq!(block.num_frames_allocated, 5);
724        assert_eq!(
725            block.channel_iter(0).copied().collect::<Vec<_>>(),
726            vec![0.0, 1.0, 2.0, 3.0, 4.0]
727        );
728        assert_eq!(
729            block.channel_iter(1).copied().collect::<Vec<_>>(),
730            vec![5.0, 6.0, 7.0, 8.0, 9.0]
731        );
732        assert_eq!(
733            block.frame_iter(0).copied().collect::<Vec<_>>(),
734            vec![0.0, 5.0]
735        );
736        assert_eq!(
737            block.frame_iter(1).copied().collect::<Vec<_>>(),
738            vec![1.0, 6.0]
739        );
740        assert_eq!(
741            block.frame_iter(2).copied().collect::<Vec<_>>(),
742            vec![2.0, 7.0]
743        );
744        assert_eq!(
745            block.frame_iter(3).copied().collect::<Vec<_>>(),
746            vec![3.0, 8.0]
747        );
748        assert_eq!(
749            block.frame_iter(4).copied().collect::<Vec<_>>(),
750            vec![4.0, 9.0]
751        );
752    }
753
754    #[test]
755    fn test_view() {
756        let mut data = [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0];
757        let block = AudioBlockSequentialViewMut::<f32>::from_slice(&mut data, 2);
758        assert!(block.as_interleaved_view().is_none());
759        assert!(block.as_planar_view().is_none());
760        assert!(block.as_sequential_view().is_some());
761        let view = block.as_view();
762        assert_eq!(
763            view.channel_iter(0).copied().collect::<Vec<_>>(),
764            vec![0.0, 1.0, 2.0, 3.0, 4.0]
765        );
766        assert_eq!(
767            view.channel_iter(1).copied().collect::<Vec<_>>(),
768            vec![5.0, 6.0, 7.0, 8.0, 9.0]
769        );
770    }
771
772    #[test]
773    fn test_view_mut() {
774        let mut data = vec![0.0; 10];
775        let mut block = AudioBlockSequentialViewMut::<f32>::from_slice(&mut data, 2);
776        assert!(block.as_interleaved_view().is_none());
777        assert!(block.as_planar_view().is_none());
778        assert!(block.as_sequential_view().is_some());
779        {
780            let mut view = block.as_view_mut();
781            view.channel_iter_mut(0)
782                .enumerate()
783                .for_each(|(i, v)| *v = i as f32);
784            view.channel_iter_mut(1)
785                .enumerate()
786                .for_each(|(i, v)| *v = i as f32 + 10.0);
787        }
788
789        assert_eq!(
790            block.channel_iter(0).copied().collect::<Vec<_>>(),
791            vec![0.0, 1.0, 2.0, 3.0, 4.0]
792        );
793        assert_eq!(
794            block.channel_iter(1).copied().collect::<Vec<_>>(),
795            vec![10.0, 11.0, 12.0, 13.0, 14.0]
796        );
797    }
798
799    #[test]
800    fn test_limited() {
801        let mut data = [1.0, 2.0, 0.0, 3.0, 4.0, 0.0, 5.0, 6.0, 0.0, 0.0, 0.0, 0.0];
802
803        let mut block = AudioBlockSequentialViewMut::from_slice_limited(&mut data, 2, 3, 3, 4);
804
805        assert_eq!(block.num_channels(), 2);
806        assert_eq!(block.num_frames(), 3);
807        assert_eq!(block.num_channels_allocated, 3);
808        assert_eq!(block.num_frames_allocated, 4);
809
810        for i in 0..block.num_channels() {
811            assert_eq!(block.channel_iter(i).count(), 3);
812            assert_eq!(block.channel_iter_mut(i).count(), 3);
813        }
814        for i in 0..block.num_frames() {
815            assert_eq!(block.frame_iter(i).count(), 2);
816            assert_eq!(block.frame_iter_mut(i).count(), 2);
817        }
818    }
819
820    #[test]
821    fn test_from_ptr() {
822        let mut data = [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0];
823        let block =
824            unsafe { AudioBlockSequentialViewMut::<f32>::from_ptr(data.as_mut_ptr(), 2, 5) };
825        assert_eq!(block.num_channels(), 2);
826        assert_eq!(block.num_channels_allocated, 2);
827        assert_eq!(block.num_frames(), 5);
828        assert_eq!(block.num_frames_allocated, 5);
829        assert_eq!(block.channel(0), &[0.0, 1.0, 2.0, 3.0, 4.0]);
830        assert_eq!(block.channel(1), &[5.0, 6.0, 7.0, 8.0, 9.0]);
831    }
832
833    #[test]
834    fn test_from_ptr_limited() {
835        let mut data = [1.0, 2.0, 0.0, 3.0, 4.0, 0.0, 5.0, 6.0, 0.0, 0.0, 0.0, 0.0];
836
837        let mut block =
838            unsafe { AudioBlockSequentialViewMut::from_ptr_limited(data.as_mut_ptr(), 2, 3, 3, 4) };
839
840        assert_eq!(block.num_channels(), 2);
841        assert_eq!(block.num_frames(), 3);
842        assert_eq!(block.num_channels_allocated, 3);
843        assert_eq!(block.num_frames_allocated, 4);
844
845        for i in 0..block.num_channels() {
846            assert_eq!(block.channel_iter(i).count(), 3);
847            assert_eq!(block.channel_iter_mut(i).count(), 3);
848        }
849        for i in 0..block.num_frames() {
850            assert_eq!(block.frame_iter(i).count(), 2);
851            assert_eq!(block.frame_iter_mut(i).count(), 2);
852        }
853    }
854
855    #[test]
856    #[should_panic]
857    #[no_sanitize_realtime]
858    fn test_slice_out_of_bounds() {
859        let mut data = [0.0; 3 * 4];
860        let block = AudioBlockSequentialViewMut::from_slice_limited(&mut data, 2, 3, 3, 4);
861
862        block.channel(2);
863    }
864
865    #[test]
866    #[should_panic]
867    #[no_sanitize_realtime]
868    fn test_slice_out_of_bounds_mut() {
869        let mut data = [0.0; 3 * 4];
870        let mut block = AudioBlockSequentialViewMut::from_slice_limited(&mut data, 2, 3, 3, 4);
871
872        block.channel_mut(2);
873    }
874}