use core::mem::size_of;
use num_traits::Float;
use crate::slicetools::copy_within_slice;
use crate::SizeError;
use crate::{check_slice_length, implement_size_getters};
use audioadapter::{Adapter, AdapterMut};
use audioadapter_sample::sample::RawSample;
#[macro_export]
macro_rules! byte_slice_as_type {
($slice:ident, $type:ty) => {
unsafe {
let ptr = $slice.as_ptr() as *const $type;
let len = $slice.len();
core::slice::from_raw_parts(ptr, len / core::mem::size_of::<$type>())
}
};
}
#[macro_export]
macro_rules! byte_slice_as_type_mut {
($slice:ident, $type:ty) => {
unsafe {
let ptr = $slice.as_mut_ptr() as *mut $type;
let len = $slice.len();
core::slice::from_raw_parts_mut(ptr, len / core::mem::size_of::<$type>())
}
};
}
pub struct InterleavedNumbers<U, V> {
_phantom: core::marker::PhantomData<V>,
buf: U,
frames: usize,
channels: usize,
}
pub struct SequentialNumbers<U, V> {
_phantom: core::marker::PhantomData<V>,
buf: U,
frames: usize,
channels: usize,
}
impl<U, V> InterleavedNumbers<U, V> {
fn calc_index(&self, channel: usize, frame: usize) -> usize {
frame * self.channels + channel
}
}
impl<U, V> SequentialNumbers<U, V> {
fn calc_index(&self, channel: usize, frame: usize) -> usize {
frame + channel * self.frames
}
}
impl<'a, U, T> InterleavedNumbers<&'a [U], T>
where
T: 'a,
{
pub fn new(buf: &'a [U], channels: usize, frames: usize) -> Result<Self, SizeError> {
check_slice_length!(channels, frames, buf.len());
Ok(Self {
_phantom: core::marker::PhantomData,
buf,
frames,
channels,
})
}
pub fn new_from_bytes(
buf: &'a [u8],
channels: usize,
frames: usize,
) -> Result<Self, SizeError> {
check_slice_length!(channels, frames, buf.len(), size_of::<U>());
let buf_view = byte_slice_as_type!(buf, U);
Ok(Self {
_phantom: core::marker::PhantomData,
buf: buf_view,
frames,
channels,
})
}
}
impl<'a, U, T> InterleavedNumbers<&'a mut [U], T>
where
T: 'a,
U: Clone,
{
pub fn new_mut(buf: &'a mut [U], channels: usize, frames: usize) -> Result<Self, SizeError> {
check_slice_length!(channels, frames, buf.len());
Ok(Self {
_phantom: core::marker::PhantomData,
buf,
frames,
channels,
})
}
pub fn new_from_bytes_mut(
buf: &'a mut [u8],
channels: usize,
frames: usize,
) -> Result<Self, SizeError> {
check_slice_length!(channels, frames, buf.len(), size_of::<U>());
let buf_view = byte_slice_as_type_mut!(buf, U);
Ok(Self {
_phantom: core::marker::PhantomData,
buf: buf_view,
frames,
channels,
})
}
fn copy_frames_within_impl(&mut self, src: usize, dest: usize, count: usize) -> Option<usize> {
if src + count > self.frames || dest + count > self.frames {
return None;
}
unsafe {
copy_within_slice(
self.buf,
src * self.channels,
dest * self.channels,
count * self.channels,
);
}
Some(count)
}
}
impl<'a, U, T> SequentialNumbers<&'a [U], T>
where
T: 'a,
{
pub fn new(buf: &'a [U], channels: usize, frames: usize) -> Result<Self, SizeError> {
check_slice_length!(channels, frames, buf.len());
Ok(Self {
_phantom: core::marker::PhantomData,
buf,
frames,
channels,
})
}
pub fn new_from_bytes(
buf: &'a [u8],
channels: usize,
frames: usize,
) -> Result<Self, SizeError> {
check_slice_length!(channels, frames, buf.len(), size_of::<U>());
let buf_view = byte_slice_as_type!(buf, U);
Ok(Self {
_phantom: core::marker::PhantomData,
buf: buf_view,
frames,
channels,
})
}
}
impl<'a, U, T> SequentialNumbers<&'a mut [U], T>
where
T: 'a,
U: Clone,
{
pub fn new_mut(buf: &'a mut [U], channels: usize, frames: usize) -> Result<Self, SizeError> {
check_slice_length!(channels, frames, buf.len());
Ok(Self {
_phantom: core::marker::PhantomData,
buf,
frames,
channels,
})
}
pub fn new_from_bytes_mut(
buf: &'a mut [u8],
channels: usize,
frames: usize,
) -> Result<Self, SizeError> {
check_slice_length!(channels, frames, buf.len(), size_of::<U>());
let buf_view = byte_slice_as_type_mut!(buf, U);
Ok(Self {
_phantom: core::marker::PhantomData,
buf: buf_view,
frames,
channels,
})
}
fn copy_frames_within_impl(&mut self, src: usize, dest: usize, count: usize) -> Option<usize> {
if src + count > self.frames || dest + count > self.frames {
return None;
}
for ch in 0..self.channels {
let offset = ch * self.frames;
unsafe {
copy_within_slice(self.buf, src + offset, dest + offset, count);
}
}
Some(count)
}
}
macro_rules! impl_traits_newtype {
($structname:ident) => {
impl<'a, T, U> Adapter<'a, T> for $structname<&'a [U], T>
where
T: Float + 'a,
U: RawSample,
{
unsafe fn read_sample_unchecked(&self, channel: usize, frame: usize) -> T {
let index = self.calc_index(channel, frame);
self.buf[index].to_scaled_float()
}
implement_size_getters!();
}
impl<'a, T, U> Adapter<'a, T> for $structname<&'a mut [U], T>
where
T: Float + 'a,
U: RawSample,
{
unsafe fn read_sample_unchecked(&self, channel: usize, frame: usize) -> T {
let index = self.calc_index(channel, frame);
self.buf[index].to_scaled_float()
}
implement_size_getters!();
}
impl<'a, T, U> AdapterMut<'a, T> for $structname<&'a mut [U], T>
where
T: Float + 'a,
U: RawSample + Clone,
{
unsafe fn write_sample_unchecked(
&mut self,
channel: usize,
frame: usize,
value: &T,
) -> bool {
let index = self.calc_index(channel, frame);
let converted = U::from_scaled_float(*value);
self.buf[index] = converted.value;
converted.clipped
}
fn copy_frames_within(
&mut self,
src: usize,
dest: usize,
count: usize,
) -> Option<usize> {
self.copy_frames_within_impl(src, dest, count)
}
fn copy_sample_within(
&mut self,
source_channel: usize,
source_frame: usize,
target_channel: usize,
target_frame: usize,
) -> bool {
if source_channel >= self.channels
|| source_frame >= self.frames
|| target_channel >= self.channels
|| target_frame >= self.frames
{
return false;
}
let source_index = self.calc_index(source_channel, source_frame);
let target_index = self.calc_index(target_channel, target_frame);
self.buf[target_index] = self.buf[source_index].clone();
true
}
fn swap_samples(
&mut self,
channel_a: usize,
frame_a: usize,
channel_b: usize,
frame_b: usize,
) -> bool {
if channel_a >= self.channels
|| frame_a >= self.frames
|| channel_b >= self.channels
|| frame_b >= self.frames
{
return false;
}
let index_a = self.calc_index(channel_a, frame_a);
let index_b = self.calc_index(channel_b, frame_b);
self.buf.swap(index_a, index_b);
true
}
}
};
}
impl_traits_newtype!(InterleavedNumbers);
impl_traits_newtype!(SequentialNumbers);
#[cfg(test)]
mod tests {
use super::*;
use audioadapter_sample::sample::{I16_LE, I24_LE};
#[test]
fn read_i32() {
let data: [i32; 6] = [0, -2 << 30, 2 << 29, -2 << 29, 2 << 28, -2 << 28];
let buffer = InterleavedNumbers::<_, f32>::new(&data, 2, 3).unwrap();
assert_eq!(buffer.read_sample(0, 0).unwrap(), 0.0);
assert_eq!(buffer.read_sample(1, 0).unwrap(), -1.0);
assert_eq!(buffer.read_sample(0, 1).unwrap(), 0.5);
assert_eq!(buffer.read_sample(1, 1).unwrap(), -0.5);
assert_eq!(buffer.read_sample(0, 2).unwrap(), 0.25);
assert_eq!(buffer.read_sample(1, 2).unwrap(), -0.25);
}
#[test]
fn read_i16() {
let data: [i16; 6] = [0, -2 << 14, 2 << 13, -2 << 13, 2 << 12, -2 << 12];
let buffer = InterleavedNumbers::<_, f32>::new(&data, 2, 3).unwrap();
assert_eq!(buffer.read_sample(0, 0).unwrap(), 0.0);
assert_eq!(buffer.read_sample(1, 0).unwrap(), -1.0);
assert_eq!(buffer.read_sample(0, 1).unwrap(), 0.5);
assert_eq!(buffer.read_sample(1, 1).unwrap(), -0.5);
assert_eq!(buffer.read_sample(0, 2).unwrap(), 0.25);
assert_eq!(buffer.read_sample(1, 2).unwrap(), -0.25);
}
#[test]
fn read_i8() {
let data: [i8; 6] = [0, -2 << 6, 2 << 5, -2 << 5, 2 << 4, -2 << 4];
let buffer = InterleavedNumbers::<_, f32>::new(&data, 2, 3).unwrap();
assert_eq!(buffer.read_sample(0, 0).unwrap(), 0.0);
assert_eq!(buffer.read_sample(1, 0).unwrap(), -1.0);
assert_eq!(buffer.read_sample(0, 1).unwrap(), 0.5);
assert_eq!(buffer.read_sample(1, 1).unwrap(), -0.5);
assert_eq!(buffer.read_sample(0, 2).unwrap(), 0.25);
assert_eq!(buffer.read_sample(1, 2).unwrap(), -0.25);
}
#[test]
fn read_u8() {
let data: [u8; 6] = [
128,
128 - (2 << 6),
128 + (2 << 5),
128 - (2 << 5),
128 + (2 << 4),
128 - (2 << 4),
];
let buffer = InterleavedNumbers::<_, f32>::new(&data, 2, 3).unwrap();
assert_eq!(buffer.read_sample(0, 0).unwrap(), 0.0);
assert_eq!(buffer.read_sample(1, 0).unwrap(), -1.0);
assert_eq!(buffer.read_sample(0, 1).unwrap(), 0.5);
assert_eq!(buffer.read_sample(1, 1).unwrap(), -0.5);
assert_eq!(buffer.read_sample(0, 2).unwrap(), 0.25);
assert_eq!(buffer.read_sample(1, 2).unwrap(), -0.25);
}
#[test]
fn write_i32() {
let expected: [i32; 6] = [0, -2 << 30, 2 << 29, -2 << 29, 2 << 28, -2 << 28];
let mut data = [0; 6];
let mut buffer = InterleavedNumbers::<_, f32>::new_mut(&mut data, 2, 3).unwrap();
buffer.write_sample(0, 0, &0.0).unwrap();
buffer.write_sample(1, 0, &-1.0).unwrap();
buffer.write_sample(0, 1, &0.5).unwrap();
buffer.write_sample(1, 1, &-0.5).unwrap();
buffer.write_sample(0, 2, &0.25).unwrap();
buffer.write_sample(1, 2, &-0.25).unwrap();
assert_eq!(data, expected);
}
#[test]
fn write_i16() {
let expected: [i16; 6] = [0, -2 << 14, 2 << 13, -2 << 13, 2 << 12, -2 << 12];
let mut data = [0; 6];
let mut buffer = InterleavedNumbers::<_, f32>::new_mut(&mut data, 2, 3).unwrap();
buffer.write_sample(0, 0, &0.0).unwrap();
buffer.write_sample(1, 0, &-1.0).unwrap();
buffer.write_sample(0, 1, &0.5).unwrap();
buffer.write_sample(1, 1, &-0.5).unwrap();
buffer.write_sample(0, 2, &0.25).unwrap();
buffer.write_sample(1, 2, &-0.25).unwrap();
assert_eq!(data, expected);
}
#[test]
fn from_slice_i32() {
let expected_data: [i32; 6] = [0, -2 << 30, 2 << 29, -2 << 29, 2 << 28, -2 << 28];
let values_left = [0.0, 0.5, 0.25];
let values_right = [-1.0, -0.5, -0.25];
let mut data = [0; 6];
let mut buffer = InterleavedNumbers::<_, f32>::new_mut(&mut data, 2, 3).unwrap();
buffer.copy_from_slice_to_channel(0, 0, &values_left);
buffer.copy_from_slice_to_channel(1, 0, &values_right);
assert_eq!(data, expected_data);
}
#[test]
fn to_slice_i32() {
let data: [i32; 6] = [0, -2 << 30, 2 << 29, -2 << 29, 2 << 28, -2 << 28];
let expected_left = [0.0, 0.5, 0.25];
let expected_right = [-1.0, -0.5, -0.25];
let mut values_left = [0.0; 3];
let mut values_right = [0.0; 3];
let buffer: InterleavedNumbers<_, f32> = InterleavedNumbers::new(&data, 2, 3).unwrap();
buffer.copy_from_channel_to_slice(0, 0, &mut values_left);
buffer.copy_from_channel_to_slice(1, 0, &mut values_right);
assert_eq!(values_left, expected_left);
assert_eq!(values_right, expected_right);
}
#[allow(dead_code)]
fn test_adapter_send_and_sync<T: Sync + Send + Clone>() {
fn is_send<T: Send>() {}
fn is_sync<T: Sync>() {}
is_send::<InterleavedNumbers<&[i32], f32>>();
is_sync::<InterleavedNumbers<&[i32], f32>>();
}
#[test]
fn read_i16_bytes_interleaved() {
let data: [u8; 12] = [0, 0, 0, 128, 0, 64, 0, 192, 0, 32, 0, 224];
let buffer = InterleavedNumbers::<&[I16_LE], f32>::new_from_bytes(&data, 2, 3).unwrap();
assert_eq!(buffer.read_sample(0, 0).unwrap(), 0.0);
assert_eq!(buffer.read_sample(1, 0).unwrap(), -1.0);
assert_eq!(buffer.read_sample(0, 1).unwrap(), 0.5);
assert_eq!(buffer.read_sample(1, 1).unwrap(), -0.5);
assert_eq!(buffer.read_sample(0, 2).unwrap(), 0.25);
assert_eq!(buffer.read_sample(1, 2).unwrap(), -0.25);
}
#[test]
fn write_i16_bytes_interleaved() {
let expected: [u8; 12] = [0, 0, 0, 128, 0, 64, 0, 192, 0, 32, 0, 224];
let mut data = [0; 12];
let mut buffer =
InterleavedNumbers::<&mut [I16_LE], f32>::new_from_bytes_mut(&mut data, 2, 3).unwrap();
buffer.write_sample(0, 0, &0.0).unwrap();
buffer.write_sample(1, 0, &-1.0).unwrap();
buffer.write_sample(0, 1, &0.5).unwrap();
buffer.write_sample(1, 1, &-0.5).unwrap();
buffer.write_sample(0, 2, &0.25).unwrap();
buffer.write_sample(1, 2, &-0.25).unwrap();
assert_eq!(data, expected);
}
#[test]
fn read_i24_bytes_interleaved() {
let data: [u8; 18] = [0, 0, 0, 0, 0, 128, 0, 0, 64, 0, 0, 192, 0, 0, 32, 0, 0, 224];
let buffer = InterleavedNumbers::<&[I24_LE], f32>::new_from_bytes(&data, 2, 3).unwrap();
assert_eq!(buffer.read_sample(0, 0).unwrap(), 0.0);
assert_eq!(buffer.read_sample(1, 0).unwrap(), -1.0);
assert_eq!(buffer.read_sample(0, 1).unwrap(), 0.5);
assert_eq!(buffer.read_sample(1, 1).unwrap(), -0.5);
assert_eq!(buffer.read_sample(0, 2).unwrap(), 0.25);
assert_eq!(buffer.read_sample(1, 2).unwrap(), -0.25);
}
}