use crate::Error;
#[cfg(feature = "audioadapter")]
use audioadapter::Adapter;
#[cfg(feature = "audioadapter")]
use audioadapter::AdapterMut;
#[derive(Clone, Debug, PartialEq)]
pub struct PlanarVecs<T> {
buf: Vec<Vec<T>>,
frames: usize,
}
pub struct PlanarVecsIter<'a, T> {
inner: std::slice::Iter<'a, Vec<T>>,
}
pub struct PlanarVecsIterMut<'a, T> {
inner: std::slice::IterMut<'a, Vec<T>>,
}
impl<T> PlanarVecs<T> {
pub fn new(buf: Vec<Vec<T>>) -> Result<Self, Error> {
let frames = buf.first().map_or(0, Vec::len);
if let Some(channel) = buf.iter().find(|channel| channel.len() != frames) {
return Err(Error::WrongFrameCount {
expected: frames,
actual: channel.len(),
});
}
Ok(Self { buf, frames })
}
#[must_use]
#[inline]
pub fn channels(&self) -> usize {
self.buf.len()
}
#[must_use]
#[inline]
pub fn frames(&self) -> usize {
self.frames
}
#[must_use]
#[inline]
pub fn is_empty(&self) -> bool {
self.buf.is_empty() || self.frames == 0
}
#[must_use]
#[inline]
pub fn get_channel(&self, index: usize) -> Option<&[T]> {
self.buf.get(index).map(Vec::as_slice)
}
#[must_use]
#[inline]
pub fn get_channel_mut(&mut self, index: usize) -> Option<&mut [T]> {
self.buf.get_mut(index).map(Vec::as_mut_slice)
}
#[must_use]
#[inline]
pub fn as_slice(&self) -> &[Vec<T>] {
&self.buf
}
#[must_use]
#[inline]
pub fn into_inner(self) -> Vec<Vec<T>> {
self.buf
}
#[must_use]
#[inline]
pub fn pop_channel(&mut self) -> Option<Vec<T>> {
let channel = self.buf.pop();
if self.buf.is_empty() {
self.frames = 0;
}
channel
}
pub fn interleave(&self) -> Vec<T>
where
T: Clone,
{
let mut interleaved = Vec::with_capacity(self.channels() * self.frames());
for frame in 0..self.frames {
for channel in &self.buf {
interleaved.push(channel[frame].clone());
}
}
interleaved
}
}
impl<'a, T> Iterator for PlanarVecsIter<'a, T> {
type Item = &'a [T];
#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.inner.next().map(Vec::as_slice)
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.inner.size_hint()
}
}
impl<T> ExactSizeIterator for PlanarVecsIter<'_, T> {}
impl<'a, T> Iterator for PlanarVecsIterMut<'a, T> {
type Item = &'a mut [T];
#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.inner.next().map(Vec::as_mut_slice)
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.inner.size_hint()
}
}
impl<T> ExactSizeIterator for PlanarVecsIterMut<'_, T> {}
impl<T> From<PlanarVecs<T>> for Vec<Vec<T>> {
#[inline]
fn from(value: PlanarVecs<T>) -> Self {
value.into_inner()
}
}
impl<T> IntoIterator for PlanarVecs<T> {
type Item = Vec<T>;
type IntoIter = std::vec::IntoIter<Vec<T>>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
self.into_inner().into_iter()
}
}
impl<'a, T> IntoIterator for &'a PlanarVecs<T> {
type Item = &'a [T];
type IntoIter = PlanarVecsIter<'a, T>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
PlanarVecsIter { inner: self.buf.iter() }
}
}
impl<'a, T> IntoIterator for &'a mut PlanarVecs<T> {
type Item = &'a mut [T];
type IntoIter = PlanarVecsIterMut<'a, T>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
PlanarVecsIterMut {
inner: self.buf.iter_mut(),
}
}
}
#[cfg(feature = "audioadapter")]
unsafe impl<'a, T> Adapter<'a, T> for PlanarVecs<T>
where
T: Clone + 'a,
{
#[inline]
unsafe fn read_sample_unchecked(&self, channel: usize, frame: usize) -> T {
unsafe { self.buf.get_unchecked(channel).get_unchecked(frame).clone() }
}
#[inline]
fn channels(&self) -> usize {
self.channels()
}
#[inline]
fn frames(&self) -> usize {
self.frames()
}
fn copy_from_channel_to_slice(&self, channel: usize, skip: usize, slice: &mut [T]) -> usize {
if channel >= self.channels() || skip >= self.frames {
return 0;
}
let frames_to_write = (self.frames - skip).min(slice.len());
slice[..frames_to_write].clone_from_slice(&self.buf[channel][skip..skip + frames_to_write]);
frames_to_write
}
}
#[cfg(feature = "audioadapter")]
unsafe impl<'a, T> AdapterMut<'a, T> for PlanarVecs<T>
where
T: Clone + 'a,
{
unsafe fn write_sample_unchecked(&mut self, channel: usize, frame: usize, value: &T) -> bool {
unsafe {
*self.buf.get_unchecked_mut(channel).get_unchecked_mut(frame) = value.clone();
}
false
}
fn copy_from_slice_to_channel(&mut self, channel: usize, skip: usize, slice: &[T]) -> (usize, usize) {
if channel >= self.channels() || skip >= self.frames {
return (0, 0);
}
let frames_to_read = (self.frames - skip).min(slice.len());
self.buf[channel][skip..skip + frames_to_read].clone_from_slice(&slice[..frames_to_read]);
(frames_to_read, 0)
}
}
#[cfg(test)]
mod tests {
use super::PlanarVecs;
#[test]
fn mono_interleave_matches_pop_channel() {
let mut planar = PlanarVecs::new(vec![vec![1_i32, 2, 3, 5, 8]]).unwrap();
let interleaved = planar.interleave();
let popped = planar.pop_channel().expect("mono has one channel");
assert_eq!(interleaved, popped);
}
}