@@ -33,9 +33,9 @@ function createWasmAudioWorkletProcessor(audioParams) {
3333 this . userData = opts [ 'ud' ] ;
3434 // Then the samples per channel to process, fixed for the lifetime of the
3535 // context that created this processor. Note for when moving to Web Audio
36- // 1.1: the typed array passed to process() should be the same size as this
37- // 'render quantum size', and this exercise of passing in the value
38- // shouldn't be required (to be verified).
36+ // 1.1: the typed array passed to process() should be the same size as
37+ // this 'render quantum size', and this exercise of passing in the value
38+ // shouldn't be required (to be verified with the in/out data lengths ).
3939 this . samplesPerChannel = opts [ 'sc' ] ;
4040 // Typed views of the output buffers on the worklet's stack, which after
4141 // creation should only change if the audio chain changes.
@@ -47,6 +47,7 @@ function createWasmAudioWorkletProcessor(audioParams) {
4747 }
4848
4949 process ( inputList , outputList , parameters ) {
50+ var time = Date . now ( ) ;
5051 // Marshal all inputs and parameters to the Wasm memory on the thread stack,
5152 // then perform the wasm audio worklet call,
5253 // and finally marshal audio output data back.
@@ -65,12 +66,47 @@ function createWasmAudioWorkletProcessor(audioParams) {
6566 for ( i of outputList ) stackMemoryNeeded += i . length * bytesPerChannel ;
6667 for ( i in parameters ) stackMemoryNeeded += parameters [ i ] . byteLength + { { { C_STRUCTS . AudioParamFrame . __size__ } } } , ++ numParams ;
6768
68- // Allocate the necessary stack space.
69- inputsPtr = stackAlloc ( stackMemoryNeeded ) ;
69+ // Allocate the necessary stack space (dataPtr is always in bytes, and
70+ // advances as space for structs as data is taken, but note the switching
71+ // between bytes and indices into the various heaps).
72+ dataPtr = stackAlloc ( stackMemoryNeeded ) ;
73+
74+ // But start the output view allocs first, since once views are created we
75+ // want them to always start from the same address. Even if in the next
76+ // process() the outputList is empty, as soon as there are channels again
77+ // the views' addresses will still be the same (and only if more views are
78+ // required we will recreate them).
79+ outputDataPtr = dataPtr ;
80+ for ( /*which output*/ i of outputList ) {
81+ #if ASSERTIONS
82+ for ( /*which channel*/ j of i ) {
83+ console . assert ( j . byteLength === bytesPerChannel , `Unexpected AudioWorklet output buffer size (expected ${ bytesPerChannel } got ${ j . byteLength } )` ) ;
84+ }
85+ #endif
86+ // Keep advancing to make room for the output views
87+ dataPtr += bytesPerChannel * i . length ;
88+ // How many output views are needed in total?
89+ requiredViews += i . length ;
90+ }
91+ // Verify we have enough views (it doesn't matter if we have too many, any
92+ // excess won't be accessed) then also verify the views' start address
93+ // haven't changed.
94+ if ( this . outputViews . length < requiredViews || ( this . outputViews . length && this . outputViews [ 0 ] . byteOffset != outputDataPtr ) ) {
95+ this . outputViews = [ ] ;
96+ k = outputDataPtr >> 2 ;
97+ for ( i of outputList ) {
98+ for ( j of i ) {
99+ this . outputViews . push (
100+ HEAPF32 . subarray ( k , k += this . samplesPerChannel )
101+ ) ;
102+ }
103+ }
104+ }
70105
71106 // Copy input audio descriptor structs and data to Wasm
107+ inputsPtr = dataPtr ;
72108 k = inputsPtr >> 2 ;
73- dataPtr = inputsPtr + numInputs * { { { C_STRUCTS . AudioSampleFrame . __size__ } } } ;
109+ dataPtr += numInputs * { { { C_STRUCTS . AudioSampleFrame . __size__ } } } ;
74110 for ( i of inputList ) {
75111 // Write the AudioSampleFrame struct instance
76112 HEAPU32 [ k + { { { C_STRUCTS . AudioSampleFrame . numberOfChannels / 4 } } } ] = i . length ;
@@ -85,35 +121,18 @@ function createWasmAudioWorkletProcessor(audioParams) {
85121 }
86122
87123 // Copy output audio descriptor structs to Wasm
124+ // TODO: now dataPtr tracks the next address, move this above
88125 outputsPtr = dataPtr ;
89126 k = outputsPtr >> 2 ;
90- outputDataPtr = ( dataPtr += numOutputs * { { { C_STRUCTS . AudioSampleFrame . __size__ } } } ) >> 2 ;
127+ dataPtr += numOutputs * { { { C_STRUCTS . AudioSampleFrame . __size__ } } } ;
91128 for ( i of outputList ) {
92129 // Write the AudioSampleFrame struct instance
93130 HEAPU32 [ k + { { { C_STRUCTS . AudioSampleFrame . numberOfChannels / 4 } } } ] = i . length ;
94131 HEAPU32 [ k + { { { C_STRUCTS . AudioSampleFrame . samplesPerChannel / 4 } } } ] = this . samplesPerChannel ;
95- HEAPU32 [ k + { { { C_STRUCTS . AudioSampleFrame . data / 4 } } } ] = dataPtr ;
132+ HEAPU32 [ k + { { { C_STRUCTS . AudioSampleFrame . data / 4 } } } ] = outputDataPtr ;
96133 k += { { { C_STRUCTS . AudioSampleFrame . __size__ / 4 } } } ;
97- // Reserve space for the output data
98- dataPtr += bytesPerChannel * i . length ;
99- // How many output views are needed in total?
100- requiredViews += i . length ;
101- }
102-
103- // Verify we have enough views (it doesn't matter if we have too many, any
104- // excess won't be accessed) then also verify the views' start address
105- // hasn't changed.
106- // TODO: allocate space for outputDataPtr before any inputs?
107- k = outputDataPtr ;
108- if ( this . outputViews . length < requiredViews || ( this . outputViews . length && this . outputViews [ 0 ] . byteOffset != k << 2 ) ) {
109- this . outputViews = [ ] ;
110- for ( /*which output*/ i of outputList ) {
111- for ( /*which channel*/ j of i ) {
112- this . outputViews . push (
113- HEAPF32 . subarray ( k , k += this . samplesPerChannel )
114- ) ;
115- }
116- }
134+ // Advance the output pointer to the next output
135+ outputDataPtr += bytesPerChannel * i . length ;
117136 }
118137
119138 // Copy parameters descriptor structs and data to Wasm
@@ -144,6 +163,9 @@ function createWasmAudioWorkletProcessor(audioParams) {
144163 }
145164
146165 stackRestore ( oldStackPtr ) ;
166+
167+ time = Date . now ( ) - time ;
168+ //console.log(time);
147169
148170 // Return 'true' to tell the browser to continue running this processor.
149171 // (Returning 1 or any other truthy value won't work in Chrome)
0 commit comments