#![doc = include_str!("../README.md")]
#![cfg_attr(not(feature = "std"), no_std)]
#[cfg(feature = "alloc")]
extern crate alloc;
pub mod direct;
pub mod number_to_float;
#[cfg(feature = "alloc")]
pub mod owned;
pub mod dummy;
mod slicetools;
use core::error::Error;
use core::fmt;
pub mod adapter_to_float;
#[derive(Debug)]
pub enum SizeError {
ChannelsContainer { actual: usize, required: usize },
FramesContainer { actual: usize, required: usize },
ChannelBuffer {
index: usize,
actual: usize,
required: usize,
},
FrameBuffer {
index: usize,
actual: usize,
required: usize,
},
Total { actual: usize, required: usize },
Mask { actual: usize, required: usize },
}
impl Error for SizeError {}
impl fmt::Display for SizeError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
SizeError::ChannelsContainer { actual, required } => write!(
f,
"Channels container is too short, got: {}, required: {}",
actual, required
),
SizeError::FramesContainer { actual, required } => write!(
f,
"Frames container is too short, got: {}, required: {}",
actual, required
),
SizeError::ChannelBuffer {
index,
actual,
required,
} => write!(
f,
"Channel buffer {} is too short for requested frame count, got: {}, required: {}",
index, actual, required
),
SizeError::FrameBuffer {
index,
actual,
required,
} => write!(
f,
"Frame buffer {} is too short for requested channel count, got: {}, required: {}",
index, actual, required
),
SizeError::Total { actual, required } => write!(
f,
"Flat buffer is too short for requested dimensions, got: {}, required: {}",
actual, required
),
SizeError::Mask { actual, required } => write!(
f,
"Mask length is invalid for channel count, got: {}, required: {}",
actual, required
),
}
}
}
macro_rules! implement_size_getters {
() => {
fn channels(&self) -> usize {
self.channels
}
fn frames(&self) -> usize {
self.frames
}
};
}
pub(crate) use implement_size_getters;
macro_rules! check_slice_length {
($channels:expr , $frames:expr, $length:expr ) => {
if $length < $frames * $channels {
return Err(SizeError::Total {
actual: $length,
required: $frames * $channels,
});
}
};
($channels:expr , $frames:expr, $length:expr, $elements_per_sample:expr) => {
if $length < $frames * $channels * $elements_per_sample {
return Err(SizeError::Total {
actual: $length,
required: $frames * $channels * $elements_per_sample,
});
}
};
}
pub(crate) use check_slice_length;
#[cfg(test)]
mod tests {
use audioadapter::AdapterMut;
fn prepare_test_data(buffer: &mut dyn AdapterMut<u32>) {
for channel in 0..buffer.channels() {
for frame in 0..buffer.frames() {
let value = (100 * channel + frame) as u32;
buffer.write_sample(channel, frame, &value);
}
}
}
pub(crate) fn check_copy_within(buffer: &mut dyn AdapterMut<u32>) {
assert!(buffer.channels() > 1, "Too few channels to run tests");
assert!(buffer.frames() > 8, "Too few frames to run test");
prepare_test_data(buffer);
assert_eq!(buffer.copy_frames_within(1, 5, 3), Some(3));
check_copy_result(buffer, 1, 5, 3);
prepare_test_data(buffer);
assert_eq!(buffer.copy_frames_within(5, 1, 3), Some(3));
check_copy_result(buffer, 5, 1, 3);
prepare_test_data(buffer);
assert_eq!(buffer.copy_frames_within(1, 3, 5), Some(5));
check_copy_result(buffer, 1, 3, 5);
prepare_test_data(buffer);
assert_eq!(buffer.copy_frames_within(3, 1, 5), Some(5));
check_copy_result(buffer, 3, 1, 5);
}
fn check_copy_result(buffer: &dyn AdapterMut<u32>, src: usize, dest: usize, count: usize) {
for channel in 0..buffer.channels() {
for frame in 0..buffer.frames() {
let copied_frame = if frame >= dest && frame < dest + count {
frame + src - dest
} else {
frame
};
let expected_value = (100 * channel + copied_frame) as u32;
assert_eq!(
buffer.read_sample(channel, frame),
Some(expected_value),
"Wrong value at ch {}, frame {}",
channel,
frame
);
}
}
}
}