1
- // This file is the main bootstrap script for Wasm Audio Worklets loaded in an Emscripten application.
2
- // Build with -sAUDIO_WORKLET=1 linker flag to enable targeting Audio Worklets.
1
+ // This file is the main bootstrap script for Wasm Audio Worklets loaded in an
2
+ // Emscripten application. Build with -sAUDIO_WORKLET=1 linker flag to enable
3
+ // targeting Audio Worklets.
3
4
4
- // AudioWorkletGlobalScope does not have a onmessage/postMessage() functionality at the global scope, which
5
- // means that after creating an AudioWorkletGlobalScope and loading this script into it, we cannot
5
+ // AudioWorkletGlobalScope does not have a onmessage/postMessage() functionality
6
+ // at the global scope, which means that after creating an
7
+ // AudioWorkletGlobalScope and loading this script into it, we cannot
6
8
// postMessage() information into it like one would do with Web Workers.
7
9
8
- // Instead, we must create an AudioWorkletProcessor class, then instantiate a Web Audio graph node from it
9
- // on the main thread. Using its message port and the node constructor's
10
- // "processorOptions" field, we can share the necessary bootstrap information from the main thread to
11
- // the AudioWorkletGlobalScope.
10
+ // Instead, we must create an AudioWorkletProcessor class, then instantiate a
11
+ // Web Audio graph node from it on the main thread. Using its message port and
12
+ // the node constructor's "processorOptions" field, we can share the necessary
13
+ // bootstrap information from the main thread to the AudioWorkletGlobalScope.
12
14
13
15
function createWasmAudioWorkletProcessor ( audioParams ) {
14
16
class WasmAudioWorkletProcessor extends AudioWorkletProcessor {
@@ -98,8 +100,9 @@ function createWasmAudioWorkletProcessor(audioParams) {
98
100
// Call out to Wasm callback to perform audio processing
99
101
if ( didProduceAudio = this . callbackFunction ( numInputs , inputsPtr , numOutputs , outputsPtr , numParams , paramsPtr , this . userData ) ) {
100
102
// Read back the produced audio data to all outputs and their channels.
101
- // (A garbage-free function TypedArray.copy(dstTypedArray, dstOffset, srcTypedArray, srcOffset, count) would sure be handy..
102
- // but web does not have one, so manually copy all bytes in)
103
+ // (A garbage-free function TypedArray.copy(dstTypedArray, dstOffset,
104
+ // srcTypedArray, srcOffset, count) would sure be handy.. but web does
105
+ // not have one, so manually copy all bytes in)
103
106
for ( i of outputList ) {
104
107
for ( j of i ) {
105
108
for ( k = 0 ; k < 128 ; ++ k ) {
@@ -111,24 +114,28 @@ function createWasmAudioWorkletProcessor(audioParams) {
111
114
112
115
stackRestore ( oldStackPtr ) ;
113
116
114
- // Return 'true' to tell the browser to continue running this processor. (Returning 1 or any other truthy value won't work in Chrome)
117
+ // Return 'true' to tell the browser to continue running this processor.
118
+ // (Returning 1 or any other truthy value won't work in Chrome)
115
119
return ! ! didProduceAudio ;
116
120
}
117
121
}
118
122
return WasmAudioWorkletProcessor ;
119
123
}
120
124
121
- // Specify a worklet processor that will be used to receive messages to this AudioWorkletGlobalScope.
122
- // We never connect this initial AudioWorkletProcessor to the audio graph to do any audio processing.
125
+ // Specify a worklet processor that will be used to receive messages to this
126
+ // AudioWorkletGlobalScope. We never connect this initial AudioWorkletProcessor
127
+ // to the audio graph to do any audio processing.
123
128
class BootstrapMessages extends AudioWorkletProcessor {
124
129
constructor ( arg ) {
125
130
super ( ) ;
126
- // Initialize the global Emscripten Module object that contains e.g. the Wasm Module and Memory objects.
127
- // After this we are ready to load in the main application JS script, which the main thread will addModule()
131
+ // Initialize the global Emscripten Module object that contains e.g. the
132
+ // Wasm Module and Memory objects. After this we are ready to load in the
133
+ // main application JS script, which the main thread will addModule()
128
134
// to this scope.
129
135
globalThis . Module = arg [ 'processorOptions' ] ;
130
136
#if ! MINIMAL_RUNTIME
131
- // Default runtime relies on an injected instantiateWasm() function to initialize the Wasm Module.
137
+ // Default runtime relies on an injected instantiateWasm() function to
138
+ // initialize the Wasm Module.
132
139
globalThis . Module [ 'instantiateWasm' ] = ( info , receiveInstance ) => {
133
140
var instance = new WebAssembly . Instance ( Module [ 'wasm' ] , info ) ;
134
141
receiveInstance ( instance , Module [ 'wasm' ] ) ;
@@ -139,41 +146,55 @@ class BootstrapMessages extends AudioWorkletProcessor {
139
146
console . log ( 'AudioWorklet global scope looks like this:' ) ;
140
147
console . dir ( globalThis ) ;
141
148
#endif
142
- // Listen to messages from the main thread. These messages will ask this scope to create the real
143
- // AudioWorkletProcessors that call out to Wasm to do audio processing.
149
+ // Listen to messages from the main thread. These messages will ask this
150
+ // scope to create the real AudioWorkletProcessors that call out to Wasm to
151
+ // do audio processing.
144
152
let p = globalThis [ 'messagePort' ] = this . port ;
145
153
p . onmessage = ( msg ) => {
146
154
let d = msg . data ;
147
- if ( d [ '_wpn' ] ) { // '_wpn' is short for 'Worklet Processor Node', using an identifier that will never conflict with user messages
155
+ if ( d [ '_wpn' ] ) {
156
+ // '_wpn' is short for 'Worklet Processor Node', using an identifier
157
+ // that will never conflict with user messages
148
158
#if MODULARIZE
149
- // Instantiate the MODULARIZEd Module function, which is stored for us under the special global
150
- // name AudioWorkletModule in MODULARIZE+AUDIO_WORKLET builds.
159
+ // Instantiate the MODULARIZEd Module function, which is stored for us
160
+ // under the special global name AudioWorkletModule in
161
+ // MODULARIZE+AUDIO_WORKLET builds.
151
162
if ( globalThis . AudioWorkletModule ) {
152
- AudioWorkletModule ( Module ) ; // This populates the Module object with all the Wasm properties
153
- delete globalThis . AudioWorkletModule ; // We have now instantiated the Module function, can discard it from global scope
163
+ // This populates the Module object with all the Wasm properties
164
+ AudioWorkletModule ( Module ) ;
165
+ // We have now instantiated the Module function, can discard it from
166
+ // global scope
167
+ delete globalThis . AudioWorkletModule ;
154
168
}
155
169
#endif
156
170
// Register a real AudioWorkletProcessor that will actually do audio processing.
157
171
registerProcessor ( d [ '_wpn' ] , createWasmAudioWorkletProcessor ( d [ 'audioParams' ] ) ) ;
158
172
#if WEBAUDIO_DEBUG
159
173
console . log ( `Registered a new WasmAudioWorkletProcessor "${ d [ '_wpn' ] } " with AudioParams: ${ d [ 'audioParams' ] } ` ) ;
160
174
#endif
161
- // Post a Wasm Call message back telling that we have now registered the AudioWorkletProcessor class,
162
- // and should trigger the user onSuccess callback of the emscripten_create_wasm_audio_worklet_processor_async() call.
175
+ // Post a Wasm Call message back telling that we have now registered the
176
+ // AudioWorkletProcessor class, and should trigger the user onSuccess
177
+ // callback of the
178
+ // emscripten_create_wasm_audio_worklet_processor_async() call.
163
179
p . postMessage ( { '_wsc' : d [ 'callback' ] , 'x' : [ d [ 'contextHandle' ] , 1 /*EM_TRUE*/ , d [ 'userData' ] ] } ) ; // "WaSm Call"
164
- } else if ( d [ '_wsc' ] ) { // '_wsc' is short for 'wasm call', using an identifier that will never conflict with user messages
180
+ } else if ( d [ '_wsc' ] ) {
181
+ // '_wsc' is short for 'wasm call', using an identifier that will never
182
+ // conflict with user messages
165
183
Module [ 'wasmTable' ] . get ( d [ '_wsc' ] ) ( ...d [ 'x' ] ) ;
166
184
} ;
167
185
}
168
186
}
169
187
170
- // No-op, not doing audio processing in this processor. It is just for receiving bootstrap messages.
171
- // However browsers require it to still be present. It should never be called because we never add a
172
- // node to the graph with this processor, although it does look like Chrome does still call this function.
188
+ // No-op, not doing audio processing in this processor. It is just for
189
+ // receiving bootstrap messages. However browsers require it to still be
190
+ // present. It should never be called because we never add a node to the graph
191
+ // with this processor, although it does look like Chrome does still call this
192
+ // function.
173
193
process ( ) {
174
- // keep this function a no-op. Chrome redundantly wants to call this even though this processor is never added to the graph.
194
+ // keep this function a no-op. Chrome redundantly wants to call this even
195
+ // though this processor is never added to the graph.
175
196
}
176
197
} ;
177
198
178
199
// Register the dummy processor that will just receive messages.
179
- registerProcessor ( " message" , BootstrapMessages ) ;
200
+ registerProcessor ( ' message' , BootstrapMessages ) ;
0 commit comments