Skip to content

Commit d915944

Browse files
committed
Change the way we model the silent channel - Option<Rc<..>> is free!
1 parent b3b33ea commit d915944

File tree

1 file changed

+49
-33
lines changed

1 file changed

+49
-33
lines changed

src/render/quantum.rs

Lines changed: 49 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -13,23 +13,15 @@ pub(crate) struct Alloc;
1313

1414
thread_local! {
1515
static POOL: RefCell<Vec<Rc<[f32; RENDER_QUANTUM_SIZE]>>> = RefCell::new(Vec::with_capacity(32));
16-
static ZEROES: Rc<[f32; RENDER_QUANTUM_SIZE]> = Rc::new([0.; RENDER_QUANTUM_SIZE]);
1716
}
1817

1918
impl Alloc {
20-
pub fn with_capacity(n: usize) -> Self {
19+
pub fn with_capacity(_n: usize) -> Self {
2120
Self {}
2221
}
2322

24-
#[cfg(test)]
25-
pub fn allocate(&self) -> AudioRenderQuantumChannel {
26-
AudioRenderQuantumChannel { data: allocate() }
27-
}
28-
2923
pub fn silence(&self) -> AudioRenderQuantumChannel {
30-
AudioRenderQuantumChannel {
31-
data: ZEROES.with(Rc::clone),
32-
}
24+
AudioRenderQuantumChannel { data: None }
3325
}
3426

3527
#[cfg(test)]
@@ -67,25 +59,35 @@ fn push(data: Rc<[f32; RENDER_QUANTUM_SIZE]>) {
6759
/// mutate it from there.
6860
#[derive(Clone, Debug)]
6961
pub struct AudioRenderQuantumChannel {
70-
data: Rc<[f32; RENDER_QUANTUM_SIZE]>,
62+
data: Option<Rc<[f32; RENDER_QUANTUM_SIZE]>>,
7163
}
7264

7365
impl AudioRenderQuantumChannel {
7466
fn make_mut(&mut self) -> &mut [f32; RENDER_QUANTUM_SIZE] {
75-
if Rc::strong_count(&self.data) != 1 {
76-
let mut new = allocate();
77-
Rc::make_mut(&mut new).copy_from_slice(self.data.deref());
78-
self.data = new;
67+
if self.data.is_none() {
68+
self.data = Some(allocate());
69+
Rc::make_mut(self.data.as_mut().unwrap()).fill(0.);
7970
}
8071

81-
Rc::make_mut(&mut self.data)
72+
match &mut self.data {
73+
Some(data) => {
74+
if Rc::strong_count(data) != 1 {
75+
let mut new = allocate();
76+
Rc::make_mut(&mut new).copy_from_slice(&data[..]);
77+
*data = new;
78+
}
79+
80+
return Rc::make_mut(data);
81+
}
82+
None => unreachable!(),
83+
}
8284
}
8385

8486
/// `O(1)` check if this buffer is equal to the 'silence buffer'
8587
///
8688
/// If this function returns false, it is still possible for all samples to be zero.
8789
pub(crate) fn is_silent(&self) -> bool {
88-
ZEROES.with(|z| Rc::ptr_eq(&self.data, z))
90+
self.data.is_none()
8991
}
9092

9193
/// Sum two channels
@@ -98,9 +100,7 @@ impl AudioRenderQuantumChannel {
98100
}
99101

100102
pub(crate) fn silence(&self) -> Self {
101-
Self {
102-
data: ZEROES.with(Rc::clone),
103-
}
103+
Self { data: None }
104104
}
105105
}
106106

@@ -110,7 +110,10 @@ impl Deref for AudioRenderQuantumChannel {
110110
type Target = [f32];
111111

112112
fn deref(&self) -> &Self::Target {
113-
self.data.as_slice()
113+
match &self.data {
114+
Some(data) => data.as_slice(),
115+
None => &[0.; RENDER_QUANTUM_SIZE],
116+
}
114117
}
115118
}
116119

@@ -122,16 +125,22 @@ impl DerefMut for AudioRenderQuantumChannel {
122125

123126
impl AsRef<[f32]> for AudioRenderQuantumChannel {
124127
fn as_ref(&self) -> &[f32] {
125-
&self.data[..]
128+
match &self.data {
129+
Some(data) => data.as_slice(),
130+
None => &[0.; RENDER_QUANTUM_SIZE],
131+
}
126132
}
127133
}
128134

129135
impl std::ops::Drop for AudioRenderQuantumChannel {
130136
fn drop(&mut self) {
131-
if Rc::strong_count(&self.data) == 1 {
132-
let zeroes = ZEROES.with(Rc::clone);
133-
let rc = std::mem::replace(&mut self.data, zeroes);
134-
push(rc);
137+
let data = match self.data.take() {
138+
None => return,
139+
Some(data) => data,
140+
};
141+
142+
if Rc::strong_count(&data) == 1 {
143+
push(data);
135144
}
136145
}
137146
}
@@ -626,8 +635,15 @@ impl AudioRenderQuantum {
626635
let mut channels = self.channels.iter();
627636
let first = channels.next().unwrap();
628637
for c in channels {
629-
if !Rc::ptr_eq(&first.data, &c.data) {
630-
return false;
638+
match (&first.data, &c.data) {
639+
(None, None) => (),
640+
(None, _) => return false,
641+
(_, None) => return false,
642+
(Some(d1), Some(d2)) => {
643+
if !Rc::ptr_eq(d1, d2) {
644+
return false;
645+
}
646+
}
631647
}
632648
}
633649

@@ -650,7 +666,7 @@ mod tests {
650666
alloc_counter::deny_alloc(|| {
651667
{
652668
// take a buffer out of the pool
653-
let a = alloc.allocate();
669+
let a = alloc.silence();
654670

655671
assert_float_eq!(&a[..], &[0.; RENDER_QUANTUM_SIZE][..], abs_all <= 0.);
656672
assert_eq!(alloc.pool_size(), 1);
@@ -675,12 +691,12 @@ mod tests {
675691
assert_eq!(alloc.pool_size(), 2);
676692

677693
let c = {
678-
let a = alloc.allocate();
679-
let b = alloc.allocate();
694+
let a = alloc.silence();
695+
let b = alloc.silence();
680696

681697
let c = alloc_counter::allow_alloc(|| {
682698
// we can allocate beyond the pool size
683-
let c = alloc.allocate();
699+
let c = alloc.silence();
684700
assert_eq!(alloc.pool_size(), 0);
685701
c
686702
});
@@ -757,7 +773,7 @@ mod tests {
757773
let mut signal1 = alloc.silence();
758774
signal1.copy_from_slice(&[1.; RENDER_QUANTUM_SIZE]);
759775

760-
let mut signal2 = alloc.allocate();
776+
let mut signal2 = alloc.silence();
761777
signal2.copy_from_slice(&[2.; RENDER_QUANTUM_SIZE]);
762778

763779
// test add silence to signal

0 commit comments

Comments
 (0)