use std::ops::{Deref, DerefMut, Range, RangeBounds};
use smallvec::SmallVec;
use crate::audio::conv::FromSample;
use crate::audio::sample::{Sample, SampleBytes};
use crate::errors::Result;
use super::{
Audio, AudioBufferBytes, AudioBytes, AudioMut, AudioSlice, AudioSliceMut, AudioSpec,
Interleaved, Position,
};
use super::{AudioPlanes, AudioPlanesMut, util::*};
const MAX_STACK_PLANE_SLICES: usize = 8;
#[derive(Clone, Default)]
pub struct AudioBuffer<S: Sample> {
spec: AudioSpec,
planes: SmallVec<[Vec<S>; 3]>, num_frames: usize,
capacity: usize,
}
impl<S: Sample> AudioBuffer<S> {
pub fn new(spec: AudioSpec, capacity: usize) -> Self {
let num_channels = spec.channels().count();
assert!(
capacity <= (usize::MAX / (std::mem::size_of::<S>() * num_channels)),
"capacity too large"
);
let mut planes = SmallVec::<[Vec<S>; 3]>::with_capacity(num_channels);
planes.resize_with(num_channels, || vec![S::MID; capacity]);
AudioBuffer { spec, planes, num_frames: 0, capacity }
}
pub fn is_unused(&self) -> bool {
self.capacity == 0 || self.spec.channels.count() == 0
}
pub fn capacity(&self) -> usize {
self.capacity
}
pub fn clear(&mut self) {
self.num_frames = 0;
}
pub fn grow_capacity(&mut self, new_capacity: usize) {
if self.capacity < new_capacity {
for plane in &mut self.planes {
plane.resize(new_capacity, S::MID);
}
self.capacity = new_capacity;
}
}
pub fn slice<R: RangeBounds<usize>>(&self, range: R) -> AudioSlice<'_, S> {
let bound = 0..self.num_frames;
AudioSlice::new(&self.spec, &self.planes, get_sub_range(range, &bound))
}
pub fn slice_mut<R: RangeBounds<usize>>(&mut self, range: R) -> AudioSliceMut<'_, S> {
let bound = 0..self.num_frames;
AudioSliceMut::new(&self.spec, &mut self.planes, get_sub_range(range, &bound))
}
pub fn append<Sin, Src>(&mut self, src: &Src)
where
Sin: Sample,
S: Sample + FromSample<Sin>,
Src: Audio<Sin>,
{
assert!(self.spec() == src.spec(), "audio specifications are not identical");
let start = self.num_frames;
let end = self.num_frames + src.frames();
assert!(end <= self.capacity, "combined length would exceed capacity");
for (dst, src) in self.planes.iter_mut().zip(src.iter_planes()) {
copy_to_slice(&src[start..end], &mut dst[start..end]);
}
self.num_frames = end;
}
pub fn resize(&mut self, new_len: usize, frame: &[S]) {
assert!(new_len <= self.capacity, "new length would exceed capacity");
assert!(frame.len() == self.planes.len(), "provided frame is too small");
self.truncate(new_len);
if self.num_frames < new_len {
for (plane, &sample) in self.planes.iter_mut().zip(frame) {
for s in &mut plane[self.num_frames..new_len] {
*s = sample;
}
}
self.num_frames = new_len;
}
}
pub fn resize_with_sample(&mut self, new_len: usize, sample: S) {
assert!(new_len <= self.capacity, "new length would exceed capacity");
self.truncate(new_len);
if self.num_frames < new_len {
for plane in &mut self.planes {
for s in &mut plane[self.num_frames..new_len] {
*s = sample;
}
}
self.num_frames = new_len;
}
}
pub fn resize_with_silence(&mut self, new_len: usize) {
self.resize_with_sample(new_len, S::MID);
}
pub fn resize_uninit(&mut self, new_len: usize) {
assert!(new_len <= self.capacity, "new length would exceed capacity");
self.num_frames = new_len;
}
pub fn render(&mut self, num_frames: Option<usize>, frame: &[S]) -> usize {
let num_new_frames = num_frames.unwrap_or(self.capacity - self.num_frames);
assert!(self.num_frames + num_new_frames <= self.capacity(), "capacity will be exceeded");
assert!(frame.len() == self.planes.len(), "provided frame is too small");
for (plane, &s) in self.planes.iter_mut().zip(frame) {
for sample in &mut plane[self.num_frames..self.num_frames + num_new_frames] {
*sample = s;
}
}
self.num_frames += num_new_frames;
num_new_frames
}
pub fn render_with<F>(&mut self, num_frames: Option<usize>, mut f: F) -> Result<usize>
where
F: FnMut(usize, &mut [&mut [S]]) -> Result<()>,
{
let num_new_frames = num_frames.unwrap_or(self.capacity - self.num_frames);
let end = self.num_frames + num_new_frames;
assert!(end <= self.capacity, "capacity will be exceeded");
let mut planes = MutableAudioPlaneSlices::new(&mut self.planes, 0..end);
while self.num_frames < end {
f(self.num_frames, &mut planes)?;
self.num_frames += 1;
}
Ok(num_new_frames - (end - self.num_frames))
}
pub fn render_silence(&mut self, num_frames: Option<usize>) -> usize {
let num_new_frames = num_frames.unwrap_or(self.capacity - self.num_frames);
assert!(self.num_frames + num_new_frames <= self.capacity(), "capacity will be exceeded");
for plane in &mut self.planes {
for sample in &mut plane[self.num_frames..self.num_frames + num_new_frames] {
*sample = S::MID;
}
}
self.num_frames += num_new_frames;
num_new_frames
}
pub fn render_uninit(&mut self, num_frames: Option<usize>) -> usize {
let num_new_frames = num_frames.unwrap_or(self.capacity - self.num_frames);
assert!(self.num_frames + num_new_frames <= self.capacity(), "capacity will be exceeded");
self.num_frames += num_new_frames;
num_new_frames
}
pub fn shift(&mut self, shift: usize) {
if shift >= self.num_frames {
self.clear();
}
else if shift > 0 {
for plane in &mut self.planes {
plane.copy_within(shift..self.num_frames, 0);
}
self.num_frames -= shift;
}
}
pub fn truncate(&mut self, num_frames: usize) {
if num_frames < self.num_frames {
self.num_frames = num_frames;
}
}
pub fn trim(&mut self, start: usize, end: usize) {
self.truncate(self.frames().saturating_sub(end));
self.shift(start);
}
}
impl<S: Sample> Audio<S> for AudioBuffer<S> {
fn spec(&self) -> &AudioSpec {
&self.spec
}
fn num_planes(&self) -> usize {
self.planes.len()
}
fn is_empty(&self) -> bool {
self.num_frames == 0
}
fn frames(&self) -> usize {
self.num_frames
}
fn plane(&self, idx: usize) -> Option<&[S]> {
self.planes.get(idx).map(|plane| &plane[0..self.num_frames])
}
fn plane_pair(&self, idx0: usize, idx1: usize) -> Option<(&[S], &[S])> {
plane_pair_by_buffer_index(&self.planes, 0..self.num_frames, idx0, idx1)
}
fn iter_planes(&self) -> AudioPlanes<'_, S> {
AudioPlanes::new(&self.planes, 0..self.num_frames)
}
fn iter_interleaved(&self) -> Interleaved<'_, S> {
Interleaved::new(&self.planes, 0..self.num_frames)
}
fn copy_to_slice_interleaved<Sout, Dst>(&self, dst: Dst)
where
Sout: Sample + FromSample<S>,
Dst: AsMut<[Sout]>,
{
copy_to_slice_interleaved(&self.planes, 0..self.num_frames, dst);
}
}
impl<S: Sample> AudioMut<S> for AudioBuffer<S> {
fn plane_mut(&mut self, idx: usize) -> Option<&mut [S]> {
self.planes.get_mut(idx).map(|plane| &mut plane[0..self.num_frames])
}
fn plane_pair_mut(&mut self, idx0: usize, idx1: usize) -> Option<(&mut [S], &mut [S])> {
plane_pair_by_buffer_index_mut(&mut self.planes, 0..self.num_frames, idx0, idx1)
}
fn iter_planes_mut(&mut self) -> AudioPlanesMut<'_, S> {
AudioPlanesMut::new(&mut self.planes, 0..self.num_frames)
}
fn copy_from_slice_interleaved<Sin, Src>(&mut self, src: &Src)
where
Sin: Sample,
S: Sample + FromSample<Sin>,
Src: AsRef<[Sin]>,
{
copy_from_slice_interleaved(src, 0..self.num_frames, &mut self.planes);
}
}
impl<S: Sample + SampleBytes> AudioBytes<S> for AudioBuffer<S> {
fn copy_bytes_interleaved_as<Sout, Dst>(&self, dst: Dst)
where
Sout: SampleBytes + FromSample<S>,
Dst: AsMut<[u8]>,
{
copy_bytes_interleaved::<Sout, _, _, _, _>(&self.planes, 0..self.num_frames, convert, dst)
}
fn copy_bytes_planar_as<Sout, Dst>(&self, dst: &mut [Dst])
where
Sout: SampleBytes + FromSample<S>,
Dst: AsMut<[u8]>,
{
copy_bytes_planar::<Sout, _, _, _, _>(&self.planes, 0..self.num_frames, convert, dst)
}
fn copy_bytes_interleaved<Dst>(&self, dst: Dst)
where
Dst: AsMut<[u8]>,
{
copy_bytes_interleaved::<S, _, _, _, _>(&self.planes, 0..self.num_frames, identity, dst)
}
fn copy_bytes_planar<Dst>(&self, dst: &mut [Dst])
where
Dst: AsMut<[u8]>,
{
copy_bytes_planar::<S, _, _, _, _>(&self.planes, 0..self.num_frames, identity, dst)
}
}
impl<S: Sample + SampleBytes> AudioBufferBytes<S> for AudioBuffer<S> {
fn max_byte_len_per_plane_as<Sout>(&self) -> usize
where
Sout: SampleBytes,
{
std::mem::size_of::<Sout::RawType>() * self.capacity()
}
fn max_byte_len_per_plane(&self) -> usize {
std::mem::size_of::<S::RawType>() * self.capacity()
}
}
impl<S: Sample> std::ops::Index<Position> for AudioBuffer<S> {
type Output = [S];
fn index(&self, index: Position) -> &Self::Output {
self.plane_by_position(index).unwrap()
}
}
impl<S: Sample> std::ops::IndexMut<Position> for AudioBuffer<S> {
fn index_mut(&mut self, index: Position) -> &mut Self::Output {
self.plane_by_position_mut(index).unwrap()
}
}
impl<S: Sample> std::ops::Index<usize> for AudioBuffer<S> {
type Output = [S];
fn index(&self, index: usize) -> &Self::Output {
self.plane(index).unwrap()
}
}
impl<S: Sample> std::ops::IndexMut<usize> for AudioBuffer<S> {
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
self.plane_mut(index).unwrap()
}
}
#[derive(Default)]
struct MutableAudioPlaneSlices<'a, S: Sample> {
planes: SmallVec<[&'a mut [S]; MAX_STACK_PLANE_SLICES]>,
}
impl<'a, S: Sample> MutableAudioPlaneSlices<'a, S> {
fn new<Src>(src: &'a mut [Src], bound: Range<usize>) -> Self
where
Src: AsMut<[S]>,
{
let mut writable: MutableAudioPlaneSlices<'_, S> = Default::default();
for plane in src {
writable.planes.push(&mut plane.as_mut()[bound.clone()]);
}
writable
}
}
impl<'a, S: Sample> Deref for MutableAudioPlaneSlices<'a, S> {
type Target = [&'a mut [S]];
fn deref(&self) -> &Self::Target {
&self.planes
}
}
impl<S: Sample> DerefMut for MutableAudioPlaneSlices<'_, S> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.planes
}
}