diff --git a/src/audio_worklet.js b/src/audio_worklet.js index 23bc78b81a915..8e323401712a3 100644 --- a/src/audio_worklet.js +++ b/src/audio_worklet.js @@ -32,11 +32,51 @@ function createWasmAudioWorkletProcessor(audioParams) { this.callback = {{{ makeDynCall('iipipipp', 'opts.callback') }}}; this.userData = 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 - // 'render quantum size', and this exercise of passing in the value - // shouldn't be required (to be verified) + // context that created this processor. Even though this 'render quantum + // size' is fixed at 128 samples in the 1.0 spec, it will be variable in + // the 1.1 spec. It's passed in now, just to prove it's settable, but will + // eventually be a property of the AudioWorkletGlobalScope (globalThis). this.samplesPerChannel = opts.samplesPerChannel; + this.bytesPerChannel = this.samplesPerChannel * {{{ getNativeTypeSize('float') }}}; + + // Creates the output views (see createOutputViews() docs) + this.maxBuffers = Math.min(((wwParams.stackSize - /*minimum alloc*/ 16) / this.bytesPerChannel) | 0, /*sensible limit*/ 64); + this.outputViews = []; +#if ASSERTIONS + console.assert(this.maxBuffers > 0, `AudioWorklet needs more stack allocating (at least ${this.bytesPerChannel})`); +#endif + this.createOutputViews(); + +#if ASSERTIONS + // Explicitly verify this later in process() + this.ctorOldStackPtr = stackSave(); +#endif + } + + /** + * Create up-front as many typed views for marshalling the output data as + * may be required (with an arbitrary maximum of 64, for the case where a + * multi-MB stack is passed), allocated at the *top* of the worklet's stack + * (and whose addresses are fixed). The 'minimum alloc' firstly stops + * STACK_OVERFLOW_CHECK failing (since the stack will be full, and 16 bytes + * being the minimum allocation size due to alignments) and leaves room for + * a single AudioSampleFrame as a minumum. + */ + createOutputViews() { + // These are still alloc'd to take advantage of the overflow checks, etc. + var oldStackPtr = stackSave(); + var viewDataIdx = {{{ getHeapOffset('stackAlloc(this.maxBuffers * this.bytesPerChannel)', 'float') }}}; +#if WEBAUDIO_DEBUG + console.log(`AudioWorklet creating ${this.maxBuffers} buffer one-time views (for a stack size of ${wwParams.stackSize} at address ${ptrToString(viewDataIdx * 4)})`); +#endif + this.outputViews.length = 0; + for (var n = this.maxBuffers; n > 0; n--) { + // Added in reverse so the lowest indices are closest to the stack top + this.outputViews.unshift( + HEAPF32.subarray(viewDataIdx, viewDataIdx += this.samplesPerChannel) + ); + } + stackRestore(oldStackPtr); } static get parameterDescriptors() { @@ -44,12 +84,19 @@ function createWasmAudioWorkletProcessor(audioParams) { } /** + * Marshals all inputs and parameters to the Wasm memory on the thread's + * stack, then performs the wasm audio worklet call, and finally marshals + * audio output data back. + * * @param {Object} parameters */ process(inputList, outputList, parameters) { - // Marshal all inputs and parameters to the Wasm memory on the thread stack, - // then perform the wasm audio worklet call, - // and finally marshal audio output data back. +#if ALLOW_MEMORY_GROWTH + // recreate the output views if the heap has changed + if (HEAPF32.buffer != this.outputViews[0].buffer) { + this.createOutputViews(); + } +#endif var numInputs = inputList.length; var numOutputs = outputList.length; @@ -57,26 +104,47 @@ function createWasmAudioWorkletProcessor(audioParams) { var entry; // reused list entry or index var subentry; // reused channel or other array in each list entry or index - // Calculate how much stack space is needed. - var bytesPerChannel = this.samplesPerChannel * {{{ getNativeTypeSize('float') }}}; - var stackMemoryNeeded = (numInputs + numOutputs) * {{{ C_STRUCTS.AudioSampleFrame.__size__ }}}; + // Calculate the required stack and output buffer views (stack is further + // split into aligned structs and the raw float data). + var stackMemoryStruct = (numInputs + numOutputs) * {{{ C_STRUCTS.AudioSampleFrame.__size__ }}}; + var stackMemoryData = 0; + for (entry of inputList) { + stackMemoryData += entry.length * this.bytesPerChannel; + } + // Collect the total number of output channels (mapped to array views) + var outputViewsNeeded = 0; + for (entry of outputList) { + outputViewsNeeded += entry.length; + } + stackMemoryData += outputViewsNeeded * this.bytesPerChannel; var numParams = 0; - for (entry of inputList) stackMemoryNeeded += entry.length * bytesPerChannel; - for (entry of outputList) stackMemoryNeeded += entry.length * bytesPerChannel; for (entry in parameters) { - stackMemoryNeeded += parameters[entry].byteLength + {{{ C_STRUCTS.AudioParamFrame.__size__ }}}; ++numParams; + stackMemoryStruct += {{{ C_STRUCTS.AudioParamFrame.__size__ }}}; + stackMemoryData += parameters[entry].byteLength; } +#if ASSERTIONS + console.assert(outputViewsNeeded <= this.outputViews.length, `Too many AudioWorklet outputs (need ${outputViewsNeeded} but have stack space for ${this.outputViews.length})`); +#endif - // Allocate the necessary stack space. var oldStackPtr = stackSave(); - var inputsPtr = stackAlloc(stackMemoryNeeded); + // Allocate the necessary stack space. All pointer variables are in bytes; + // 'structPtr' starts at the first struct entry (all run sequentially) + // and is the working start to each record; 'dataPtr' is the same for the + // audio/params data, starting after *all* the structs. + // 'structPtr' begins 16-byte aligned, allocated from the internal + // _emscripten_stack_alloc(), as are the output views, and so to ensure + // the views fall on the correct addresses (and we finish at stacktop) we + // request additional bytes, taking this alignment into account, then + // offset `dataPtr` by the difference. + var stackMemoryAligned = (stackMemoryStruct + stackMemoryData + 15) & ~15; + var structPtr = stackAlloc(stackMemoryAligned); + var dataPtr = structPtr + (stackMemoryAligned - stackMemoryData); - // Copy input audio descriptor structs and data to Wasm ('structPtr' is - // reused as the working start to each struct record, 'dataPtr' start of - // the data section, usually after all structs). - var structPtr = inputsPtr; - var dataPtr = inputsPtr + numInputs * {{{ C_STRUCTS.AudioSampleFrame.__size__ }}}; + // Copy input audio descriptor structs and data to Wasm (recall, structs + // first, audio data after). 'inputsPtr' is the start of the C callback's + // input AudioSampleFrame. + var /*const*/ inputsPtr = structPtr; for (entry of inputList) { // Write the AudioSampleFrame struct instance {{{ makeSetValue('structPtr', C_STRUCTS.AudioSampleFrame.numberOfChannels, 'entry.length', 'u32') }}}; @@ -86,28 +154,13 @@ function createWasmAudioWorkletProcessor(audioParams) { // Marshal the input audio sample data for each audio channel of this input for (subentry of entry) { HEAPF32.set(subentry, {{{ getHeapOffset('dataPtr', 'float') }}}); - dataPtr += bytesPerChannel; + dataPtr += this.bytesPerChannel; } } - // Copy output audio descriptor structs to Wasm - var outputsPtr = dataPtr; - structPtr = outputsPtr; - var outputDataPtr = (dataPtr += numOutputs * {{{ C_STRUCTS.AudioSampleFrame.__size__ }}}); - for (entry of outputList) { - // Write the AudioSampleFrame struct instance - {{{ makeSetValue('structPtr', C_STRUCTS.AudioSampleFrame.numberOfChannels, 'entry.length', 'u32') }}}; - {{{ makeSetValue('structPtr', C_STRUCTS.AudioSampleFrame.samplesPerChannel, 'this.samplesPerChannel', 'u32') }}}; - {{{ makeSetValue('structPtr', C_STRUCTS.AudioSampleFrame.data, 'dataPtr', '*') }}}; - structPtr += {{{ C_STRUCTS.AudioSampleFrame.__size__ }}}; - // Reserve space for the output data - dataPtr += bytesPerChannel * entry.length; - } - - // Copy parameters descriptor structs and data to Wasm - var paramsPtr = dataPtr; - structPtr = paramsPtr; - dataPtr += numParams * {{{ C_STRUCTS.AudioParamFrame.__size__ }}}; + // Copy parameters descriptor structs and data to Wasm. 'paramsPtr' is the + // start of the C callback's input AudioParamFrame. + var /*const*/ paramsPtr = structPtr; for (entry = 0; subentry = parameters[entry++];) { // Write the AudioParamFrame struct instance {{{ makeSetValue('structPtr', C_STRUCTS.AudioParamFrame.length, 'subentry.length', 'u32') }}}; @@ -118,20 +171,53 @@ function createWasmAudioWorkletProcessor(audioParams) { dataPtr += subentry.length * {{{ getNativeTypeSize('float') }}}; } + // Copy output audio descriptor structs to Wasm. 'outputsPtr' is the start + // of the C callback's output AudioSampleFrame. 'dataPtr' will now be + // aligned with the output views, ending at stacktop. + var /*const*/ outputsPtr = structPtr; + for (entry of outputList) { + // Write the AudioSampleFrame struct instance + {{{ makeSetValue('structPtr', C_STRUCTS.AudioSampleFrame.numberOfChannels, 'entry.length', 'u32') }}}; + {{{ makeSetValue('structPtr', C_STRUCTS.AudioSampleFrame.samplesPerChannel, 'this.samplesPerChannel', 'u32') }}}; + {{{ makeSetValue('structPtr', C_STRUCTS.AudioSampleFrame.data, 'dataPtr', '*') }}}; + structPtr += {{{ C_STRUCTS.AudioSampleFrame.__size__ }}}; + // Advance the output pointer to the next output (matching the pre-allocated views) + dataPtr += this.bytesPerChannel * entry.length; + } + +#if ASSERTIONS + // If all the maths worked out, we arrived at the original stack address + console.assert(dataPtr == oldStackPtr, `AudioWorklet stack missmatch (audio data finishes at ${dataPtr} instead of ${oldStackPtr})`); + + // Sanity checks. If these trip the most likely cause, beyond unforeseen + // stack shenanigans, is that the 'render quantum size' changed after + // construction (which shouldn't be possible). + if (numOutputs) { + // First that the output view addresses match the stack positions + dataPtr -= this.bytesPerChannel; + for (entry = 0; entry < outputViewsNeeded; entry++) { + console.assert(dataPtr == this.outputViews[entry].byteOffset, 'AudioWorklet internal error in addresses of the output array views'); + dataPtr -= this.bytesPerChannel; + } + // And that the views' size match the passed in output buffers + for (entry of outputList) { + for (subentry of entry) { + console.assert(subentry.byteLength == this.bytesPerChannel, `AudioWorklet unexpected output buffer size (expected ${this.bytesPerChannel} got ${subentry.byteLength})`); + } + } + } +#endif + // Call out to Wasm callback to perform audio processing var didProduceAudio = this.callback(numInputs, inputsPtr, numOutputs, outputsPtr, numParams, paramsPtr, this.userData); if (didProduceAudio) { // 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') }}}; + // The preallocated 'outputViews' already have the correct offsets and + // sizes into the stack (recall from createOutputViews() that they run + // backwards). for (entry of outputList) { for (subentry of entry) { - // repurposing structPtr for now - for (structPtr = 0; structPtr < this.samplesPerChannel; ++structPtr) { - subentry[structPtr] = HEAPF32[outputDataPtr++]; - } + subentry.set(this.outputViews[--outputViewsNeeded]); } } } diff --git a/test/code_size/audio_worklet_wasm.js b/test/code_size/audio_worklet_wasm.js index c12517dca2e7f..7e7b6e491c75d 100644 --- a/test/code_size/audio_worklet_wasm.js +++ b/test/code_size/audio_worklet_wasm.js @@ -1,15 +1,15 @@ -var l = globalThis.Module || "undefined" != typeof Module ? Module : {}, n = "em-ww" == globalThis.name, q = "undefined" !== typeof AudioWorkletGlobalScope, t, A, v, K, L, F, H, B, X, I, E, C, Y, Z; +var l = globalThis.Module || "undefined" != typeof Module ? Module : {}, n = "em-ww" == globalThis.name, q = "undefined" !== typeof AudioWorkletGlobalScope, t, z, v, J, K, H, E, A, X, F, C, B, Y, Z; q && (n = !0); function u(a) { t = a; - v = a.I; - y(); + v = a.M; + w(); l ||= {}; - l.wasm = a.C; - z(); - a.C = a.J = 0; + l.wasm = a.H; + y(); + a.H = a.N = 0; } n && !q && (onmessage = a => { @@ -23,60 +23,68 @@ if (q) { constructor(d) { super(); d = d.processorOptions; - this.u = B.get(d.u); - this.v = d.v; - this.s = d.s; + this.v = A.get(d.v); + this.A = d.A; + this.u = d.u; + this.s = 4 * this.u; + this.G = Math.min((t.F - 16) / this.s | 0, 64); + this.B = []; + this.I(); + } + I() { + var d = B(), f = C(this.G * this.s) >> 2; + this.B.length = 0; + for (var g = this.G; 0 < g; g--) this.B.unshift(E.subarray(f, f += this.u)); + F(d); } static get parameterDescriptors() { return c; } - process(d, g, h) { - var p = d.length, w = g.length, k, r, x = 4 * this.s, f = 12 * (p + w), D = 0; - for (k of d) f += k.length * x; - for (k of g) f += k.length * x; - for (k in h) f += h[k].byteLength + 8, ++D; - var W = C(), G = E(f); - f = G; - var m = G + 12 * p; + process(d, f, g) { + var p = d.length, x = f.length, k, r, h = 12 * (p + x), m = 0; + for (k of d) m += k.length * this.s; + var G = 0; + for (k of f) G += k.length; + m += G * this.s; + var O = 0; + for (k in g) ++O, h += 8, m += g[k].byteLength; + var V = B(), D = h + m + 15 & -16; + h = C(D); + m = h + (D - m); + D = h; for (k of d) { - F[f >> 2] = k.length; - F[f + 4 >> 2] = this.s; - F[f + 8 >> 2] = m; - f += 12; - for (r of k) H.set(r, m >> 2), m += x; + H[h >> 2] = k.length; + H[h + 4 >> 2] = this.u; + H[h + 8 >> 2] = m; + h += 12; + for (r of k) E.set(r, m >> 2), m += this.s; } - var P = m; - f = P; - d = m += 12 * w; - for (k of g) F[f >> 2] = k.length, F[f + 4 >> 2] = this.s, F[f + 8 >> 2] = m, f += 12, - m += x * k.length; - f = x = m; - m += 8 * D; - for (k = 0; r = h[k++]; ) F[f >> 2] = r.length, F[f + 4 >> 2] = m, f += 8, H.set(r, m >> 2), + d = h; + for (k = 0; r = g[k++]; ) H[h >> 2] = r.length, H[h + 4 >> 2] = m, h += 8, E.set(r, m >> 2), m += 4 * r.length; - if (h = this.u(p, G, w, P, D, x, this.v)) { - d >>= 2; - for (k of g) for (r of k) for (f = 0; f < this.s; ++f) r[f] = H[d++]; - } - I(W); - return !!h; + g = h; + for (k of f) H[h >> 2] = k.length, H[h + 4 >> 2] = this.u, H[h + 8 >> 2] = m, h += 12, + m += this.s * k.length; + if (p = this.v(p, D, x, g, O, d, this.A)) for (k of f) for (r of k) r.set(this.B[--G]); + F(V); + return !!p; } } return e; } - var J; + var I; class b extends AudioWorkletProcessor { constructor(c) { super(); u(c.processorOptions); - J = this.port; - J.onmessage = async e => { - await A; + I = this.port; + I.onmessage = async e => { + await z; e = e.data; - e._wpn ? (registerProcessor(e._wpn, a(e.D)), J.postMessage({ - _wsc: e.u, - A: [ e.F, 1, e.v ] - })) : e._wsc && B.get(e._wsc)(...e.A); + e._wpn ? (registerProcessor(e._wpn, a(e.J)), I.postMessage({ + _wsc: e.v, + C: [ e.K, 1, e.A ] + })) : e._wsc && A.get(e._wsc)(...e.C); }; } process() {} @@ -84,160 +92,160 @@ if (q) { registerProcessor("em-bootstrap", b); } -function y() { +function w() { var a = v.buffer; - K = new Uint8Array(a); - L = new Int32Array(a); - F = new Uint32Array(a); - H = new Float32Array(a); + J = new Uint8Array(a); + K = new Int32Array(a); + H = new Uint32Array(a); + E = new Float32Array(a); } n || (v = l.mem || new WebAssembly.Memory({ initial: 256, maximum: 256, shared: !0 -}), y()); +}), w()); -var M = [], N = a => { +var L = [], M = a => { a = a.data; let b = a._wsc; - b && B.get(b)(...a.x); -}, O = a => { - M.push(a); -}, Q = a => I(a), R = () => C(), aa = (a, b, c, e) => { - b = S[b]; - 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 = K, c = a, e = c + void 0; b[c] && !(c >= e); ) ++c; + b && A.get(b)(...a.x); +}, N = a => { + L.push(a); +}, P = a => F(a), Q = () => B(), S = (a, b, c, e) => { + b = R[b]; + R[a].connect(b.destination || b, c, e); +}, R = {}, T = 0, U = "undefined" != typeof TextDecoder ? new TextDecoder : void 0, W = (a = 0) => { + for (var b = J, 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 (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; + var f = b[a++] & 63; + if (192 == (d & 224)) e += String.fromCharCode((d & 31) << 6 | f); else { + var g = b[a++] & 63; + d = 224 == (d & 240) ? (d & 15) << 12 | f << 6 | g : (d & 7) << 18 | f << 12 | g << 6 | b[a++] & 63; 65536 > d ? e += String.fromCharCode(d) : (d -= 65536, e += String.fromCharCode(55296 | d >> 10, 56320 | d & 1023)); } } else e += String.fromCharCode(d); } return e; -}, ba = a => { +}, aa = a => { var b = window.AudioContext || window.webkitAudioContext; if (a) { - var c = F[a >> 2]; + var c = H[a >> 2]; a = { - latencyHint: (c ? V(c) : "") || void 0, - sampleRate: F[a + 4 >> 2] || void 0 + latencyHint: (c ? W(c) : "") || void 0, + sampleRate: H[a + 4 >> 2] || void 0 }; } else a = void 0; - if (c = b) b = new b(a), S[++T] = b, c = T; + if (c = b) b = new b(a), R[++T] = b, c = T; return c; -}, ca = (a, b, c, e, d) => { - var g = c ? L[c + 4 >> 2] : 0; +}, ba = (a, b, c, e, d) => { + var f = c ? K[c + 4 >> 2] : 0; if (c) { - var h = L[c >> 2]; - c = F[c + 8 >> 2]; - var p = g; + var g = K[c >> 2]; + c = H[c + 8 >> 2]; + var p = f; if (c) { c >>= 2; - for (var w = []; p--; ) w.push(F[c++]); - c = w; + for (var x = []; p--; ) x.push(H[c++]); + c = x; } else c = void 0; e = { - numberOfInputs: h, - numberOfOutputs: g, + numberOfInputs: g, + numberOfOutputs: f, outputChannelCount: c, processorOptions: { - u: e, - v: d, - s: 128 + v: e, + A: d, + u: 128 } }; } else e = void 0; - a = new AudioWorkletNode(S[a], b ? V(b) : "", e); - S[++T] = a; + a = new AudioWorkletNode(R[a], b ? W(b) : "", e); + R[++T] = a; return T; -}, da = (a, b, c, e) => { - var d = [], g = (g = F[b >> 2]) ? V(g) : "", h = L[b + 4 >> 2]; - b = F[b + 8 >> 2]; - for (var p = 0; h--; ) d.push({ +}, ca = (a, b, c, e) => { + var d = [], f = (f = H[b >> 2]) ? W(f) : "", g = K[b + 4 >> 2]; + b = H[b + 8 >> 2]; + for (var p = 0; g--; ) d.push({ name: p++, - defaultValue: H[b >> 2], - minValue: H[b + 4 >> 2], - maxValue: H[b + 8 >> 2], - automationRate: (L[b + 12 >> 2] ? "k" : "a") + "-rate" + defaultValue: E[b >> 2], + minValue: E[b + 4 >> 2], + maxValue: E[b + 8 >> 2], + automationRate: (K[b + 12 >> 2] ? "k" : "a") + "-rate" }), b += 16; - S[a].audioWorklet.B.port.postMessage({ - _wpn: g, - D: d, - F: a, - u: c, - v: e + R[a].audioWorklet.D.port.postMessage({ + _wpn: f, + J: d, + K: a, + v: c, + A: e }); -}, ea = () => !1, fa = 1, ha = a => { +}, da = () => !1, ea = 1, fa = a => { a = a.data; var b = a._wsc; - b && B.get(b)(...a.A); -}, ia = a => E(a), ja = (a, b, c, e, d) => { - var g = S[a], h = g.audioWorklet, p = () => { - B.get(e)(a, 0, d); + b && A.get(b)(...a.C); +}, ha = a => C(a), ia = (a, b, c, e, d) => { + var f = R[a], g = f.audioWorklet, p = () => { + A.get(e)(a, 0, d); }; - if (!h) return p(); - h.addModule(l.js).then((() => { - h.B = new AudioWorkletNode(g, "em-bootstrap", { + if (!g) return p(); + g.addModule(l.js).then((() => { + g.D = new AudioWorkletNode(f, "em-bootstrap", { processorOptions: { - K: fa++, - C: l.wasm, - I: v, - G: b, - H: c + O: ea++, + H: l.wasm, + M: v, + L: b, + F: c } }); - h.B.port.onmessage = ha; - B.get(e)(a, 1, d); + g.D.port.onmessage = fa; + A.get(e)(a, 1, d); })).catch(p); }; -function ka(a) { +function ja(a) { let b = document.createElement("button"); b.innerHTML = "Toggle playback"; document.body.appendChild(b); - a = S[a]; + a = R[a]; b.onclick = () => { "running" != a.state ? a.resume() : a.suspend(); }; } -function z() { +function y() { Z = { - f: ka, - g: aa, - d: ba, - h: ca, - e: da, - b: ea, - c: ja, + f: ja, + g: S, + d: aa, + h: ba, + e: ca, + b: da, + c: ia, a: v }; - A = WebAssembly.instantiate(l.wasm, { + z = WebAssembly.instantiate(l.wasm, { a: Z }).then((a => { a = (a.instance || a).exports; X = a.j; - I = a.l; - E = a.m; - C = a.n; + F = a.l; + C = a.m; + B = a.n; Y = a.o; - B = a.k; - l.stackSave = R; - l.stackAlloc = ia; - l.stackRestore = Q; - l.wasmTable = B; - n ? (Y(t.G, t.H), "undefined" === typeof AudioWorkletGlobalScope && (removeEventListener("message", O), - M = M.forEach(N), addEventListener("message", N))) : a.i(); + A = a.k; + l.stackSave = Q; + l.stackAlloc = ha; + l.stackRestore = P; + l.wasmTable = A; + n ? (Y(t.L, t.F), "undefined" === typeof AudioWorkletGlobalScope && (removeEventListener("message", N), + L = L.forEach(M), addEventListener("message", M))) : a.i(); n || X(); })); } -n || z(); \ No newline at end of file +n || y(); \ No newline at end of file diff --git a/test/code_size/test_minimal_runtime_code_size_audio_worklet.json b/test/code_size/test_minimal_runtime_code_size_audio_worklet.json index 396f6f055b6f9..3130cc6363ed8 100644 --- a/test/code_size/test_minimal_runtime_code_size_audio_worklet.json +++ b/test/code_size/test_minimal_runtime_code_size_audio_worklet.json @@ -1,10 +1,10 @@ { "a.html": 519, "a.html.gz": 357, - "a.js": 3896, - "a.js.gz": 2049, + "a.js": 4084, + "a.js.gz": 2134, "a.wasm": 1288, "a.wasm.gz": 860, - "total": 5703, - "total_gz": 3266 + "total": 5891, + "total_gz": 3351 } diff --git a/test/webaudio/audioworklet_params_mixing.c b/test/webaudio/audioworklet_params_mixing.c index 7b2f56a80cae0..21f8661cd0817 100644 --- a/test/webaudio/audioworklet_params_mixing.c +++ b/test/webaudio/audioworklet_params_mixing.c @@ -33,7 +33,7 @@ bool process(int numInputs, const AudioSampleFrame* inputs, int numOutputs, Audi } // Interestingly, params varies per browser. Chrome won't have a length > 1 // unless the value changes, and FF has all 128 entries even for a k-rate - // parameter. The only given is that two params are incoming: + // parameter. The only given for this test is that two params are incoming: assert(numParams == 2); assert(params[0].length == 1 || params[0].length == outSamplesPerChannel); assert(params[1].length == 1 || params[1].length == outSamplesPerChannel);