use std::cmp;
use std::fmt;
use std::hash;
use std::ptr;
use audio_core::{
Buf, BufMut, ExactSizeBuf, InterleavedBuf, InterleavedBufMut, ResizableBuf, Sample, UniformBuf,
};
use crate::buf::interleaved::{IterChannels, IterChannelsMut};
use crate::channel::{InterleavedChannel, InterleavedChannelMut};
use crate::frame::{InterleavedFrame, InterleavedFramesIter, RawInterleaved};
#[derive(Default)]
pub struct Interleaved<T> {
data: Vec<T>,
channels: usize,
frames: usize,
}
impl<T> Interleaved<T> {
pub fn new() -> Self {
Self {
data: Vec::new(),
channels: 0,
frames: 0,
}
}
pub fn with_topology(channels: usize, frames: usize) -> Self
where
T: Sample,
{
Self {
data: vec![T::ZERO; channels * frames],
channels,
frames,
}
}
pub fn from_vec(data: Vec<T>, channels: usize, frames: usize) -> Self {
Self {
data,
channels,
frames,
}
}
pub fn from_frames<const N: usize>(frames: [T; N], channels: usize) -> Self
where
T: Copy,
{
return Self {
data: data_from_frames(frames, channels),
channels,
frames: N,
};
fn data_from_frames<T, const N: usize>(frames: [T; N], channels: usize) -> Vec<T>
where
T: Copy,
{
let mut data = Vec::with_capacity(N * channels);
for f in frames {
for _ in 0..channels {
data.push(f);
}
}
data
}
}
pub fn from_array<const F: usize, const C: usize>(channels: [[T; F]; C]) -> Self
where
T: Copy,
{
return Self {
data: data_from_array(channels),
channels: C,
frames: F,
};
#[inline]
fn data_from_array<T, const F: usize, const C: usize>(channels: [[T; F]; C]) -> Vec<T> {
let mut data = Vec::with_capacity(C * F);
let mut vecs: Vec<_> = IntoIterator::into_iter(channels)
.map(IntoIterator::into_iter)
.collect();
for _ in 0..F {
for v in vecs.iter_mut() {
data.extend(v.next());
}
}
data
}
}
pub fn into_vec(self) -> Vec<T> {
self.data
}
pub fn as_slice(&self) -> &[T] {
&self.data
}
pub fn as_slice_mut(&mut self) -> &mut [T] {
&mut self.data
}
pub fn capacity(&self) -> usize {
self.data.capacity()
}
pub fn frames(&self) -> usize {
self.frames
}
pub fn channels(&self) -> usize {
self.channels
}
pub fn resize_channels(&mut self, channels: usize)
where
T: Sample,
{
self.inner_resize(channels, self.frames);
}
pub fn resize_frames(&mut self, frames: usize)
where
T: Sample,
{
self.inner_resize(self.channels, frames);
}
pub fn get_channel(&self, channel: usize) -> Option<InterleavedChannel<'_, T>> {
if channel < self.channels {
unsafe {
let ptr = ptr::NonNull::new_unchecked(self.data.as_ptr() as *mut _);
let len = self.data.len();
Some(InterleavedChannel::new_unchecked(
ptr,
len,
channel,
self.channels,
))
}
} else {
None
}
}
pub fn sample(&self, channel: usize, frame: usize) -> Option<T>
where
T: Copy,
{
self.get_channel(channel)?.get(frame)
}
pub fn get_mut(&mut self, channel: usize) -> Option<InterleavedChannelMut<'_, T>> {
if channel < self.channels {
unsafe {
let ptr = ptr::NonNull::new_unchecked(self.data.as_mut_ptr());
let len = self.data.len();
Some(InterleavedChannelMut::new_unchecked(
ptr,
len,
channel,
self.channels,
))
}
} else {
None
}
}
#[inline]
pub fn sample_mut(&mut self, channel: usize, frame: usize) -> Option<&mut T> {
self.get_mut(channel)?.into_mut(frame)
}
#[inline]
fn as_raw(&self) -> RawInterleaved<T> {
unsafe { RawInterleaved::new(&self.data, self.channels, self.frames) }
}
fn inner_resize(&mut self, channels: usize, frames: usize)
where
T: Sample,
{
if self.channels == channels && self.frames == frames {
return;
}
self.inner_reserve_cap(frames.saturating_mul(channels));
if self.channels != channels {
let len = usize::min(self.channels, channels);
unsafe {
if channels < self.channels {
self.inner_shuffle_channels(1..frames, len, channels);
} else {
self.inner_shuffle_channels((1..frames).rev(), len, channels);
}
}
}
self.channels = channels;
self.frames = frames;
}
fn inner_reserve_cap(&mut self, new_cap: usize)
where
T: Sample,
{
let old_cap = self.data.capacity();
if new_cap > old_cap {
self.data.reserve(new_cap - self.data.len());
let new_cap = self.data.capacity();
unsafe {
ptr::write_bytes(self.data.as_mut_ptr().add(old_cap), 0, new_cap - old_cap);
}
}
unsafe {
self.data.set_len(new_cap);
}
}
#[inline]
unsafe fn inner_shuffle_channels<F>(&mut self, frames: F, len: usize, channels: usize)
where
F: IntoIterator<Item = usize>,
{
let base = self.data.as_mut_ptr();
for f in frames {
let from = f * self.channels;
let to = f * channels;
ptr::copy(base.add(from), base.add(to), len)
}
}
}
impl<T> Interleaved<T>
where
T: Copy,
{
pub fn iter_channels(&self) -> IterChannels<'_, T> {
unsafe {
IterChannels::new_unchecked(
ptr::NonNull::new_unchecked(self.data.as_ptr() as *mut _),
self.data.len(),
self.channels,
)
}
}
pub fn iter_channels_mut(&mut self) -> IterChannelsMut<'_, T> {
unsafe {
IterChannelsMut::new_unchecked(
ptr::NonNull::new_unchecked(self.data.as_mut_ptr()),
self.data.len(),
self.channels,
)
}
}
}
impl<T> fmt::Debug for Interleaved<T>
where
T: Copy + fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_list().entries(self.iter_channels()).finish()
}
}
impl<T> cmp::PartialEq for Interleaved<T>
where
T: Copy + cmp::PartialEq,
{
fn eq(&self, other: &Self) -> bool {
self.iter_channels().eq(other.iter_channels())
}
}
impl<T> cmp::Eq for Interleaved<T> where T: Copy + cmp::Eq {}
impl<T> cmp::PartialOrd for Interleaved<T>
where
T: Copy + cmp::PartialOrd,
{
fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
self.iter_channels().partial_cmp(other.iter_channels())
}
}
impl<T> cmp::Ord for Interleaved<T>
where
T: Copy + cmp::Ord,
{
fn cmp(&self, other: &Self) -> cmp::Ordering {
self.iter_channels().cmp(other.iter_channels())
}
}
impl<T> hash::Hash for Interleaved<T>
where
T: Copy + hash::Hash,
{
fn hash<H: hash::Hasher>(&self, state: &mut H) {
for channel in self.iter_channels() {
for f in channel.iter() {
f.hash(state);
}
}
}
}
impl<T> ExactSizeBuf for Interleaved<T>
where
T: Copy,
{
#[inline]
fn frames(&self) -> usize {
(*self).frames()
}
}
impl<T> Buf for Interleaved<T>
where
T: Copy,
{
type Sample = T;
type Channel<'this>
= InterleavedChannel<'this, Self::Sample>
where
Self::Sample: 'this;
type IterChannels<'this>
= IterChannels<'this, Self::Sample>
where
Self::Sample: '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.data, channel, self.channels)
}
#[inline]
fn iter_channels(&self) -> Self::IterChannels<'_> {
(*self).iter_channels()
}
}
impl<T> UniformBuf for Interleaved<T>
where
T: Copy,
{
type Frame<'this>
= InterleavedFrame<'this, T>
where
Self: 'this;
type IterFrames<'this>
= InterleavedFramesIter<'this, T>
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> ResizableBuf for Interleaved<T>
where
T: Sample,
{
#[inline]
fn try_reserve(&mut self, capacity: usize) -> bool {
self.inner_reserve_cap(capacity);
true
}
#[inline]
fn resize_frames(&mut self, frames: usize) {
(*self).resize_frames(frames);
}
#[inline]
fn resize_topology(&mut self, channels: usize, frames: usize) {
self.inner_resize(channels, frames);
}
}
impl<T> BufMut for Interleaved<T>
where
T: Copy,
{
type ChannelMut<'this>
= InterleavedChannelMut<'this, Self::Sample>
where
Self::Sample: 'this;
type IterChannelsMut<'this>
= IterChannelsMut<'this, Self::Sample>
where
Self::Sample: 'this;
#[inline]
fn get_channel_mut(&mut self, channel: usize) -> Option<Self::ChannelMut<'_>> {
InterleavedChannelMut::from_slice(&mut self.data, channel, self.channels)
}
fn copy_channel(&mut self, from: usize, to: usize) {
unsafe {
crate::utils::copy_channels_interleaved(
ptr::NonNull::new_unchecked(self.data.as_mut_ptr()),
self.channels,
self.frames,
from,
to,
)
}
}
#[inline]
fn iter_channels_mut(&mut self) -> Self::IterChannelsMut<'_> {
(*self).iter_channels_mut()
}
#[inline]
fn fill(&mut self, value: T)
where
T: Copy,
{
self.data.fill(value);
}
}
impl<'a, T> IntoIterator for &'a Interleaved<T>
where
T: Copy,
{
type IntoIter = IterChannels<'a, T>;
type Item = <Self::IntoIter as Iterator>::Item;
#[inline]
fn into_iter(self) -> Self::IntoIter {
(*self).iter_channels()
}
}
impl<T> InterleavedBuf for Interleaved<T>
where
T: Copy,
{
type Sample = T;
#[inline]
fn as_interleaved(&self) -> &[Self::Sample] {
self.as_slice()
}
}
impl<T> InterleavedBufMut for Interleaved<T>
where
T: Copy,
{
#[inline]
fn as_interleaved_mut(&mut self) -> &mut [Self::Sample] {
self.as_slice_mut()
}
#[inline]
fn as_interleaved_mut_ptr(&mut self) -> ptr::NonNull<Self::Sample> {
unsafe { ptr::NonNull::new_unchecked(self.data.as_mut_ptr()) }
}
#[inline]
unsafe fn set_interleaved_topology(&mut self, channels: usize, frames: usize) {
self.channels = channels;
self.frames = frames;
}
}