@@ -241,9 +241,12 @@ impl AudioProcessor for ScriptProcessorRenderer {
241
241
// move next output buffer into current output buffer
242
242
std:: mem:: swap ( & mut self . output_buffer , & mut self . next_output_buffer ) ;
243
243
244
- // fill next output buffer with silence
244
+ // fill next output buffer with silence (with the right channel count)
245
+ let mut silent_quantum = silence;
246
+ silent_quantum. set_number_of_channels ( self . number_of_output_channels ) ;
245
247
self . next_output_buffer . clear ( ) ;
246
- self . next_output_buffer . resize ( number_of_quanta, silence) ;
248
+ self . next_output_buffer
249
+ . resize ( number_of_quanta, silent_quantum) ;
247
250
}
248
251
249
252
false // node is kept alive as long as the handle in the event loop still exists
@@ -268,6 +271,7 @@ impl AudioProcessor for ScriptProcessorRenderer {
268
271
mod tests {
269
272
use super :: * ;
270
273
use crate :: context:: OfflineAudioContext ;
274
+ use crate :: node:: scheduled_source:: AudioScheduledSourceNode ;
271
275
use float_eq:: assert_float_eq;
272
276
273
277
#[ test]
@@ -322,4 +326,64 @@ mod tests {
322
326
abs_all <= 0.
323
327
) ;
324
328
}
329
+
330
+ #[ test]
331
+ fn test_multiple_channels ( ) {
332
+ const BUFFER_SIZE : usize = 256 ;
333
+
334
+ let mut context = OfflineAudioContext :: new ( 2 , BUFFER_SIZE * 3 , 48000. ) ;
335
+
336
+ // 2 input channels, 2 output channels
337
+ let node = context. create_script_processor ( BUFFER_SIZE , 2 , 2 ) ;
338
+ node. connect ( & context. destination ( ) ) ;
339
+ node. set_onaudioprocess ( |e| {
340
+ // left output buffer is left input * 2
341
+ e. output_buffer
342
+ . get_channel_data_mut ( 0 )
343
+ . iter_mut ( )
344
+ . zip ( e. input_buffer . get_channel_data ( 0 ) )
345
+ . for_each ( |( o, i) | * o = * i * 2. ) ;
346
+
347
+ // right output buffer is right input * 3
348
+ e. output_buffer
349
+ . get_channel_data_mut ( 1 )
350
+ . iter_mut ( )
351
+ . zip ( e. input_buffer . get_channel_data ( 1 ) )
352
+ . for_each ( |( o, i) | * o = * i * 3. ) ;
353
+ } ) ;
354
+
355
+ // let the input be a mono constant source, it will be upmixed to two channels
356
+ let mut src = context. create_constant_source ( ) ;
357
+ src. start ( ) ;
358
+ src. connect ( & node) ;
359
+
360
+ let result = context. start_rendering_sync ( ) ;
361
+ let channel1 = result. get_channel_data ( 0 ) ;
362
+ let channel2 = result. get_channel_data ( 1 ) ;
363
+
364
+ // first `2 * BUFFER_SIZE` samples should be silent due to buffering
365
+ assert_float_eq ! (
366
+ channel1[ ..2 * BUFFER_SIZE ] ,
367
+ & [ 0. ; 2 * BUFFER_SIZE ] [ ..] ,
368
+ abs_all <= 0.
369
+ ) ;
370
+ assert_float_eq ! (
371
+ channel2[ ..2 * BUFFER_SIZE ] ,
372
+ & [ 0. ; 2 * BUFFER_SIZE ] [ ..] ,
373
+ abs_all <= 0.
374
+ ) ;
375
+
376
+ // rest of the samples should be 2. for left buffer
377
+ assert_float_eq ! (
378
+ channel1[ 2 * BUFFER_SIZE ..] ,
379
+ & [ 2. ; BUFFER_SIZE ] [ ..] ,
380
+ abs_all <= 0.
381
+ ) ;
382
+ // rest of the samples should be 3. for right buffer
383
+ assert_float_eq ! (
384
+ channel2[ 2 * BUFFER_SIZE ..] ,
385
+ & [ 3. ; BUFFER_SIZE ] [ ..] ,
386
+ abs_all <= 0.
387
+ ) ;
388
+ }
325
389
}
0 commit comments