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::SequentialView;
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 = SequentialViewMut::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 SequentialViewMut<'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> SequentialViewMut<'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 ExactSizeIterator<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 ExactSizeIterator<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) -> SequentialView<'_, S> {
225        SequentialView::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) -> SequentialViewMut<'_, S> {
236        SequentialViewMut::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 SequentialViewMut<'_, 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 ExactSizeIterator<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 ExactSizeIterator<Item = impl ExactSizeIterator<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 ExactSizeIterator<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 ExactSizeIterator<Item = impl ExactSizeIterator<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<SequentialView<'_, S>> {
354        Some(self.view())
355    }
356}
357
358impl<S: Sample> AudioBlockMut<S> for SequentialViewMut<'_, 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 ExactSizeIterator<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 ExactSizeIterator<Item = impl ExactSizeIterator<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 ExactSizeIterator<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(
416        &mut self,
417    ) -> impl ExactSizeIterator<Item = impl ExactSizeIterator<Item = &mut S>> {
418        let num_channels = self.num_channels as usize;
419        let num_frames = self.num_frames;
420        let stride = self.num_frames_allocated;
421        let data_ptr = self.data.as_mut_ptr();
422
423        (0..num_frames).map(move |frame_idx| {
424            // Safety check: Ensure data isn't empty if we calculate a start_ptr.
425            // If num_frames or num_channels is 0, remaining will be 0, iterator is safe.
426            // If data is empty, ptr is dangling, but add(0) is okay. add(>0) is UB.
427            // But if data is empty, num_channels or num_frames must be 0.
428            let start_ptr = if self.data.is_empty() {
429                NonNull::dangling().as_ptr() // Use dangling pointer if slice is empty
430            } else {
431                // Safety: channel_idx is < num_channels <= num_channels_allocated.
432                // Adding it to a valid data_ptr is safe within slice bounds.
433                unsafe { data_ptr.add(frame_idx) }
434            };
435
436            StridedSampleIterMut::<'_, S> {
437                // Note: '_ lifetime from &self borrow
438                // Safety: Pointer is either dangling (if empty) or valid start pointer.
439                // NonNull::new is safe if start_ptr is non-null (i.e., data not empty).
440                ptr: NonNull::new(start_ptr).unwrap_or(NonNull::dangling()), // Use dangling on null/empty
441                stride,
442                remaining: num_channels, // If 0, iterator yields None immediately
443                _marker: PhantomData,
444            }
445        })
446    }
447
448    #[nonblocking]
449    fn as_view_mut(&mut self) -> impl AudioBlockMut<S> {
450        self.view_mut()
451    }
452
453    #[nonblocking]
454    fn as_sequential_view_mut(&mut self) -> Option<SequentialViewMut<'_, S>> {
455        Some(self.view_mut())
456    }
457}
458
459impl<S: Sample + core::fmt::Debug> core::fmt::Debug for SequentialViewMut<'_, S> {
460    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
461        writeln!(f, "audio_blocks::SequentialViewMut {{")?;
462        writeln!(f, "  num_channels: {}", self.num_channels)?;
463        writeln!(f, "  num_frames: {}", self.num_frames)?;
464        writeln!(
465            f,
466            "  num_channels_allocated: {}",
467            self.num_channels_allocated
468        )?;
469        writeln!(f, "  num_frames_allocated: {}", self.num_frames_allocated)?;
470        writeln!(f, "  channels:")?;
471
472        for (i, channel) in self.channels().enumerate() {
473            writeln!(f, "    {}: {:?}", i, channel)?;
474        }
475
476        writeln!(f, "  raw_data: {:?}", self.raw_data())?;
477        writeln!(f, "}}")?;
478
479        Ok(())
480    }
481}
482
483#[cfg(test)]
484mod tests {
485    use super::*;
486    use rtsan_standalone::no_sanitize_realtime;
487
488    #[test]
489    fn test_member_functions() {
490        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];
491        let mut block = SequentialViewMut::<f32>::from_slice_limited(&mut data, 2, 3, 3, 4);
492
493        // single frame
494        assert_eq!(block.channel(0), &[0.0, 1.0, 2.0]);
495        assert_eq!(block.channel(1), &[4.0, 5.0, 6.0]);
496
497        assert_eq!(block.channel_mut(0), &[0.0, 1.0, 2.0]);
498        assert_eq!(block.channel_mut(1), &[4.0, 5.0, 6.0]);
499
500        // all frames
501        let mut channels = block.channels();
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        let mut channels = block.channels_mut();
508        assert_eq!(channels.next().unwrap(), &[0.0, 1.0, 2.0]);
509        assert_eq!(channels.next().unwrap(), &[4.0, 5.0, 6.0]);
510        assert_eq!(channels.next(), None);
511        drop(channels);
512
513        // raw data
514        assert_eq!(
515            block.raw_data(),
516            &[0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 0.0, 0.0, 0.0, 0.0]
517        );
518
519        // views
520        let view = block.view();
521        assert_eq!(view.num_channels(), block.num_channels());
522        assert_eq!(view.num_frames(), block.num_frames());
523        assert_eq!(
524            view.num_channels_allocated(),
525            block.num_channels_allocated()
526        );
527        assert_eq!(view.num_frames_allocated(), block.num_frames_allocated());
528        assert_eq!(view.raw_data(), block.raw_data());
529
530        let num_channels = block.num_channels();
531        let num_frames = block.num_frames();
532        let num_channels_allocated = block.num_channels_allocated();
533        let num_frames_allocated = block.num_frames_allocated();
534        let data = block.raw_data().to_vec();
535        let view = block.view_mut();
536        assert_eq!(view.num_channels(), num_channels);
537        assert_eq!(view.num_frames(), num_frames);
538        assert_eq!(view.num_channels_allocated(), num_channels_allocated);
539        assert_eq!(view.num_frames_allocated(), num_frames_allocated);
540        assert_eq!(view.raw_data(), &data);
541    }
542
543    #[test]
544    fn test_samples() {
545        let mut data = vec![0.0; 10];
546        let mut block = SequentialViewMut::<f32>::from_slice(&mut data, 2);
547
548        let num_frames = block.num_frames();
549        for ch in 0..block.num_channels() {
550            for f in 0..block.num_frames() {
551                *block.sample_mut(ch, f) = (ch as usize * num_frames + f) as f32;
552            }
553        }
554
555        for ch in 0..block.num_channels() {
556            for f in 0..block.num_frames() {
557                assert_eq!(block.sample(ch, f), (ch as usize * num_frames + f) as f32);
558            }
559        }
560
561        assert_eq!(
562            block.raw_data(),
563            &[0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0]
564        );
565    }
566
567    #[test]
568    fn test_channels() {
569        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];
570        let mut block = SequentialViewMut::from_slice_limited(&mut data, 2, 3, 3, 4);
571
572        let mut channels = block.channels();
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        drop(channels);
577
578        let mut channels = block.channels_mut();
579        assert_eq!(channels.next().unwrap(), &[0.0, 1.0, 2.0]);
580        assert_eq!(channels.next().unwrap(), &[4.0, 5.0, 6.0]);
581        assert_eq!(channels.next(), None);
582    }
583
584    #[test]
585    fn test_channel_iter() {
586        let mut data = vec![0.0; 10];
587        let mut block = SequentialViewMut::<f32>::from_slice(&mut data, 2);
588
589        let channel = block.channel_iter(0).copied().collect::<Vec<_>>();
590        assert_eq!(channel, vec![0.0, 0.0, 0.0, 0.0, 0.0]);
591        let channel = block.channel_iter(1).copied().collect::<Vec<_>>();
592        assert_eq!(channel, vec![0.0, 0.0, 0.0, 0.0, 0.0]);
593
594        block
595            .channel_iter_mut(0)
596            .enumerate()
597            .for_each(|(i, v)| *v = i as f32);
598        block
599            .channel_iter_mut(1)
600            .enumerate()
601            .for_each(|(i, v)| *v = i as f32 + 10.0);
602
603        let channel = block.channel_iter(0).copied().collect::<Vec<_>>();
604        assert_eq!(channel, vec![0.0, 1.0, 2.0, 3.0, 4.0]);
605        let channel = block.channel_iter(1).copied().collect::<Vec<_>>();
606        assert_eq!(channel, vec![10.0, 11.0, 12.0, 13.0, 14.0]);
607    }
608
609    #[test]
610    fn test_channel_iters() {
611        let mut data = vec![0.0; 10];
612        let mut block = SequentialViewMut::<f32>::from_slice(&mut data, 2);
613
614        let mut channels_iter = block.channels_iter();
615        let channel = channels_iter.next().unwrap().copied().collect::<Vec<_>>();
616        assert_eq!(channel, vec![0.0, 0.0, 0.0, 0.0, 0.0]);
617        let channel = channels_iter.next().unwrap().copied().collect::<Vec<_>>();
618        assert_eq!(channel, vec![0.0, 0.0, 0.0, 0.0, 0.0]);
619        assert!(channels_iter.next().is_none());
620        drop(channels_iter);
621
622        let mut channels_iter = block.channels_iter_mut();
623        channels_iter
624            .next()
625            .unwrap()
626            .enumerate()
627            .for_each(|(i, v)| *v = i as f32);
628        channels_iter
629            .next()
630            .unwrap()
631            .enumerate()
632            .for_each(|(i, v)| *v = i as f32 + 10.0);
633        assert!(channels_iter.next().is_none());
634        drop(channels_iter);
635
636        let mut channels_iter = block.channels_iter();
637        let channel = channels_iter.next().unwrap().copied().collect::<Vec<_>>();
638        assert_eq!(channel, vec![0.0, 1.0, 2.0, 3.0, 4.0]);
639        let channel = channels_iter.next().unwrap().copied().collect::<Vec<_>>();
640        assert_eq!(channel, vec![10.0, 11.0, 12.0, 13.0, 14.0]);
641        assert!(channels_iter.next().is_none());
642        drop(channels_iter);
643    }
644
645    #[test]
646    fn test_frame_iter() {
647        let mut data = vec![0.0; 12];
648        let mut block = SequentialViewMut::<f32>::from_slice(&mut data, 2);
649        block.set_visible(2, 5);
650
651        for i in 0..block.num_frames() {
652            let frame = block.frame_iter(i).copied().collect::<Vec<_>>();
653            assert_eq!(frame, vec![0.0, 0.0]);
654        }
655
656        for i in 0..block.num_frames() {
657            let add = i as f32 * 10.0;
658            block
659                .frame_iter_mut(i)
660                .enumerate()
661                .for_each(|(i, v)| *v = i as f32 + add);
662        }
663
664        let channel = block.frame_iter(0).copied().collect::<Vec<_>>();
665        assert_eq!(channel, vec![0.0, 1.0]);
666        let channel = block.frame_iter(1).copied().collect::<Vec<_>>();
667        assert_eq!(channel, vec![10.0, 11.0]);
668        let channel = block.frame_iter(2).copied().collect::<Vec<_>>();
669        assert_eq!(channel, vec![20.0, 21.0]);
670        let channel = block.frame_iter(3).copied().collect::<Vec<_>>();
671        assert_eq!(channel, vec![30.0, 31.0]);
672        let channel = block.frame_iter(4).copied().collect::<Vec<_>>();
673        assert_eq!(channel, vec![40.0, 41.0]);
674    }
675
676    #[test]
677    fn test_frame_iters() {
678        let mut data = vec![0.0; 12];
679        let mut block = SequentialViewMut::<f32>::from_slice(&mut data, 2);
680        block.set_visible(2, 5);
681
682        let num_frames = block.num_frames;
683        let mut frames_iter = block.frames_iter();
684        for _ in 0..num_frames {
685            let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
686            assert_eq!(frame, vec![0.0, 0.0]);
687        }
688        assert!(frames_iter.next().is_none());
689        drop(frames_iter);
690
691        let mut frames_iter = block.frames_iter_mut();
692        for i in 0..num_frames {
693            let add = i as f32 * 10.0;
694            frames_iter
695                .next()
696                .unwrap()
697                .enumerate()
698                .for_each(|(i, v)| *v = i as f32 + add);
699        }
700        assert!(frames_iter.next().is_none());
701        drop(frames_iter);
702
703        let mut frames_iter = block.frames_iter();
704        let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
705        assert_eq!(frame, vec![0.0, 1.0]);
706        let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
707        assert_eq!(frame, vec![10.0, 11.0]);
708        let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
709        assert_eq!(frame, vec![20.0, 21.0]);
710        let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
711        assert_eq!(frame, vec![30.0, 31.0]);
712        let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
713        assert_eq!(frame, vec![40.0, 41.0]);
714        assert!(frames_iter.next().is_none());
715    }
716
717    #[test]
718    fn test_from_slice() {
719        let mut data = [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0];
720        let block = SequentialViewMut::<f32>::from_slice(&mut data, 2);
721        assert_eq!(block.num_channels(), 2);
722        assert_eq!(block.num_channels_allocated, 2);
723        assert_eq!(block.num_frames(), 5);
724        assert_eq!(block.num_frames_allocated, 5);
725        assert_eq!(
726            block.channel_iter(0).copied().collect::<Vec<_>>(),
727            vec![0.0, 1.0, 2.0, 3.0, 4.0]
728        );
729        assert_eq!(
730            block.channel_iter(1).copied().collect::<Vec<_>>(),
731            vec![5.0, 6.0, 7.0, 8.0, 9.0]
732        );
733        assert_eq!(
734            block.frame_iter(0).copied().collect::<Vec<_>>(),
735            vec![0.0, 5.0]
736        );
737        assert_eq!(
738            block.frame_iter(1).copied().collect::<Vec<_>>(),
739            vec![1.0, 6.0]
740        );
741        assert_eq!(
742            block.frame_iter(2).copied().collect::<Vec<_>>(),
743            vec![2.0, 7.0]
744        );
745        assert_eq!(
746            block.frame_iter(3).copied().collect::<Vec<_>>(),
747            vec![3.0, 8.0]
748        );
749        assert_eq!(
750            block.frame_iter(4).copied().collect::<Vec<_>>(),
751            vec![4.0, 9.0]
752        );
753    }
754
755    #[test]
756    fn test_view() {
757        let mut data = [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0];
758        let block = SequentialViewMut::<f32>::from_slice(&mut data, 2);
759        assert!(block.as_interleaved_view().is_none());
760        assert!(block.as_planar_view().is_none());
761        assert!(block.as_sequential_view().is_some());
762        let view = block.as_view();
763        assert_eq!(
764            view.channel_iter(0).copied().collect::<Vec<_>>(),
765            vec![0.0, 1.0, 2.0, 3.0, 4.0]
766        );
767        assert_eq!(
768            view.channel_iter(1).copied().collect::<Vec<_>>(),
769            vec![5.0, 6.0, 7.0, 8.0, 9.0]
770        );
771    }
772
773    #[test]
774    fn test_view_mut() {
775        let mut data = vec![0.0; 10];
776        let mut block = SequentialViewMut::<f32>::from_slice(&mut data, 2);
777        assert!(block.as_interleaved_view().is_none());
778        assert!(block.as_planar_view().is_none());
779        assert!(block.as_sequential_view().is_some());
780        {
781            let mut view = block.as_view_mut();
782            view.channel_iter_mut(0)
783                .enumerate()
784                .for_each(|(i, v)| *v = i as f32);
785            view.channel_iter_mut(1)
786                .enumerate()
787                .for_each(|(i, v)| *v = i as f32 + 10.0);
788        }
789
790        assert_eq!(
791            block.channel_iter(0).copied().collect::<Vec<_>>(),
792            vec![0.0, 1.0, 2.0, 3.0, 4.0]
793        );
794        assert_eq!(
795            block.channel_iter(1).copied().collect::<Vec<_>>(),
796            vec![10.0, 11.0, 12.0, 13.0, 14.0]
797        );
798    }
799
800    #[test]
801    fn test_limited() {
802        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];
803
804        let mut block = SequentialViewMut::from_slice_limited(&mut data, 2, 3, 3, 4);
805
806        assert_eq!(block.num_channels(), 2);
807        assert_eq!(block.num_frames(), 3);
808        assert_eq!(block.num_channels_allocated, 3);
809        assert_eq!(block.num_frames_allocated, 4);
810
811        for i in 0..block.num_channels() {
812            assert_eq!(block.channel_iter(i).count(), 3);
813            assert_eq!(block.channel_iter_mut(i).count(), 3);
814        }
815        for i in 0..block.num_frames() {
816            assert_eq!(block.frame_iter(i).count(), 2);
817            assert_eq!(block.frame_iter_mut(i).count(), 2);
818        }
819    }
820
821    #[test]
822    fn test_from_ptr() {
823        let mut data = [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0];
824        let block = unsafe { SequentialViewMut::<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 { SequentialViewMut::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 = SequentialViewMut::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 = SequentialViewMut::from_slice_limited(&mut data, 2, 3, 3, 4);
871
872        block.channel_mut(2);
873    }
874}