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