diff --git a/src/context/offline.rs b/src/context/offline.rs index d49ce298..918af68a 100644 --- a/src/context/offline.rs +++ b/src/context/offline.rs @@ -2,10 +2,10 @@ use std::sync::atomic::AtomicU64; use std::sync::Arc; -use crate::assert_valid_sample_rate; use crate::buffer::AudioBuffer; use crate::context::{BaseAudioContext, ConcreteBaseAudioContext}; use crate::render::RenderThread; +use crate::{assert_valid_sample_rate, RENDER_QUANTUM_SIZE}; /// The `OfflineAudioContext` doesn't render the audio to the device hardware; instead, it generates /// it, as fast as it can, and outputs the result to an `AudioBuffer`. @@ -44,7 +44,7 @@ impl OfflineAudioContext { let (sender, receiver) = crossbeam_channel::unbounded(); let (node_id_producer, node_id_consumer) = llq::Queue::new().split(); - let graph = crate::render::graph::Graph::new(node_id_producer); + let graph = crate::render::graph::Graph::new(RENDER_QUANTUM_SIZE, node_id_producer); let message = crate::message::ControlMessage::Startup { graph }; sender.send(message).unwrap(); diff --git a/src/context/online.rs b/src/context/online.rs index 4172080f..b3e5c876 100644 --- a/src/context/online.rs +++ b/src/context/online.rs @@ -10,8 +10,7 @@ use crate::media_streams::{MediaStream, MediaStreamTrack}; use crate::message::ControlMessage; use crate::node::{self, ChannelConfigOptions}; use crate::render::graph::Graph; -use crate::MediaElement; -use crate::{AudioRenderCapacity, Event}; +use crate::{AudioRenderCapacity, Event, MediaElement, RENDER_QUANTUM_SIZE}; /// Check if the provided sink_id is available for playback /// @@ -174,7 +173,7 @@ impl AudioContext { } = control_thread_init; let (node_id_producer, node_id_consumer) = llq::Queue::new().split(); - let graph = Graph::new(node_id_producer); + let graph = Graph::new(RENDER_QUANTUM_SIZE, node_id_producer); let message = ControlMessage::Startup { graph }; ctrl_msg_send.send(message).unwrap(); diff --git a/src/param.rs b/src/param.rs index ec794ceb..11a02e84 100644 --- a/src/param.rs +++ b/src/param.rs @@ -3281,7 +3281,7 @@ mod tests { #[test] fn test_varying_param_size_modulated() { - let alloc = Alloc::with_capacity(1); + let alloc = Alloc::new(RENDER_QUANTUM_SIZE, 1); // buffer length is 1 and input is silence (no modulation) { @@ -3348,7 +3348,7 @@ mod tests { #[test] fn test_full_render_chain() { - let alloc = Alloc::with_capacity(1); + let alloc = Alloc::new(RENDER_QUANTUM_SIZE, 1); // prevent regression between the different processing stage let context = OfflineAudioContext::new(1, 0, 48000.); diff --git a/src/render/graph.rs b/src/render/graph.rs index 34b07111..7b52ba3b 100644 --- a/src/render/graph.rs +++ b/src/render/graph.rs @@ -95,10 +95,10 @@ pub(crate) struct Graph { } impl Graph { - pub fn new(reclaim_id_channel: llq::Producer) -> Self { + pub fn new(buffer_size: usize, reclaim_id_channel: llq::Producer) -> Self { Graph { nodes: NodeCollection::new(), - alloc: Alloc::with_capacity(64), + alloc: Alloc::new(buffer_size, 64), reclaim_id_channel, ordered: vec![], marked: vec![], @@ -487,6 +487,7 @@ impl Graph { #[cfg(test)] mod tests { use super::*; + use crate::RENDER_QUANTUM_SIZE; #[derive(Debug, Clone)] struct TestNode { @@ -530,7 +531,7 @@ mod tests { #[test] fn test_add_remove() { - let mut graph = Graph::new(llq::Queue::new().split().0); + let mut graph = Graph::new(RENDER_QUANTUM_SIZE, llq::Queue::new().split().0); let node = Box::new(TestNode { tail_time: false }); add_node(&mut graph, 0, node.clone()); @@ -581,7 +582,7 @@ mod tests { #[test] fn test_remove_all() { - let mut graph = Graph::new(llq::Queue::new().split().0); + let mut graph = Graph::new(RENDER_QUANTUM_SIZE, llq::Queue::new().split().0); let node = Box::new(TestNode { tail_time: false }); add_node(&mut graph, 0, node.clone()); @@ -620,7 +621,7 @@ mod tests { #[test] fn test_cycle() { - let mut graph = Graph::new(llq::Queue::new().split().0); + let mut graph = Graph::new(RENDER_QUANTUM_SIZE, llq::Queue::new().split().0); let node = Box::new(TestNode { tail_time: false }); add_node(&mut graph, 0, node.clone()); @@ -656,7 +657,7 @@ mod tests { #[test] fn test_lifecycle_and_reclaim() { let (node_id_producer, mut node_id_consumer) = llq::Queue::new().split(); - let mut graph = Graph::new(node_id_producer); + let mut graph = Graph::new(RENDER_QUANTUM_SIZE, node_id_producer); let node = Box::new(TestNode { tail_time: false }); @@ -698,7 +699,7 @@ mod tests { #[test] fn test_audio_param_lifecycle() { let (node_id_producer, mut node_id_consumer) = llq::Queue::new().split(); - let mut graph = Graph::new(node_id_producer); + let mut graph = Graph::new(RENDER_QUANTUM_SIZE, node_id_producer); let node = Box::new(TestNode { tail_time: false }); diff --git a/src/render/quantum.rs b/src/render/quantum.rs index 6f7a2479..09b63bda 100644 --- a/src/render/quantum.rs +++ b/src/render/quantum.rs @@ -6,7 +6,7 @@ use std::rc::Rc; use crate::node::{ChannelConfig, ChannelCountMode, ChannelInterpretation}; use crate::assert_valid_number_of_channels; -use crate::{MAX_CHANNELS, RENDER_QUANTUM_SIZE}; +use crate::MAX_CHANNELS; // object pool for `AudioRenderQuantumChannel`s, only allocate if the pool is empty pub(crate) struct Alloc { @@ -15,16 +15,19 @@ pub(crate) struct Alloc { #[derive(Debug)] struct AllocInner { - pool: RefCell>>, - zeroes: Rc<[f32; RENDER_QUANTUM_SIZE]>, + buffer_size: usize, + pool: RefCell>>, + zeroes: Rc<[f32]>, } 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]); + pub fn new(buffer_size: usize, capacity: usize) -> Self { + let array = vec![0.; buffer_size]; + let pool: Vec<_> = (0..capacity).map(|_| Rc::from(array.as_slice())).collect(); + let zeroes = Rc::from(array); let inner = AllocInner { + buffer_size, pool: RefCell::new(pool), zeroes, }; @@ -56,17 +59,18 @@ impl Alloc { } impl AllocInner { - fn allocate(&self) -> Rc<[f32; RENDER_QUANTUM_SIZE]> { + fn allocate(&self) -> Rc<[f32]> { if let Some(rc) = self.pool.borrow_mut().pop() { // reuse from pool rc } else { // allocate - Rc::new([0.; RENDER_QUANTUM_SIZE]) + let array = vec![0.; self.buffer_size]; + Rc::from(array.as_slice()) } } - fn push(&self, data: Rc<[f32; RENDER_QUANTUM_SIZE]>) { + fn push(&self, data: Rc<[f32]>) { self.pool .borrow_mut() // infallible when single threaded .push(data); @@ -96,19 +100,21 @@ impl AllocInner { /// ``` #[derive(Clone, Debug)] pub struct AudioRenderQuantumChannel { - data: Rc<[f32; RENDER_QUANTUM_SIZE]>, + data: Rc<[f32]>, alloc: Rc, } impl AudioRenderQuantumChannel { - fn make_mut(&mut self) -> &mut [f32; RENDER_QUANTUM_SIZE] { + fn make_mut(&mut self) -> &mut [f32] { if Rc::strong_count(&self.data) != 1 { let mut new = self.alloc.allocate(); - Rc::make_mut(&mut new).copy_from_slice(self.data.deref()); + Rc::get_mut(&mut new) + .unwrap() + .copy_from_slice(self.data.deref()); self.data = new; } - Rc::make_mut(&mut self.data) + Rc::get_mut(&mut self.data).unwrap() } /// `O(1)` check if this buffer is equal to the 'silence buffer' @@ -141,7 +147,7 @@ impl Deref for AudioRenderQuantumChannel { type Target = [f32]; fn deref(&self) -> &Self::Target { - self.data.as_slice() + &self.data[..] } } @@ -675,10 +681,12 @@ mod tests { use super::*; + use crate::RENDER_QUANTUM_SIZE; + #[test] fn test_pool() { // Create pool of size 2 - let alloc = Alloc::with_capacity(2); + let alloc = Alloc::new(RENDER_QUANTUM_SIZE, 2); assert_eq!(alloc.pool_size(), 2); alloc_counter::deny_alloc(|| { @@ -756,7 +764,7 @@ mod tests { #[test] fn test_silence() { - let alloc = Alloc::with_capacity(1); + let alloc = Alloc::new(RENDER_QUANTUM_SIZE, 1); let silence = alloc.silence(); assert_float_eq!(&silence[..], &[0.; RENDER_QUANTUM_SIZE][..], abs_all <= 0.); @@ -785,7 +793,7 @@ mod tests { #[test] fn test_channel_add() { - let alloc = Alloc::with_capacity(1); + let alloc = Alloc::new(RENDER_QUANTUM_SIZE, 1); let silence = alloc.silence(); let mut signal1 = alloc.silence(); @@ -810,7 +818,7 @@ mod tests { #[test] fn test_audiobuffer_channels() { - let alloc = Alloc::with_capacity(1); + let alloc = Alloc::new(RENDER_QUANTUM_SIZE, 1); let silence = alloc.silence(); let buffer = AudioRenderQuantum::from(silence); @@ -827,7 +835,7 @@ mod tests { #[test] fn test_audiobuffer_mix_discrete() { - let alloc = Alloc::with_capacity(1); + let alloc = Alloc::new(RENDER_QUANTUM_SIZE, 1); let mut signal = alloc.silence(); signal.copy_from_slice(&[1.; RENDER_QUANTUM_SIZE]); @@ -869,7 +877,7 @@ mod tests { #[test] fn test_audiobuffer_upmix_speakers() { - let alloc = Alloc::with_capacity(1); + let alloc = Alloc::new(RENDER_QUANTUM_SIZE, 1); { // 1 -> 2 @@ -1275,7 +1283,7 @@ mod tests { #[test] fn test_audiobuffer_downmix_speakers() { - let alloc = Alloc::with_capacity(1); + let alloc = Alloc::new(RENDER_QUANTUM_SIZE, 1); { // 2 -> 1 @@ -1627,7 +1635,7 @@ mod tests { #[test] fn test_audiobuffer_add() { - let alloc = Alloc::with_capacity(1); + let alloc = Alloc::new(RENDER_QUANTUM_SIZE, 1); let mut signal = alloc.silence(); signal.copy_from_slice(&[1.; RENDER_QUANTUM_SIZE]); @@ -1662,7 +1670,7 @@ mod tests { #[test] fn test_is_silent_quantum() { - let alloc = Alloc::with_capacity(1); + let alloc = Alloc::new(RENDER_QUANTUM_SIZE, 1); // create 2 channel silent buffer let signal = alloc.silence(); @@ -1685,7 +1693,7 @@ mod tests { #[test] fn test_is_not_silent_quantum() { - let alloc = Alloc::with_capacity(1); + let alloc = Alloc::new(RENDER_QUANTUM_SIZE, 1); // create 2 channel silent buffer let mut signal = alloc.silence();