Skip to content

Commit 4d4a226

Browse files
committed
[libwebaudio.js] Convert to handle allocator. NFC
Also, removing duplication in precondition check.
1 parent b1072be commit 4d4a226

File tree

1 file changed

+77
-82
lines changed

1 file changed

+77
-82
lines changed

src/lib/libwebaudio.js

Lines changed: 77 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -9,38 +9,50 @@
99
#endif
1010

1111
var LibraryWebAudio = {
12-
$EmAudio: {},
13-
$EmAudioCounter: 0,
12+
$emAudio__deps: ['$HandleAllocator'],
13+
$emAudio: 'new HandleAllocator();',
1414

1515
// Call this function from JavaScript to register a Wasm-side handle to an AudioContext that
1616
// you have already created manually without calling emscripten_create_audio_context().
1717
// Note: To let that AudioContext be garbage collected later, call the function
1818
// emscriptenDestroyAudioContext() to unbind it from Wasm.
19-
$emscriptenRegisterAudioObject__deps: ['$EmAudio', '$EmAudioCounter'],
2019
$emscriptenRegisterAudioObject: (object) => {
2120
#if ASSERTIONS
2221
assert(object, 'Called emscriptenRegisterAudioObject() with a null object handle!');
2322
#endif
24-
EmAudio[++EmAudioCounter] = object;
23+
var id = emAudio.allocate(object);
2524
#if WEBAUDIO_DEBUG
26-
console.log(`Registered new WebAudio object ${object} with ID ${EmAudioCounter}`);
25+
console.log(`Registered new WebAudio object ${object} with ID ${id}`);
2726
#endif
28-
return EmAudioCounter;
27+
return id;
2928
},
3029

30+
#if ASSERTIONS || WEBAUDIO_DEBUG
31+
$emAudioCheckHandle__internal: true,
32+
$emAudioCheckHandle(contextHandle, methodName) {
33+
#if WEBAUDIO_DEBUG
34+
dbg(`called ${methodName}() with ID ${contextHandle}`);
35+
#endif
36+
#if ASSERTIONS
37+
assert(emAudio.has(contextHandle), `Called ${methodName}() on a nonexisting context handle ${contextHandle}`);
38+
assert(emAudio.get(contextHandle) instanceof (window.AudioContext || window.webkitAudioContext), `Called ${methodName}() on a context handle ${contextHandle} that is not an AudioContext, but of type ${typeof emAudio.get(contextHandle)}`);
39+
#endif
40+
},
41+
#endif
42+
3143
// Call this function from JavaScript to destroy a Wasm-side handle to an AudioContext.
3244
// After calling this function, it is no longer possible to reference this AudioContext
3345
// from Wasm code - and the GC can reclaim it after all references to it are cleared.
3446
$emscriptenDestroyAudioContext: 'emscripten_destroy_audio_context',
3547

3648
// Call this function from JavaScript to get the Web Audio object corresponding to the given
3749
// Wasm handle ID.
38-
$emscriptenGetAudioObject: (objectHandle) => EmAudio[objectHandle],
50+
$emscriptenGetAudioObject: (objectHandle) => emAudio.get(objectHandle),
3951

4052
// Performs the work of getting the AudioContext's render quantum size.
4153
$emscriptenGetContextQuantumSize: (contextHandle) => {
4254
// TODO: in a future release this will be something like:
43-
// return EmAudio[contextHandle].renderQuantumSize || 128;
55+
// return emAudio.get(contextHandle).renderQuantumSize || 128;
4456
// It comes two caveats: it needs the hint when generating the context adding to
4557
// emscripten_create_audio_context(), and altering the quantum requires a secure
4658
// context and fallback implementing. Until then we simply use the 1.0 API value:
@@ -68,7 +80,7 @@ var LibraryWebAudio = {
6880
} : undefined;
6981

7082
#if WEBAUDIO_DEBUG
71-
console.log(`Creating new WebAudio context with parameters:`);
83+
dbg(`Creating new WebAudio context with parameters:`);
7284
console.dir(opts);
7385
#endif
7486

@@ -81,79 +93,65 @@ var LibraryWebAudio = {
8193
},
8294

8395
emscripten_resume_audio_context_async: (contextHandle, callback, userData) => {
96+
var audio = emAudio.get(contextHandle);
8497
function cb(state) {
8598
#if WEBAUDIO_DEBUG
86-
console.log(`emscripten_resume_audio_context_async() callback: New audio state="${EmAudio[contextHandle].state}", ID=${state}`);
99+
dbg(`emscripten_resume_audio_context_async() callback: New audio state="${audio.state}", ID=${state}`);
87100
#endif
88101
{{{ makeDynCall('viip', 'callback') }}}(contextHandle, state, userData);
89102
}
90103
#if WEBAUDIO_DEBUG
91-
console.log(`emscripten_resume_audio_context_async() resuming...`);
104+
dbg('emscripten_resume_audio_context_async() resuming...');
92105
#endif
93-
EmAudio[contextHandle].resume().then(() => { cb(1/*running*/) }).catch(() => { cb(0/*suspended*/) });
106+
audio.resume().then(() => { cb(1/*running*/) }).catch(() => { cb(0/*suspended*/) });
94107
},
95108

96109
emscripten_resume_audio_context_sync: (contextHandle) => {
97-
#if ASSERTIONS
98-
assert(EmAudio[contextHandle], `Called emscripten_resume_audio_context_sync() on a nonexisting context handle ${contextHandle}`);
99-
assert(EmAudio[contextHandle] instanceof (window.AudioContext || window.webkitAudioContext), `Called emscripten_resume_audio_context_sync() on a context handle ${contextHandle} that is not an AudioContext, but of type ${typeof EmAudio[contextHandle]}`);
100-
#endif
101-
#if WEBAUDIO_DEBUG
102-
console.log(`AudioContext.resume() on WebAudio context with ID ${contextHandle}`);
110+
#if ASSERTIONS || WEBAUDIO_DEBUG
111+
emAudioCheckHandle(contextHandle, 'emscripten_resume_audio_context_sync');
103112
#endif
104-
EmAudio[contextHandle].resume();
113+
emAudio.get(contextHandle).resume();
105114
},
106115

107116
emscripten_audio_context_state: (contextHandle) => {
108-
#if ASSERTIONS
109-
assert(EmAudio[contextHandle], `Called emscripten_audio_context_state() on a nonexisting context handle ${contextHandle}`);
110-
assert(EmAudio[contextHandle] instanceof (window.AudioContext || window.webkitAudioContext), `Called emscripten_audio_context_state() on a context handle ${contextHandle} that is not an AudioContext, but of type ${typeof EmAudio[contextHandle]}`);
117+
#if ASSERTIONS || WEBAUDIO_DEBUG
118+
emAudioCheckHandle(contextHandle, 'emscripten_audio_context_state');
111119
#endif
112-
return ['suspended', 'running', 'closed', 'interrupted'].indexOf(EmAudio[contextHandle].state);
120+
return ['suspended', 'running', 'closed', 'interrupted'].indexOf(emAudio.get(contextHandle).state);
113121
},
114122

115123
emscripten_destroy_audio_context: (contextHandle) => {
116-
#if ASSERTIONS
117-
assert(EmAudio[contextHandle], `Called emscripten_destroy_audio_context() on an already freed context handle ${contextHandle}`);
118-
assert(EmAudio[contextHandle] instanceof (window.AudioContext || window.webkitAudioContext), `Called emscripten_destroy_audio_context() on a context handle ${contextHandle} that is not an AudioContext, but of type ${typeof EmAudio[contextHandle]}`);
119-
#endif
120-
#if WEBAUDIO_DEBUG
121-
console.log(`Destroyed WebAudio context with ID ${contextHandle}`);
124+
#if ASSERTIONS || WEBAUDIO_DEBUG
125+
emAudioCheckHandle(contextHandle, 'emscripten_destroy_audio_context');
122126
#endif
123-
EmAudio[contextHandle].suspend();
124-
delete EmAudio[contextHandle];
127+
emAudio.get(contextHandle).suspend();
128+
emAudio.free(contextHandle);
125129
},
126130

127131
emscripten_destroy_web_audio_node: (objectHandle) => {
128-
#if ASSERTIONS
129-
assert(EmAudio[objectHandle], `Called emscripten_destroy_web_audio_node() on a nonexisting/already freed object handle ${objectHandle}`);
130-
assert(EmAudio[objectHandle].disconnect, `Called emscripten_destroy_web_audio_node() on a handle ${objectHandle} that is not an Web Audio Node, but of type ${typeof EmAudio[objectHandle]}`);
131-
#endif
132-
#if WEBAUDIO_DEBUG
133-
console.log(`Destroyed Web Audio Node with ID ${objectHandle}`);
132+
#if ASSERTIONS || WEBAUDIO_DEBUG
133+
emAudioCheckHandle(objectHandle, 'emscripten_destroy_web_audio_node');
134134
#endif
135135
// Explicitly disconnect the node from Web Audio graph before letting it GC,
136136
// to work around browser bugs such as https://webkit.org/b/222098#c23
137-
EmAudio[objectHandle].disconnect();
138-
delete EmAudio[objectHandle];
137+
emAduio.get(objectHandle).disconnect();
138+
emAudio.free(objectHandle);
139139
},
140140

141141
#if AUDIO_WORKLET
142142
// emscripten_start_wasm_audio_worklet_thread_async() doesn't use stackAlloc,
143143
// etc., but the created worklet does.
144144
emscripten_start_wasm_audio_worklet_thread_async__deps: [
145145
'$_wasmWorkersID',
146-
'$_EmAudioDispatchProcessorCallback',
146+
'$_emAudioDispatchProcessorCallback',
147147
'$stackAlloc', '$stackRestore', '$stackSave'],
148148
emscripten_start_wasm_audio_worklet_thread_async: (contextHandle, stackLowestAddress, stackSize, callback, userData) => {
149149

150-
#if ASSERTIONS
151-
assert(contextHandle, `Called emscripten_start_wasm_audio_worklet_thread_async() with a null Web Audio Context handle!`);
152-
assert(EmAudio[contextHandle], `Called emscripten_start_wasm_audio_worklet_thread_async() with a nonexisting/already freed Web Audio Context handle ${contextHandle}!`);
153-
assert(EmAudio[contextHandle] instanceof (window.AudioContext || window.webkitAudioContext), `Called emscripten_start_wasm_audio_worklet_thread_async() on a context handle ${contextHandle} that is not an AudioContext, but of type ${typeof EmAudio[contextHandle]}`);
150+
#if ASSERTIONS || WEBAUDIO_DEBUG
151+
emAudioCheckHandle(contextHandle, 'emscripten_start_wasm_audio_worklet_thread_async');
154152
#endif
155153

156-
var audioContext = EmAudio[contextHandle];
154+
var audioContext = emAudio.get(contextHandle);
157155
var audioWorklet = audioContext.audioWorklet;
158156

159157
#if ASSERTIONS
@@ -166,12 +164,12 @@ var LibraryWebAudio = {
166164
#endif
167165

168166
#if WEBAUDIO_DEBUG
169-
console.log(`emscripten_start_wasm_audio_worklet_thread_async() adding audioworklet.js...`);
167+
dbg(`emscripten_start_wasm_audio_worklet_thread_async() adding audioworklet.js...`);
170168
#endif
171169

172170
var audioWorkletCreationFailed = () => {
173171
#if ASSERTIONS || WEBAUDIO_DEBUG
174-
console.error(`emscripten_start_wasm_audio_worklet_thread_async() addModule() failed!`);
172+
dbg(`emscripten_start_wasm_audio_worklet_thread_async() addModule() failed!`);
175173
#endif
176174
{{{ makeDynCall('viip', 'callback') }}}(contextHandle, 0/*EM_FALSE*/, userData);
177175
};
@@ -190,7 +188,7 @@ var LibraryWebAudio = {
190188

191189
audioWorklet.addModule({{{ wasmWorkerJs }}}).then(() => {
192190
#if WEBAUDIO_DEBUG
193-
console.log(`emscripten_start_wasm_audio_worklet_thread_async() addModule() completed`);
191+
dbg(`emscripten_start_wasm_audio_worklet_thread_async() addModule() completed`);
194192
#endif
195193

196194
#if MIN_FIREFOX_VERSION < 138 || MIN_CHROME_VERSION != TARGET_NOT_SUPPORTED || MIN_SAFARI_VERSION != TARGET_NOT_SUPPORTED
@@ -234,13 +232,13 @@ var LibraryWebAudio = {
234232
stackLowestAddress, // sb = stack base
235233
stackSize, // sz = stack size
236234
});
237-
audioWorklet['port'].onmessage = _EmAudioDispatchProcessorCallback;
235+
audioWorklet['port'].onmessage = _emAudioDispatchProcessorCallback;
238236
{{{ makeDynCall('viip', 'callback') }}}(contextHandle, 1/*EM_TRUE*/, userData);
239237
}).catch(audioWorkletCreationFailed);
240238
},
241239

242-
$_EmAudioDispatchProcessorCallback__deps: ['$getWasmTableEntry'],
243-
$_EmAudioDispatchProcessorCallback: (e) => {
240+
$_emAudioDispatchProcessorCallback__deps: ['$getWasmTableEntry'],
241+
$_emAudioDispatchProcessorCallback: (e) => {
244242
var data = e.data;
245243
// '_wsc' is short for 'wasm call', trying to use an identifier name that
246244
// will never conflict with user code. This is used to call both the 3-param
@@ -250,10 +248,8 @@ var LibraryWebAudio = {
250248
},
251249

252250
emscripten_create_wasm_audio_worklet_processor_async: (contextHandle, options, callback, userData) => {
253-
#if ASSERTIONS
254-
assert(contextHandle, `Called emscripten_create_wasm_audio_worklet_processor_async() with a null Web Audio Context handle!`);
255-
assert(EmAudio[contextHandle], `Called emscripten_create_wasm_audio_worklet_processor_async() with a nonexisting/already freed Web Audio Context handle ${contextHandle}!`);
256-
assert(EmAudio[contextHandle] instanceof (window.AudioContext || window.webkitAudioContext), `Called emscripten_create_wasm_audio_worklet_processor_async() on a context handle ${contextHandle} that is not an AudioContext, but of type ${typeof EmAudio[contextHandle]}`);
251+
#if ASSERTIONS || WEBAUDIO_DEBUG
252+
emAudioCheckHandle(contextHandle, 'emscripten_create_wasm_audio_worklet_processor_async');
257253
#endif
258254

259255
var processorName = UTF8ToString({{{ makeGetValue('options', C_STRUCTS.WebAudioWorkletProcessorCreateOptions.name, '*') }}});
@@ -282,7 +278,7 @@ var LibraryWebAudio = {
282278
console.log(`emscripten_create_wasm_audio_worklet_processor_async() creating a new AudioWorklet processor with name ${processorName}`);
283279
#endif
284280

285-
EmAudio[contextHandle].audioWorklet['port'].postMessage({
281+
emAudio.get(contextHandle).audioWorklet['port'].postMessage({
286282
// Deliberately mangled and short names used here ('_wpn', the 'Worklet
287283
// Processor Name' used as a 'key' to verify the message type so as to
288284
// not get accidentally mixed with user submitted messages, the remainder
@@ -299,10 +295,8 @@ var LibraryWebAudio = {
299295

300296
emscripten_create_wasm_audio_worklet_node__deps: ['$emscriptenGetContextQuantumSize'],
301297
emscripten_create_wasm_audio_worklet_node: (contextHandle, name, options, callback, userData) => {
302-
#if ASSERTIONS
303-
assert(contextHandle, `Called emscripten_create_wasm_audio_worklet_node() with a null Web Audio Context handle!`);
304-
assert(EmAudio[contextHandle], `Called emscripten_create_wasm_audio_worklet_node() with a nonexisting/already freed Web Audio Context handle ${contextHandle}!`);
305-
assert(EmAudio[contextHandle] instanceof (window.AudioContext || window.webkitAudioContext), `Called emscripten_create_wasm_audio_worklet_node() on a context handle ${contextHandle} that is not an AudioContext, but of type ${typeof EmAudio[contextHandle]}`);
298+
#if ASSERTIONS || WEBAUDIO_DEBUG
299+
emAudioCheckHandle(contextHandle, 'emscripten_create_wasm_audio_worklet_node');
306300
#endif
307301

308302
function readChannelCountArray(heapIndex, numOutputs) {
@@ -329,53 +323,49 @@ var LibraryWebAudio = {
329323
} : undefined;
330324

331325
#if WEBAUDIO_DEBUG
332-
console.log(`Creating AudioWorkletNode "${UTF8ToString(name)}" on context=${contextHandle} with options:`);
326+
dbg(`Creating AudioWorkletNode "${UTF8ToString(name)}" on context=${contextHandle} with options:`);
333327
console.dir(opts);
334328
#endif
335-
return emscriptenRegisterAudioObject(new AudioWorkletNode(EmAudio[contextHandle], UTF8ToString(name), opts));
329+
return emscriptenRegisterAudioObject(new AudioWorkletNode(emAudio.get(contextHandle), UTF8ToString(name), opts));
336330
},
337331
#endif // ~AUDIO_WORKLET
338332

339333
emscripten_audio_context_quantum_size__deps: ['$emscriptenGetContextQuantumSize'],
340334
emscripten_audio_context_quantum_size: (contextHandle) => {
341-
#if ASSERTIONS
342-
assert(EmAudio[contextHandle], `Called emscripten_audio_context_quantum_size() with an invalid Web Audio Context handle ${contextHandle}`);
343-
assert(EmAudio[contextHandle] instanceof (window.AudioContext || window.webkitAudioContext), `Called emscripten_audio_context_quantum_size() on handle ${contextHandle} that is not an AudioContext, but of type ${EmAudio[contextHandle]}`);
335+
#if ASSERTIONS || WEBAUDIO_DEBUG
336+
emAudioCheckHandle(contextHandle, 'emscripten_audio_context_quantum_size')
344337
#endif
345338
return emscriptenGetContextQuantumSize(contextHandle);
346339
},
347340

348341
emscripten_audio_context_sample_rate: (contextHandle) => {
349-
#if ASSERTIONS
350-
assert(EmAudio[contextHandle], `Called emscripten_audio_context_sample_rate() with an invalid Web Audio Context handle ${contextHandle}`);
351-
assert(EmAudio[contextHandle] instanceof (window.AudioContext || window.webkitAudioContext), `Called emscripten_audio_context_sample_rate() on handle ${contextHandle} that is not an AudioContext, but of type ${EmAudio[contextHandle]}`);
342+
#if ASSERTIONS || WEBAUDIO_DEBUG
343+
emAudioCheckHandle(contextHandle, 'emscripten_audio_context_sample_rate');
352344
#endif
353-
return EmAudio[contextHandle]['sampleRate'];
345+
return emAudio.get(contextHandle)['sampleRate'];
354346
},
355347

356348
emscripten_audio_node_connect: (source, destination, outputIndex, inputIndex) => {
357-
var srcNode = EmAudio[source];
358-
var dstNode = EmAudio[destination];
359-
#if ASSERTIONS
360-
assert(srcNode, `Called emscripten_audio_node_connect() with an invalid AudioNode handle ${source}`);
361-
assert(srcNode instanceof window.AudioNode, `Called emscripten_audio_node_connect() on handle ${source} that is not an AudiotNode, but of type ${srcNode}`);
362-
assert(dstNode, `Called emscripten_audio_node_connect() with an invalid AudioNode handle ${destination}!`);
363-
assert(dstNode instanceof (window.AudioContext || window.webkitAudioContext) || dstNode instanceof window.AudioNode, `Called emscripten_audio_node_connect() on handle ${destination} that is not an AudioContext or AudioNode, but of type ${dstNode}`);
349+
#if ASSERTIONS || WEBAUDIO_DEBUG
350+
emAudioCheckHandle(source, 'emscripten_audio_context_sample_rate');
351+
emAudioCheckHandle(destination, 'emscripten_audio_context_sample_rate');
364352
#endif
353+
var srcNode = emAudio.get(source);
354+
var dstNode = emAudio.get(destination);
365355
#if WEBAUDIO_DEBUG
366-
console.log(`Connecting audio node ID ${source} to audio node ID ${destination} (${srcNode} to ${dstNode})`);
356+
dbg(`Connecting audio node ID ${source} to audio node ID ${destination} (${srcNode} to ${dstNode})`);
367357
#endif
368358
srcNode.connect(dstNode.destination || dstNode, outputIndex, inputIndex);
369359
},
370360

371361
emscripten_current_thread_is_audio_worklet: () => ENVIRONMENT_IS_AUDIO_WORKLET,
372362

373363
emscripten_audio_worklet_post_function_v: (audioContext, funcPtr) => {
374-
(audioContext ? EmAudio[audioContext].audioWorklet['port'] : port).postMessage({'_wsc': funcPtr, args: [] }); // "WaSm Call"
364+
(audioContext ? emAudio.get(audioContext).audioWorklet['port'] : port).postMessage({'_wsc': funcPtr, args: [] }); // "WaSm Call"
375365
},
376366

377367
$emscripten_audio_worklet_post_function_1: (audioContext, funcPtr, arg0) => {
378-
(audioContext ? EmAudio[audioContext].audioWorklet['port'] : port).postMessage({'_wsc': funcPtr, args: [arg0] }); // "WaSm Call"
368+
(audioContext ? emAudio.get(audioContext).audioWorklet['port'] : port).postMessage({'_wsc': funcPtr, args: [arg0] }); // "WaSm Call"
379369
},
380370

381371
emscripten_audio_worklet_post_function_vi__deps: ['$emscripten_audio_worklet_post_function_1'],
@@ -389,7 +379,7 @@ var LibraryWebAudio = {
389379
},
390380

391381
$emscripten_audio_worklet_post_function_2: (audioContext, funcPtr, arg0, arg1) => {
392-
(audioContext ? EmAudio[audioContext].audioWorklet['port'] : port).postMessage({'_wsc': funcPtr, args: [arg0, arg1] }); // "WaSm Call"
382+
(audioContext ? emAudio.get(audioContext).audioWorklet['port'] : port).postMessage({'_wsc': funcPtr, args: [arg0, arg1] }); // "WaSm Call"
393383
},
394384

395385
emscripten_audio_worklet_post_function_vii__deps: ['$emscripten_audio_worklet_post_function_2'],
@@ -403,7 +393,7 @@ var LibraryWebAudio = {
403393
},
404394

405395
$emscripten_audio_worklet_post_function_3: (audioContext, funcPtr, arg0, arg1, arg2) => {
406-
(audioContext ? EmAudio[audioContext].audioWorklet['port'] : port).postMessage({'_wsc': funcPtr, args: [arg0, arg1, arg2] }); // "WaSm Call"
396+
(audioContext ? emAudio.get(audioContext).audioWorklet['port'] : port).postMessage({'_wsc': funcPtr, args: [arg0, arg1, arg2] }); // "WaSm Call"
407397
},
408398
emscripten_audio_worklet_post_function_viii__deps: ['$emscripten_audio_worklet_post_function_3'],
409399
emscripten_audio_worklet_post_function_viii: (audioContext, funcPtr, arg0, arg1, arg2) => {
@@ -423,8 +413,13 @@ var LibraryWebAudio = {
423413
assert(UTF8ToString(sigPtr)[0] != 'v', 'Do NOT specify the return argument in the signature string for a call to emscripten_audio_worklet_post_function_sig(), just pass the function arguments.');
424414
assert(varargs);
425415
#endif
426-
(audioContext ? EmAudio[audioContext].audioWorklet['port'] : port).postMessage({'_wsc': funcPtr, args: readEmAsmArgs(sigPtr, varargs) });
416+
(audioContext ? emAudio.get(audioContext).audioWorklet['port'] : port).postMessage({'_wsc': funcPtr, args: readEmAsmArgs(sigPtr, varargs) });
427417
}
428418
};
429419

420+
autoAddDeps(LibraryWebAudio, '$emAudio');
421+
#if ASSERTIONS || WEBAUDIO_DEBUG
422+
autoAddDeps(LibraryWebAudio, '$emAudioCheckHandle');
423+
#endif
424+
430425
addToLibrary(LibraryWebAudio);

0 commit comments

Comments
 (0)