use core::mem::MaybeUninit;
use rtsan_standalone::nonblocking;
use std::marker::PhantomData;
use crate::{AudioBlock, AudioBlockMut, Sample};
use super::PlanarView;
pub struct PlanarViewMut<'a, S: Sample, V: AsMut<[S]> + AsRef<[S]>> {
data: &'a mut [V],
num_channels: u16,
num_frames: usize,
num_channels_allocated: u16,
num_frames_allocated: usize,
_phantom: PhantomData<S>,
}
impl<'a, S: Sample, V: AsMut<[S]> + AsRef<[S]>> PlanarViewMut<'a, S, V> {
#[nonblocking]
pub fn from_slice(data: &'a mut [V]) -> Self {
let num_frames_allocated = if data.is_empty() {
0
} else {
data[0].as_ref().len()
};
Self::from_slice_limited(data, data.len() as u16, num_frames_allocated)
}
#[nonblocking]
pub fn from_slice_limited(
data: &'a mut [V],
num_channels_visible: u16,
num_frames_visible: usize,
) -> Self {
let num_channels_allocated = data.len();
let num_frames_allocated = if num_channels_allocated == 0 {
0
} else {
data[0].as_ref().len()
};
assert!(num_channels_visible <= num_channels_allocated as u16);
assert!(num_frames_visible <= num_frames_allocated);
data.iter()
.for_each(|v| assert_eq!(v.as_ref().len(), num_frames_allocated));
Self {
data,
num_channels: num_channels_visible,
num_frames: num_frames_visible,
num_channels_allocated: num_channels_allocated as u16,
num_frames_allocated,
_phantom: PhantomData,
}
}
#[nonblocking]
pub fn channel(&self, channel: u16) -> &[S] {
assert!(channel < self.num_channels);
&self.data[channel as usize].as_ref()[..self.num_frames]
}
#[nonblocking]
pub fn channel_mut(&mut self, channel: u16) -> &mut [S] {
assert!(channel < self.num_channels);
&mut self.data[channel as usize].as_mut()[..self.num_frames]
}
#[nonblocking]
pub fn channels(&self) -> impl ExactSizeIterator<Item = &[S]> {
self.data
.iter()
.take(self.num_channels as usize)
.map(|channel_data| &channel_data.as_ref()[..self.num_frames])
}
#[nonblocking]
pub fn channels_mut(&mut self) -> impl ExactSizeIterator<Item = &mut [S]> {
self.data
.iter_mut()
.take(self.num_channels as usize)
.map(|channel_data| &mut channel_data.as_mut()[..self.num_frames])
}
#[nonblocking]
pub fn raw_data(&self) -> &[V] {
self.data
}
#[nonblocking]
pub fn raw_data_mut(&mut self) -> &mut [V] {
self.data
}
#[nonblocking]
pub fn view(&self) -> PlanarView<'_, S, V> {
PlanarView::from_slice_limited(self.data, self.num_channels, self.num_frames)
}
#[nonblocking]
pub fn view_mut(&mut self) -> PlanarViewMut<'_, S, V> {
PlanarViewMut::from_slice_limited(self.data, self.num_channels, self.num_frames)
}
}
impl<S: Sample, V: AsMut<[S]> + AsRef<[S]>> AudioBlock<S> for PlanarViewMut<'_, S, V> {
type PlanarView = V;
#[nonblocking]
fn num_channels(&self) -> u16 {
self.num_channels
}
#[nonblocking]
fn num_frames(&self) -> usize {
self.num_frames
}
#[nonblocking]
fn num_channels_allocated(&self) -> u16 {
self.num_channels_allocated
}
#[nonblocking]
fn num_frames_allocated(&self) -> usize {
self.num_frames_allocated
}
#[nonblocking]
fn layout(&self) -> crate::BlockLayout {
crate::BlockLayout::Planar
}
#[nonblocking]
fn sample(&self, channel: u16, frame: usize) -> S {
assert!(channel < self.num_channels);
assert!(frame < self.num_frames);
unsafe {
*self
.data
.get_unchecked(channel as usize)
.as_ref()
.get_unchecked(frame)
}
}
#[nonblocking]
fn channel_iter(&self, channel: u16) -> impl ExactSizeIterator<Item = &S> {
assert!(channel < self.num_channels);
unsafe {
self.data
.get_unchecked(channel as usize)
.as_ref()
.iter()
.take(self.num_frames)
}
}
#[nonblocking]
fn channels_iter(&self) -> impl ExactSizeIterator<Item = impl ExactSizeIterator<Item = &S>> {
let num_frames = self.num_frames; self.data
.iter()
.take(self.num_channels as usize)
.map(move |channel_data| channel_data.as_ref().iter().take(num_frames))
}
#[nonblocking]
fn frame_iter(&self, frame: usize) -> impl ExactSizeIterator<Item = &S> {
assert!(frame < self.num_frames);
self.data
.iter()
.take(self.num_channels as usize)
.map(move |channel_data| unsafe { channel_data.as_ref().get_unchecked(frame) })
}
#[nonblocking]
fn frames_iter(&self) -> impl ExactSizeIterator<Item = impl ExactSizeIterator<Item = &'_ S>> {
let num_channels = self.num_channels as usize;
let num_frames = self.num_frames;
let data_slice: &[V] = self.data;
(0..num_frames).map(move |frame_idx| {
data_slice[..num_channels]
.iter() .map(move |channel_view: &V| {
let channel_slice: &[S] = channel_view.as_ref();
&channel_slice[frame_idx]
})
})
}
#[nonblocking]
fn as_view(&self) -> impl AudioBlock<S> {
PlanarView::from_slice_limited(self.data, self.num_channels, self.num_frames)
}
#[nonblocking]
fn as_planar_view(&self) -> Option<PlanarView<'_, S, Self::PlanarView>> {
Some(self.view())
}
}
impl<S: Sample, V: AsMut<[S]> + AsRef<[S]>> AudioBlockMut<S> for PlanarViewMut<'_, S, V> {
type PlanarViewMut = V;
#[nonblocking]
fn set_num_channels_visible(&mut self, num_channels: u16) {
assert!(num_channels <= self.num_channels_allocated);
self.num_channels = num_channels;
}
#[nonblocking]
fn set_num_frames_visible(&mut self, num_frames: usize) {
assert!(num_frames <= self.num_frames_allocated);
self.num_frames = num_frames;
}
#[nonblocking]
fn sample_mut(&mut self, channel: u16, frame: usize) -> &mut S {
assert!(channel < self.num_channels);
assert!(frame < self.num_frames);
unsafe {
self.data
.get_unchecked_mut(channel as usize)
.as_mut()
.get_unchecked_mut(frame)
}
}
#[nonblocking]
fn channel_iter_mut(&mut self, channel: u16) -> impl ExactSizeIterator<Item = &mut S> {
assert!(channel < self.num_channels);
unsafe {
self.data
.get_unchecked_mut(channel as usize)
.as_mut()
.iter_mut()
.take(self.num_frames)
}
}
#[nonblocking]
fn channels_iter_mut(
&mut self,
) -> impl ExactSizeIterator<Item = impl ExactSizeIterator<Item = &mut S>> {
let num_frames = self.num_frames;
self.data
.iter_mut()
.take(self.num_channels as usize)
.map(move |channel_data| channel_data.as_mut().iter_mut().take(num_frames))
}
#[nonblocking]
fn frame_iter_mut(&mut self, frame: usize) -> impl ExactSizeIterator<Item = &mut S> {
assert!(frame < self.num_frames);
self.data
.iter_mut()
.take(self.num_channels as usize)
.map(move |channel_data| unsafe { channel_data.as_mut().get_unchecked_mut(frame) })
}
#[nonblocking]
fn frames_iter_mut(
&mut self,
) -> impl ExactSizeIterator<Item = impl ExactSizeIterator<Item = &mut S>> {
let num_channels = self.num_channels as usize;
let num_frames = self.num_frames;
let data_slice: &mut [V] = self.data;
let data_ptr: *mut [V] = data_slice;
(0..num_frames).map(move |frame_idx| {
let current_channel_views: &mut [V] = unsafe { &mut *data_ptr };
current_channel_views[..num_channels]
.iter_mut() .map(move |channel_view: &mut V| {
let channel_slice: &mut [S] = channel_view.as_mut();
unsafe { channel_slice.get_unchecked_mut(frame_idx) }
})
})
}
#[nonblocking]
fn as_view_mut(&mut self) -> impl AudioBlockMut<S> {
self.view_mut()
}
#[nonblocking]
fn as_planar_view_mut(&mut self) -> Option<PlanarViewMut<'_, S, Self::PlanarViewMut>> {
Some(self.view_mut())
}
}
impl<S: Sample + core::fmt::Debug, V: AsMut<[S]> + AsRef<[S]> + core::fmt::Debug> core::fmt::Debug
for PlanarViewMut<'_, S, V>
{
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
writeln!(f, "audio_blocks::PlanarViewMut {{")?;
writeln!(f, " num_channels: {}", self.num_channels)?;
writeln!(f, " num_frames: {}", self.num_frames)?;
writeln!(
f,
" num_channels_allocated: {}",
self.num_channels_allocated
)?;
writeln!(f, " num_frames_allocated: {}", self.num_frames_allocated)?;
writeln!(f, " channels:")?;
for (i, channel) in self.channels().enumerate() {
writeln!(f, " {}: {:?}", i, channel)?;
}
writeln!(f, " raw_data: {:?}", self.raw_data())?;
writeln!(f, "}}")?;
Ok(())
}
}
pub struct PlanarPtrAdapterMut<'a, S: Sample, const MAX_CHANNELS: usize> {
data: [MaybeUninit<&'a mut [S]>; MAX_CHANNELS],
num_channels: u16,
}
impl<'a, S: Sample, const MAX_CHANNELS: usize> PlanarPtrAdapterMut<'a, S, MAX_CHANNELS> {
#[nonblocking]
pub unsafe fn from_ptr(ptrs: *mut *mut S, num_channels: u16, num_frames: usize) -> Self {
assert!(
num_channels as usize <= MAX_CHANNELS,
"num_channels exceeds MAX_CHANNELS"
);
let mut data: [MaybeUninit<&'a mut [S]>; MAX_CHANNELS] =
unsafe { MaybeUninit::uninit().assume_init() };
let ptr_slice: &mut [*mut S] =
unsafe { core::slice::from_raw_parts_mut(ptrs, num_channels as usize) };
for ch in 0..num_channels as usize {
data[ch].write(unsafe { core::slice::from_raw_parts_mut(ptr_slice[ch], num_frames) });
}
Self { data, num_channels }
}
#[inline]
pub fn data_slice_mut(&mut self) -> &mut [&'a mut [S]] {
let initialized_part: &mut [MaybeUninit<&'a mut [S]>] =
&mut self.data[..self.num_channels as usize];
unsafe {
core::slice::from_raw_parts_mut(
initialized_part.as_mut_ptr() as *mut &'a mut [S],
self.num_channels as usize,
)
}
}
#[nonblocking]
pub fn planar_view_mut(&mut self) -> PlanarViewMut<'a, S, &mut [S]> {
PlanarViewMut::from_slice(self.data_slice_mut())
}
}
#[cfg(test)]
mod tests {
use super::*;
use rtsan_standalone::no_sanitize_realtime;
#[test]
fn test_member_functions() {
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],
];
let mut block = PlanarViewMut::from_slice_limited(&mut data, 2, 3);
assert_eq!(block.channel(0), &[0.0, 1.0, 2.0]);
assert_eq!(block.channel(1), &[4.0, 5.0, 6.0]);
assert_eq!(block.channel_mut(0), &[0.0, 1.0, 2.0]);
assert_eq!(block.channel_mut(1), &[4.0, 5.0, 6.0]);
let mut channels = block.channels();
assert_eq!(channels.next().unwrap(), &[0.0, 1.0, 2.0]);
assert_eq!(channels.next().unwrap(), &[4.0, 5.0, 6.0]);
assert_eq!(channels.next(), None);
drop(channels);
let mut channels = block.channels_mut();
assert_eq!(channels.next().unwrap(), &[0.0, 1.0, 2.0]);
assert_eq!(channels.next().unwrap(), &[4.0, 5.0, 6.0]);
assert_eq!(channels.next(), None);
drop(channels);
assert_eq!(block.raw_data()[0].as_ref(), &[0.0, 1.0, 2.0, 3.0]);
assert_eq!(block.raw_data()[1].as_ref(), &[4.0, 5.0, 6.0, 7.0]);
assert_eq!(block.raw_data()[2].as_ref(), &[0.0, 0.0, 0.0, 0.0]);
assert_eq!(block.raw_data_mut()[0].as_ref(), &[0.0, 1.0, 2.0, 3.0]);
assert_eq!(block.raw_data_mut()[1].as_ref(), &[4.0, 5.0, 6.0, 7.0]);
assert_eq!(block.raw_data_mut()[2].as_ref(), &[0.0, 0.0, 0.0, 0.0]);
let view = block.view();
assert_eq!(view.num_channels(), block.num_channels());
assert_eq!(view.num_frames(), block.num_frames());
assert_eq!(
view.num_channels_allocated(),
block.num_channels_allocated()
);
assert_eq!(view.num_frames_allocated(), block.num_frames_allocated());
assert_eq!(view.raw_data(), block.raw_data());
let num_channels = block.num_channels();
let num_frames = block.num_frames();
let num_channels_allocated = block.num_channels_allocated();
let num_frames_allocated = block.num_frames_allocated();
let data = block.raw_data().to_vec();
let view = block.view_mut();
assert_eq!(view.num_channels(), num_channels);
assert_eq!(view.num_frames(), num_frames);
assert_eq!(view.num_channels_allocated(), num_channels_allocated);
assert_eq!(view.num_frames_allocated(), num_frames_allocated);
assert_eq!(view.raw_data(), &data);
}
#[test]
fn test_samples() {
let mut ch1 = vec![0.0; 5];
let mut ch2 = vec![0.0; 5];
let mut data = vec![ch1.as_mut_slice(), ch2.as_mut_slice()];
let mut block = PlanarViewMut::from_slice(&mut data);
let num_frames = block.num_frames();
for ch in 0..block.num_channels() {
for f in 0..block.num_frames() {
*block.sample_mut(ch, f) = (ch as usize * num_frames + f) as f32;
}
}
for ch in 0..block.num_channels() {
for f in 0..block.num_frames() {
assert_eq!(block.sample(ch, f), (ch as usize * num_frames + f) as f32);
}
}
assert_eq!(block.channel(0), &[0.0, 1.0, 2.0, 3.0, 4.0]);
assert_eq!(block.channel(1), &[5.0, 6.0, 7.0, 8.0, 9.0]);
}
#[test]
fn test_channel_iter() {
let mut ch1 = vec![0.0; 5];
let mut ch2 = vec![0.0; 5];
let mut data = vec![ch1.as_mut_slice(), ch2.as_mut_slice()];
let mut block = PlanarViewMut::from_slice(&mut data);
let channel = block.channel_iter(0).copied().collect::<Vec<_>>();
assert_eq!(channel, vec![0.0, 0.0, 0.0, 0.0, 0.0]);
let channel = block.channel_iter(1).copied().collect::<Vec<_>>();
assert_eq!(channel, vec![0.0, 0.0, 0.0, 0.0, 0.0]);
block
.channel_iter_mut(0)
.enumerate()
.for_each(|(i, v)| *v = i as f32);
block
.channel_iter_mut(1)
.enumerate()
.for_each(|(i, v)| *v = i as f32 + 10.0);
let channel = block.channel_iter(0).copied().collect::<Vec<_>>();
assert_eq!(channel, vec![0.0, 1.0, 2.0, 3.0, 4.0]);
let channel = block.channel_iter(1).copied().collect::<Vec<_>>();
assert_eq!(channel, vec![10.0, 11.0, 12.0, 13.0, 14.0]);
}
#[test]
fn test_channel_iters() {
let mut ch1 = vec![0.0; 5];
let mut ch2 = vec![0.0; 5];
let mut data = vec![ch1.as_mut_slice(), ch2.as_mut_slice()];
let mut block = PlanarViewMut::from_slice(&mut data);
let mut channels_iter = block.channels_iter();
let channel = channels_iter.next().unwrap().copied().collect::<Vec<_>>();
assert_eq!(channel, vec![0.0, 0.0, 0.0, 0.0, 0.0]);
let channel = channels_iter.next().unwrap().copied().collect::<Vec<_>>();
assert_eq!(channel, vec![0.0, 0.0, 0.0, 0.0, 0.0]);
assert!(channels_iter.next().is_none());
drop(channels_iter);
let mut channels_iter = block.channels_iter_mut();
channels_iter
.next()
.unwrap()
.enumerate()
.for_each(|(i, v)| *v = i as f32);
channels_iter
.next()
.unwrap()
.enumerate()
.for_each(|(i, v)| *v = i as f32 + 10.0);
assert!(channels_iter.next().is_none());
drop(channels_iter);
let mut channels_iter = block.channels_iter();
let channel = channels_iter.next().unwrap().copied().collect::<Vec<_>>();
assert_eq!(channel, vec![0.0, 1.0, 2.0, 3.0, 4.0]);
let channel = channels_iter.next().unwrap().copied().collect::<Vec<_>>();
assert_eq!(channel, vec![10.0, 11.0, 12.0, 13.0, 14.0]);
assert!(channels_iter.next().is_none());
drop(channels_iter);
}
#[test]
fn test_frame_iter() {
let mut ch1 = vec![0.0; 5];
let mut ch2 = vec![0.0; 5];
let mut data = vec![ch1.as_mut_slice(), ch2.as_mut_slice()];
let mut block = PlanarViewMut::from_slice(&mut data);
for i in 0..block.num_frames() {
let frame = block.frame_iter(i).copied().collect::<Vec<_>>();
assert_eq!(frame, vec![0.0, 0.0]);
}
for i in 0..block.num_frames() {
let add = i as f32 * 10.0;
block
.frame_iter_mut(i)
.enumerate()
.for_each(|(i, v)| *v = i as f32 + add);
}
let channel = block.frame_iter(0).copied().collect::<Vec<_>>();
assert_eq!(channel, vec![0.0, 1.0]);
let channel = block.frame_iter(1).copied().collect::<Vec<_>>();
assert_eq!(channel, vec![10.0, 11.0]);
let channel = block.frame_iter(2).copied().collect::<Vec<_>>();
assert_eq!(channel, vec![20.0, 21.0]);
let channel = block.frame_iter(3).copied().collect::<Vec<_>>();
assert_eq!(channel, vec![30.0, 31.0]);
let channel = block.frame_iter(4).copied().collect::<Vec<_>>();
assert_eq!(channel, vec![40.0, 41.0]);
}
#[test]
fn test_frame_iters() {
let mut ch1 = vec![0.0; 10];
let mut ch2 = vec![0.0; 10];
let mut ch3 = vec![0.0; 10];
let mut data = vec![ch1.as_mut_slice(), ch2.as_mut_slice(), ch3.as_mut_slice()];
let mut block = PlanarViewMut::from_slice(&mut data);
block.set_visible(2, 5);
let num_frames = block.num_frames;
let mut frames_iter = block.frames_iter();
for _ in 0..num_frames {
let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
assert_eq!(frame, vec![0.0, 0.0]);
}
assert!(frames_iter.next().is_none());
drop(frames_iter);
let mut frames_iter = block.frames_iter_mut();
for i in 0..num_frames {
let add = i as f32 * 10.0;
frames_iter
.next()
.unwrap()
.enumerate()
.for_each(|(i, v)| *v = i as f32 + add);
}
assert!(frames_iter.next().is_none());
drop(frames_iter);
let mut frames_iter = block.frames_iter();
let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
assert_eq!(frame, vec![0.0, 1.0]);
let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
assert_eq!(frame, vec![10.0, 11.0]);
let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
assert_eq!(frame, vec![20.0, 21.0]);
let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
assert_eq!(frame, vec![30.0, 31.0]);
let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
assert_eq!(frame, vec![40.0, 41.0]);
assert!(frames_iter.next().is_none());
}
#[test]
fn test_from_vec() {
let mut vec = vec![vec![0.0, 2.0, 4.0, 6.0, 8.0], vec![1.0, 3.0, 5.0, 7.0, 9.0]];
let block = PlanarViewMut::from_slice(&mut vec);
assert_eq!(block.num_channels(), 2);
assert_eq!(block.num_frames(), 5);
assert_eq!(
block.channel_iter(0).copied().collect::<Vec<_>>(),
vec![0.0, 2.0, 4.0, 6.0, 8.0]
);
assert_eq!(
block.channel_iter(1).copied().collect::<Vec<_>>(),
vec![1.0, 3.0, 5.0, 7.0, 9.0]
);
assert_eq!(
block.frame_iter(0).copied().collect::<Vec<_>>(),
vec![0.0, 1.0]
);
assert_eq!(
block.frame_iter(1).copied().collect::<Vec<_>>(),
vec![2.0, 3.0]
);
assert_eq!(
block.frame_iter(2).copied().collect::<Vec<_>>(),
vec![4.0, 5.0]
);
assert_eq!(
block.frame_iter(3).copied().collect::<Vec<_>>(),
vec![6.0, 7.0]
);
assert_eq!(
block.frame_iter(4).copied().collect::<Vec<_>>(),
vec![8.0, 9.0]
);
}
#[test]
fn test_view() {
let mut vec = vec![vec![0.0, 2.0, 4.0, 6.0, 8.0], vec![1.0, 3.0, 5.0, 7.0, 9.0]];
let block = PlanarViewMut::from_slice(&mut vec);
assert!(block.as_interleaved_view().is_none());
assert!(block.as_planar_view().is_some());
assert!(block.as_sequential_view().is_none());
let view = block.as_view();
assert_eq!(
view.channel_iter(0).copied().collect::<Vec<_>>(),
vec![0.0, 2.0, 4.0, 6.0, 8.0]
);
assert_eq!(
view.channel_iter(1).copied().collect::<Vec<_>>(),
vec![1.0, 3.0, 5.0, 7.0, 9.0]
);
}
#[test]
fn test_view_mut() {
let mut data = vec![vec![0.0; 5]; 2];
let mut block = PlanarViewMut::from_slice(&mut data);
assert!(block.as_interleaved_view().is_none());
assert!(block.as_planar_view().is_some());
assert!(block.as_sequential_view().is_none());
{
let mut view = block.as_view_mut();
view.channel_iter_mut(0)
.enumerate()
.for_each(|(i, v)| *v = i as f32);
view.channel_iter_mut(1)
.enumerate()
.for_each(|(i, v)| *v = i as f32 + 10.0);
}
assert_eq!(
block.channel_iter(0).copied().collect::<Vec<_>>(),
vec![0.0, 1.0, 2.0, 3.0, 4.0]
);
assert_eq!(
block.channel_iter(1).copied().collect::<Vec<_>>(),
vec![10.0, 11.0, 12.0, 13.0, 14.0]
);
}
#[test]
fn test_limited() {
let mut data = vec![vec![0.0; 4]; 3];
let mut block = PlanarViewMut::from_slice_limited(&mut data, 2, 3);
assert_eq!(block.num_channels(), 2);
assert_eq!(block.num_frames(), 3);
assert_eq!(block.num_channels_allocated, 3);
assert_eq!(block.num_frames_allocated, 4);
for i in 0..block.num_channels() {
assert_eq!(block.channel_iter(i).count(), 3);
assert_eq!(block.channel_iter_mut(i).count(), 3);
}
for i in 0..block.num_frames() {
assert_eq!(block.frame_iter(i).count(), 2);
assert_eq!(block.frame_iter_mut(i).count(), 2);
}
}
#[test]
fn test_pointer() {
unsafe {
let num_channels = 2;
let num_frames = 5;
let mut data = [vec![0.0, 2.0, 4.0, 6.0, 8.0], vec![1.0, 3.0, 5.0, 7.0, 9.0]];
let mut ptr_vec: Vec<*mut f32> = data
.iter_mut()
.map(|inner_vec| inner_vec.as_mut_ptr())
.collect();
let ptr = ptr_vec.as_mut_ptr();
let mut adaptor = PlanarPtrAdapterMut::<_, 16>::from_ptr(ptr, num_channels, num_frames);
let planar = adaptor.planar_view_mut();
assert_eq!(
planar.channel_iter(0).copied().collect::<Vec<_>>(),
vec![0.0, 2.0, 4.0, 6.0, 8.0]
);
assert_eq!(
planar.channel_iter(1).copied().collect::<Vec<_>>(),
vec![1.0, 3.0, 5.0, 7.0, 9.0]
);
}
}
#[test]
#[should_panic]
#[no_sanitize_realtime]
fn test_slice_out_of_bounds() {
let mut data = [[0.0; 4]; 3];
let block = PlanarViewMut::from_slice_limited(&mut data, 2, 3);
block.channel(2);
}
#[test]
#[should_panic]
#[no_sanitize_realtime]
fn test_slice_out_of_bounds_mut() {
let mut data = [[0.0; 4]; 3];
let mut block = PlanarViewMut::from_slice_limited(&mut data, 2, 3);
block.channel_mut(2);
}
}