@@ -13,7 +13,7 @@ use futures_channel::{mpsc, oneshot};
1313use futures_util:: StreamExt as _;
1414
1515use super :: AudioRenderQuantum ;
16- use crate :: buffer:: { AudioBuffer , AudioBufferOptions } ;
16+ use crate :: buffer:: AudioBuffer ;
1717use crate :: context:: {
1818 AudioContextState , AudioNodeId , OfflineAudioContext , OfflineAudioContextCallback ,
1919} ;
@@ -240,13 +240,10 @@ impl RenderThread {
240240 ) -> AudioBuffer {
241241 let length = context. length ( ) ;
242242
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) ) ;
248246
249- let mut buffer = AudioBuffer :: new ( options) ;
250247 let num_frames = ( length + RENDER_QUANTUM_SIZE - 1 ) / RENDER_QUANTUM_SIZE ;
251248
252249 // Handle initial control messages
@@ -271,7 +268,7 @@ impl RenderThread {
271268 }
272269 }
273270
274- buffer
271+ AudioBuffer :: from ( buffer, self . sample_rate )
275272 }
276273
277274 // Render method of the `OfflineAudioContext::start_rendering`
@@ -286,13 +283,10 @@ impl RenderThread {
286283 mut resume_receiver : mpsc:: Receiver < ( ) > ,
287284 event_loop : & EventLoop ,
288285 ) -> 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) ) ;
294289
295- let mut buffer = AudioBuffer :: new ( options) ;
296290 let num_frames = ( length + RENDER_QUANTUM_SIZE - 1 ) / RENDER_QUANTUM_SIZE ;
297291
298292 // Handle addition/removal of nodes/edges
@@ -318,11 +312,11 @@ impl RenderThread {
318312 }
319313 }
320314
321- buffer
315+ AudioBuffer :: from ( buffer, self . sample_rate )
322316 }
323317
324318 /// 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 > ] ) {
326320 // Update time
327321 let current_frame = self
328322 . frames_played
@@ -346,17 +340,18 @@ impl RenderThread {
346340 #[ cfg( not( any( target_arch = "x86" , target_arch = "x86_64" , target_arch = "aarch64" ) ) ) ]
347341 let rendered = graph. render ( & scope) ;
348342
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+ } ) ;
360355 }
361356
362357 pub fn render < S : FromSample < f32 > + Clone > ( & mut self , output_buffer : & mut [ S ] ) {
0 commit comments