use audioadapter_sample::sample::{BytesSample, RawSample};
use core::ops::Range;
pub fn fill_buffers_interleaved<T: RawSample>(
output_buffer: &mut [&mut [f32]],
output_buffer_range: Range<usize>,
start_frame_in_resource: u64,
resource_channels: usize,
resource_frames: usize,
resource_samples: &[T],
) -> usize {
if output_buffer.is_empty() {
return 0;
}
let Some(frames) = valid_frames(
output_buffer_range.clone(),
start_frame_in_resource,
resource_frames,
) else {
return 0;
};
let start_frame_in_resource = start_frame_in_resource as usize;
if resource_channels == 1 {
for (buf_s, src_s) in output_buffer[0][output_buffer_range.clone()]
.iter_mut()
.zip(&resource_samples[start_frame_in_resource..start_frame_in_resource + frames])
{
*buf_s = src_s.to_scaled_float();
}
return frames;
}
if resource_channels == 2 && output_buffer.len() >= 2 {
let (buf0, buf1) = output_buffer.split_first_mut().unwrap();
let buf0 = &mut buf0[output_buffer_range.clone()];
let buf1 = &mut buf1[0][output_buffer_range.clone()];
let src_slice =
&resource_samples[start_frame_in_resource * 2..(start_frame_in_resource + frames) * 2];
for (src_chunk, (buf0_s, buf1_s)) in src_slice
.chunks_exact(2)
.zip(buf0.iter_mut().zip(buf1.iter_mut()))
{
*buf0_s = src_chunk[0].to_scaled_float();
*buf1_s = src_chunk[1].to_scaled_float();
}
return frames;
}
let src_slice = &resource_samples[start_frame_in_resource * resource_channels
..(start_frame_in_resource + frames) * resource_channels];
for (ch_i, buf_ch) in (0..resource_channels).zip(output_buffer.iter_mut()) {
for (src_chunk, buf_s) in src_slice
.chunks_exact(resource_channels)
.zip(buf_ch[output_buffer_range.clone()].iter_mut())
{
*buf_s = src_chunk[ch_i].to_scaled_float();
}
}
frames
}
pub fn fill_buffers_interleaved_bytes<T: BytesSample>(
output_buffer: &mut [&mut [f32]],
output_buffer_range: Range<usize>,
start_frame_in_resource: u64,
resource_channels: usize,
resource_frames: usize,
resource_data: &[u8],
) -> usize
where
T::NumericType: RawSample,
{
if output_buffer.is_empty() {
return 0;
}
let Some(frames) = valid_frames(
output_buffer_range.clone(),
start_frame_in_resource,
resource_frames,
) else {
return 0;
};
let start_frame_in_resource = start_frame_in_resource as usize;
if resource_channels == 1 {
for (buf_s, src_s) in output_buffer[0][output_buffer_range.clone()]
.iter_mut()
.zip(
resource_data[start_frame_in_resource * T::BYTES_PER_SAMPLE
..(start_frame_in_resource + frames) * T::BYTES_PER_SAMPLE]
.chunks_exact(T::BYTES_PER_SAMPLE),
)
{
*buf_s = T::from_slice(src_s).to_number().to_scaled_float();
}
return frames;
}
if resource_channels == 2 && output_buffer.len() >= 2 {
let (buf0, buf1) = output_buffer.split_first_mut().unwrap();
let buf0 = &mut buf0[output_buffer_range.clone()];
let buf1 = &mut buf1[0][output_buffer_range.clone()];
let src_slice = &resource_data[start_frame_in_resource * 2 * T::BYTES_PER_SAMPLE
..(start_frame_in_resource + frames) * 2 * T::BYTES_PER_SAMPLE];
for (src_chunk, (buf0_s, buf1_s)) in src_slice
.chunks_exact(2 * T::BYTES_PER_SAMPLE)
.zip(buf0.iter_mut().zip(buf1.iter_mut()))
{
*buf0_s = T::from_slice(&src_chunk[0..T::BYTES_PER_SAMPLE])
.to_number()
.to_scaled_float();
*buf1_s = T::from_slice(&src_chunk[T::BYTES_PER_SAMPLE..2 * T::BYTES_PER_SAMPLE])
.to_number()
.to_scaled_float();
}
return frames;
}
let src_slice = &resource_data[start_frame_in_resource * resource_channels * T::BYTES_PER_SAMPLE
..(start_frame_in_resource + frames) * resource_channels * T::BYTES_PER_SAMPLE];
for (ch_i, buf_ch) in (0..resource_channels).zip(output_buffer.iter_mut()) {
for (src_chunk, buf_s) in src_slice
.chunks_exact(resource_channels * T::BYTES_PER_SAMPLE)
.zip(buf_ch[output_buffer_range.clone()].iter_mut())
{
*buf_s = T::from_slice(
&src_chunk[ch_i * T::BYTES_PER_SAMPLE..(ch_i + 1) * T::BYTES_PER_SAMPLE],
)
.to_number()
.to_scaled_float();
}
}
frames
}
pub fn fill_buffers_deinterleaved<T: RawSample, V: AsRef<[T]>>(
output_buffer: &mut [&mut [f32]],
output_buffer_range: Range<usize>,
start_frame_in_resource: u64,
resource_frames: usize,
resource_channels: &[V],
) -> usize {
if output_buffer.is_empty() {
return 0;
}
let Some(frames) = valid_frames(
output_buffer_range.clone(),
start_frame_in_resource,
resource_frames,
) else {
return 0;
};
let start_frame_in_resource = start_frame_in_resource as usize;
for (buf, ch) in output_buffer.iter_mut().zip(resource_channels.iter()) {
for (buf_s, ch_s) in buf[output_buffer_range.clone()]
.iter_mut()
.zip(ch.as_ref()[start_frame_in_resource..start_frame_in_resource + frames].iter())
{
*buf_s = ch_s.to_scaled_float();
}
}
frames
}
pub fn fill_buffers_deinterleaved_bytes<T: BytesSample, V: AsRef<[u8]>>(
output_buffer: &mut [&mut [f32]],
output_buffer_range: Range<usize>,
start_frame_in_resource: u64,
resource_frames: usize,
resource_channels: &[V],
) -> usize
where
T::NumericType: RawSample,
{
if output_buffer.is_empty() {
return 0;
}
let Some(frames) = valid_frames(
output_buffer_range.clone(),
start_frame_in_resource,
resource_frames,
) else {
return 0;
};
let start_frame_in_resource = start_frame_in_resource as usize;
for (buf, ch) in output_buffer.iter_mut().zip(resource_channels.iter()) {
for (buf_s, ch_s) in buf[output_buffer_range.clone()].iter_mut().zip(
ch.as_ref()[start_frame_in_resource * T::BYTES_PER_SAMPLE
..(start_frame_in_resource + frames) * T::BYTES_PER_SAMPLE]
.chunks_exact(T::BYTES_PER_SAMPLE),
) {
*buf_s = T::from_slice(ch_s).to_number().to_scaled_float();
}
}
frames
}
pub fn fill_buffers_deinterleaved_f32<V: AsRef<[f32]>>(
output_buffer: &mut [&mut [f32]],
output_buffer_range: Range<usize>,
start_frame_in_resource: u64,
resource_frames: usize,
resource_channels: &[V],
) -> usize {
if output_buffer.is_empty() {
return 0;
}
let Some(frames) = valid_frames(
output_buffer_range.clone(),
start_frame_in_resource,
resource_frames,
) else {
return 0;
};
let start_frame_in_resource = start_frame_in_resource as usize;
for (buf, ch) in output_buffer.iter_mut().zip(resource_channels.iter()) {
buf[output_buffer_range.clone()].copy_from_slice(
&ch.as_ref()[start_frame_in_resource..start_frame_in_resource + frames],
);
}
frames
}
fn valid_frames(
output_buffer_range: Range<usize>,
start_frame_in_resource: u64,
resource_frames: usize,
) -> Option<usize> {
let frames = ((output_buffer_range.end - output_buffer_range.start) as u64)
.min((resource_frames as u64).saturating_sub(start_frame_in_resource))
as usize;
if frames == 0 { None } else { Some(frames) }
}