@@ -4,7 +4,6 @@ use std::cell::RefCell;
44use std:: panic:: { self , AssertUnwindSafe } ;
55
66use crate :: context:: AudioNodeId ;
7- use rustc_hash:: FxHashMap ;
87use smallvec:: { smallvec, SmallVec } ;
98
109use super :: { Alloc , AudioParamValues , AudioProcessor , AudioRenderQuantum } ;
@@ -76,7 +75,7 @@ impl Node {
7675/// The audio graph
7776pub ( crate ) struct Graph {
7877 /// Processing Nodes
79- nodes : FxHashMap < AudioNodeId , RefCell < Node > > ,
78+ nodes : Vec < Option < RefCell < Node > > > ,
8079 /// Allocator for audio buffers
8180 alloc : Alloc ,
8281
@@ -95,7 +94,7 @@ pub(crate) struct Graph {
9594impl Graph {
9695 pub fn new ( ) -> Self {
9796 Graph {
98- nodes : FxHashMap :: default ( ) ,
97+ nodes : Vec :: with_capacity ( 64 ) ,
9998 ordered : vec ! [ ] ,
10099 marked : vec ! [ ] ,
101100 marked_temp : vec ! [ ] ,
@@ -126,25 +125,28 @@ impl Graph {
126125 let inputs = vec ! [ AudioRenderQuantum :: from( self . alloc. silence( ) ) ; number_of_inputs] ;
127126 let outputs = vec ! [ AudioRenderQuantum :: from( self . alloc. silence( ) ) ; number_of_outputs] ;
128127
129- self . nodes . insert (
130- index,
131- RefCell :: new ( Node {
132- processor,
133- inputs,
134- outputs,
135- channel_config,
136- outgoing_edges : smallvec ! [ ] ,
137- free_when_finished : false ,
138- has_inputs_connected : false ,
139- cycle_breaker : false ,
140- } ) ,
141- ) ;
128+ let index = index. 0 as usize ;
129+ if index >= self . nodes . len ( ) {
130+ self . nodes . resize_with ( index + 1 , || None ) ;
131+ }
132+ self . nodes [ index] = Some ( RefCell :: new ( Node {
133+ processor,
134+ inputs,
135+ outputs,
136+ channel_config,
137+ outgoing_edges : smallvec ! [ ] ,
138+ free_when_finished : false ,
139+ has_inputs_connected : false ,
140+ cycle_breaker : false ,
141+ } ) ) ;
142142 }
143143
144144 pub fn add_edge ( & mut self , source : ( AudioNodeId , usize ) , dest : ( AudioNodeId , usize ) ) {
145145 self . nodes
146- . get_mut ( & source. 0 )
146+ . get_mut ( source. 0 . 0 as usize )
147147 . unwrap_or_else ( || panic ! ( "cannot connect {:?} to {:?}" , source, dest) )
148+ . as_mut ( )
149+ . unwrap ( )
148150 . get_mut ( )
149151 . outgoing_edges
150152 . push ( OutgoingEdge {
@@ -158,8 +160,10 @@ impl Graph {
158160
159161 pub fn remove_edge ( & mut self , source : AudioNodeId , dest : AudioNodeId ) {
160162 self . nodes
161- . get_mut ( & source)
163+ . get_mut ( source. 0 as usize )
162164 . unwrap_or_else ( || panic ! ( "cannot remove the edge from {:?} to {:?}" , source, dest) )
165+ . as_mut ( )
166+ . unwrap ( )
163167 . get_mut ( )
164168 . outgoing_edges
165169 . retain ( |edge| edge. other_id != dest) ;
@@ -169,13 +173,15 @@ impl Graph {
169173
170174 pub fn remove_edges_from ( & mut self , source : AudioNodeId ) {
171175 self . nodes
172- . get_mut ( & source)
176+ . get_mut ( source. 0 as usize )
173177 . unwrap_or_else ( || panic ! ( "cannot remove edges from {:?}" , source) )
178+ . as_mut ( )
179+ . unwrap ( )
174180 . get_mut ( )
175181 . outgoing_edges
176182 . clear ( ) ;
177183
178- self . nodes . values_mut ( ) . for_each ( |node| {
184+ self . nodes . iter_mut ( ) . flatten ( ) . for_each ( |node| {
179185 node. get_mut ( )
180186 . outgoing_edges
181187 . retain ( |edge| edge. other_id != source) ;
@@ -188,18 +194,26 @@ impl Graph {
188194 // Issue #92, a race condition can occur for AudioParams. They may have already been
189195 // removed from the audio graph if the node they feed into was dropped.
190196 // Therefore, do not assume this node still exists:
191- if let Some ( node) = self . nodes . get_mut ( & index) {
197+ if let Some ( node) = self . nodes . get_mut ( index. 0 as usize ) . unwrap ( ) . as_mut ( ) {
192198 node. get_mut ( ) . free_when_finished = true ;
193199 }
194200 }
195201
196202 pub fn mark_cycle_breaker ( & mut self , index : AudioNodeId ) {
197- self . nodes . get_mut ( & index) . unwrap ( ) . get_mut ( ) . cycle_breaker = true ;
203+ self . nodes
204+ . get_mut ( index. 0 as usize )
205+ . unwrap ( )
206+ . as_mut ( )
207+ . unwrap ( )
208+ . get_mut ( )
209+ . cycle_breaker = true ;
198210 }
199211
200212 pub fn route_message ( & mut self , index : AudioNodeId , msg : & mut dyn Any ) {
201213 self . nodes
202- . get_mut ( & index)
214+ . get_mut ( index. 0 as usize )
215+ . unwrap ( )
216+ . as_mut ( )
203217 . unwrap ( )
204218 . get_mut ( )
205219 . processor
@@ -223,10 +237,15 @@ impl Graph {
223237 // If this node is in the cycle detection list, it is part of a cycle!
224238 if let Some ( pos) = marked_temp. iter ( ) . position ( |& m| m == node_id) {
225239 // check if we can find some node that can break the cycle
226- let cycle_breaker_node = marked_temp
227- . iter ( )
228- . skip ( pos)
229- . find ( |node_id| self . nodes . get ( node_id) . unwrap ( ) . borrow ( ) . cycle_breaker ) ;
240+ let cycle_breaker_node = marked_temp. iter ( ) . skip ( pos) . find ( |node_id| {
241+ self . nodes
242+ . get ( node_id. 0 as usize )
243+ . unwrap ( )
244+ . as_ref ( )
245+ . unwrap ( )
246+ . borrow ( )
247+ . cycle_breaker
248+ } ) ;
230249
231250 match cycle_breaker_node {
232251 Some ( & node_id) => {
@@ -257,7 +276,9 @@ impl Graph {
257276 // Visit outgoing nodes, and call `visit` on them recursively
258277 for edge in self
259278 . nodes
260- . get ( & node_id)
279+ . get ( node_id. 0 as usize )
280+ . unwrap ( )
281+ . as_ref ( )
261282 . unwrap ( )
262283 . borrow ( )
263284 . outgoing_edges
@@ -324,7 +345,13 @@ impl Graph {
324345 // since the audio graph could contain legs detached from the destination and those should
325346 // still be rendered.
326347 let mut cycle_breaker_applied = false ;
327- for & node_id in self . nodes . keys ( ) {
348+ for node_id in self
349+ . nodes
350+ . iter ( )
351+ . enumerate ( )
352+ . filter ( |( _, v) | v. is_some ( ) )
353+ . map ( |( i, _) | AudioNodeId ( i as u64 ) )
354+ {
328355 cycle_breaker_applied = self . visit (
329356 node_id,
330357 & mut marked,
@@ -343,7 +370,7 @@ impl Graph {
343370 // clear the outgoing edges of the nodes that have been recognized as cycle breaker
344371 let nodes = & mut self . nodes ;
345372 cycle_breakers. iter ( ) . for_each ( |node_id| {
346- let node = nodes. get_mut ( node_id) . unwrap ( ) ;
373+ let node = nodes. get_mut ( node_id. 0 as usize ) . unwrap ( ) . as_mut ( ) . unwrap ( ) ;
347374 node. get_mut ( ) . outgoing_edges . clear ( ) ;
348375 } ) ;
349376
@@ -385,7 +412,12 @@ impl Graph {
385412 // process every node, in topological sorted order
386413 self . ordered . iter ( ) . for_each ( |index| {
387414 // acquire a mutable borrow of the current processing node
388- let mut node = nodes. get ( index) . unwrap ( ) . borrow_mut ( ) ;
415+ let mut node = nodes
416+ . get ( index. 0 as usize )
417+ . unwrap ( )
418+ . as_ref ( )
419+ . unwrap ( )
420+ . borrow_mut ( ) ;
389421
390422 // make sure all input buffers have the correct number of channels, this might not be
391423 // the case if the node has no inputs connected or the channel count has just changed
@@ -396,7 +428,7 @@ impl Graph {
396428 . for_each ( |i| i. mix ( count, interpretation) ) ;
397429
398430 // let the current node process (catch any panics that may occur)
399- let params = AudioParamValues :: from ( & * nodes) ;
431+ let params = AudioParamValues :: from ( nodes. as_slice ( ) ) ;
400432 scope. node_id . set ( * index) ;
401433 let ( success, tail_time) = {
402434 // We are abusing AssertUnwindSafe here, we cannot guarantee it upholds.
@@ -420,7 +452,12 @@ impl Graph {
420452 // audio params are connected to the 'hidden' usize::MAX output, ignore them here
421453 . filter ( |edge| edge. other_index != usize:: MAX )
422454 . for_each ( |edge| {
423- let mut output_node = nodes. get ( & edge. other_id ) . unwrap ( ) . borrow_mut ( ) ;
455+ let mut output_node = nodes
456+ . get ( edge. other_id . 0 as usize )
457+ . unwrap ( )
458+ . as_ref ( )
459+ . unwrap ( )
460+ . borrow_mut ( ) ;
424461 output_node. has_inputs_connected = true ;
425462 let signal = & node. outputs [ edge. self_index ] ;
426463 let channel_config = & output_node. channel_config . clone ( ) ;
@@ -446,33 +483,44 @@ impl Graph {
446483 // Check if we can decommission this node (end of life)
447484 if can_free {
448485 // Node is dropped, remove it from the node list
449- nodes. remove ( index) ;
486+ nodes[ index. 0 as usize ] = None ;
450487
451488 // And remove it from the ordering after we have processed all nodes
452489 nodes_dropped = true ;
453490
454491 // Nodes are only dropped when they do not have incoming connections.
455492 // But they may have AudioParams feeding into them, these can de dropped too.
456- nodes. retain ( |id, n| {
493+ for ( id, node) in nodes. iter_mut ( ) . enumerate ( ) {
494+ if node. is_none ( ) {
495+ continue ;
496+ }
457497 // Check if this node was connected to the dropped node. In that case, it is
458498 // either an AudioParam (which can be dropped), or the AudioListener that feeds
459499 // into a PannerNode (which can be disconnected).
460- let outgoing_edges = & mut n. borrow_mut ( ) . outgoing_edges ;
461- let prev_len = outgoing_edges. len ( ) ;
462- outgoing_edges. retain ( |e| e. other_id != * index) ;
463- let was_connected = outgoing_edges. len ( ) != prev_len;
464-
465- let special = id. 0 < 2 ; // never drop Listener and Destination node
466- special || !was_connected
467- } ) ;
500+ let was_connected = {
501+ let outgoing_edges =
502+ & mut node. as_mut ( ) . unwrap ( ) . borrow_mut ( ) . outgoing_edges ;
503+ let prev_len = outgoing_edges. len ( ) ;
504+ outgoing_edges. retain ( |e| e. other_id != * index) ;
505+ outgoing_edges. len ( ) != prev_len
506+ } ;
507+
508+ let special = id < 2 ; // never drop Listener and Destination node
509+
510+ if special || !was_connected {
511+ // retain
512+ } else {
513+ * node = None ;
514+ }
515+ }
468516 }
469517 } ) ;
470518
471519 // If there were any nodes decommissioned, remove from graph order
472520 if nodes_dropped {
473521 let mut i = 0 ;
474522 while i < self . ordered . len ( ) {
475- if ! nodes. contains_key ( & self . ordered [ i] ) {
523+ if nodes[ self . ordered [ i] . 0 as usize ] . is_none ( ) {
476524 self . ordered . remove ( i) ;
477525 } else {
478526 i += 1 ;
@@ -483,7 +531,9 @@ impl Graph {
483531 // Return the output buffer of destination node
484532 & self
485533 . nodes
486- . get_mut ( & AudioNodeId ( 0 ) )
534+ . get_mut ( 0 )
535+ . unwrap ( )
536+ . as_mut ( )
487537 . unwrap ( )
488538 . get_mut ( )
489539 . outputs [ 0 ]
0 commit comments