@@ -323,11 +323,15 @@ impl AudioProcessor for AudioWorkletRenderer {
323
323
324
324
// Create an iterator for the output channel counts without allocating, handling also the
325
325
// case where self.output_channel_count is empty.
326
- let output_channel_count = self
327
- . output_channel_count
328
- . iter ( )
329
- . copied ( )
330
- . chain ( std:: iter:: once ( inputs[ 0 ] . number_of_channels ( ) ) ) ;
326
+ let single_case = [ inputs
327
+ . get ( 0 )
328
+ . map ( |i| i. number_of_channels ( ) )
329
+ . unwrap_or_default ( ) ] ;
330
+ let output_channel_count = if self . output_channel_count . is_empty ( ) {
331
+ & single_case[ ..]
332
+ } else {
333
+ & self . output_channel_count [ ..]
334
+ } ;
331
335
332
336
outputs
333
337
. iter_mut ( )
@@ -342,7 +346,7 @@ impl AudioProcessor for AudioWorkletRenderer {
342
346
343
347
let mut outputs_flat = & mut self . outputs_flat [ ..] ;
344
348
for c in output_channel_count {
345
- let ( left, right) = outputs_flat. split_at_mut ( c) ;
349
+ let ( left, right) = outputs_flat. split_at_mut ( * c) ;
346
350
// SAFETY - see comments above
347
351
let left_static = unsafe { std:: mem:: transmute ( left) } ;
348
352
self . outputs_grouped . push ( left_static) ;
@@ -374,15 +378,113 @@ impl AudioProcessor for AudioWorkletRenderer {
374
378
mod tests {
375
379
use super :: * ;
376
380
use crate :: context:: OfflineAudioContext ;
381
+ use float_eq:: assert_float_eq;
382
+
383
+ struct TestProcessor ;
384
+
385
+ impl AudioWorkletProcessor for TestProcessor {
386
+ type ProcessorOptions = ( ) ;
387
+
388
+ fn constructor ( _opts : Self :: ProcessorOptions ) -> Self {
389
+ TestProcessor { }
390
+ }
391
+
392
+ fn process < ' a , ' b > (
393
+ & mut self ,
394
+ _inputs : & ' b [ & ' a [ & ' a [ f32 ] ] ] ,
395
+ _outputs : & ' b mut [ & ' a mut [ & ' a mut [ f32 ] ] ] ,
396
+ _params : AudioParamValues < ' b > ,
397
+ _scope : & ' b RenderScope ,
398
+ ) -> bool {
399
+ true
400
+ }
401
+ }
402
+
403
+ #[ test]
404
+ fn test_worklet_render ( ) {
405
+ let mut context = OfflineAudioContext :: new ( 1 , 128 , 48000. ) ;
406
+ let options = AudioWorkletNodeOptions :: default ( ) ;
407
+ let worklet = AudioWorkletNode :: new :: < TestProcessor > ( & context, options) ;
408
+ worklet. connect ( & context. destination ( ) ) ;
409
+ let buffer = context. start_rendering_sync ( ) ;
410
+ assert_float_eq ! (
411
+ buffer. get_channel_data( 0 ) [ ..] ,
412
+ & [ 0. ; 128 ] [ ..] ,
413
+ abs_all <= 0.
414
+ ) ;
415
+ }
416
+
417
+ #[ test]
418
+ fn test_worklet_inputs_outputs ( ) {
419
+ let matrix = [ 0 , 1 , 2 ] ;
420
+ let mut context = OfflineAudioContext :: new ( 1 , 128 , 48000. ) ;
421
+ for inputs in matrix {
422
+ for outputs in matrix {
423
+ if inputs == 0 && outputs == 0 {
424
+ continue ; // this case is not allowed
425
+ }
426
+ let options = AudioWorkletNodeOptions {
427
+ number_of_inputs : inputs,
428
+ number_of_outputs : outputs,
429
+ ..AudioWorkletNodeOptions :: default ( )
430
+ } ;
431
+ let worklet = AudioWorkletNode :: new :: < TestProcessor > ( & context, options) ;
432
+
433
+ if outputs > 0 {
434
+ worklet. connect ( & context. destination ( ) ) ;
435
+ }
436
+ }
437
+ }
438
+ let buffer = context. start_rendering_sync ( ) ;
439
+ assert_float_eq ! (
440
+ buffer. get_channel_data( 0 ) [ ..] ,
441
+ & [ 0. ; 128 ] [ ..] ,
442
+ abs_all <= 0.
443
+ ) ;
444
+ }
445
+
446
+ #[ test]
447
+ fn test_worklet_output_channel_count ( ) {
448
+ let mut context = OfflineAudioContext :: new ( 1 , 128 , 48000. ) ;
449
+
450
+ let options1 = AudioWorkletNodeOptions {
451
+ output_channel_count : vec ! [ ] ,
452
+ ..AudioWorkletNodeOptions :: default ( )
453
+ } ;
454
+ let worklet1 = AudioWorkletNode :: new :: < TestProcessor > ( & context, options1) ;
455
+ worklet1. connect ( & context. destination ( ) ) ;
456
+
457
+ let options2 = AudioWorkletNodeOptions {
458
+ output_channel_count : vec ! [ 1 ] ,
459
+ ..AudioWorkletNodeOptions :: default ( )
460
+ } ;
461
+ let worklet2 = AudioWorkletNode :: new :: < TestProcessor > ( & context, options2) ;
462
+ worklet2. connect ( & context. destination ( ) ) ;
463
+
464
+ let options3 = AudioWorkletNodeOptions {
465
+ number_of_outputs : 2 ,
466
+ output_channel_count : vec ! [ 1 , 2 ] ,
467
+ ..AudioWorkletNodeOptions :: default ( )
468
+ } ;
469
+ let worklet3 = AudioWorkletNode :: new :: < TestProcessor > ( & context, options3) ;
470
+ worklet3. connect ( & context. destination ( ) ) ;
471
+
472
+ let buffer = context. start_rendering_sync ( ) ;
473
+ assert_float_eq ! (
474
+ buffer. get_channel_data( 0 ) [ ..] ,
475
+ & [ 0. ; 128 ] [ ..] ,
476
+ abs_all <= 0.
477
+ ) ;
478
+ }
377
479
378
480
#[ test]
379
481
fn send_bound ( ) {
380
482
#[ derive( Default ) ]
381
- struct MyProcessor {
483
+ struct RcProcessor {
382
484
_rc : std:: rc:: Rc < ( ) > , // not send
383
485
}
384
486
385
- impl AudioWorkletProcessor for MyProcessor {
487
+ impl AudioWorkletProcessor for RcProcessor {
386
488
type ProcessorOptions = ( ) ;
387
489
388
490
fn constructor ( _opts : Self :: ProcessorOptions ) -> Self {
@@ -402,6 +504,6 @@ mod tests {
402
504
403
505
let context = OfflineAudioContext :: new ( 1 , 128 , 48000. ) ;
404
506
let options = AudioWorkletNodeOptions :: default ( ) ;
405
- let _worklet = AudioWorkletNode :: new :: < MyProcessor > ( & context, options) ;
507
+ let _worklet = AudioWorkletNode :: new :: < RcProcessor > ( & context, options) ;
406
508
}
407
509
}
0 commit comments