@@ -6,7 +6,7 @@ use std::panic::{self, AssertUnwindSafe};
6
6
use crate :: context:: AudioNodeId ;
7
7
use smallvec:: { smallvec, SmallVec } ;
8
8
9
- use super :: { Alloc , AudioParamValues , AudioProcessor , AudioRenderQuantum } ;
9
+ use super :: { Alloc , AudioParamValues , AudioProcessor , AudioRenderQuantum , NodeCollection } ;
10
10
use crate :: node:: ChannelConfig ;
11
11
use crate :: render:: RenderScope ;
12
12
@@ -75,7 +75,7 @@ impl Node {
75
75
/// The audio graph
76
76
pub ( crate ) struct Graph {
77
77
/// Processing Nodes
78
- nodes : Vec < Option < RefCell < Node > > > ,
78
+ nodes : NodeCollection ,
79
79
/// Allocator for audio buffers
80
80
alloc : Alloc ,
81
81
@@ -94,7 +94,7 @@ pub(crate) struct Graph {
94
94
impl Graph {
95
95
pub fn new ( ) -> Self {
96
96
Graph {
97
- nodes : Vec :: with_capacity ( 64 ) ,
97
+ nodes : NodeCollection :: new ( ) ,
98
98
ordered : vec ! [ ] ,
99
99
marked : vec ! [ ] ,
100
100
marked_temp : vec ! [ ] ,
@@ -126,27 +126,23 @@ impl Graph {
126
126
let outputs = vec ! [ AudioRenderQuantum :: from( self . alloc. silence( ) ) ; number_of_outputs] ;
127
127
128
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
- } ) ) ;
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
+ ) ;
142
142
}
143
143
144
144
pub fn add_edge ( & mut self , source : ( AudioNodeId , usize ) , dest : ( AudioNodeId , usize ) ) {
145
- self . nodes
146
- . get_mut ( source. 0 . 0 as usize )
147
- . unwrap_or_else ( || panic ! ( "cannot connect {:?} to {:?}" , source, dest) )
148
- . as_mut ( )
149
- . unwrap ( )
145
+ self . nodes [ source. 0 . 0 as usize ]
150
146
. get_mut ( )
151
147
. outgoing_edges
152
148
. push ( OutgoingEdge {
@@ -159,11 +155,7 @@ impl Graph {
159
155
}
160
156
161
157
pub fn remove_edge ( & mut self , source : AudioNodeId , dest : AudioNodeId ) {
162
- self . nodes
163
- . get_mut ( source. 0 as usize )
164
- . unwrap_or_else ( || panic ! ( "cannot remove the edge from {:?} to {:?}" , source, dest) )
165
- . as_mut ( )
166
- . unwrap ( )
158
+ self . nodes [ source. 0 as usize ]
167
159
. get_mut ( )
168
160
. outgoing_edges
169
161
. retain ( |edge| edge. other_id != dest) ;
@@ -172,16 +164,12 @@ impl Graph {
172
164
}
173
165
174
166
pub fn remove_edges_from ( & mut self , source : AudioNodeId ) {
175
- self . nodes
176
- . get_mut ( source. 0 as usize )
177
- . unwrap_or_else ( || panic ! ( "cannot remove edges from {:?}" , source) )
178
- . as_mut ( )
179
- . unwrap ( )
167
+ self . nodes [ source. 0 as usize ]
180
168
. get_mut ( )
181
169
. outgoing_edges
182
170
. clear ( ) ;
183
171
184
- self . nodes . iter_mut ( ) . flatten ( ) . for_each ( |node| {
172
+ self . nodes . values_mut ( ) . for_each ( |node| {
185
173
node. get_mut ( )
186
174
. outgoing_edges
187
175
. retain ( |edge| edge. other_id != source) ;
@@ -194,27 +182,17 @@ impl Graph {
194
182
// Issue #92, a race condition can occur for AudioParams. They may have already been
195
183
// removed from the audio graph if the node they feed into was dropped.
196
184
// Therefore, do not assume this node still exists:
197
- if let Some ( node) = self . nodes . get_mut ( index. 0 as usize ) . unwrap ( ) . as_mut ( ) {
185
+ if let Some ( node) = self . nodes . get_mut ( index. 0 as usize ) {
198
186
node. get_mut ( ) . free_when_finished = true ;
199
187
}
200
188
}
201
189
202
190
pub fn mark_cycle_breaker ( & mut self , index : AudioNodeId ) {
203
- self . nodes
204
- . get_mut ( index. 0 as usize )
205
- . unwrap ( )
206
- . as_mut ( )
207
- . unwrap ( )
208
- . get_mut ( )
209
- . cycle_breaker = true ;
191
+ self . nodes [ index. 0 as usize ] . get_mut ( ) . cycle_breaker = true ;
210
192
}
211
193
212
194
pub fn route_message ( & mut self , index : AudioNodeId , msg : & mut dyn Any ) {
213
- self . nodes
214
- . get_mut ( index. 0 as usize )
215
- . unwrap ( )
216
- . as_mut ( )
217
- . unwrap ( )
195
+ self . nodes [ index. 0 as usize ]
218
196
. get_mut ( )
219
197
. processor
220
198
. onmessage ( msg) ;
@@ -237,15 +215,10 @@ impl Graph {
237
215
// If this node is in the cycle detection list, it is part of a cycle!
238
216
if let Some ( pos) = marked_temp. iter ( ) . position ( |& m| m == node_id) {
239
217
// check if we can find some node that can break the cycle
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
- } ) ;
218
+ let cycle_breaker_node = marked_temp
219
+ . iter ( )
220
+ . skip ( pos)
221
+ . find ( |node_id| self . nodes [ node_id. 0 as usize ] . borrow ( ) . cycle_breaker ) ;
249
222
250
223
match cycle_breaker_node {
251
224
Some ( & node_id) => {
@@ -274,12 +247,7 @@ impl Graph {
274
247
marked_temp. push ( node_id) ;
275
248
276
249
// Visit outgoing nodes, and call `visit` on them recursively
277
- for edge in self
278
- . nodes
279
- . get ( node_id. 0 as usize )
280
- . unwrap ( )
281
- . as_ref ( )
282
- . unwrap ( )
250
+ for edge in self . nodes [ node_id. 0 as usize ]
283
251
. borrow ( )
284
252
. outgoing_edges
285
253
. iter ( )
@@ -345,13 +313,7 @@ impl Graph {
345
313
// since the audio graph could contain legs detached from the destination and those should
346
314
// still be rendered.
347
315
let mut cycle_breaker_applied = false ;
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
- {
316
+ for node_id in self . nodes . keys ( ) . map ( |i| AudioNodeId ( i as u64 ) ) {
355
317
cycle_breaker_applied = self . visit (
356
318
node_id,
357
319
& mut marked,
@@ -370,8 +332,7 @@ impl Graph {
370
332
// clear the outgoing edges of the nodes that have been recognized as cycle breaker
371
333
let nodes = & mut self . nodes ;
372
334
cycle_breakers. iter ( ) . for_each ( |node_id| {
373
- let node = nodes. get_mut ( node_id. 0 as usize ) . unwrap ( ) . as_mut ( ) . unwrap ( ) ;
374
- node. get_mut ( ) . outgoing_edges . clear ( ) ;
335
+ nodes[ node_id. 0 as usize ] . get_mut ( ) . outgoing_edges . clear ( ) ;
375
336
} ) ;
376
337
377
338
continue ;
@@ -412,12 +373,7 @@ impl Graph {
412
373
// process every node, in topological sorted order
413
374
self . ordered . iter ( ) . for_each ( |index| {
414
375
// acquire a mutable borrow of the current processing node
415
- let mut node = nodes
416
- . get ( index. 0 as usize )
417
- . unwrap ( )
418
- . as_ref ( )
419
- . unwrap ( )
420
- . borrow_mut ( ) ;
376
+ let mut node = nodes[ index. 0 as usize ] . borrow_mut ( ) ;
421
377
422
378
// make sure all input buffers have the correct number of channels, this might not be
423
379
// the case if the node has no inputs connected or the channel count has just changed
@@ -428,7 +384,7 @@ impl Graph {
428
384
. for_each ( |i| i. mix ( count, interpretation) ) ;
429
385
430
386
// let the current node process (catch any panics that may occur)
431
- let params = AudioParamValues :: from ( nodes. as_slice ( ) ) ;
387
+ let params = AudioParamValues :: from ( nodes) ;
432
388
scope. node_id . set ( * index) ;
433
389
let ( success, tail_time) = {
434
390
// We are abusing AssertUnwindSafe here, we cannot guarantee it upholds.
@@ -452,12 +408,7 @@ impl Graph {
452
408
// audio params are connected to the 'hidden' usize::MAX output, ignore them here
453
409
. filter ( |edge| edge. other_index != usize:: MAX )
454
410
. for_each ( |edge| {
455
- let mut output_node = nodes
456
- . get ( edge. other_id . 0 as usize )
457
- . unwrap ( )
458
- . as_ref ( )
459
- . unwrap ( )
460
- . borrow_mut ( ) ;
411
+ let mut output_node = nodes[ edge. other_id . 0 as usize ] . borrow_mut ( ) ;
461
412
output_node. has_inputs_connected = true ;
462
413
let signal = & node. outputs [ edge. self_index ] ;
463
414
let channel_config = & output_node. channel_config . clone ( ) ;
@@ -483,44 +434,36 @@ impl Graph {
483
434
// Check if we can decommission this node (end of life)
484
435
if can_free {
485
436
// Node is dropped, remove it from the node list
486
- nodes[ index. 0 as usize ] = None ;
437
+ nodes. remove ( index. 0 as usize ) ;
487
438
488
439
// And remove it from the ordering after we have processed all nodes
489
440
nodes_dropped = true ;
490
441
491
442
// Nodes are only dropped when they do not have incoming connections.
492
443
// But they may have AudioParams feeding into them, these can de dropped too.
493
- for ( id, node) in nodes. iter_mut ( ) . enumerate ( ) {
494
- if node. is_none ( ) {
495
- continue ;
496
- }
444
+ nodes. retain ( |id, node| {
497
445
// Check if this node was connected to the dropped node. In that case, it is
498
446
// either an AudioParam (which can be dropped), or the AudioListener that feeds
499
447
// into a PannerNode (which can be disconnected).
500
448
let was_connected = {
501
- let outgoing_edges =
502
- & mut node. as_mut ( ) . unwrap ( ) . borrow_mut ( ) . outgoing_edges ;
449
+ let outgoing_edges = & mut node. borrow_mut ( ) . outgoing_edges ;
503
450
let prev_len = outgoing_edges. len ( ) ;
504
451
outgoing_edges. retain ( |e| e. other_id != * index) ;
505
452
outgoing_edges. len ( ) != prev_len
506
453
} ;
507
454
455
+ // retain when special or not connected to this dropped node
508
456
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
- }
457
+ special || !was_connected
458
+ } )
516
459
}
517
460
} ) ;
518
461
519
462
// If there were any nodes decommissioned, remove from graph order
520
463
if nodes_dropped {
521
464
let mut i = 0 ;
522
465
while i < self . ordered . len ( ) {
523
- if nodes[ self . ordered [ i] . 0 as usize ] . is_none ( ) {
466
+ if nodes. get ( self . ordered [ i] . 0 as usize ) . is_none ( ) {
524
467
self . ordered . remove ( i) ;
525
468
} else {
526
469
i += 1 ;
@@ -529,14 +472,7 @@ impl Graph {
529
472
}
530
473
531
474
// Return the output buffer of destination node
532
- & self
533
- . nodes
534
- . get_mut ( 0 )
535
- . unwrap ( )
536
- . as_mut ( )
537
- . unwrap ( )
538
- . get_mut ( )
539
- . outputs [ 0 ]
475
+ & self . nodes [ 0 ] . get_mut ( ) . outputs [ 0 ]
540
476
}
541
477
}
542
478
0 commit comments