use arrayvec::ArrayVec;
use std::cell::RefCell;
use std::rc::Rc;
use crate::buffer::ChannelInterpretation;
const LEN: usize = crate::BUFFER_SIZE as usize;
use crate::MAX_CHANNELS;
pub(crate) struct Alloc {
inner: Rc<AllocInner>,
}
struct AllocInner {
pool: RefCell<Vec<Rc<[f32; LEN]>>>,
zeroes: Rc<[f32; LEN]>,
}
impl Alloc {
pub fn with_capacity(n: usize) -> Self {
let pool: Vec<_> = (0..n).map(|_| Rc::new([0.; LEN])).collect();
let zeroes = Rc::new([0.; LEN]);
let inner = AllocInner {
pool: RefCell::new(pool),
zeroes,
};
Self {
inner: Rc::new(inner),
}
}
#[cfg(test)]
pub fn allocate(&self) -> ChannelData {
ChannelData {
data: self.inner.allocate(),
alloc: Rc::clone(&self.inner),
}
}
pub fn silence(&self) -> ChannelData {
ChannelData {
data: Rc::clone(&self.inner.zeroes),
alloc: Rc::clone(&self.inner),
}
}
#[cfg(test)]
pub fn pool_size(&self) -> usize {
self.inner.pool.borrow().len()
}
}
impl AllocInner {
fn allocate(&self) -> Rc<[f32; LEN]> {
if let Some(rc) = self.pool.borrow_mut().pop() {
rc
} else {
Rc::new([0.; LEN])
}
}
fn push(&self, data: Rc<[f32; LEN]>) {
self.pool
.borrow_mut() .push(data);
}
}
#[derive(Clone)]
pub struct ChannelData {
data: Rc<[f32; LEN]>,
alloc: Rc<AllocInner>,
}
impl ChannelData {
fn make_mut(&mut self) -> &mut [f32; LEN] {
if Rc::strong_count(&self.data) != 1 {
let mut new = self.alloc.allocate();
Rc::make_mut(&mut new).copy_from_slice(self.data.deref());
self.data = new;
}
Rc::make_mut(&mut self.data)
}
pub fn is_silent(&self) -> bool {
Rc::ptr_eq(&self.data, &self.alloc.zeroes)
}
pub fn add(&mut self, other: &Self) {
if self.is_silent() {
*self = other.clone();
} else if !other.is_silent() {
self.iter_mut().zip(other.iter()).for_each(|(a, b)| *a += b)
}
}
pub fn silence(&self) -> Self {
ChannelData {
data: self.alloc.zeroes.clone(),
alloc: Rc::clone(&self.alloc),
}
}
}
use std::ops::{Deref, DerefMut};
impl Deref for ChannelData {
type Target = [f32; LEN];
fn deref(&self) -> &Self::Target {
&self.data
}
}
impl DerefMut for ChannelData {
fn deref_mut(&mut self) -> &mut Self::Target {
self.make_mut()
}
}
impl std::ops::Drop for ChannelData {
fn drop(&mut self) {
if Rc::strong_count(&self.data) == 1 {
let rc = std::mem::replace(&mut self.data, self.alloc.zeroes.clone());
self.alloc.push(rc);
}
}
}
#[derive(Clone)]
pub struct AudioBuffer {
channels: ArrayVec<[ChannelData; MAX_CHANNELS]>,
}
impl AudioBuffer {
pub fn new(channel: ChannelData) -> Self {
let mut channels = ArrayVec::new();
channels.push(channel);
Self { channels }
}
pub fn number_of_channels(&self) -> usize {
self.channels.len()
}
pub fn set_number_of_channels(&mut self, n: usize) {
assert!(n <= MAX_CHANNELS);
for _ in self.number_of_channels()..n {
self.channels.push(self.channels[0].clone());
}
self.channels.truncate(n);
}
pub fn channel_data(&self, index: usize) -> &ChannelData {
&self.channels[index]
}
pub fn channel_data_mut(&mut self, index: usize) -> &mut ChannelData {
&mut self.channels[index]
}
pub fn channels(&self) -> &[ChannelData] {
&self.channels[..]
}
pub fn channels_mut(&mut self) -> &mut [ChannelData] {
&mut self.channels[..]
}
pub fn mix(&mut self, channels: usize, interpretation: ChannelInterpretation) {
assert!(channels < MAX_CHANNELS);
if self.number_of_channels() == channels {
return;
}
let silence = self.channels[0].silence();
if interpretation == ChannelInterpretation::Discrete {
for _ in self.number_of_channels()..channels {
self.channels.push(silence.clone());
}
self.channels.truncate(channels);
return;
}
match (self.number_of_channels(), channels) {
(1, 2) => {
self.channels.push(self.channels[0].clone());
}
(1, 4) => {
self.channels.push(self.channels[0].clone());
self.channels.push(silence.clone());
self.channels.push(silence);
}
(1, 6) => {
let main = std::mem::replace(&mut self.channels[0], silence.clone());
self.channels.push(silence.clone());
self.channels.push(main);
self.channels.push(silence.clone());
self.channels.push(silence);
}
(2, 1) => {
let right = self.channels[1].clone();
self.channels[0]
.iter_mut()
.zip(right.iter())
.for_each(|(l, r)| *l = (*l + *r) / 2.);
self.channels.truncate(1);
}
_ => todo!(),
}
}
pub fn make_silent(&mut self) {
let silence = self.channels[0].silence();
self.channels[0] = silence;
self.channels.truncate(1);
}
pub fn force_mono(&mut self) {
self.channels.truncate(1);
}
pub fn modify_channels<F: Fn(&mut ChannelData)>(&mut self, fun: F) {
self.channels.iter_mut().for_each(fun)
}
pub fn add(&mut self, other: &Self, interpretation: ChannelInterpretation) {
let channels_self = self.number_of_channels();
let channels_other = other.number_of_channels();
let channels = channels_self.max(channels_other);
self.mix(channels, interpretation);
let mut other_mixed = other.clone();
other_mixed.mix(channels, interpretation);
self.channels
.iter_mut()
.zip(other_mixed.channels.iter())
.take(channels)
.for_each(|(s, o)| s.add(o));
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_pool() {
let alloc = Alloc::with_capacity(2);
assert_eq!(alloc.pool_size(), 2);
alloc_counter::deny_alloc(|| {
{
let a = alloc.allocate();
assert_eq!(*a.as_ref(), [0.; LEN]);
assert_eq!(alloc.pool_size(), 1);
let mut a = a;
a.iter_mut().for_each(|v| *v += 1.);
assert_eq!(*a.as_ref(), [1.; LEN]);
assert_eq!(alloc.pool_size(), 1);
let mut b: ChannelData = a.clone();
assert_eq!(alloc.pool_size(), 1);
b.iter_mut().for_each(|v| *v += 1.);
assert_eq!(alloc.pool_size(), 0);
}
assert_eq!(alloc.pool_size(), 2);
let c = {
let a = alloc.allocate();
let b = alloc.allocate();
let c = alloc_counter::allow_alloc(|| {
let c = alloc.allocate();
assert_eq!(alloc.pool_size(), 0);
c
});
assert_eq!(*a.as_ref(), [1.; LEN]);
assert_eq!(*b.as_ref(), [2.; LEN]);
assert_eq!(*c.as_ref(), [0.; LEN]);
c
};
alloc_counter::allow_alloc(move || {
std::mem::drop(c);
});
assert_eq!(alloc.pool_size(), 3);
{
let mut a = alloc.silence();
assert!(a.is_silent());
assert_eq!(alloc.pool_size(), 3);
let a_vals = a.deref_mut();
assert_eq!(alloc.pool_size(), 2);
assert_eq!(*a_vals, [0.; LEN]);
assert_eq!(*a_vals, [0.; LEN]);
assert_eq!(a.is_silent(), false);
}
});
}
#[test]
fn test_silence() {
let alloc = Alloc::with_capacity(1);
let silence = alloc.silence();
assert_eq!(&silence[..], &[0.; LEN]);
assert!(silence.is_silent());
let mut changed = silence;
changed.iter_mut().for_each(|v| *v = 1.);
assert_eq!(&changed[..], &[1.; LEN]);
assert!(!changed.is_silent());
let silence = alloc.silence();
assert_eq!(&silence[..], &[0.; LEN]);
assert!(silence.is_silent());
let from_channel = silence.silence();
assert_eq!(&from_channel[..], &[0.; LEN]);
assert!(from_channel.is_silent());
}
#[test]
fn test_channel_add() {
let alloc = Alloc::with_capacity(1);
let silence = alloc.silence();
let mut signal1 = alloc.silence();
signal1.copy_from_slice(&[1.; LEN]);
let mut signal2 = alloc.allocate();
signal2.copy_from_slice(&[2.; LEN]);
signal1.add(&silence);
assert_eq!(&signal1[..], &[1.; LEN]);
let mut sum = alloc.silence();
sum.add(&signal1);
assert_eq!(&sum[..], &[1.; LEN]);
signal1.add(&signal2);
assert_eq!(&signal1[..], &[3.; LEN]);
}
#[test]
fn test_audiobuffer_channels() {
let alloc = Alloc::with_capacity(1);
let silence = alloc.silence();
let buffer = AudioBuffer::new(silence);
assert_eq!(buffer.number_of_channels(), 1);
let mut buffer = buffer;
buffer.set_number_of_channels(5);
assert_eq!(buffer.number_of_channels(), 5);
let _ = buffer.channel_data(4);
buffer.set_number_of_channels(2);
assert_eq!(buffer.number_of_channels(), 2);
}
#[test]
fn test_audiobuffer_mix_discrete() {
let alloc = Alloc::with_capacity(1);
let mut signal = alloc.silence();
signal.copy_from_slice(&[1.; LEN]);
let mut buffer = AudioBuffer::new(signal);
buffer.mix(1, ChannelInterpretation::Discrete);
assert_eq!(buffer.number_of_channels(), 1);
assert_eq!(&buffer.channel_data(0)[..], &[1.; LEN]);
buffer.mix(2, ChannelInterpretation::Discrete);
assert_eq!(buffer.number_of_channels(), 2);
assert_eq!(&buffer.channel_data(0)[..], &[1.; LEN]);
assert_eq!(&buffer.channel_data(1)[..], &[0.; LEN]);
buffer.mix(1, ChannelInterpretation::Discrete);
assert_eq!(buffer.number_of_channels(), 1);
assert_eq!(&buffer.channel_data(0)[..], &[1.; LEN]);
}
#[test]
fn test_audiobuffer_mix_speakers() {
let alloc = Alloc::with_capacity(1);
let mut signal = alloc.silence();
signal.copy_from_slice(&[1.; LEN]);
let mut buffer = AudioBuffer::new(signal);
buffer.mix(1, ChannelInterpretation::Speakers);
assert_eq!(buffer.number_of_channels(), 1);
assert_eq!(&buffer.channel_data(0)[..], &[1.; LEN]);
buffer.mix(2, ChannelInterpretation::Speakers);
assert_eq!(buffer.number_of_channels(), 2);
assert_eq!(&buffer.channel_data(0)[..], &[1.; LEN]);
assert_eq!(&buffer.channel_data(1)[..], &[1.; LEN]);
buffer.mix(1, ChannelInterpretation::Speakers);
assert_eq!(buffer.number_of_channels(), 1);
assert_eq!(&buffer.channel_data(0)[..], &[1.; LEN]);
}
#[test]
fn test_audiobuffer_add() {
let alloc = Alloc::with_capacity(1);
let mut signal = alloc.silence();
signal.copy_from_slice(&[1.; LEN]);
let mut buffer = AudioBuffer::new(signal);
buffer.mix(2, ChannelInterpretation::Speakers);
let mut signal2 = alloc.silence();
signal2.copy_from_slice(&[2.; LEN]);
let buffer2 = AudioBuffer::new(signal2);
buffer.add(&buffer2, ChannelInterpretation::Discrete);
assert_eq!(buffer.number_of_channels(), 2);
assert_eq!(&buffer.channel_data(0)[..], &[3.; LEN]);
assert_eq!(&buffer.channel_data(1)[..], &[1.; LEN]);
}
}