use core::mem;
use core::ptr;
use audio_core::{
Buf, BufMut, ExactSizeBuf, InterleavedBuf, InterleavedBufMut, ReadBuf, ResizableBuf,
UniformBuf, WriteBuf,
};
use crate::buf::interleaved::{IterChannels, IterChannelsMut};
use crate::channel::{InterleavedChannel, InterleavedChannelMut};
use crate::frame::{InterleavedFrame, InterleavedFramesIter, RawInterleaved};
use crate::slice::{Slice, SliceIndex, SliceMut};
pub struct Interleaved<T> {
value: T,
channels: usize,
frames: usize,
}
impl<T> Interleaved<T>
where
T: Slice,
{
pub(super) fn new(value: T, channels: usize) -> Self {
assert!(
channels != 0 && value.as_ref().len() % channels == 0,
"slice provided {} doesn't match channel configuration {}",
value.as_ref().len(),
channels,
);
let frames = value.as_ref().len() / channels;
Self {
value,
channels,
frames,
}
}
#[inline]
pub fn into_inner(self) -> T {
self.value
}
#[inline]
pub fn iter(&self) -> IterChannels<'_, T::Item> {
unsafe { IterChannels::new_unchecked(self.value.as_ptr(), self.value.len(), self.channels) }
}
#[inline]
fn as_raw(&self) -> RawInterleaved<T::Item>
where
T: Slice,
{
unsafe { RawInterleaved::new(self.value.as_ref(), self.channels, self.frames) }
}
}
impl<T> Interleaved<T>
where
T: SliceMut,
{
#[inline]
pub fn iter_mut(&mut self) -> IterChannelsMut<'_, T::Item> {
unsafe {
IterChannelsMut::new_unchecked(self.value.as_mut_ptr(), self.value.len(), self.channels)
}
}
}
impl<T> Buf for Interleaved<T>
where
T: Slice,
{
type Sample = T::Item;
type Channel<'this> = InterleavedChannel<'this, Self::Sample>
where
Self: 'this;
type IterChannels<'this> = IterChannels<'this, Self::Sample>
where
Self: 'this;
#[inline]
fn frames_hint(&self) -> Option<usize> {
Some(self.frames)
}
#[inline]
fn channels(&self) -> usize {
self.channels
}
#[inline]
fn get_channel(&self, channel: usize) -> Option<Self::Channel<'_>> {
InterleavedChannel::from_slice(self.value.as_ref(), channel, self.channels)
}
#[inline]
fn iter_channels(&self) -> Self::IterChannels<'_> {
(*self).iter()
}
}
impl<T> UniformBuf for Interleaved<T>
where
T: Slice,
{
type Frame<'this> = InterleavedFrame<'this, T::Item>
where
Self: 'this;
type IterFrames<'this> = InterleavedFramesIter<'this, T::Item>
where
Self: 'this;
#[inline]
fn get_frame(&self, frame: usize) -> Option<Self::Frame<'_>> {
if frame >= self.frames {
return None;
}
Some(InterleavedFrame::new(frame, self.as_raw()))
}
#[inline]
fn iter_frames(&self) -> Self::IterFrames<'_> {
InterleavedFramesIter::new(0, self.as_raw())
}
}
impl<T> ExactSizeBuf for Interleaved<T>
where
T: Slice,
{
fn frames(&self) -> usize {
self.frames
}
}
impl<T> InterleavedBuf for Interleaved<T>
where
T: Slice,
{
type Sample = T::Item;
#[inline]
fn as_interleaved(&self) -> &[Self::Sample] {
self.value.as_ref()
}
}
impl<T> InterleavedBufMut for Interleaved<T>
where
T: SliceMut,
{
#[inline]
fn as_interleaved_mut(&mut self) -> &mut [Self::Sample] {
self.value.as_mut()
}
#[inline]
fn as_interleaved_mut_ptr(&mut self) -> ptr::NonNull<Self::Sample> {
self.value.as_mut_ptr()
}
#[inline]
unsafe fn set_interleaved_topology(&mut self, channels: usize, frames: usize) {
self.channels = channels;
self.frames = frames;
}
}
impl<T> BufMut for Interleaved<T>
where
T: SliceMut,
{
type ChannelMut<'this> = InterleavedChannelMut<'this, T::Item>
where
Self: 'this;
type IterChannelsMut<'this> = IterChannelsMut<'this, Self::Sample>
where
Self: 'this;
#[inline]
fn get_channel_mut(&mut self, channel: usize) -> Option<Self::ChannelMut<'_>> {
InterleavedChannelMut::from_slice(self.value.as_mut(), channel, self.channels)
}
#[inline]
fn copy_channel(&mut self, from: usize, to: usize) {
unsafe {
crate::utils::copy_channels_interleaved(
self.value.as_mut_ptr(),
self.channels,
self.frames,
from,
to,
);
}
}
#[inline]
fn iter_channels_mut(&mut self) -> Self::IterChannelsMut<'_> {
(*self).iter_mut()
}
}
impl<T> ReadBuf for Interleaved<T>
where
T: Default + SliceIndex,
{
#[inline]
fn remaining(&self) -> usize {
self.frames
}
fn advance(&mut self, n: usize) {
self.frames = self.frames.saturating_sub(n);
let value = mem::take(&mut self.value);
self.value = value.index_from(n.saturating_mul(self.channels));
}
}
impl<T> WriteBuf for Interleaved<&'_ mut [T]>
where
T: Copy,
{
#[inline]
fn remaining_mut(&self) -> usize {
self.frames
}
fn advance_mut(&mut self, n: usize) {
self.frames = self.frames.saturating_sub(n);
let value = mem::take(&mut self.value);
self.value = value
.get_mut(n.saturating_mul(self.channels)..)
.unwrap_or_default();
}
}
impl<T> ResizableBuf for Interleaved<&'_ mut [T]>
where
T: Copy,
{
#[inline]
fn try_reserve(&mut self, capacity: usize) -> bool {
capacity <= self.value.len()
}
fn resize_frames(&mut self, frames: usize) {
if frames > self.value.len() {
panic!(
"required number of frames {new_len} is larger than the wrapped buffer {len}",
new_len = frames,
len = self.value.len()
);
}
}
fn resize_topology(&mut self, channels: usize, frames: usize) {
let new_len = channels * frames;
let len = self.value.len();
let value = mem::take(&mut self.value);
let value = match value.get_mut(..new_len) {
Some(value) => value,
None => {
panic!(
"the topology {channels}:{frames} requires {new_len}, which is larger than the wrapped buffer {len}",
channels = channels,
frames = frames,
new_len = new_len,
len = len,
);
}
};
self.value = value;
self.channels = channels;
self.frames = frames;
}
}