use rtsan_standalone::nonblocking;
use crate::{
AudioBlock, AudioBlockMut, BlockLayout, Sample,
mono::{MonoView, MonoViewMut},
};
pub trait AudioBlockOps<S: Sample> {
fn mix_to_mono(&self, dest: &mut MonoViewMut<S>) -> Option<usize>
where
S: std::ops::AddAssign + std::ops::Div<Output = S> + From<u16>;
fn mix_to_mono_exact(&self, dest: &mut MonoViewMut<S>)
where
S: std::ops::AddAssign + std::ops::Div<Output = S> + From<u16>;
fn copy_channel_to_mono(&self, dest: &mut MonoViewMut<S>, channel: u16) -> Option<usize>;
fn copy_channel_to_mono_exact(&self, dest: &mut MonoViewMut<S>, channel: u16);
}
pub trait AudioBlockOpsMut<S: Sample> {
fn copy_from_block(&mut self, block: &impl AudioBlock<S>) -> Option<(u16, usize)>;
fn copy_from_block_exact(&mut self, block: &impl AudioBlock<S>);
fn copy_mono_to_all_channels(&mut self, mono: &MonoView<S>) -> Option<usize>;
fn copy_mono_to_all_channels_exact(&mut self, mono: &MonoView<S>);
fn for_each(&mut self, f: impl FnMut(&mut S));
fn enumerate(&mut self, f: impl FnMut(u16, usize, &mut S));
fn for_each_allocated(&mut self, f: impl FnMut(&mut S));
fn enumerate_allocated(&mut self, f: impl FnMut(u16, usize, &mut S));
fn fill_with(&mut self, sample: S);
fn clear(&mut self)
where
S: Default;
fn gain(&mut self, gain: S)
where
S: std::ops::Mul<Output = S> + Copy;
}
impl<S: Sample, B: AudioBlock<S>> AudioBlockOps<S> for B {
#[nonblocking]
fn mix_to_mono(&self, dest: &mut MonoViewMut<S>) -> Option<usize>
where
S: std::ops::AddAssign + std::ops::Div<Output = S> + From<u16>,
{
let frames = self.num_frames().min(dest.num_frames());
let num_channels = S::from(self.num_channels());
for frame in 0..frames {
let mut sum = *self.frame_iter(frame).next().unwrap();
for sample in self.frame_iter(frame).skip(1) {
sum += *sample;
}
*dest.sample_mut(frame) = sum / num_channels;
}
if frames == self.num_frames() {
None
} else {
Some(frames)
}
}
#[nonblocking]
fn mix_to_mono_exact(&self, dest: &mut MonoViewMut<S>)
where
S: std::ops::AddAssign + std::ops::Div<Output = S> + From<u16>,
{
assert_eq!(self.num_frames(), dest.num_frames());
let num_channels = S::from(self.num_channels());
for frame in 0..self.num_frames() {
let mut sum = *self.frame_iter(frame).next().unwrap();
for sample in self.frame_iter(frame).skip(1) {
sum += *sample;
}
*dest.sample_mut(frame) = sum / num_channels;
}
}
#[nonblocking]
fn copy_channel_to_mono(&self, dest: &mut MonoViewMut<S>, channel: u16) -> Option<usize> {
let frames = self.num_frames().min(dest.num_frames());
for (o, i) in dest
.raw_data_mut()
.iter_mut()
.take(frames)
.zip(self.channel_iter(channel).take(frames))
{
*o = *i;
}
if frames == self.num_frames() {
None
} else {
Some(frames)
}
}
#[nonblocking]
fn copy_channel_to_mono_exact(&self, dest: &mut MonoViewMut<S>, channel: u16) {
assert_eq!(self.num_frames(), dest.num_frames());
for (o, i) in dest
.raw_data_mut()
.iter_mut()
.zip(self.channel_iter(channel))
{
*o = *i;
}
}
}
impl<S: Sample, B: AudioBlockMut<S>> AudioBlockOpsMut<S> for B {
#[nonblocking]
fn copy_from_block(&mut self, block: &impl AudioBlock<S>) -> Option<(u16, usize)> {
let channels = self.num_channels().min(block.num_channels());
let frames = self.num_frames().min(block.num_frames());
for (this_channel, other_channel) in self.channels_iter_mut().zip(block.channels_iter()) {
for (sample_mut, sample) in this_channel.zip(other_channel) {
*sample_mut = *sample;
}
}
if channels == block.num_channels() && frames == block.num_frames() {
None
} else {
Some((channels, frames))
}
}
#[nonblocking]
fn copy_from_block_exact(&mut self, block: &impl AudioBlock<S>) {
assert_eq!(block.num_channels(), self.num_channels());
assert_eq!(block.num_frames(), self.num_frames());
for ch in 0..self.num_channels() {
for (sample_mut, sample) in self.channel_iter_mut(ch).zip(block.channel_iter(ch)) {
*sample_mut = *sample;
}
}
}
#[nonblocking]
fn copy_mono_to_all_channels(&mut self, mono: &MonoView<S>) -> Option<usize> {
let frames = mono.num_frames().min(self.num_frames());
for channel in self.channels_iter_mut() {
for (sample_mut, sample) in channel.take(frames).zip(mono.samples().iter().take(frames))
{
*sample_mut = *sample;
}
}
if frames == mono.num_frames() {
None
} else {
Some(frames)
}
}
#[nonblocking]
fn copy_mono_to_all_channels_exact(&mut self, mono: &MonoView<S>) {
assert_eq!(mono.num_frames(), self.num_frames());
for channel in self.channels_iter_mut() {
for (sample_mut, sample) in channel.zip(mono.samples()) {
*sample_mut = *sample;
}
}
}
#[nonblocking]
fn for_each(&mut self, mut f: impl FnMut(&mut S)) {
if self.num_channels() < 8 {
for channel in self.channels_iter_mut() {
channel.for_each(&mut f);
}
} else {
match self.layout() {
BlockLayout::Sequential | BlockLayout::Planar => {
for channel in self.channels_iter_mut() {
channel.for_each(&mut f);
}
}
BlockLayout::Interleaved => {
for frame in 0..self.num_frames() {
self.frame_iter_mut(frame).for_each(&mut f);
}
}
}
}
}
#[nonblocking]
fn enumerate(&mut self, mut f: impl FnMut(u16, usize, &mut S)) {
if self.num_channels() < 8 {
for (ch, channel) in self.channels_iter_mut().enumerate() {
for (fr, sample) in channel.enumerate() {
f(ch as u16, fr, sample)
}
}
} else {
match self.layout() {
BlockLayout::Interleaved => {
for (fr, frame) in self.frames_iter_mut().enumerate() {
for (ch, sample) in frame.enumerate() {
f(ch as u16, fr, sample)
}
}
}
BlockLayout::Planar | BlockLayout::Sequential => {
for (ch, channel) in self.channels_iter_mut().enumerate() {
for (fr, sample) in channel.enumerate() {
f(ch as u16, fr, sample)
}
}
}
}
}
}
#[nonblocking]
fn for_each_allocated(&mut self, mut f: impl FnMut(&mut S)) {
match self.layout() {
BlockLayout::Interleaved => self
.as_interleaved_view_mut()
.expect("Layout is interleaved")
.raw_data_mut()
.iter_mut()
.for_each(&mut f),
BlockLayout::Planar => self
.as_planar_view_mut()
.expect("Layout is planar")
.raw_data_mut()
.iter_mut()
.for_each(|c| c.as_mut().iter_mut().for_each(&mut f)),
BlockLayout::Sequential => self
.as_sequential_view_mut()
.expect("Layout is sequential")
.raw_data_mut()
.iter_mut()
.for_each(&mut f),
}
}
#[nonblocking]
fn enumerate_allocated(&mut self, mut f: impl FnMut(u16, usize, &mut S)) {
match self.layout() {
BlockLayout::Interleaved => {
let num_frames = self.num_frames_allocated();
self.as_interleaved_view_mut()
.expect("Layout is interleaved")
.raw_data_mut()
.iter_mut()
.enumerate()
.for_each(|(i, sample)| {
let channel = i % num_frames;
let frame = i / num_frames;
f(channel as u16, frame, sample)
});
}
BlockLayout::Planar => self
.as_planar_view_mut()
.expect("Layout is planar")
.raw_data_mut()
.iter_mut()
.enumerate()
.for_each(|(ch, v)| {
v.as_mut()
.iter_mut()
.enumerate()
.for_each(|(frame, sample)| f(ch as u16, frame, sample))
}),
BlockLayout::Sequential => {
let num_frames = self.num_frames_allocated();
self.as_sequential_view_mut()
.expect("Layout is sequential")
.raw_data_mut()
.iter_mut()
.enumerate()
.for_each(|(i, sample)| {
let channel = i / num_frames;
let frame = i % num_frames;
f(channel as u16, frame, sample)
});
}
}
}
#[nonblocking]
fn fill_with(&mut self, sample: S) {
self.for_each_allocated(|v| *v = sample);
}
#[nonblocking]
fn clear(&mut self)
where
S: Default,
{
self.fill_with(S::default());
}
#[nonblocking]
fn gain(&mut self, gain: S)
where
S: std::ops::Mul<Output = S> + Copy,
{
self.for_each_allocated(|v| *v = *v * gain);
}
}
#[cfg(test)]
mod tests {
use rtsan_standalone::no_sanitize_realtime;
use crate::{
interleaved::InterleavedViewMut,
sequential::{SequentialView, SequentialViewMut},
};
use super::*;
#[test]
fn test_copy_from_block_dest_larger() {
let mut data = [0.0; 15];
let mut block = InterleavedViewMut::from_slice(&mut data, 3);
let view = SequentialView::from_slice(&[0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0], 2);
let result = block.copy_from_block(&view);
assert_eq!(result, None);
assert_eq!(block.num_channels(), 3);
assert_eq!(block.num_frames(), 5);
assert_eq!(
block.channel_iter(0).take(4).copied().collect::<Vec<_>>(),
vec![0.0, 1.0, 2.0, 3.0]
);
assert_eq!(
block.channel_iter(1).take(4).copied().collect::<Vec<_>>(),
vec![4.0, 5.0, 6.0, 7.0]
);
}
#[test]
fn test_copy_from_block_exact_match_returns_none() {
let mut data = [0.0; 8];
let mut block = InterleavedViewMut::from_slice(&mut data, 2);
let view = SequentialView::from_slice(&[0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0], 2);
let result = block.copy_from_block(&view);
assert_eq!(result, None); }
#[test]
fn test_copy_from_block_clamps_to_dest_size() {
let mut data = [0.0; 4]; let mut block = SequentialViewMut::from_slice(&mut data, 2);
let view = SequentialView::from_slice(&[0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0], 2);
let result = block.copy_from_block(&view);
assert_eq!(result, Some((2, 2))); assert_eq!(
block.channel_iter(0).copied().collect::<Vec<_>>(),
vec![0.0, 1.0]
);
assert_eq!(
block.channel_iter(1).copied().collect::<Vec<_>>(),
vec![4.0, 5.0]
);
}
#[test]
fn test_copy_from_block_source_larger_channels() {
let mut data = [0.0; 4]; let mut block = SequentialViewMut::from_slice(&mut data, 1);
let view = SequentialView::from_slice(&[0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0], 2);
let result = block.copy_from_block(&view);
assert_eq!(result, Some((1, 4)));
assert_eq!(
block.channel_iter(0).copied().collect::<Vec<_>>(),
vec![0.0, 1.0, 2.0, 3.0]
);
}
#[test]
fn test_copy_from_block_exact() {
let mut data = [0.0; 8];
let mut block = InterleavedViewMut::from_slice(&mut data, 2);
let view = SequentialView::from_slice(&[0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0], 2);
block.copy_from_block_exact(&view);
assert_eq!(block.num_channels(), 2);
assert_eq!(block.num_frames(), 4);
assert_eq!(
block.channel_iter(0).take(4).copied().collect::<Vec<_>>(),
vec![0.0, 1.0, 2.0, 3.0]
);
assert_eq!(
block.channel_iter(1).take(4).copied().collect::<Vec<_>>(),
vec![4.0, 5.0, 6.0, 7.0]
);
}
#[test]
#[should_panic]
#[no_sanitize_realtime]
fn test_copy_from_block_exact_wrong_channels() {
let mut data = [0.0; 12];
let mut block = InterleavedViewMut::from_slice(&mut data, 3);
let view = SequentialView::from_slice(&[0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0], 2);
block.copy_from_block_exact(&view);
}
#[test]
#[should_panic]
#[no_sanitize_realtime]
fn test_copy_from_block_exact_wrong_frames() {
let mut data = [0.0; 10];
let mut block = InterleavedViewMut::from_slice(&mut data, 2);
let view = SequentialView::from_slice(&[0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0], 2);
block.copy_from_block_exact(&view);
}
#[test]
fn test_for_each() {
let mut data = [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0];
let mut block = SequentialViewMut::from_slice(&mut data, 2);
let mut count = 0;
block.for_each(|v| {
*v *= 2.0;
count += 1;
});
assert_eq!(count, 8); assert_eq!(data, [0.0, 2.0, 4.0, 6.0, 8.0, 10.0, 12.0, 14.0]);
let mut data = [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0];
let mut block = InterleavedViewMut::from_slice(&mut data, 2);
let mut seen = Vec::with_capacity(8);
block.enumerate(|c, f, v| {
seen.push((c, f, *v));
});
assert_eq!(seen.len(), 8);
let mut values: Vec<f32> = seen.iter().map(|(_, _, v)| *v).collect();
values.sort_by(|a, b| a.partial_cmp(b).unwrap());
assert_eq!(values, vec![0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0]);
for (c, _, _) in &seen {
assert!(*c == 0 || *c == 1);
}
for (_, f, _) in &seen {
assert!(*f < 4);
}
}
#[test]
fn test_for_each_allocated() {
let mut data = [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0];
let mut block = SequentialViewMut::from_slice(&mut data, 2);
block.set_visible(2, 2);
let mut count = 0;
block.for_each_allocated(|v| {
*v *= 2.0;
count += 1;
});
assert_eq!(count, 8);
assert_eq!(data, [0.0, 2.0, 4.0, 6.0, 8.0, 10.0, 12.0, 14.0]);
}
#[test]
fn test_enumerate_allocated() {
let mut data = [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0];
let mut block = SequentialViewMut::from_slice(&mut data, 2);
block.set_visible(2, 2);
let mut seen = Vec::with_capacity(8);
block.enumerate_allocated(|c, f, v| {
seen.push((c, f, *v));
*v = 0.0;
});
assert_eq!(seen.len(), 8);
assert_eq!(seen[0], (0, 0, 0.0));
assert_eq!(seen[1], (0, 1, 1.0));
assert_eq!(seen[2], (0, 2, 2.0));
assert_eq!(seen[3], (0, 3, 3.0));
assert_eq!(seen[4], (1, 0, 4.0));
assert_eq!(seen[5], (1, 1, 5.0));
assert_eq!(seen[6], (1, 2, 6.0));
assert_eq!(seen[7], (1, 3, 7.0));
assert_eq!(data, [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]);
}
#[test]
fn test_clear() {
let mut data = [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0];
let mut block = SequentialViewMut::from_slice(&mut data, 2);
block.fill_with(1.0);
assert_eq!(
block.channel_iter(0).copied().collect::<Vec<_>>(),
vec![1.0, 1.0, 1.0, 1.0]
);
assert_eq!(
block.channel_iter(1).copied().collect::<Vec<_>>(),
vec![1.0, 1.0, 1.0, 1.0]
);
block.clear();
assert_eq!(
block.channel_iter(0).copied().collect::<Vec<_>>(),
vec![0.0, 0.0, 0.0, 0.0]
);
assert_eq!(
block.channel_iter(1).copied().collect::<Vec<_>>(),
vec![0.0, 0.0, 0.0, 0.0]
);
}
#[test]
fn test_mix_to_mono() {
use crate::mono::MonoViewMut;
let data = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0];
let block = SequentialView::from_slice(&data, 2);
let mut mono_data = [0.0; 4];
let mut mono = MonoViewMut::from_slice(&mut mono_data);
block.mix_to_mono(&mut mono);
assert_eq!(mono.num_frames(), 4);
assert_eq!(
mono.samples().iter().copied().collect::<Vec<_>>(),
vec![3.0, 4.0, 5.0, 6.0] );
}
#[test]
fn test_copy_mono_to_all_channels() {
use crate::mono::MonoView;
let mono_data = [1.0, 2.0, 3.0, 4.0];
let mono = MonoView::from_slice(&mono_data);
let mut data = [0.0; 12];
let mut block = SequentialViewMut::from_slice(&mut data, 3);
block.copy_mono_to_all_channels(&mono);
assert_eq!(
block.channel_iter(0).copied().collect::<Vec<_>>(),
vec![1.0, 2.0, 3.0, 4.0]
);
assert_eq!(
block.channel_iter(1).copied().collect::<Vec<_>>(),
vec![1.0, 2.0, 3.0, 4.0]
);
assert_eq!(
block.channel_iter(2).copied().collect::<Vec<_>>(),
vec![1.0, 2.0, 3.0, 4.0]
);
}
#[test]
fn test_mix_to_mono_flexible_dest_smaller() {
use crate::mono::MonoViewMut;
let data = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0];
let block = SequentialView::from_slice(&data, 2);
let mut mono_data = [0.0; 2];
let mut mono = MonoViewMut::from_slice(&mut mono_data);
let result = block.mix_to_mono(&mut mono);
assert_eq!(result, Some(2));
assert_eq!(mono.num_frames(), 2);
assert_eq!(
mono.samples().iter().copied().collect::<Vec<_>>(),
vec![3.0, 4.0] );
}
#[test]
fn test_mix_to_mono_flexible_self_smaller() {
use crate::mono::MonoViewMut;
let data = [1.0, 2.0, 3.0, 4.0];
let block = SequentialView::from_slice(&data, 2);
let mut mono_data = [99.0; 4];
let mut mono = MonoViewMut::from_slice(&mut mono_data);
let result = block.mix_to_mono(&mut mono);
assert_eq!(result, None);
assert_eq!(mono.num_frames(), 4);
assert_eq!(
mono.samples().iter().copied().collect::<Vec<_>>(),
vec![2.0, 3.0, 99.0, 99.0] );
}
#[test]
fn test_mix_to_mono_exact() {
use crate::mono::MonoViewMut;
let data = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0];
let block = SequentialView::from_slice(&data, 2);
let mut mono_data = [0.0; 4];
let mut mono = MonoViewMut::from_slice(&mut mono_data);
block.mix_to_mono_exact(&mut mono);
assert_eq!(mono.num_frames(), 4);
assert_eq!(
mono.samples().iter().copied().collect::<Vec<_>>(),
vec![3.0, 4.0, 5.0, 6.0] );
}
#[test]
#[should_panic]
#[no_sanitize_realtime]
fn test_mix_to_mono_exact_wrong_frames() {
use crate::mono::MonoViewMut;
let data = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0];
let block = SequentialView::from_slice(&data, 2);
let mut mono_data = [0.0; 2]; let mut mono = MonoViewMut::from_slice(&mut mono_data);
block.mix_to_mono_exact(&mut mono);
}
#[test]
fn test_copy_channel_to_mono_flexible_dest_smaller() {
use crate::mono::MonoViewMut;
let data = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0];
let block = SequentialView::from_slice(&data, 2);
let mut mono_data = [0.0; 2];
let mut mono = MonoViewMut::from_slice(&mut mono_data);
let result = block.copy_channel_to_mono(&mut mono, 0);
assert_eq!(result, Some(2));
assert_eq!(mono.num_frames(), 2);
assert_eq!(
mono.samples().iter().copied().collect::<Vec<_>>(),
vec![1.0, 2.0] );
}
#[test]
fn test_copy_channel_to_mono_flexible_self_smaller() {
use crate::mono::MonoViewMut;
let data = [1.0, 2.0, 3.0, 4.0];
let block = SequentialView::from_slice(&data, 2);
let mut mono_data = [0.0; 4];
let mut mono = MonoViewMut::from_slice(&mut mono_data);
let result = block.copy_channel_to_mono(&mut mono, 1);
assert_eq!(result, None);
assert_eq!(mono.num_frames(), 4);
assert_eq!(
mono.samples().iter().copied().collect::<Vec<_>>(),
vec![3.0, 4.0, 0.0, 0.0]
);
}
#[test]
fn test_copy_channel_to_mono_exact_match_returns_none() {
use crate::mono::MonoViewMut;
let data = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0];
let block = SequentialView::from_slice(&data, 2);
let mut mono_data = [0.0; 4];
let mut mono = MonoViewMut::from_slice(&mut mono_data);
let result = block.copy_channel_to_mono(&mut mono, 0);
assert_eq!(result, None);
assert_eq!(
mono.samples().iter().copied().collect::<Vec<_>>(),
vec![1.0, 2.0, 3.0, 4.0]
);
}
#[test]
fn test_copy_channel_to_mono_exact() {
use crate::mono::MonoViewMut;
let data = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0];
let block = SequentialView::from_slice(&data, 2);
let mut mono_data = [0.0; 4];
let mut mono = MonoViewMut::from_slice(&mut mono_data);
block.copy_channel_to_mono_exact(&mut mono, 1);
assert_eq!(
mono.samples().iter().copied().collect::<Vec<_>>(),
vec![5.0, 6.0, 7.0, 8.0]
);
}
#[test]
#[should_panic]
#[no_sanitize_realtime]
fn test_copy_channel_to_mono_exact_wrong_frames() {
use crate::mono::MonoViewMut;
let data = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0];
let block = SequentialView::from_slice(&data, 2);
let mut mono_data = [0.0; 2]; let mut mono = MonoViewMut::from_slice(&mut mono_data);
block.copy_channel_to_mono_exact(&mut mono, 0);
}
#[test]
fn test_copy_mono_to_all_channels_flexible_dest_smaller() {
use crate::mono::MonoView;
let mono_data = [1.0, 2.0, 3.0, 4.0];
let mono = MonoView::from_slice(&mono_data);
let mut data = [0.0; 2]; let mut block = SequentialViewMut::from_slice(&mut data, 1);
let result = block.copy_mono_to_all_channels(&mono);
assert_eq!(result, Some(2));
assert_eq!(
block.channel_iter(0).copied().collect::<Vec<_>>(),
vec![1.0, 2.0] );
}
#[test]
fn test_copy_mono_to_all_channels_flexible_self_smaller() {
use crate::mono::MonoView;
let mono_data = [1.0, 2.0];
let mono = MonoView::from_slice(&mono_data);
let mut data = [0.0; 8]; let mut block = SequentialViewMut::from_slice(&mut data, 2);
let result = block.copy_mono_to_all_channels(&mono);
assert_eq!(result, None);
assert_eq!(
block.channel_iter(0).copied().collect::<Vec<_>>(),
vec![1.0, 2.0, 0.0, 0.0] );
assert_eq!(
block.channel_iter(1).copied().collect::<Vec<_>>(),
vec![1.0, 2.0, 0.0, 0.0] );
}
#[test]
fn test_copy_mono_to_all_channels_exact_match_returns_none() {
use crate::mono::MonoView;
let mono_data = [1.0, 2.0, 3.0, 4.0];
let mono = MonoView::from_slice(&mono_data);
let mut data = [0.0; 12]; let mut block = SequentialViewMut::from_slice(&mut data, 3);
let result = block.copy_mono_to_all_channels(&mono);
assert_eq!(result, None);
assert_eq!(
block.channel_iter(0).copied().collect::<Vec<_>>(),
vec![1.0, 2.0, 3.0, 4.0]
);
}
#[test]
fn test_copy_mono_to_all_channels_exact() {
use crate::mono::MonoView;
let mono_data = [1.0, 2.0, 3.0, 4.0];
let mono = MonoView::from_slice(&mono_data);
let mut data = [0.0; 12];
let mut block = SequentialViewMut::from_slice(&mut data, 3);
block.copy_mono_to_all_channels_exact(&mono);
assert_eq!(
block.channel_iter(0).copied().collect::<Vec<_>>(),
vec![1.0, 2.0, 3.0, 4.0]
);
assert_eq!(
block.channel_iter(1).copied().collect::<Vec<_>>(),
vec![1.0, 2.0, 3.0, 4.0]
);
assert_eq!(
block.channel_iter(2).copied().collect::<Vec<_>>(),
vec![1.0, 2.0, 3.0, 4.0]
);
}
#[test]
#[should_panic]
#[no_sanitize_realtime]
fn test_copy_mono_to_all_channels_exact_wrong_frames() {
use crate::mono::MonoView;
let mono_data = [1.0, 2.0, 3.0, 4.0, 5.0]; let mono = MonoView::from_slice(&mono_data);
let mut data = [0.0; 12]; let mut block = SequentialViewMut::from_slice(&mut data, 3);
block.copy_mono_to_all_channels_exact(&mono);
}
}