From 81531412233267d1b09f5d1b1d03e27373ee18e6 Mon Sep 17 00:00:00 2001 From: Carl Woffenden Date: Tue, 15 Jul 2025 13:08:25 +0200 Subject: [PATCH 1/8] Additional struct data --- src/struct_info.json | 16 ++++++++++++++++ src/struct_info_generated.json | 19 +++++++++++++++++++ src/struct_info_generated_wasm64.json | 19 +++++++++++++++++++ 3 files changed, 54 insertions(+) diff --git a/src/struct_info.json b/src/struct_info.json index e94e38326b46e..13012a6aaf176 100644 --- a/src/struct_info.json +++ b/src/struct_info.json @@ -1266,6 +1266,17 @@ { "file": "emscripten/webaudio.h", "structs": { + "WebAudioParamDescriptor": [ + "defaultValue", + "minValue", + "maxValue", + "automationRate" + ], + "WebAudioWorkletProcessorCreateOptions": [ + "name", + "numAudioParams", + "audioParamDescriptors" + ], "AudioSampleFrame": [ "numberOfChannels", "samplesPerChannel", @@ -1274,6 +1285,11 @@ "AudioParamFrame": [ "length", "data" + ], + "EmscriptenAudioWorkletNodeCreateOptions": [ + "numberOfInputs", + "numberOfOutputs", + "outputChannelCounts" ] } }, diff --git a/src/struct_info_generated.json b/src/struct_info_generated.json index a31f2e572669e..f25f609305472 100644 --- a/src/struct_info_generated.json +++ b/src/struct_info_generated.json @@ -534,6 +534,12 @@ "numberOfChannels": 0, "samplesPerChannel": 4 }, + "EmscriptenAudioWorkletNodeCreateOptions": { + "__size__": 12, + "numberOfInputs": 0, + "numberOfOutputs": 4, + "outputChannelCounts": 8 + }, "EmscriptenBatteryEvent": { "__size__": 32, "charging": 24, @@ -1479,6 +1485,19 @@ "module": 4, "nextInChain": 0 }, + "WebAudioParamDescriptor": { + "__size__": 16, + "automationRate": 12, + "defaultValue": 0, + "maxValue": 8, + "minValue": 4 + }, + "WebAudioWorkletProcessorCreateOptions": { + "__size__": 12, + "audioParamDescriptors": 8, + "name": 0, + "numAudioParams": 4 + }, "__cxa_exception": { "__size__": 24, "adjustedPtr": 16, diff --git a/src/struct_info_generated_wasm64.json b/src/struct_info_generated_wasm64.json index b3fdd4c8208f0..1e0f770888c92 100644 --- a/src/struct_info_generated_wasm64.json +++ b/src/struct_info_generated_wasm64.json @@ -534,6 +534,12 @@ "numberOfChannels": 0, "samplesPerChannel": 4 }, + "EmscriptenAudioWorkletNodeCreateOptions": { + "__size__": 16, + "numberOfInputs": 0, + "numberOfOutputs": 4, + "outputChannelCounts": 8 + }, "EmscriptenBatteryEvent": { "__size__": 32, "charging": 24, @@ -1479,6 +1485,19 @@ "module": 8, "nextInChain": 0 }, + "WebAudioParamDescriptor": { + "__size__": 16, + "automationRate": 12, + "defaultValue": 0, + "maxValue": 8, + "minValue": 4 + }, + "WebAudioWorkletProcessorCreateOptions": { + "__size__": 24, + "audioParamDescriptors": 16, + "name": 0, + "numAudioParams": 8 + }, "__cxa_exception": { "__size__": 48, "adjustedPtr": 32, From cb5f21732ff7f9d7a08d9a11c1b8a1a630967d78 Mon Sep 17 00:00:00 2001 From: Carl Woffenden Date: Tue, 15 Jul 2025 13:39:56 +0200 Subject: [PATCH 2/8] Initial work to playback audio --- src/audio_worklet.js | 18 +++++++++++------- src/lib/libwebaudio.js | 33 ++++++++++++++++++--------------- 2 files changed, 29 insertions(+), 22 deletions(-) diff --git a/src/audio_worklet.js b/src/audio_worklet.js index e427e4ee3519a..782383e423db6 100644 --- a/src/audio_worklet.js +++ b/src/audio_worklet.js @@ -25,8 +25,8 @@ function createWasmAudioWorkletProcessor(audioParams) { assert(opts.callback) assert(opts.samplesPerChannel) #endif - this.callback = getWasmTableEntry(opts.callback); - this.userData = opts.userData; + this.callback = getWasmTableEntry({{{ toIndexType("opts.callback") }}}); + this.userData = {{{ toIndexType("opts.userData") }}}; // Then the samples per channel to process, fixed for the lifetime of the // context that created this processor. Note for when moving to Web Audio // 1.1: the typed array passed to process() should be the same size as this @@ -82,13 +82,16 @@ function createWasmAudioWorkletProcessor(audioParams) { // Copy output audio descriptor structs to Wasm outputsPtr = dataPtr; - k = outputsPtr >> 2; - outputDataPtr = (dataPtr += numOutputs * {{{ C_STRUCTS.AudioSampleFrame.__size__ }}}) >> 2; + k = {{{ getHeapOffset('outputsPtr', 'u32') }}}; + outputDataPtr = (dataPtr += numOutputs * {{{ C_STRUCTS.AudioSampleFrame.__size__ }}}); for (i of outputList) { // Write the AudioSampleFrame struct instance HEAPU32[k + {{{ C_STRUCTS.AudioSampleFrame.numberOfChannels / 4 }}}] = i.length; HEAPU32[k + {{{ C_STRUCTS.AudioSampleFrame.samplesPerChannel / 4 }}}] = this.samplesPerChannel; HEAPU32[k + {{{ C_STRUCTS.AudioSampleFrame.data / 4 }}}] = dataPtr; +#if MEMORY64 + HEAPU32[k + {{{ C_STRUCTS.AudioSampleFrame.data / 4 + 1 }}}] = dataPtr / 0x100000000; +#endif k += {{{ C_STRUCTS.AudioSampleFrame.__size__ / 4 }}}; // Reserve space for the output data dataPtr += bytesPerChannel * i.length; @@ -110,11 +113,12 @@ function createWasmAudioWorkletProcessor(audioParams) { } // Call out to Wasm callback to perform audio processing - if (didProduceAudio = this.callback(numInputs, inputsPtr, numOutputs, outputsPtr, numParams, paramsPtr, this.userData)) { + if (didProduceAudio = this.callback(numInputs, {{{ toIndexType('inputsPtr') }}}, numOutputs, {{{ toIndexType('outputsPtr') }}}, numParams, {{{ toIndexType('paramsPtr') }}}, this.userData)) { // Read back the produced audio data to all outputs and their channels. // (A garbage-free function TypedArray.copy(dstTypedArray, dstOffset, // srcTypedArray, srcOffset, count) would sure be handy.. but web does // not have one, so manually copy all bytes in) + outputDataPtr = {{{ getHeapOffset('outputDataPtr', 'float') }}}; for (i of outputList) { for (j of i) { for (k = 0; k < this.samplesPerChannel; ++k) { @@ -168,9 +172,9 @@ class BootstrapMessages extends AudioWorkletProcessor { // // '_wsc' is short for 'wasm call', using an identifier that will never // conflict with user messages - messagePort.postMessage({'_wsc': d.callback, args: [d.contextHandle, 1/*EM_TRUE*/, d.userData] }); + messagePort.postMessage({'_wsc': {{{ toIndexType("d.callback") }}}, args: [d.contextHandle, 1/*EM_TRUE*/, {{{ toIndexType("d.userData") }}}] }); } else if (d['_wsc']) { - getWasmTableEntry(d['_wsc'])(...d.args); + getWasmTableEntry({{{ toIndexType("d['_wsc']") }}})(...d.args); }; } } diff --git a/src/lib/libwebaudio.js b/src/lib/libwebaudio.js index 113dc0f5b7eba..41fe1e4353e5d 100644 --- a/src/lib/libwebaudio.js +++ b/src/lib/libwebaudio.js @@ -78,7 +78,7 @@ let LibraryWebAudio = { #if WEBAUDIO_DEBUG console.log(`emscripten_resume_audio_context_async() callback: New audio state="${EmAudio[contextHandle].state}", ID=${state}`); #endif - {{{ makeDynCall('viii', 'callback') }}}(contextHandle, state, userData); + {{{ makeDynCall('viip', 'callback') }}}(contextHandle, state, userData); } #if WEBAUDIO_DEBUG console.log(`emscripten_resume_audio_context_async() resuming...`); @@ -202,7 +202,7 @@ let LibraryWebAudio = { } }); audioWorklet.bootstrapMessage.port.onmessage = _EmAudioDispatchProcessorCallback; - {{{ makeDynCall('viii', 'callback') }}}(contextHandle, 1/*EM_TRUE*/, userData); + {{{ makeDynCall('viip', 'callback') }}}(contextHandle, 1/*EM_TRUE*/, userData); }).catch(audioWorkletCreationFailed); }, @@ -222,24 +222,25 @@ let LibraryWebAudio = { 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]}`); #endif - options >>= 2; let audioParams = [], - numAudioParams = HEAPU32[options+1], - audioParamDescriptors = HEAPU32[options+2] >> 2, + processorName = UTF8ToString({{{ makeGetValue('options', C_STRUCTS.WebAudioWorkletProcessorCreateOptions.name, '*') }}}), + numAudioParams = {{{ makeGetValue('options', C_STRUCTS.WebAudioWorkletProcessorCreateOptions.numAudioParams, 'i32') }}}, + audioParamDescriptors = {{{ makeGetValue('options', C_STRUCTS.WebAudioWorkletProcessorCreateOptions.audioParamDescriptors, '*') }}}, i = 0; while (numAudioParams--) { audioParams.push({ name: i++, - defaultValue: HEAPF32[audioParamDescriptors++], - minValue: HEAPF32[audioParamDescriptors++], - maxValue: HEAPF32[audioParamDescriptors++], - automationRate: ['a','k'][HEAPU32[audioParamDescriptors++]] + '-rate', + defaultValue: {{{ makeGetValue('audioParamDescriptors', C_STRUCTS.WebAudioParamDescriptor.defaultValue, 'float') }}}, + minValue: {{{ makeGetValue('audioParamDescriptors', C_STRUCTS.WebAudioParamDescriptor.minValue, 'float') }}}, + maxValue: {{{ makeGetValue('audioParamDescriptors', C_STRUCTS.WebAudioParamDescriptor.maxValue, 'float') }}}, + automationRate: ({{{ makeGetValue('audioParamDescriptors', C_STRUCTS.WebAudioParamDescriptor.automationRate, 'i32') }}} ? 'k' : 'a') + '-rate' }); + audioParamDescriptors += {{{ C_STRUCTS.WebAudioParamDescriptor.__size__ }}}; } #if WEBAUDIO_DEBUG - console.log(`emscripten_create_wasm_audio_worklet_processor_async() creating a new AudioWorklet processor with name ${UTF8ToString(HEAPU32[options])}`); + console.log(`emscripten_create_wasm_audio_worklet_processor_async() creating a new AudioWorklet processor with name ${processorName}`); #endif EmAudio[contextHandle].audioWorklet.bootstrapMessage.port.postMessage({ @@ -247,7 +248,7 @@ let LibraryWebAudio = { // Processor Name' used as a 'key' to verify the message type so as to // not get accidentally mixed with user submitted messages, the remainder // for space saving reasons, abbreviated from their variable names). - '_wpn': UTF8ToString(HEAPU32[options]), + '_wpn': processorName, audioParams, contextHandle, callback, @@ -262,18 +263,20 @@ let LibraryWebAudio = { assert(EmAudio[contextHandle], `Called emscripten_create_wasm_audio_worklet_node() with a nonexisting/already freed Web Audio Context handle ${contextHandle}!`); 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]}`); #endif - options >>= 2; function readChannelCountArray(heapIndex, numOutputs) { + if (!heapIndex) return void 0; + heapIndex = {{{ getHeapOffset('heapIndex', 'i32') }}}; let channelCounts = []; while (numOutputs--) channelCounts.push(HEAPU32[heapIndex++]); return channelCounts; } + let optionsOutputs = options ? {{{ makeGetValue('options', C_STRUCTS.EmscriptenAudioWorkletNodeCreateOptions.numberOfOutputs, 'i32') }}} : 0; let opts = options ? { - numberOfInputs: HEAP32[options], - numberOfOutputs: HEAP32[options+1], - outputChannelCount: HEAPU32[options+2] ? readChannelCountArray(HEAPU32[options+2]>>2, HEAP32[options+1]) : void 0, + numberOfInputs: {{{ makeGetValue('options', C_STRUCTS.EmscriptenAudioWorkletNodeCreateOptions.numberOfInputs, 'i32') }}}, + numberOfOutputs: optionsOutputs, + outputChannelCount: readChannelCountArray({{{ makeGetValue('options', C_STRUCTS.EmscriptenAudioWorkletNodeCreateOptions.outputChannelCounts, 'i32*') }}}, optionsOutputs), processorOptions: { callback, userData, From 3d3d0e2d88b1c94534f50f5af7d38372eb7f140c Mon Sep 17 00:00:00 2001 From: Carl Woffenden Date: Thu, 17 Jul 2025 16:07:16 +0200 Subject: [PATCH 3/8] Outputs working --- src/audio_worklet.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/audio_worklet.js b/src/audio_worklet.js index 782383e423db6..aad313ab9d15b 100644 --- a/src/audio_worklet.js +++ b/src/audio_worklet.js @@ -65,17 +65,20 @@ function createWasmAudioWorkletProcessor(audioParams) { inputsPtr = stackAlloc(stackMemoryNeeded); // Copy input audio descriptor structs and data to Wasm - k = inputsPtr >> 2; + k = {{{ getHeapOffset('inputsPtr', 'u32') }}}; dataPtr = inputsPtr + numInputs * {{{ C_STRUCTS.AudioSampleFrame.__size__ }}}; for (i of inputList) { // Write the AudioSampleFrame struct instance HEAPU32[k + {{{ C_STRUCTS.AudioSampleFrame.numberOfChannels / 4 }}}] = i.length; HEAPU32[k + {{{ C_STRUCTS.AudioSampleFrame.samplesPerChannel / 4 }}}] = this.samplesPerChannel; HEAPU32[k + {{{ C_STRUCTS.AudioSampleFrame.data / 4 }}}] = dataPtr; +#if MEMORY64 + HEAPU32[k + {{{ C_STRUCTS.AudioSampleFrame.data / 4 + 1 }}}] = dataPtr / 0x100000000; +#endif k += {{{ C_STRUCTS.AudioSampleFrame.__size__ / 4 }}}; // Marshal the input audio sample data for each audio channel of this input for (j of i) { - HEAPF32.set(j, dataPtr>>2); + HEAPF32.set(j, {{{ getHeapOffset('dataPtr', 'float') }}}); dataPtr += bytesPerChannel; } } From 0804e5f60c2cb62e1b054d0496f7b49401d39774 Mon Sep 17 00:00:00 2001 From: Carl Woffenden Date: Thu, 17 Jul 2025 16:16:01 +0200 Subject: [PATCH 4/8] Params working --- src/audio_worklet.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/audio_worklet.js b/src/audio_worklet.js index aad313ab9d15b..9a63ed1b6fb90 100644 --- a/src/audio_worklet.js +++ b/src/audio_worklet.js @@ -102,16 +102,19 @@ function createWasmAudioWorkletProcessor(audioParams) { // Copy parameters descriptor structs and data to Wasm paramsPtr = dataPtr; - k = paramsPtr >> 2; + k = {{{ getHeapOffset('paramsPtr', 'u32') }}}; dataPtr += numParams * {{{ C_STRUCTS.AudioParamFrame.__size__ }}}; for (i = 0; paramArray = parameters[i++];) { // Write the AudioParamFrame struct instance HEAPU32[k + {{{ C_STRUCTS.AudioParamFrame.length / 4 }}}] = paramArray.length; HEAPU32[k + {{{ C_STRUCTS.AudioParamFrame.data / 4 }}}] = dataPtr; +#if MEMORY64 + HEAPU32[k + {{{ C_STRUCTS.AudioSampleFrame.data / 4 + 1 }}}] = dataPtr / 0x100000000; +#endif k += {{{ C_STRUCTS.AudioParamFrame.__size__ / 4 }}}; // Marshal the audio parameters array - HEAPF32.set(paramArray, dataPtr>>2); + HEAPF32.set(paramArray, {{{ getHeapOffset('dataPtr', 'float') }}}); dataPtr += paramArray.length*4; } From 8872c6ac94bacffba6839626ada4ee97e1842941 Mon Sep 17 00:00:00 2001 From: Carl Woffenden Date: Thu, 17 Jul 2025 16:24:26 +0200 Subject: [PATCH 5/8] Re-enabled wasm64 tests --- test/test_browser.py | 8 -------- 1 file changed, 8 deletions(-) diff --git a/test/test_browser.py b/test/test_browser.py index 00ec71c038c53..10555620fce31 100644 --- a/test/test_browser.py +++ b/test/test_browser.py @@ -5497,8 +5497,6 @@ def test_full_js_library_strict(self): 'es6': (['-sEXPORT_ES6'],), 'strict': (['-sSTRICT'],), }) - @no_wasm64('https://github.com/emscripten-core/emscripten/pull/23508') - @no_2gb('https://github.com/emscripten-core/emscripten/pull/23508') @requires_sound_hardware def test_audio_worklet(self, args): self.btest_exit('webaudio/audioworklet.c', cflags=['-sAUDIO_WORKLET', '-sWASM_WORKERS', '-DTEST_AND_EXIT'] + args) @@ -5521,8 +5519,6 @@ def test_audio_worklet_post_function(self, args): '': ([],), 'closure': (['--closure', '1', '-Oz'],), }) - @no_wasm64('https://github.com/emscripten-core/emscripten/pull/23508') - @no_2gb('https://github.com/emscripten-core/emscripten/pull/23508') @requires_sound_hardware def test_audio_worklet_modularize(self, args): self.btest_exit('webaudio/audioworklet.c', cflags=['-sAUDIO_WORKLET', '-sWASM_WORKERS', '-sMODULARIZE=1', '-sEXPORT_NAME=MyModule', '--shell-file', test_file('shell_that_launches_modularize.html'), '-DTEST_AND_EXIT'] + args) @@ -5534,8 +5530,6 @@ def test_audio_worklet_modularize(self, args): '': ([],), 'minimal_with_closure': (['-sMINIMAL_RUNTIME', '--closure=1', '-Oz'],), }) - @no_wasm64('https://github.com/emscripten-core/emscripten/pull/23508') - @no_2gb('https://github.com/emscripten-core/emscripten/pull/23508') @requires_sound_hardware def test_audio_worklet_params_mixing(self, args): os.mkdir('audio_files') @@ -5544,8 +5538,6 @@ def test_audio_worklet_params_mixing(self, args): self.btest_exit('webaudio/audioworklet_params_mixing.c', cflags=['-sAUDIO_WORKLET', '-sWASM_WORKERS', '-DTEST_AND_EXIT'] + args) # Tests AudioWorklet with emscripten_lock_busyspin_wait_acquire() and friends - @no_wasm64('https://github.com/emscripten-core/emscripten/pull/23508') - @no_2gb('https://github.com/emscripten-core/emscripten/pull/23508') @requires_sound_hardware @also_with_minimal_runtime def test_audio_worklet_emscripten_locks(self): From 986ee8773c576891d7aa93fced0e0ca0b72a9703 Mon Sep 17 00:00:00 2001 From: Carl Woffenden Date: Thu, 17 Jul 2025 19:26:46 +0200 Subject: [PATCH 6/8] 'let' breaks closure (when used with makeGetValue) --- src/lib/libwebaudio.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/libwebaudio.js b/src/lib/libwebaudio.js index 41fe1e4353e5d..200318bece58f 100644 --- a/src/lib/libwebaudio.js +++ b/src/lib/libwebaudio.js @@ -222,7 +222,7 @@ let LibraryWebAudio = { 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]}`); #endif - let audioParams = [], + var audioParams = [], processorName = UTF8ToString({{{ makeGetValue('options', C_STRUCTS.WebAudioWorkletProcessorCreateOptions.name, '*') }}}), numAudioParams = {{{ makeGetValue('options', C_STRUCTS.WebAudioWorkletProcessorCreateOptions.numAudioParams, 'i32') }}}, audioParamDescriptors = {{{ makeGetValue('options', C_STRUCTS.WebAudioWorkletProcessorCreateOptions.audioParamDescriptors, '*') }}}, From bc161b580643fc5d8a1bd047d7c279eb6784a135 Mon Sep 17 00:00:00 2001 From: Carl Woffenden Date: Mon, 21 Jul 2025 11:44:54 +0200 Subject: [PATCH 7/8] Rebaseline audio test size (compressed is smaller, uncompressed larger) --- test/code_size/audio_worklet_wasm.js | 219 +++++++++++++------------ test/code_size/audio_worklet_wasm.json | 8 +- 2 files changed, 114 insertions(+), 113 deletions(-) diff --git a/test/code_size/audio_worklet_wasm.js b/test/code_size/audio_worklet_wasm.js index 80e2b3ab5538c..fe15da6171acb 100644 --- a/test/code_size/audio_worklet_wasm.js +++ b/test/code_size/audio_worklet_wasm.js @@ -1,65 +1,68 @@ -var k = globalThis.Module || "undefined" != typeof Module ? Module : {}, p = "em-ww" == globalThis.name, q = "undefined" !== typeof AudioWorkletGlobalScope, r, v, L, M, G, I, C, X, J, E, D, Y, Z; +var l = globalThis.Module || "undefined" != typeof Module ? Module : {}, n = "em-ww" == globalThis.name, q = "undefined" !== typeof AudioWorkletGlobalScope, r, v, L, M, G, I, C, X, J, E, D, Y, Z; -q && (p = !0); +q && (n = !0); function u(a) { r = a; v = a.I; x(); - k ||= {}; - k.wasm = a.C; + l ||= {}; + l.wasm = a.C; y(); a.C = a.J = 0; } -p && !q && (onmessage = a => { +n && !q && (onmessage = a => { onmessage = null; u(a.data); }); if (q) { function a(c) { - class d extends AudioWorkletProcessor { - constructor(e) { + class e extends AudioWorkletProcessor { + constructor(d) { super(); - e = e.processorOptions; - this.u = C.get(e.u); - this.v = e.v; - this.s = e.s; + d = d.processorOptions; + this.u = C.get(d.u); + this.v = d.v; + this.s = d.s; } static get parameterDescriptors() { return c; } - process(e, h, f) { - let m = e.length, w = h.length, F = 0, l, z, n, t = 4 * this.s, g = 12 * (m + w), W = D(), A, H, B; - for (l of e) g += l.length * t; - for (l of h) g += l.length * t; - for (l in f) g += f[l].byteLength + 8, ++F; - A = E(g); - g = A >> 2; - n = A + 12 * m; - for (l of e) { - G[g] = l.length; - G[g + 1] = this.s; - G[g + 2] = n; - g += 3; - for (z of l) I.set(z, n >> 2), n += t; + process(d, g, h) { + let p = d.length, w = g.length, F = 0, k, z, m, t = 4 * this.s, f = 12 * (p + w), W = D(), A, H, B; + for (k of d) f += k.length * t; + for (k of g) f += k.length * t; + for (k in h) f += h[k].byteLength + 8, ++F; + A = E(f); + f = A >> 2; + m = A + 12 * p; + for (k of d) { + G[f] = k.length; + G[f + 1] = this.s; + G[f + 2] = m; + f += 3; + for (z of k) I.set(z, m >> 2), m += t; + } + H = m; + f = H >> 2; + d = m += 12 * w; + for (k of g) G[f] = k.length, G[f + 1] = this.s, G[f + 2] = m, f += 3, m += t * k.length; + t = m; + f = t >> 2; + m += 8 * F; + for (k = 0; B = h[k++]; ) G[f] = B.length, G[f + 1] = m, f += 2, I.set(B, m >> 2), + m += 4 * B.length; + if (h = this.u(p, A, w, H, F, t, this.v)) { + d >>= 2; + for (k of g) for (z of k) for (f = 0; f < this.s; ++f) z[f] = I[d++]; } - H = n; - g = H >> 2; - e = (n += 12 * w) >> 2; - for (l of h) G[g] = l.length, G[g + 1] = this.s, G[g + 2] = n, g += 3, n += t * l.length; - t = n; - g = t >> 2; - n += 8 * F; - for (l = 0; B = f[l++]; ) G[g] = B.length, G[g + 1] = n, g += 2, I.set(B, n >> 2), - n += 4 * B.length; - if (f = this.u(m, A, w, H, F, t, this.v)) for (l of h) for (z of l) for (g = 0; g < this.s; ++g) z[g] = I[e++]; J(W); - return !!f; + return !!h; } } - return d; + return e; } var K; class b extends AudioWorkletProcessor { @@ -67,12 +70,12 @@ if (q) { super(); u(c.processorOptions); K = this.port; - K.onmessage = async d => { - d = d.data; - d._wpn ? (registerProcessor(d._wpn, a(d.D)), K.postMessage({ - _wsc: d.u, - A: [ d.F, 1, d.v ] - })) : d._wsc && C.get(d._wsc)(...d.A); + K.onmessage = async e => { + e = e.data; + e._wpn ? (registerProcessor(e._wpn, a(e.D)), K.postMessage({ + _wsc: e.u, + A: [ e.F, 1, e.v ] + })) : e._wsc && C.get(e._wsc)(...e.A); }; } process() {} @@ -88,7 +91,7 @@ function x() { I = new Float32Array(a); } -p || (v = k.mem || new WebAssembly.Memory({ +n || (v = l.mem || new WebAssembly.Memory({ initial: 256, maximum: 256, shared: !0 @@ -100,24 +103,24 @@ var N = [], O = a => { b && C.get(b)(...a.x); }, P = a => { N.push(a); -}, Q = a => J(a), R = () => D(), aa = (a, b, c, d) => { +}, Q = a => J(a), R = () => D(), aa = (a, b, c, e) => { b = S[b]; - S[a].connect(b.destination || b, c, d); + S[a].connect(b.destination || b, c, e); }, S = {}, T = 0, U = "undefined" != typeof TextDecoder ? new TextDecoder : void 0, V = (a = 0) => { - for (var b = L, c = a, d = c + void 0; b[c] && !(c >= d); ) ++c; + for (var b = L, c = a, e = c + void 0; b[c] && !(c >= e); ) ++c; if (16 < c - a && b.buffer && U) return U.decode(b.slice(a, c)); - for (d = ""; a < c; ) { - var e = b[a++]; - if (e & 128) { - var h = b[a++] & 63; - if (192 == (e & 224)) d += String.fromCharCode((e & 31) << 6 | h); else { - var f = b[a++] & 63; - e = 224 == (e & 240) ? (e & 15) << 12 | h << 6 | f : (e & 7) << 18 | h << 12 | f << 6 | b[a++] & 63; - 65536 > e ? d += String.fromCharCode(e) : (e -= 65536, d += String.fromCharCode(55296 | e >> 10, 56320 | e & 1023)); + for (e = ""; a < c; ) { + var d = b[a++]; + if (d & 128) { + var g = b[a++] & 63; + if (192 == (d & 224)) e += String.fromCharCode((d & 31) << 6 | g); else { + var h = b[a++] & 63; + d = 224 == (d & 240) ? (d & 15) << 12 | g << 6 | h : (d & 7) << 18 | g << 12 | h << 6 | b[a++] & 63; + 65536 > d ? e += String.fromCharCode(d) : (d -= 65536, e += String.fromCharCode(55296 | d >> 10, 56320 | d & 1023)); } - } else d += String.fromCharCode(e); + } else e += String.fromCharCode(d); } - return d; + return e; }, ba = a => { var b = window.AudioContext || window.webkitAudioContext; if (a >>= 2) { @@ -129,72 +132,70 @@ var N = [], O = a => { } else a = void 0; if (c = b) b = new b(a), S[++T] = b, c = T; return c; -}, ca = (a, b, c, d, e) => { - if (c >>= 2) { - var h = M[c], f = M[c + 1]; - if (G[c + 2]) { - var m = G[c + 2] >> 2; - c = M[c + 1]; - let w = []; - for (;c--; ) w.push(G[m++]); - m = w; - } else m = void 0; - d = { +}, ca = (a, b, c, e, d) => { + let g = c ? M[c + 4 >> 2] : 0; + if (c) { + var h = M[c >> 2]; + c = G[c + 8 >> 2]; + var p = g; + if (c) { + c >>= 2; + for (var w = []; p--; ) w.push(G[c++]); + c = w; + } else c = void 0; + e = { numberOfInputs: h, - numberOfOutputs: f, - outputChannelCount: m, + numberOfOutputs: g, + outputChannelCount: c, processorOptions: { - u: d, - v: e, + u: e, + v: d, s: 128 } }; - } else d = void 0; - a = new AudioWorkletNode(S[a], b ? V(b) : "", d); + } else e = void 0; + a = new AudioWorkletNode(S[a], b ? V(b) : "", e); S[++T] = a; return T; -}, da = (a, b, c, d) => { - b >>= 2; - let e = [], h = G[b + 1], f = G[b + 2] >> 2, m = 0; - for (;h--; ) e.push({ - name: m++, - defaultValue: I[f++], - minValue: I[f++], - maxValue: I[f++], - automationRate: [ "a", "k" ][G[f++]] + "-rate" - }); - h = S[a].audioWorklet.B.port; - f = h.postMessage; - b = (b = G[b]) ? V(b) : ""; - f.call(h, { - _wpn: b, - D: e, +}, da = (a, b, c, e) => { + var d = [], g = (g = G[b >> 2]) ? V(g) : "", h = M[b + 4 >> 2]; + b = G[b + 8 >> 2]; + for (var p = 0; h--; ) d.push({ + name: p++, + defaultValue: I[b >> 2], + minValue: I[b + 4 >> 2], + maxValue: I[b + 8 >> 2], + automationRate: (M[b + 12 >> 2] ? "k" : "a") + "-rate" + }), b += 16; + S[a].audioWorklet.B.port.postMessage({ + _wpn: g, + D: d, F: a, u: c, - v: d + v: e }); }, ea = () => !1, fa = 1, ha = a => { a = a.data; let b = a._wsc; b && C.get(b)(...a.A); -}, ia = a => E(a), ja = (a, b, c, d, e) => { - let h = S[a], f = h.audioWorklet, m = () => { - C.get(d)(a, 0, e); +}, ia = a => E(a), ja = (a, b, c, e, d) => { + let g = S[a], h = g.audioWorklet, p = () => { + C.get(e)(a, 0, d); }; - if (!f) return m(); - f.addModule(k.js).then((() => { - f.B = new AudioWorkletNode(h, "em-bootstrap", { + if (!h) return p(); + h.addModule(l.js).then((() => { + h.B = new AudioWorkletNode(g, "em-bootstrap", { processorOptions: { K: fa++, - C: k.wasm, + C: l.wasm, I: v, G: b, H: c } }); - f.B.port.onmessage = ha; - C.get(d)(a, 1, e); - })).catch(m); + h.B.port.onmessage = ha; + C.get(e)(a, 1, d); + })).catch(p); }; function ka(a) { @@ -218,7 +219,7 @@ function y() { c: ja, a: v }; - WebAssembly.instantiate(k.wasm, { + WebAssembly.instantiate(l.wasm, { a: Z }).then((a => { a = a.instance.exports; @@ -228,14 +229,14 @@ function y() { D = a.n; Y = a.o; C = a.k; - k.stackSave = R; - k.stackAlloc = ia; - k.stackRestore = Q; - k.wasmTable = C; - p ? (Y(r.G, r.H), "undefined" === typeof AudioWorkletGlobalScope && (removeEventListener("message", P), + l.stackSave = R; + l.stackAlloc = ia; + l.stackRestore = Q; + l.wasmTable = C; + n ? (Y(r.G, r.H), "undefined" === typeof AudioWorkletGlobalScope && (removeEventListener("message", P), N = N.forEach(O), addEventListener("message", O))) : a.i(); - p || X(); + n || X(); })); } -p || y(); \ No newline at end of file +n || y(); \ No newline at end of file diff --git a/test/code_size/audio_worklet_wasm.json b/test/code_size/audio_worklet_wasm.json index 9648aff3d49a7..ac82d5d9d9179 100644 --- a/test/code_size/audio_worklet_wasm.json +++ b/test/code_size/audio_worklet_wasm.json @@ -1,10 +1,10 @@ { "a.html": 519, "a.html.gz": 357, - "a.js": 3853, - "a.js.gz": 2045, + "a.js": 3864, + "a.js.gz": 2041, "a.wasm": 1288, "a.wasm.gz": 860, - "total": 5660, - "total_gz": 3262 + "total": 5671, + "total_gz": 3258 } From 5fe41a5791f385fe134c1b2246992d4b237b73e5 Mon Sep 17 00:00:00 2001 From: Carl Woffenden Date: Tue, 22 Jul 2025 11:50:03 +0200 Subject: [PATCH 8/8] Something to re-run CI --- src/lib/libwebaudio.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/libwebaudio.js b/src/lib/libwebaudio.js index 200318bece58f..d86244a6c2313 100644 --- a/src/lib/libwebaudio.js +++ b/src/lib/libwebaudio.js @@ -234,7 +234,7 @@ let LibraryWebAudio = { defaultValue: {{{ makeGetValue('audioParamDescriptors', C_STRUCTS.WebAudioParamDescriptor.defaultValue, 'float') }}}, minValue: {{{ makeGetValue('audioParamDescriptors', C_STRUCTS.WebAudioParamDescriptor.minValue, 'float') }}}, maxValue: {{{ makeGetValue('audioParamDescriptors', C_STRUCTS.WebAudioParamDescriptor.maxValue, 'float') }}}, - automationRate: ({{{ makeGetValue('audioParamDescriptors', C_STRUCTS.WebAudioParamDescriptor.automationRate, 'i32') }}} ? 'k' : 'a') + '-rate' + automationRate: ({{{ makeGetValue('audioParamDescriptors', C_STRUCTS.WebAudioParamDescriptor.automationRate, 'i32') }}} ? 'k' : 'a') + '-rate', }); audioParamDescriptors += {{{ C_STRUCTS.WebAudioParamDescriptor.__size__ }}}; }