use arrayvec::ArrayVec;
use std::cell::RefCell;
use std::rc::Rc;
use crate::node::{ChannelConfig, ChannelCountMode, ChannelInterpretation};
use crate::assert_valid_number_of_channels;
use crate::{MAX_CHANNELS, RENDER_QUANTUM_SIZE};
pub(crate) struct Alloc {
inner: Rc<AllocInner>,
}
#[derive(Debug)]
struct AllocInner {
pool: RefCell<Vec<Rc<[f32; RENDER_QUANTUM_SIZE]>>>,
zeroes: Rc<[f32; RENDER_QUANTUM_SIZE]>,
}
impl Alloc {
pub fn with_capacity(n: usize) -> Self {
let pool: Vec<_> = (0..n).map(|_| Rc::new([0.; RENDER_QUANTUM_SIZE])).collect();
let zeroes = Rc::new([0.; RENDER_QUANTUM_SIZE]);
let inner = AllocInner {
pool: RefCell::new(pool),
zeroes,
};
Self {
inner: Rc::new(inner),
}
}
#[cfg(test)]
pub fn allocate(&self) -> AudioRenderQuantumChannel {
AudioRenderQuantumChannel {
data: self.inner.allocate(),
alloc: Rc::clone(&self.inner),
}
}
pub fn silence(&self) -> AudioRenderQuantumChannel {
AudioRenderQuantumChannel {
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; RENDER_QUANTUM_SIZE]> {
if let Some(rc) = self.pool.borrow_mut().pop() {
rc
} else {
Rc::new([0.; RENDER_QUANTUM_SIZE])
}
}
fn push(&self, data: Rc<[f32; RENDER_QUANTUM_SIZE]>) {
self.pool
.borrow_mut() .push(data);
}
}
#[derive(Clone, Debug)]
pub struct AudioRenderQuantumChannel {
data: Rc<[f32; RENDER_QUANTUM_SIZE]>,
alloc: Rc<AllocInner>,
}
impl AudioRenderQuantumChannel {
fn make_mut(&mut self) -> &mut [f32; RENDER_QUANTUM_SIZE] {
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(crate) fn is_silent(&self) -> bool {
Rc::ptr_eq(&self.data, &self.alloc.zeroes)
}
pub(crate) 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(crate) fn silence(&self) -> Self {
Self {
data: self.alloc.zeroes.clone(),
alloc: Rc::clone(&self.alloc),
}
}
}
use std::ops::{Deref, DerefMut};
impl Deref for AudioRenderQuantumChannel {
type Target = [f32];
fn deref(&self) -> &Self::Target {
self.data.as_slice()
}
}
impl DerefMut for AudioRenderQuantumChannel {
fn deref_mut(&mut self) -> &mut Self::Target {
self.make_mut()
}
}
impl AsRef<[f32]> for AudioRenderQuantumChannel {
fn as_ref(&self) -> &[f32] {
&self.data[..]
}
}
impl std::ops::Drop for AudioRenderQuantumChannel {
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, Debug)]
pub struct AudioRenderQuantum {
channels: ArrayVec<AudioRenderQuantumChannel, MAX_CHANNELS>,
single_valued: bool,
}
impl AudioRenderQuantum {
pub(crate) fn from(channel: AudioRenderQuantumChannel) -> Self {
let mut channels = ArrayVec::new();
channels.push(channel);
Self {
channels,
single_valued: false,
}
}
pub(crate) fn single_valued(&self) -> bool {
self.single_valued
}
pub(crate) fn set_single_valued(&mut self, value: bool) {
self.single_valued = value;
}
pub fn number_of_channels(&self) -> usize {
self.channels.len()
}
pub fn set_number_of_channels(&mut self, n: usize) {
assert_valid_number_of_channels(n);
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) -> &AudioRenderQuantumChannel {
&self.channels[index]
}
pub fn channel_data_mut(&mut self, index: usize) -> &mut AudioRenderQuantumChannel {
&mut self.channels[index]
}
pub fn channels(&self) -> &[AudioRenderQuantumChannel] {
&self.channels[..]
}
pub fn channels_mut(&mut self) -> &mut [AudioRenderQuantumChannel] {
&mut self.channels[..]
}
pub fn is_silent(&self) -> bool {
!self.channels.iter().any(|channel| !channel.is_silent())
}
pub(crate) fn stereo_mut(&mut self) -> [&mut AudioRenderQuantumChannel; 2] {
assert_eq!(self.number_of_channels(), 2);
let (ls, rs) = self.channels_mut().split_at_mut(1);
[&mut ls[0], &mut rs[0]]
}
#[inline(always)]
pub(crate) fn mix(
&mut self,
computed_number_of_channels: usize,
interpretation: ChannelInterpretation,
) {
if self.number_of_channels() == computed_number_of_channels {
return;
}
self.mix_inner(computed_number_of_channels, interpretation)
}
fn mix_inner(
&mut self,
computed_number_of_channels: usize,
interpretation: ChannelInterpretation,
) {
assert_valid_number_of_channels(computed_number_of_channels);
let silence = self.channels[0].silence();
if interpretation == ChannelInterpretation::Discrete {
for _ in self.number_of_channels()..computed_number_of_channels {
self.channels.push(silence.clone());
}
self.channels.truncate(computed_number_of_channels);
} else if interpretation == ChannelInterpretation::Speakers {
match (self.number_of_channels(), computed_number_of_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.clone());
self.channels.push(silence);
}
(2, 4) => {
self.channels.push(silence.clone());
self.channels.push(silence);
}
(2, 6) => {
self.channels.push(silence.clone());
self.channels.push(silence.clone());
self.channels.push(silence.clone());
self.channels.push(silence);
}
(4, 6) => {
let sl = std::mem::replace(&mut self.channels[2], silence.clone());
let sr = std::mem::replace(&mut self.channels[3], silence);
self.channels.push(sl);
self.channels.push(sr);
}
(2, 1) => {
let right = self.channels[1].clone();
self.channels[0]
.iter_mut()
.zip(right.iter())
.for_each(|(l, r)| *l = 0.5 * (*l + *r));
self.channels.truncate(1);
}
(4, 1) => {
let right = self.channels[1].clone();
let s_left = self.channels[2].clone();
let s_right = self.channels[3].clone();
self.channels[0]
.iter_mut()
.zip(right.iter())
.zip(s_left.iter())
.zip(s_right.iter())
.for_each(|(((l, r), sl), sr)| *l = 0.25 * (*l + *r + *sl + *sr));
self.channels.truncate(1);
}
(6, 1) => {
let right = self.channels[1].clone();
let center = self.channels[2].clone();
let s_left = self.channels[4].clone();
let s_right = self.channels[5].clone();
let sqrt05 = (0.5_f32).sqrt();
self.channels[0]
.iter_mut()
.zip(right.iter())
.zip(center.iter())
.zip(s_left.iter())
.zip(s_right.iter())
.for_each(|((((l, r), c), sl), sr)| {
*l = sqrt05.mul_add(*l + *r, 0.5f32.mul_add(*sl + *sr, *c))
});
self.channels.truncate(1);
}
(4, 2) => {
let s_left = self.channels[2].clone();
let s_right = self.channels[3].clone();
self.channels[0]
.iter_mut()
.zip(s_left.iter())
.for_each(|(l, sl)| *l = 0.5 * (*l + *sl));
self.channels[1]
.iter_mut()
.zip(s_right.iter())
.for_each(|(r, sr)| *r = 0.5 * (*r + *sr));
self.channels.truncate(2);
}
(6, 2) => {
let center = self.channels[2].clone();
let s_left = self.channels[4].clone();
let s_right = self.channels[5].clone();
let sqrt05 = (0.5_f32).sqrt();
self.channels[0]
.iter_mut()
.zip(center.iter())
.zip(s_left.iter())
.for_each(|((l, c), sl)| *l += sqrt05 * (*c + *sl));
self.channels[1]
.iter_mut()
.zip(center.iter())
.zip(s_right.iter())
.for_each(|((r, c), sr)| *r += sqrt05 * (*c + *sr));
self.channels.truncate(2)
}
(6, 4) => {
let _low_f = self.channels.swap_remove(3); let center = self.channels.swap_remove(2); let sqrt05 = (0.5_f32).sqrt();
self.channels[0]
.iter_mut()
.zip(center.iter())
.for_each(|(l, c)| *l += sqrt05 * c);
self.channels[1]
.iter_mut()
.zip(center.iter())
.for_each(|(r, c)| *r += sqrt05 * c);
}
_ => panic!(
"{mixing} from {from} to {to} channels not supported",
mixing = if self.number_of_channels() < computed_number_of_channels {
"Up-mixing"
} else {
"Down-mixing"
},
from = self.number_of_channels(),
to = computed_number_of_channels,
),
}
}
}
pub fn make_silent(&mut self) {
let silence = self.channels[0].silence();
self.channels[0] = silence;
self.channels.truncate(1);
}
pub(crate) fn force_mono(&mut self) {
self.channels.truncate(1);
}
pub(crate) fn modify_channels<F: Fn(&mut AudioRenderQuantumChannel)>(&mut self, fun: F) {
self.channels.iter_mut().for_each(fun)
}
pub(crate) fn add(&mut self, other: &Self, channel_config: &ChannelConfig) {
let channels_self = self.number_of_channels();
let channels_other = other.number_of_channels();
let max_channels = channels_self.max(channels_other);
let interpretation = channel_config.interpretation();
let mode = channel_config.count_mode();
let count = channel_config.count();
let new_channels = match mode {
ChannelCountMode::Max => max_channels,
ChannelCountMode::Explicit => count,
ChannelCountMode::ClampedMax => max_channels.min(count),
};
if interpretation == ChannelInterpretation::Speakers
&& self.all_channels_identical()
&& other.all_channels_identical()
{
self.channels.truncate(1);
self.channels[0].add(&other.channels[0]);
self.mix(new_channels, interpretation);
return;
}
self.mix(new_channels, interpretation);
let mut other_mixed = other.clone();
other_mixed.mix(new_channels, interpretation);
self.channels
.iter_mut()
.zip(other_mixed.channels.iter())
.for_each(|(s, o)| s.add(o));
}
fn all_channels_identical(&self) -> bool {
let mut channels = self.channels.iter();
let first = channels.next().unwrap();
for c in channels {
if !Rc::ptr_eq(&first.data, &c.data) {
return false;
}
}
true
}
}
#[cfg(test)]
mod tests {
use float_eq::assert_float_eq;
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_float_eq!(&a[..], &[0.; RENDER_QUANTUM_SIZE][..], abs_all <= 0.);
assert_eq!(alloc.pool_size(), 1);
let mut a = a;
a.iter_mut().for_each(|v| *v += 1.);
assert_float_eq!(&a[..], &[1.; RENDER_QUANTUM_SIZE][..], abs_all <= 0.);
assert_eq!(alloc.pool_size(), 1);
#[allow(clippy::redundant_clone)]
let mut b: AudioRenderQuantumChannel = 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_float_eq!(&a[..], &[1.; RENDER_QUANTUM_SIZE][..], abs_all <= 0.);
assert_float_eq!(&b[..], &[2.; RENDER_QUANTUM_SIZE][..], abs_all <= 0.);
assert_float_eq!(&c[..], &[0.; RENDER_QUANTUM_SIZE][..], abs_all <= 0.);
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_float_eq!(a_vals, &[0.; RENDER_QUANTUM_SIZE][..], abs_all <= 0.);
assert!(!a.is_silent());
}
});
}
#[test]
fn test_silence() {
let alloc = Alloc::with_capacity(1);
let silence = alloc.silence();
assert_float_eq!(&silence[..], &[0.; RENDER_QUANTUM_SIZE][..], abs_all <= 0.);
assert!(silence.is_silent());
let mut changed = silence;
changed.iter_mut().for_each(|v| *v = 1.);
assert_float_eq!(&changed[..], &[1.; RENDER_QUANTUM_SIZE][..], abs_all <= 0.);
assert!(!changed.is_silent());
let silence = alloc.silence();
assert_float_eq!(&silence[..], &[0.; RENDER_QUANTUM_SIZE][..], abs_all <= 0.);
assert!(silence.is_silent());
let from_channel = silence.silence();
assert_float_eq!(
&from_channel[..],
&[0.; RENDER_QUANTUM_SIZE][..],
abs_all <= 0.
);
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.; RENDER_QUANTUM_SIZE]);
let mut signal2 = alloc.allocate();
signal2.copy_from_slice(&[2.; RENDER_QUANTUM_SIZE]);
signal1.add(&silence);
assert_float_eq!(&signal1[..], &[1.; RENDER_QUANTUM_SIZE][..], abs_all <= 0.);
let mut silence = alloc.silence();
silence.add(&signal1);
assert_float_eq!(&silence[..], &[1.; RENDER_QUANTUM_SIZE][..], abs_all <= 0.);
signal1.add(&signal2);
assert_float_eq!(&signal1[..], &[3.; RENDER_QUANTUM_SIZE][..], abs_all <= 0.);
}
#[test]
fn test_audiobuffer_channels() {
let alloc = Alloc::with_capacity(1);
let silence = alloc.silence();
let buffer = AudioRenderQuantum::from(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.; RENDER_QUANTUM_SIZE]);
let mut buffer = AudioRenderQuantum::from(signal);
buffer.mix(1, ChannelInterpretation::Discrete);
assert_eq!(buffer.number_of_channels(), 1);
assert_float_eq!(
&buffer.channel_data(0)[..],
&[1.; RENDER_QUANTUM_SIZE][..],
abs_all <= 0.
);
buffer.mix(2, ChannelInterpretation::Discrete);
assert_eq!(buffer.number_of_channels(), 2);
assert_float_eq!(
&buffer.channel_data(0)[..],
&[1.; RENDER_QUANTUM_SIZE][..],
abs_all <= 0.
);
assert_float_eq!(
&buffer.channel_data(1)[..],
&[0.; RENDER_QUANTUM_SIZE][..],
abs_all <= 0.
);
buffer.mix(1, ChannelInterpretation::Discrete);
assert_eq!(buffer.number_of_channels(), 1);
assert_float_eq!(
&buffer.channel_data(0)[..],
&[1.; RENDER_QUANTUM_SIZE][..],
abs_all <= 0.
);
}
#[test]
fn test_audiobuffer_upmix_speakers() {
let alloc = Alloc::with_capacity(1);
{
let mut signal = alloc.silence();
signal.copy_from_slice(&[1.; RENDER_QUANTUM_SIZE]);
let mut buffer = AudioRenderQuantum::from(signal);
buffer.mix(1, ChannelInterpretation::Speakers);
assert_eq!(buffer.number_of_channels(), 1);
assert_float_eq!(
&buffer.channel_data(0)[..],
&[1.; RENDER_QUANTUM_SIZE][..],
abs_all <= 0.
);
buffer.mix(2, ChannelInterpretation::Speakers);
assert_eq!(buffer.number_of_channels(), 2);
assert_float_eq!(
&buffer.channel_data(0)[..],
&[1.; RENDER_QUANTUM_SIZE][..],
abs_all <= 0.
);
assert_float_eq!(
&buffer.channel_data(1)[..],
&[1.; RENDER_QUANTUM_SIZE][..],
abs_all <= 0.
);
}
{
let mut signal = alloc.silence();
signal.copy_from_slice(&[1.; RENDER_QUANTUM_SIZE]);
let mut buffer = AudioRenderQuantum::from(signal);
buffer.mix(4, ChannelInterpretation::Speakers);
assert_eq!(buffer.number_of_channels(), 4);
assert_float_eq!(
&buffer.channel_data(0)[..],
&[1.; RENDER_QUANTUM_SIZE][..],
abs_all <= 0.
);
assert_float_eq!(
&buffer.channel_data(1)[..],
&[1.; RENDER_QUANTUM_SIZE][..],
abs_all <= 0.
);
assert_float_eq!(
&buffer.channel_data(2)[..],
&[0.; RENDER_QUANTUM_SIZE][..],
abs_all <= 0.
);
assert_float_eq!(
&buffer.channel_data(3)[..],
&[0.; RENDER_QUANTUM_SIZE][..],
abs_all <= 0.
);
}
{
let mut signal = alloc.silence();
signal.copy_from_slice(&[1.; RENDER_QUANTUM_SIZE]);
let mut buffer = AudioRenderQuantum::from(signal);
buffer.mix(6, ChannelInterpretation::Speakers);
assert_eq!(buffer.number_of_channels(), 6);
assert_float_eq!(
&buffer.channel_data(0)[..],
&[0.; RENDER_QUANTUM_SIZE][..],
abs_all <= 0.
);
assert_float_eq!(
&buffer.channel_data(1)[..],
&[0.; RENDER_QUANTUM_SIZE][..],
abs_all <= 0.
);
assert_float_eq!(
&buffer.channel_data(2)[..],
&[1.; RENDER_QUANTUM_SIZE][..],
abs_all <= 0.
);
assert_float_eq!(
&buffer.channel_data(3)[..],
&[0.; RENDER_QUANTUM_SIZE][..],
abs_all <= 0.
);
assert_float_eq!(
&buffer.channel_data(4)[..],
&[0.; RENDER_QUANTUM_SIZE][..],
abs_all <= 0.
);
assert_float_eq!(
&buffer.channel_data(5)[..],
&[0.; RENDER_QUANTUM_SIZE][..],
abs_all <= 0.
);
}
{
let mut left_signal = alloc.silence();
left_signal.copy_from_slice(&[1.; RENDER_QUANTUM_SIZE]);
let mut right_signal = alloc.silence();
right_signal.copy_from_slice(&[0.5; RENDER_QUANTUM_SIZE]);
let mut buffer = AudioRenderQuantum::from(left_signal);
buffer.channels.push(right_signal);
assert_eq!(buffer.number_of_channels(), 2);
assert_float_eq!(
&buffer.channel_data(0)[..],
&[1.; RENDER_QUANTUM_SIZE][..],
abs_all <= 0.
);
assert_float_eq!(
&buffer.channel_data(1)[..],
&[0.5; RENDER_QUANTUM_SIZE][..],
abs_all <= 0.
);
buffer.mix(4, ChannelInterpretation::Speakers);
assert_eq!(buffer.number_of_channels(), 4);
assert_float_eq!(
&buffer.channel_data(0)[..],
&[1.; RENDER_QUANTUM_SIZE][..],
abs_all <= 0.
);
assert_float_eq!(
&buffer.channel_data(1)[..],
&[0.5; RENDER_QUANTUM_SIZE][..],
abs_all <= 0.
);
assert_float_eq!(
&buffer.channel_data(2)[..],
&[0.; RENDER_QUANTUM_SIZE][..],
abs_all <= 0.
);
assert_float_eq!(
&buffer.channel_data(3)[..],
&[0.; RENDER_QUANTUM_SIZE][..],
abs_all <= 0.
);
}
{
let mut left_signal = alloc.silence();
left_signal.copy_from_slice(&[1.; RENDER_QUANTUM_SIZE]);
let mut right_signal = alloc.silence();
right_signal.copy_from_slice(&[0.5; RENDER_QUANTUM_SIZE]);
let mut buffer = AudioRenderQuantum::from(left_signal);
buffer.channels.push(right_signal);
assert_eq!(buffer.number_of_channels(), 2);
assert_float_eq!(
&buffer.channel_data(0)[..],
&[1.; RENDER_QUANTUM_SIZE][..],
abs_all <= 0.
);
assert_float_eq!(
&buffer.channel_data(1)[..],
&[0.5; RENDER_QUANTUM_SIZE][..],
abs_all <= 0.
);
buffer.mix(6, ChannelInterpretation::Speakers);
assert_eq!(buffer.number_of_channels(), 6);
assert_float_eq!(
&buffer.channel_data(0)[..],
&[1.; RENDER_QUANTUM_SIZE][..],
abs_all <= 0.
);
assert_float_eq!(
&buffer.channel_data(1)[..],
&[0.5; RENDER_QUANTUM_SIZE][..],
abs_all <= 0.
);
assert_float_eq!(
&buffer.channel_data(2)[..],
&[0.; RENDER_QUANTUM_SIZE][..],
abs_all <= 0.
);
assert_float_eq!(
&buffer.channel_data(3)[..],
&[0.; RENDER_QUANTUM_SIZE][..],
abs_all <= 0.
);
assert_float_eq!(
&buffer.channel_data(4)[..],
&[0.; RENDER_QUANTUM_SIZE][..],
abs_all <= 0.
);
assert_float_eq!(
&buffer.channel_data(5)[..],
&[0.; RENDER_QUANTUM_SIZE][..],
abs_all <= 0.
);
}
{
let mut left_signal = alloc.silence();
left_signal.copy_from_slice(&[0.25; RENDER_QUANTUM_SIZE]);
let mut right_signal = alloc.silence();
right_signal.copy_from_slice(&[0.5; RENDER_QUANTUM_SIZE]);
let mut s_left_signal = alloc.silence();
s_left_signal.copy_from_slice(&[0.75; RENDER_QUANTUM_SIZE]);
let mut s_right_signal = alloc.silence();
s_right_signal.copy_from_slice(&[1.; RENDER_QUANTUM_SIZE]);
let mut buffer = AudioRenderQuantum::from(left_signal);
buffer.channels.push(right_signal);
buffer.channels.push(s_left_signal);
buffer.channels.push(s_right_signal);
assert_eq!(buffer.number_of_channels(), 4);
assert_float_eq!(
&buffer.channel_data(0)[..],
&[0.25; RENDER_QUANTUM_SIZE][..],
abs_all <= 0.
);
assert_float_eq!(
&buffer.channel_data(1)[..],
&[0.5; RENDER_QUANTUM_SIZE][..],
abs_all <= 0.
);
assert_float_eq!(
&buffer.channel_data(2)[..],
&[0.75; RENDER_QUANTUM_SIZE][..],
abs_all <= 0.
);
assert_float_eq!(
&buffer.channel_data(3)[..],
&[1.; RENDER_QUANTUM_SIZE][..],
abs_all <= 0.
);
buffer.mix(6, ChannelInterpretation::Speakers);
assert_eq!(buffer.number_of_channels(), 6);
assert_float_eq!(
&buffer.channel_data(0)[..],
&[0.25; RENDER_QUANTUM_SIZE][..],
abs_all <= 0.
);
assert_float_eq!(
&buffer.channel_data(1)[..],
&[0.5; RENDER_QUANTUM_SIZE][..],
abs_all <= 0.
);
assert_float_eq!(
&buffer.channel_data(2)[..],
&[0.; RENDER_QUANTUM_SIZE][..],
abs_all <= 0.
);
assert_float_eq!(
&buffer.channel_data(3)[..],
&[0.; RENDER_QUANTUM_SIZE][..],
abs_all <= 0.
);
assert_float_eq!(
&buffer.channel_data(4)[..],
&[0.75; RENDER_QUANTUM_SIZE][..],
abs_all <= 0.
);
assert_float_eq!(
&buffer.channel_data(5)[..],
&[1.; RENDER_QUANTUM_SIZE][..],
abs_all <= 0.
);
}
}
#[test]
fn test_audiobuffer_downmix_speakers() {
let alloc = Alloc::with_capacity(1);
{
let mut left_signal = alloc.silence();
left_signal.copy_from_slice(&[1.; RENDER_QUANTUM_SIZE]);
let mut right_signal = alloc.silence();
right_signal.copy_from_slice(&[0.5; RENDER_QUANTUM_SIZE]);
let mut buffer = AudioRenderQuantum::from(left_signal);
buffer.channels.push(right_signal);
assert_eq!(buffer.number_of_channels(), 2);
assert_float_eq!(
&buffer.channel_data(0)[..],
&[1.; RENDER_QUANTUM_SIZE][..],
abs_all <= 0.
);
assert_float_eq!(
&buffer.channel_data(1)[..],
&[0.5; RENDER_QUANTUM_SIZE][..],
abs_all <= 0.
);
buffer.mix(1, ChannelInterpretation::Speakers);
assert_eq!(buffer.number_of_channels(), 1);
assert_float_eq!(
&buffer.channel_data(0)[..],
&[0.75; RENDER_QUANTUM_SIZE][..],
abs_all <= 0.
);
}
{
let mut left_signal = alloc.silence();
left_signal.copy_from_slice(&[1.; RENDER_QUANTUM_SIZE]);
let mut right_signal = alloc.silence();
right_signal.copy_from_slice(&[0.75; RENDER_QUANTUM_SIZE]);
let mut s_left_signal = alloc.silence();
s_left_signal.copy_from_slice(&[0.5; RENDER_QUANTUM_SIZE]);
let mut s_right_signal = alloc.silence();
s_right_signal.copy_from_slice(&[0.25; RENDER_QUANTUM_SIZE]);
let mut buffer = AudioRenderQuantum::from(left_signal);
buffer.channels.push(right_signal);
buffer.channels.push(s_left_signal);
buffer.channels.push(s_right_signal);
assert_eq!(buffer.number_of_channels(), 4);
assert_float_eq!(
&buffer.channel_data(0)[..],
&[1.; RENDER_QUANTUM_SIZE][..],
abs_all <= 0.
);
assert_float_eq!(
&buffer.channel_data(1)[..],
&[0.75; RENDER_QUANTUM_SIZE][..],
abs_all <= 0.
);
assert_float_eq!(
&buffer.channel_data(2)[..],
&[0.5; RENDER_QUANTUM_SIZE][..],
abs_all <= 0.
);
assert_float_eq!(
&buffer.channel_data(3)[..],
&[0.25; RENDER_QUANTUM_SIZE][..],
abs_all <= 0.
);
buffer.mix(1, ChannelInterpretation::Speakers);
assert_eq!(buffer.number_of_channels(), 1);
assert_float_eq!(
&buffer.channel_data(0)[..],
&[0.625; RENDER_QUANTUM_SIZE][..],
abs_all <= 0.
);
}
{
let mut left_signal = alloc.silence();
left_signal.copy_from_slice(&[1.; RENDER_QUANTUM_SIZE]);
let mut right_signal = alloc.silence();
right_signal.copy_from_slice(&[0.9; RENDER_QUANTUM_SIZE]);
let mut center_signal = alloc.silence();
center_signal.copy_from_slice(&[0.8; RENDER_QUANTUM_SIZE]);
let mut low_freq_signal = alloc.silence();
low_freq_signal.copy_from_slice(&[0.7; RENDER_QUANTUM_SIZE]);
let mut s_left_signal = alloc.silence();
s_left_signal.copy_from_slice(&[0.6; RENDER_QUANTUM_SIZE]);
let mut s_right_signal = alloc.silence();
s_right_signal.copy_from_slice(&[0.5; RENDER_QUANTUM_SIZE]);
let mut buffer = AudioRenderQuantum::from(left_signal);
buffer.channels.push(right_signal);
buffer.channels.push(center_signal);
buffer.channels.push(low_freq_signal);
buffer.channels.push(s_left_signal);
buffer.channels.push(s_right_signal);
assert_eq!(buffer.number_of_channels(), 6);
assert_float_eq!(
&buffer.channel_data(0)[..],
&[1.; RENDER_QUANTUM_SIZE][..],
abs_all <= 0.
);
assert_float_eq!(
&buffer.channel_data(1)[..],
&[0.9; RENDER_QUANTUM_SIZE][..],
abs_all <= 0.
);
assert_float_eq!(
&buffer.channel_data(2)[..],
&[0.8; RENDER_QUANTUM_SIZE][..],
abs_all <= 0.
);
assert_float_eq!(
&buffer.channel_data(3)[..],
&[0.7; RENDER_QUANTUM_SIZE][..],
abs_all <= 0.
);
assert_float_eq!(
&buffer.channel_data(4)[..],
&[0.6; RENDER_QUANTUM_SIZE][..],
abs_all <= 0.
);
assert_float_eq!(
&buffer.channel_data(5)[..],
&[0.5; RENDER_QUANTUM_SIZE][..],
abs_all <= 0.
);
buffer.mix(1, ChannelInterpretation::Speakers);
assert_eq!(buffer.number_of_channels(), 1);
let res = (0.5_f32).sqrt() * (1. + 0.9) + 0.8 + 0.5 * (0.6 + 0.5);
assert_float_eq!(
&buffer.channel_data(0)[..],
&[res; RENDER_QUANTUM_SIZE][..],
abs_all <= 0.
);
}
{
let mut left_signal = alloc.silence();
left_signal.copy_from_slice(&[0.25; RENDER_QUANTUM_SIZE]);
let mut right_signal = alloc.silence();
right_signal.copy_from_slice(&[0.5; RENDER_QUANTUM_SIZE]);
let mut s_left_signal = alloc.silence();
s_left_signal.copy_from_slice(&[0.75; RENDER_QUANTUM_SIZE]);
let mut s_right_signal = alloc.silence();
s_right_signal.copy_from_slice(&[1.; RENDER_QUANTUM_SIZE]);
let mut buffer = AudioRenderQuantum::from(left_signal);
buffer.channels.push(right_signal);
buffer.channels.push(s_left_signal);
buffer.channels.push(s_right_signal);
assert_eq!(buffer.number_of_channels(), 4);
assert_float_eq!(
&buffer.channel_data(0)[..],
&[0.25; RENDER_QUANTUM_SIZE][..],
abs_all <= 0.
);
assert_float_eq!(
&buffer.channel_data(1)[..],
&[0.5; RENDER_QUANTUM_SIZE][..],
abs_all <= 0.
);
assert_float_eq!(
&buffer.channel_data(2)[..],
&[0.75; RENDER_QUANTUM_SIZE][..],
abs_all <= 0.
);
assert_float_eq!(
&buffer.channel_data(3)[..],
&[1.; RENDER_QUANTUM_SIZE][..],
abs_all <= 0.
);
buffer.mix(2, ChannelInterpretation::Speakers);
assert_eq!(buffer.number_of_channels(), 2);
assert_float_eq!(
&buffer.channel_data(0)[..],
&[0.5; RENDER_QUANTUM_SIZE][..],
abs_all <= 0.
);
assert_float_eq!(
&buffer.channel_data(1)[..],
&[0.75; RENDER_QUANTUM_SIZE][..],
abs_all <= 0.
);
}
{
let mut left_signal = alloc.silence();
left_signal.copy_from_slice(&[1.; RENDER_QUANTUM_SIZE]);
let mut right_signal = alloc.silence();
right_signal.copy_from_slice(&[0.9; RENDER_QUANTUM_SIZE]);
let mut center_signal = alloc.silence();
center_signal.copy_from_slice(&[0.8; RENDER_QUANTUM_SIZE]);
let mut low_freq_signal = alloc.silence();
low_freq_signal.copy_from_slice(&[0.7; RENDER_QUANTUM_SIZE]);
let mut s_left_signal = alloc.silence();
s_left_signal.copy_from_slice(&[0.6; RENDER_QUANTUM_SIZE]);
let mut s_right_signal = alloc.silence();
s_right_signal.copy_from_slice(&[0.5; RENDER_QUANTUM_SIZE]);
let mut buffer = AudioRenderQuantum::from(left_signal);
buffer.channels.push(right_signal);
buffer.channels.push(center_signal);
buffer.channels.push(low_freq_signal);
buffer.channels.push(s_left_signal);
buffer.channels.push(s_right_signal);
assert_eq!(buffer.number_of_channels(), 6);
assert_float_eq!(
&buffer.channel_data(0)[..],
&[1.; RENDER_QUANTUM_SIZE][..],
abs_all <= 0.
);
assert_float_eq!(
&buffer.channel_data(1)[..],
&[0.9; RENDER_QUANTUM_SIZE][..],
abs_all <= 0.
);
assert_float_eq!(
&buffer.channel_data(2)[..],
&[0.8; RENDER_QUANTUM_SIZE][..],
abs_all <= 0.
);
assert_float_eq!(
&buffer.channel_data(3)[..],
&[0.7; RENDER_QUANTUM_SIZE][..],
abs_all <= 0.
);
assert_float_eq!(
&buffer.channel_data(4)[..],
&[0.6; RENDER_QUANTUM_SIZE][..],
abs_all <= 0.
);
assert_float_eq!(
&buffer.channel_data(5)[..],
&[0.5; RENDER_QUANTUM_SIZE][..],
abs_all <= 0.
);
buffer.mix(2, ChannelInterpretation::Speakers);
assert_eq!(buffer.number_of_channels(), 2);
let res_left = 1. + (0.5_f32).sqrt() * (0.8 + 0.6);
let res_right = 0.9 + (0.5_f32).sqrt() * (0.8 + 0.5);
assert_float_eq!(
&buffer.channel_data(0)[..],
&[res_left; RENDER_QUANTUM_SIZE][..],
abs_all <= 0.
);
assert_float_eq!(
&buffer.channel_data(1)[..],
&[res_right; RENDER_QUANTUM_SIZE][..],
abs_all <= 0.
);
}
{
let mut left_signal = alloc.silence();
left_signal.copy_from_slice(&[1.; RENDER_QUANTUM_SIZE]);
let mut right_signal = alloc.silence();
right_signal.copy_from_slice(&[0.9; RENDER_QUANTUM_SIZE]);
let mut center_signal = alloc.silence();
center_signal.copy_from_slice(&[0.8; RENDER_QUANTUM_SIZE]);
let mut low_freq_signal = alloc.silence();
low_freq_signal.copy_from_slice(&[0.7; RENDER_QUANTUM_SIZE]);
let mut s_left_signal = alloc.silence();
s_left_signal.copy_from_slice(&[0.6; RENDER_QUANTUM_SIZE]);
let mut s_right_signal = alloc.silence();
s_right_signal.copy_from_slice(&[0.5; RENDER_QUANTUM_SIZE]);
let mut buffer = AudioRenderQuantum::from(left_signal);
buffer.channels.push(right_signal);
buffer.channels.push(center_signal);
buffer.channels.push(low_freq_signal);
buffer.channels.push(s_left_signal);
buffer.channels.push(s_right_signal);
assert_eq!(buffer.number_of_channels(), 6);
assert_float_eq!(
&buffer.channel_data(0)[..],
&[1.; RENDER_QUANTUM_SIZE][..],
abs_all <= 0.
);
assert_float_eq!(
&buffer.channel_data(1)[..],
&[0.9; RENDER_QUANTUM_SIZE][..],
abs_all <= 0.
);
assert_float_eq!(
&buffer.channel_data(2)[..],
&[0.8; RENDER_QUANTUM_SIZE][..],
abs_all <= 0.
);
assert_float_eq!(
&buffer.channel_data(3)[..],
&[0.7; RENDER_QUANTUM_SIZE][..],
abs_all <= 0.
);
assert_float_eq!(
&buffer.channel_data(4)[..],
&[0.6; RENDER_QUANTUM_SIZE][..],
abs_all <= 0.
);
assert_float_eq!(
&buffer.channel_data(5)[..],
&[0.5; RENDER_QUANTUM_SIZE][..],
abs_all <= 0.
);
buffer.mix(4, ChannelInterpretation::Speakers);
assert_eq!(buffer.number_of_channels(), 4);
let res_left = 1. + (0.5_f32).sqrt() * 0.8;
let res_right = 0.9 + (0.5_f32).sqrt() * 0.8;
assert_float_eq!(
&buffer.channel_data(0)[..],
&[res_left; RENDER_QUANTUM_SIZE][..],
abs_all <= 0.
);
assert_float_eq!(
&buffer.channel_data(1)[..],
&[res_right; RENDER_QUANTUM_SIZE][..],
abs_all <= 0.
);
assert_float_eq!(
&buffer.channel_data(2)[..],
&[0.6; RENDER_QUANTUM_SIZE][..],
abs_all <= 0.
);
assert_float_eq!(
&buffer.channel_data(3)[..],
&[0.5; RENDER_QUANTUM_SIZE][..],
abs_all <= 0.
);
}
}
#[test]
fn test_audiobuffer_add() {
let alloc = Alloc::with_capacity(1);
let mut signal = alloc.silence();
signal.copy_from_slice(&[1.; RENDER_QUANTUM_SIZE]);
let mut buffer = AudioRenderQuantum::from(signal);
buffer.mix(2, ChannelInterpretation::Speakers);
let mut signal2 = alloc.silence();
signal2.copy_from_slice(&[2.; RENDER_QUANTUM_SIZE]);
let buffer2 = AudioRenderQuantum::from(signal2);
let channel_config = crate::node::ChannelConfigOptions {
count: 2,
count_mode: ChannelCountMode::Explicit,
interpretation: ChannelInterpretation::Discrete,
}
.into();
buffer.add(&buffer2, &channel_config);
assert_eq!(buffer.number_of_channels(), 2);
assert_float_eq!(
&buffer.channel_data(0)[..],
&[3.; RENDER_QUANTUM_SIZE][..],
abs_all <= 0.
);
assert_float_eq!(
&buffer.channel_data(1)[..],
&[1.; RENDER_QUANTUM_SIZE][..],
abs_all <= 0.
);
}
#[test]
fn test_is_silent_quantum() {
let alloc = Alloc::with_capacity(1);
let signal = alloc.silence();
let mut buffer = AudioRenderQuantum::from(signal);
buffer.mix(2, ChannelInterpretation::Speakers);
assert_float_eq!(
&buffer.channel_data(0)[..],
&[0.; RENDER_QUANTUM_SIZE][..],
abs_all <= 0.
);
assert_float_eq!(
&buffer.channel_data(1)[..],
&[0.; RENDER_QUANTUM_SIZE][..],
abs_all <= 0.
);
assert!(buffer.is_silent());
}
#[test]
fn test_is_not_silent_quantum() {
let alloc = Alloc::with_capacity(1);
let mut signal = alloc.silence();
signal.copy_from_slice(&[1.; RENDER_QUANTUM_SIZE]);
let mut buffer = AudioRenderQuantum::from(signal);
buffer.mix(2, ChannelInterpretation::Discrete);
assert_float_eq!(
&buffer.channel_data(0)[..],
&[1.; RENDER_QUANTUM_SIZE][..],
abs_all <= 0.
);
assert_float_eq!(
&buffer.channel_data(1)[..],
&[0.; RENDER_QUANTUM_SIZE][..],
abs_all <= 0.
);
assert!(!buffer.is_silent());
}
}