use arrayvec::ArrayVec;
#[derive(Clone, Default)]
pub struct Frame {
samples: Vec<i32>,
channels: usize,
channel_len: usize,
bits_per_sample: u32,
}
impl Frame {
#[inline]
pub fn empty(channels: usize, bits_per_sample: u32) -> Self {
Self {
samples: Vec::new(),
channels,
channel_len: 0,
bits_per_sample,
}
}
#[inline]
pub fn pcm_frames(&self) -> usize {
self.channel_len
}
pub fn resize(
&mut self,
bits_per_sample: u32,
channels: usize,
block_size: usize,
) -> &mut [i32] {
self.bits_per_sample = bits_per_sample;
self.channels = channels;
self.channel_len = block_size;
self.samples.resize(channels * block_size, 0);
&mut self.samples
}
pub fn resized_channels(
&mut self,
bits_per_sample: u32,
channels: usize,
block_size: usize,
) -> impl Iterator<Item = &mut [i32]> {
self.resize(bits_per_sample, channels, block_size)
.chunks_exact_mut(block_size)
}
pub fn resized_stereo(
&mut self,
bits_per_sample: u32,
block_size: usize,
) -> (&mut [i32], &mut [i32]) {
self.resize(bits_per_sample, 2, block_size)
.split_at_mut(block_size)
}
#[inline]
pub fn bytes_per_sample(&self) -> usize {
self.bits_per_sample.div_ceil(8) as usize
}
#[inline]
pub fn bytes_len(&self) -> usize {
self.bytes_per_sample() * self.samples.len()
}
#[inline]
pub fn iter(&self) -> impl Iterator<Item = i32> {
MultiZip {
iters: self.channels().map(|c| c.iter().copied()).collect(),
}
.flatten()
}
#[inline]
pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut i32> {
MultiZip {
iters: self.channels_mut().map(|c| c.iter_mut()).collect(),
}
.flatten()
}
pub fn to_buf<E: crate::byteorder::Endianness>(&self, buf: &mut [u8]) {
match self.bytes_per_sample() {
1 => {
for (sample, bytes) in self.iter().zip(buf.as_chunks_mut().0) {
*bytes = E::i8_to_bytes(sample as i8);
}
}
2 => {
for (sample, bytes) in self.iter().zip(buf.as_chunks_mut().0) {
*bytes = E::i16_to_bytes(sample as i16);
}
}
3 => {
for (sample, bytes) in self.iter().zip(buf.as_chunks_mut().0) {
*bytes = E::i24_to_bytes(sample);
}
}
4 => {
for (sample, bytes) in self.iter().zip(buf.as_chunks_mut().0) {
*bytes = E::i32_to_bytes(sample);
}
}
_ => panic!("unsupported number of bytes per sample"),
}
}
#[inline]
pub fn channels(&self) -> impl Iterator<Item = &[i32]> {
self.samples.chunks_exact(self.channel_len)
}
#[inline]
pub fn channels_mut(&mut self) -> impl Iterator<Item = &mut [i32]> {
self.samples.chunks_exact_mut(self.channel_len)
}
pub fn fill_from_buf<E: crate::byteorder::Endianness>(&mut self, buf: &[u8]) -> &Self {
match self.bytes_per_sample() {
1 => {
self.channel_len = buf.len() / self.channels;
self.samples.resize(buf.len(), 0);
for (sample, bytes) in self.iter_mut().zip(buf.as_chunks().0) {
*sample = E::bytes_to_i8(*bytes).into()
}
}
2 => {
self.channel_len = (buf.len() / 2) / self.channels;
self.samples.resize(buf.len() / 2, 0);
for (sample, bytes) in self.iter_mut().zip(buf.as_chunks().0) {
*sample = E::bytes_to_i16(*bytes).into()
}
}
3 => {
self.channel_len = (buf.len() / 3) / self.channels;
self.samples.resize(buf.len() / 3, 0);
for (sample, bytes) in self.iter_mut().zip(buf.as_chunks().0) {
*sample = E::bytes_to_i24(*bytes)
}
}
4 => {
self.channel_len = (buf.len() / 4) / self.channels;
self.samples.resize(buf.len() / 4, 0);
for (sample, bytes) in self.iter_mut().zip(buf.as_chunks().0) {
*sample = E::bytes_to_i32(*bytes)
}
}
_ => panic!("unsupported number of bytes per sample"),
}
self
}
pub fn fill_from_samples(&mut self, samples: &[i32]) -> &Self {
self.channel_len = samples.len() / self.channels;
self.samples.resize(samples.len(), 0);
for (o, i) in self.iter_mut().zip(samples) {
*o = *i;
}
self
}
pub fn fill_from_channels<C, S>(&mut self, channels: C) -> &Self
where
C: AsRef<[S]>,
S: AsRef<[i32]>,
{
let channels = channels.as_ref();
debug_assert_eq!(self.channels, channels.len());
self.channel_len = channels[0].as_ref().len();
self.samples.resize(channels.len() * self.channel_len, 0);
for (o, i) in self
.samples
.chunks_exact_mut(self.channel_len)
.zip(channels)
{
o.copy_from_slice(i.as_ref());
}
self
}
}
const MAX_CHANNELS: usize = 8;
pub struct MultiZip<I> {
iters: ArrayVec<I, MAX_CHANNELS>,
}
impl<I: Iterator> Iterator for MultiZip<I> {
type Item = ArrayVec<I::Item, MAX_CHANNELS>;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.iters.iter_mut().map(|i| i.next()).collect()
}
}
impl<I> FromIterator<I> for MultiZip<I> {
#[inline]
fn from_iter<T: IntoIterator<Item = I>>(iter: T) -> Self {
Self {
iters: iter.into_iter().collect(),
}
}
}