Skip to content

Commit 402e21f

Browse files
committed
NodeCollection is now indexed by AudioNodeId, not usize
1 parent 3e517c6 commit 402e21f

File tree

4 files changed

+46
-56
lines changed

4 files changed

+46
-56
lines changed

src/context/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ pub(crate) struct AudioNodeId(pub u64);
4343
///
4444
/// Store these in your `AudioProcessor` to get access to `AudioParam` values.
4545
#[derive(Debug)]
46-
pub struct AudioParamId(pub(crate) u64);
46+
pub struct AudioParamId(u64);
4747

4848
// bit contrived, but for type safety only the context mod can access the inner u64
4949
impl From<&AudioParamId> for AudioNodeId {

src/render/graph.rs

Lines changed: 19 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,6 @@ impl Graph {
130130
let inputs = vec![AudioRenderQuantum::from(self.alloc.silence()); number_of_inputs];
131131
let outputs = vec![AudioRenderQuantum::from(self.alloc.silence()); number_of_outputs];
132132

133-
let index = index.0 as usize;
134133
self.nodes.insert(
135134
index,
136135
RefCell::new(Node {
@@ -148,7 +147,7 @@ impl Graph {
148147
}
149148

150149
pub fn add_edge(&mut self, source: (AudioNodeId, usize), dest: (AudioNodeId, usize)) {
151-
self.nodes[source.0 .0 as usize]
150+
self.nodes[source.0]
152151
.get_mut()
153152
.outgoing_edges
154153
.push(OutgoingEdge {
@@ -161,7 +160,7 @@ impl Graph {
161160
}
162161

163162
pub fn remove_edge(&mut self, source: AudioNodeId, dest: AudioNodeId) {
164-
self.nodes[source.0 as usize]
163+
self.nodes[source]
165164
.get_mut()
166165
.outgoing_edges
167166
.retain(|edge| edge.other_id != dest);
@@ -170,10 +169,7 @@ impl Graph {
170169
}
171170

172171
pub fn remove_edges_from(&mut self, source: AudioNodeId) {
173-
self.nodes[source.0 as usize]
174-
.get_mut()
175-
.outgoing_edges
176-
.clear();
172+
self.nodes[source].get_mut().outgoing_edges.clear();
177173

178174
self.nodes.values_mut().for_each(|node| {
179175
node.get_mut()
@@ -188,20 +184,17 @@ impl Graph {
188184
// Issue #92, a race condition can occur for AudioParams. They may have already been
189185
// removed from the audio graph if the node they feed into was dropped.
190186
// Therefore, do not assume this node still exists:
191-
if let Some(node) = self.nodes.get_mut(index.0 as usize) {
187+
if let Some(node) = self.nodes.get_mut(index) {
192188
node.get_mut().free_when_finished = true;
193189
}
194190
}
195191

196192
pub fn mark_cycle_breaker(&mut self, index: AudioNodeId) {
197-
self.nodes[index.0 as usize].get_mut().cycle_breaker = true;
193+
self.nodes[index].get_mut().cycle_breaker = true;
198194
}
199195

200196
pub fn route_message(&mut self, index: AudioNodeId, msg: &mut dyn Any) {
201-
self.nodes[index.0 as usize]
202-
.get_mut()
203-
.processor
204-
.onmessage(msg);
197+
self.nodes[index].get_mut().processor.onmessage(msg);
205198
}
206199

207200
/// Helper function for `order_nodes` - traverse node and outgoing edges
@@ -224,7 +217,7 @@ impl Graph {
224217
let cycle_breaker_node = marked_temp
225218
.iter()
226219
.skip(pos)
227-
.find(|node_id| self.nodes[node_id.0 as usize].borrow().cycle_breaker);
220+
.find(|&&node_id| self.nodes[node_id].borrow().cycle_breaker);
228221

229222
match cycle_breaker_node {
230223
Some(&node_id) => {
@@ -253,11 +246,7 @@ impl Graph {
253246
marked_temp.push(node_id);
254247

255248
// Visit outgoing nodes, and call `visit` on them recursively
256-
for edge in self.nodes[node_id.0 as usize]
257-
.borrow()
258-
.outgoing_edges
259-
.iter()
260-
{
249+
for edge in self.nodes[node_id].borrow().outgoing_edges.iter() {
261250
let cycle_breaker_applied = self.visit(
262251
edge.other_id,
263252
marked,
@@ -319,7 +308,7 @@ impl Graph {
319308
// since the audio graph could contain legs detached from the destination and those should
320309
// still be rendered.
321310
let mut cycle_breaker_applied = false;
322-
for node_id in self.nodes.keys().map(|i| AudioNodeId(i as u64)) {
311+
for node_id in self.nodes.keys() {
323312
cycle_breaker_applied = self.visit(
324313
node_id,
325314
&mut marked,
@@ -338,7 +327,7 @@ impl Graph {
338327
// clear the outgoing edges of the nodes that have been recognized as cycle breaker
339328
let nodes = &mut self.nodes;
340329
cycle_breakers.iter().for_each(|node_id| {
341-
nodes[node_id.0 as usize].get_mut().outgoing_edges.clear();
330+
nodes[*node_id].get_mut().outgoing_edges.clear();
342331
});
343332

344333
continue;
@@ -379,7 +368,7 @@ impl Graph {
379368
// process every node, in topological sorted order
380369
self.ordered.iter().for_each(|index| {
381370
// acquire a mutable borrow of the current processing node
382-
let mut node = nodes[index.0 as usize].borrow_mut();
371+
let mut node = nodes[*index].borrow_mut();
383372

384373
// make sure all input buffers have the correct number of channels, this might not be
385374
// the case if the node has no inputs connected or the channel count has just changed
@@ -414,7 +403,7 @@ impl Graph {
414403
// audio params are connected to the 'hidden' usize::MAX output, ignore them here
415404
.filter(|edge| edge.other_index != usize::MAX)
416405
.for_each(|edge| {
417-
let mut output_node = nodes[edge.other_id.0 as usize].borrow_mut();
406+
let mut output_node = nodes[edge.other_id].borrow_mut();
418407
output_node.has_inputs_connected = true;
419408
let signal = &node.outputs[edge.self_index];
420409
let channel_config = &output_node.channel_config.clone();
@@ -440,7 +429,7 @@ impl Graph {
440429
// Check if we can decommission this node (end of life)
441430
if can_free {
442431
// Node is dropped, remove it from the node list
443-
let mut node = nodes.remove(index.0 as usize).into_inner();
432+
let mut node = nodes.remove(*index).into_inner();
444433
self.reclaim_id_channel
445434
.push(node.reclaim_id.take().unwrap());
446435
drop(node);
@@ -467,7 +456,7 @@ impl Graph {
467456
// - special node (destination = id 0, listener = id 1), or
468457
// - not connected to this dropped node, or
469458
// - if the control thread still has a handle to it.
470-
let retain = id < 2 || !was_connected || !node.free_when_finished;
459+
let retain = id.0 < 2 || !was_connected || !node.free_when_finished;
471460

472461
if !retain {
473462
self.reclaim_id_channel
@@ -482,7 +471,7 @@ impl Graph {
482471
if nodes_dropped {
483472
let mut i = 0;
484473
while i < self.ordered.len() {
485-
if nodes.get(self.ordered[i].0 as usize).is_none() {
474+
if nodes.get(self.ordered[i]).is_none() {
486475
self.ordered.remove(i);
487476
} else {
488477
i += 1;
@@ -491,7 +480,7 @@ impl Graph {
491480
}
492481

493482
// Return the output buffer of destination node
494-
&self.nodes[0].get_mut().outputs[0]
483+
&self.nodes[AudioNodeId(0)].get_mut().outputs[0]
495484
}
496485
}
497486

@@ -681,7 +670,7 @@ mod tests {
681670
// dropped and the AudioNodeId(3) should be reclaimed
682671
add_node(&mut graph, 2, node.clone());
683672
// Mark the node as 'detached from the control thread', so it is allowed to drop
684-
graph.nodes[2].get_mut().free_when_finished = true;
673+
graph.nodes[AudioNodeId(2)].get_mut().free_when_finished = true;
685674

686675
// Connect the regular node to the AudioDestinationNode
687676
add_edge(&mut graph, 2, 0);
@@ -723,7 +712,7 @@ mod tests {
723712
// dropped and the AudioNodeId(3) should be reclaimed
724713
add_node(&mut graph, 2, node.clone());
725714
// Mark the node as 'detached from the control thread', so it is allowed to drop
726-
graph.nodes[2].get_mut().free_when_finished = true;
715+
graph.nodes[AudioNodeId(2)].get_mut().free_when_finished = true;
727716

728717
// Connect the regular node to the AudioDestinationNode
729718
add_edge(&mut graph, 2, 0);
@@ -732,7 +721,7 @@ mod tests {
732721
let param = Box::new(TestNode { tail_time: true }); // audio params have tail time true
733722
add_node(&mut graph, 3, param);
734723
// Mark the node as 'detached from the control thread', so it is allowed to drop
735-
graph.nodes[3].get_mut().free_when_finished = true;
724+
graph.nodes[AudioNodeId(3)].get_mut().free_when_finished = true;
736725

737726
// Connect the audioparam to the regular node
738727
add_audioparam(&mut graph, 3, 2);

src/render/node_collection.rs

Lines changed: 25 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1+
use crate::context::AudioNodeId;
12
use crate::render::graph::Node;
3+
24
use std::cell::RefCell;
35
use std::ops::{Index, IndexMut};
46

5-
pub struct NodeCollection {
7+
pub(crate) struct NodeCollection {
68
nodes: Vec<Option<RefCell<Node>>>,
79
}
810

@@ -26,26 +28,25 @@ impl NodeCollection {
2628
}
2729

2830
#[inline(always)]
29-
pub fn insert(&mut self, index: usize, value: RefCell<Node>) {
31+
pub fn insert(&mut self, index: AudioNodeId, value: RefCell<Node>) {
32+
let index = index.0 as usize;
3033
self.ensure_capacity(index + 1);
3134
self.nodes[index] = Some(value);
3235
}
3336

3437
#[inline(always)]
35-
pub fn remove(&mut self, index: usize) -> RefCell<Node> {
36-
self.nodes
37-
.get_mut(index)
38-
.expect("Unexpected remove index for NodeCollection")
38+
pub fn remove(&mut self, index: AudioNodeId) -> RefCell<Node> {
39+
self.nodes[index.0 as usize]
3940
.take()
4041
.expect("Unable to remove non-existing Node in NodeCollection")
4142
}
4243

4344
#[inline(always)]
44-
pub fn keys(&self) -> impl Iterator<Item = usize> + '_ {
45+
pub fn keys(&self) -> impl Iterator<Item = AudioNodeId> + '_ {
4546
self.nodes
4647
.iter()
4748
.enumerate()
48-
.filter_map(|(i, v)| v.as_ref().and(Some(i)))
49+
.filter_map(|(i, v)| v.as_ref().and(Some(AudioNodeId(i as u64))))
4950
}
5051

5152
#[inline(always)]
@@ -54,52 +55,52 @@ impl NodeCollection {
5455
}
5556

5657
#[inline(always)]
57-
pub fn get(&self, index: usize) -> Option<&RefCell<Node>> {
58-
self.nodes[index].as_ref()
58+
pub fn get(&self, index: AudioNodeId) -> Option<&RefCell<Node>> {
59+
self.nodes[index.0 as usize].as_ref()
5960
}
6061

6162
#[inline(always)]
62-
pub fn get_mut(&mut self, index: usize) -> Option<&mut RefCell<Node>> {
63-
self.nodes[index].as_mut()
63+
pub fn get_mut(&mut self, index: AudioNodeId) -> Option<&mut RefCell<Node>> {
64+
self.nodes[index.0 as usize].as_mut()
6465
}
6566

6667
#[inline(always)]
6768
pub fn retain<F>(&mut self, mut f: F)
6869
where
69-
F: FnMut(usize, &mut RefCell<Node>) -> bool,
70+
F: FnMut(AudioNodeId, &mut RefCell<Node>) -> bool,
7071
{
7172
self.nodes.iter_mut().enumerate().for_each(|(i, opt)| {
7273
if let Some(v) = opt.as_mut() {
73-
if !f(i, v) {
74+
if !f(AudioNodeId(i as u64), v) {
7475
*opt = None;
7576
}
7677
}
7778
})
7879
}
7980
}
8081

81-
impl Index<usize> for NodeCollection {
82+
impl Index<AudioNodeId> for NodeCollection {
8283
type Output = RefCell<Node>;
8384

8485
#[track_caller]
8586
#[inline(always)]
86-
fn index(&self, index: usize) -> &Self::Output {
87+
fn index(&self, index: AudioNodeId) -> &Self::Output {
8788
self.nodes
88-
.get(index)
89-
.unwrap_or_else(|| panic!("Unexpected index {} for NodeCollection", index))
89+
.get(index.0 as usize)
90+
.unwrap_or_else(|| panic!("Unexpected index {} for NodeCollection", index.0))
9091
.as_ref()
91-
.unwrap_or_else(|| panic!("Index {} for dropped Node in NodeCollection", index))
92+
.unwrap_or_else(|| panic!("Index {} for dropped Node in NodeCollection", index.0))
9293
}
9394
}
9495

95-
impl IndexMut<usize> for NodeCollection {
96+
impl IndexMut<AudioNodeId> for NodeCollection {
9697
#[track_caller]
9798
#[inline(always)]
98-
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
99+
fn index_mut(&mut self, index: AudioNodeId) -> &mut Self::Output {
99100
self.nodes
100-
.get_mut(index)
101-
.unwrap_or_else(|| panic!("Unexpected index {} for NodeCollection", index))
101+
.get_mut(index.0 as usize)
102+
.unwrap_or_else(|| panic!("Unexpected index {} for NodeCollection", index.0))
102103
.as_mut()
103-
.unwrap_or_else(|| panic!("Index {} for dropped Node in NodeCollection", index))
104+
.unwrap_or_else(|| panic!("Index {} for dropped Node in NodeCollection", index.0))
104105
}
105106
}

src/render/processor.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ impl<'a> AudioParamValues<'a> {
154154
/// provide a slice of length equal to the render quantum size (default: 128)
155155
#[allow(clippy::missing_panics_doc)]
156156
pub fn get(&self, index: &AudioParamId) -> impl Deref<Target = [f32]> + '_ {
157-
DerefAudioRenderQuantumChannel(self.nodes[index.0 as usize].borrow())
157+
DerefAudioRenderQuantumChannel(self.nodes[index.into()].borrow())
158158
}
159159

160160
pub(crate) fn listener_params(&self) -> [impl Deref<Target = [f32]> + '_; 9] {

0 commit comments

Comments
 (0)