@@ -13,7 +13,7 @@ use futures_channel::{mpsc, oneshot};
13
13
use futures_util:: StreamExt as _;
14
14
15
15
use super :: AudioRenderQuantum ;
16
- use crate :: buffer:: { AudioBuffer , AudioBufferOptions } ;
16
+ use crate :: buffer:: AudioBuffer ;
17
17
use crate :: context:: {
18
18
AudioContextState , AudioNodeId , OfflineAudioContext , OfflineAudioContextCallback ,
19
19
} ;
@@ -240,13 +240,10 @@ impl RenderThread {
240
240
) -> AudioBuffer {
241
241
let length = context. length ( ) ;
242
242
243
- let options = AudioBufferOptions {
244
- number_of_channels : self . number_of_channels ,
245
- length,
246
- sample_rate : self . sample_rate ,
247
- } ;
243
+ // construct a properly sized output buffer
244
+ let mut buffer = Vec :: with_capacity ( self . number_of_channels ) ;
245
+ buffer. resize_with ( buffer. capacity ( ) , || Vec :: with_capacity ( length) ) ;
248
246
249
- let mut buffer = AudioBuffer :: new ( options) ;
250
247
let num_frames = ( length + RENDER_QUANTUM_SIZE - 1 ) / RENDER_QUANTUM_SIZE ;
251
248
252
249
// Handle initial control messages
@@ -271,7 +268,7 @@ impl RenderThread {
271
268
}
272
269
}
273
270
274
- buffer
271
+ AudioBuffer :: from ( buffer, self . sample_rate )
275
272
}
276
273
277
274
// Render method of the `OfflineAudioContext::start_rendering`
@@ -286,13 +283,10 @@ impl RenderThread {
286
283
mut resume_receiver : mpsc:: Receiver < ( ) > ,
287
284
event_loop : & EventLoop ,
288
285
) -> AudioBuffer {
289
- let options = AudioBufferOptions {
290
- number_of_channels : self . number_of_channels ,
291
- length,
292
- sample_rate : self . sample_rate ,
293
- } ;
286
+ // construct a properly sized output buffer
287
+ let mut buffer = Vec :: with_capacity ( self . number_of_channels ) ;
288
+ buffer. resize_with ( buffer. capacity ( ) , || Vec :: with_capacity ( length) ) ;
294
289
295
- let mut buffer = AudioBuffer :: new ( options) ;
296
290
let num_frames = ( length + RENDER_QUANTUM_SIZE - 1 ) / RENDER_QUANTUM_SIZE ;
297
291
298
292
// Handle addition/removal of nodes/edges
@@ -318,11 +312,11 @@ impl RenderThread {
318
312
}
319
313
}
320
314
321
- buffer
315
+ AudioBuffer :: from ( buffer, self . sample_rate )
322
316
}
323
317
324
318
/// Render a single quantum into an AudioBuffer
325
- fn render_offline_quantum ( & mut self , buffer : & mut AudioBuffer ) {
319
+ fn render_offline_quantum ( & mut self , buffer : & mut [ Vec < f32 > ] ) {
326
320
// Update time
327
321
let current_frame = self
328
322
. frames_played
@@ -346,17 +340,18 @@ impl RenderThread {
346
340
#[ cfg( not( any( target_arch = "x86" , target_arch = "x86_64" , target_arch = "aarch64" ) ) ) ]
347
341
let rendered = graph. render ( & scope) ;
348
342
349
- rendered
350
- . channels ( )
351
- . iter ( )
352
- . enumerate ( )
353
- . for_each ( |( channel_number, rendered_channel) | {
354
- buffer. copy_to_channel_with_offset (
355
- rendered_channel,
356
- channel_number,
357
- current_frame as usize ,
358
- ) ;
359
- } ) ;
343
+ // Use a specialized copyToChannel implementation for performance
344
+ let remaining = ( buffer[ 0 ] . capacity ( ) - buffer[ 0 ] . len ( ) ) . min ( RENDER_QUANTUM_SIZE ) ;
345
+ let channels = rendered. channels ( ) ;
346
+ buffer. iter_mut ( ) . enumerate ( ) . for_each ( |( i, b) | {
347
+ let c = channels
348
+ . get ( i)
349
+ . map ( AsRef :: as_ref)
350
+ // When there are no input nodes for the destination, only a single silent channel
351
+ // is emitted. So manually pad the missing channels with silence
352
+ . unwrap_or ( & [ 0. ; RENDER_QUANTUM_SIZE ] ) ;
353
+ b. extend_from_slice ( & c[ ..remaining] ) ;
354
+ } ) ;
360
355
}
361
356
362
357
pub fn render < S : FromSample < f32 > + Clone > ( & mut self , output_buffer : & mut [ S ] ) {
0 commit comments