Skip to content

Commit 7d0322e

Browse files
authored
Add setting -sAUDIO_WORKLET_SUPPORT_AUDIO_PARAMS (#25357)
Add setting -sAUDIO_WORKLET_SUPPORT_AUDIO_PARAMS to allow disabling the often unused AudioParams mechanism.
1 parent 93cdde9 commit 7d0322e

File tree

6 files changed

+78
-29
lines changed

6 files changed

+78
-29
lines changed

site/source/docs/tools_reference/settings_reference.rst

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2511,6 +2511,18 @@ full documentation in site/source/docs/api_reference/wasm_audio_worklets.rst
25112511

25122512
Default value: 0
25132513

2514+
.. _audio_worklet_support_audio_params:
2515+
2516+
AUDIO_WORKLET_SUPPORT_AUDIO_PARAMS
2517+
==================================
2518+
2519+
If true, enables utilizing k- and a-rate AudioParams based properties in
2520+
Wasm Audio Worklet code. If false, AudioParams are not used. Set to false
2521+
for a tiny improvement to code size and AudioWorklet CPU performance when
2522+
audio synthesis is synchronized using custom WebAssembly Memory-based means.
2523+
2524+
Default value: true
2525+
25142526
.. _webaudio_debug:
25152527

25162528
WEBAUDIO_DEBUG

src/audio_worklet.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,11 @@ var instantiatePromise;
1818

1919
if (ENVIRONMENT_IS_AUDIO_WORKLET) {
2020

21+
#if AUDIO_WORKLET_SUPPORT_AUDIO_PARAMS
2122
function createWasmAudioWorkletProcessor(audioParams) {
23+
#else
24+
function createWasmAudioWorkletProcessor() {
25+
#endif
2226
class WasmAudioWorkletProcessor extends AudioWorkletProcessor {
2327
constructor(args) {
2428
super();
@@ -76,9 +80,11 @@ function createWasmAudioWorkletProcessor(audioParams) {
7680
stackRestore(oldStackPtr);
7781
}
7882

83+
#if AUDIO_WORKLET_SUPPORT_AUDIO_PARAMS
7984
static get parameterDescriptors() {
8085
return audioParams;
8186
}
87+
#endif
8288

8389
/**
8490
* Marshals all inputs and parameters to the Wasm memory on the thread's
@@ -87,7 +93,13 @@ function createWasmAudioWorkletProcessor(audioParams) {
8793
*
8894
* @param {Object} parameters
8995
*/
96+
#if AUDIO_WORKLET_SUPPORT_AUDIO_PARAMS
9097
process(inputList, outputList, parameters) {
98+
#else
99+
/** @suppress {checkTypes} */
100+
process(inputList, outputList) {
101+
#endif
102+
91103
#if ALLOW_MEMORY_GROWTH
92104
// Recreate the output views if the heap has changed
93105
// TODO: add support for GROWABLE_ARRAYBUFFERS
@@ -117,11 +129,13 @@ function createWasmAudioWorkletProcessor(audioParams) {
117129
}
118130
stackMemoryData += outputViewsNeeded * this.bytesPerChannel;
119131
var numParams = 0;
132+
#if AUDIO_WORKLET_SUPPORT_AUDIO_PARAMS
120133
for (entry in parameters) {
121134
++numParams;
122135
stackMemoryStruct += {{{ C_STRUCTS.AudioParamFrame.__size__ }}};
123136
stackMemoryData += parameters[entry].byteLength;
124137
}
138+
#endif
125139
var oldStackPtr = stackSave();
126140
#if ASSERTIONS
127141
console.assert(oldStackPtr == this.ctorOldStackPtr, 'AudioWorklet stack address has unexpectedly moved');
@@ -158,6 +172,7 @@ function createWasmAudioWorkletProcessor(audioParams) {
158172
}
159173
}
160174

175+
#if AUDIO_WORKLET_SUPPORT_AUDIO_PARAMS
161176
// Copy parameters descriptor structs and data to Wasm. 'paramsPtr' is the
162177
// start of the C callback's input AudioParamFrame.
163178
var /*const*/ paramsPtr = structPtr;
@@ -170,6 +185,9 @@ function createWasmAudioWorkletProcessor(audioParams) {
170185
HEAPF32.set(subentry, {{{ getHeapOffset('dataPtr', 'float') }}});
171186
dataPtr += subentry.length * {{{ getNativeTypeSize('float') }}};
172187
}
188+
#else
189+
var paramsPtr = 0;
190+
#endif
173191

174192
// Copy output audio descriptor structs to Wasm. 'outputsPtr' is the start
175193
// of the C callback's output AudioSampleFrame. 'dataPtr' will now be
@@ -261,7 +279,11 @@ class BootstrapMessages extends AudioWorkletProcessor {
261279
// '_wpn' is short for 'Worklet Processor Node', using an identifier
262280
// that will never conflict with user messages
263281
// Register a real AudioWorkletProcessor that will actually do audio processing.
282+
#if AUDIO_WORKLET_SUPPORT_AUDIO_PARAMS
264283
registerProcessor(d['_wpn'], createWasmAudioWorkletProcessor(d.audioParams));
284+
#else
285+
registerProcessor(d['_wpn'], createWasmAudioWorkletProcessor());
286+
#endif
265287
#if WEBAUDIO_DEBUG
266288
console.log(`Registered a new WasmAudioWorkletProcessor "${d['_wpn']}" with AudioParams: ${d.audioParams}`);
267289
#endif

src/lib/libwebaudio.js

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -230,12 +230,13 @@ var LibraryWebAudio = {
230230
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]}`);
231231
#endif
232232

233-
var audioParams = [];
234233
var processorName = UTF8ToString({{{ makeGetValue('options', C_STRUCTS.WebAudioWorkletProcessorCreateOptions.name, '*') }}});
234+
235+
#if AUDIO_WORKLET_SUPPORT_AUDIO_PARAMS
235236
var numAudioParams = {{{ makeGetValue('options', C_STRUCTS.WebAudioWorkletProcessorCreateOptions.numAudioParams, 'i32') }}};
236237
var audioParamDescriptors = {{{ makeGetValue('options', C_STRUCTS.WebAudioWorkletProcessorCreateOptions.audioParamDescriptors, '*') }}};
238+
var audioParams = [];
237239
var paramIndex = 0;
238-
239240
while (numAudioParams--) {
240241
audioParams.push({
241242
name: paramIndex++,
@@ -246,6 +247,10 @@ var LibraryWebAudio = {
246247
});
247248
audioParamDescriptors += {{{ C_STRUCTS.WebAudioParamDescriptor.__size__ }}};
248249
}
250+
#elif ASSERTIONS
251+
var numAudioParams = {{{ makeGetValue('options', C_STRUCTS.WebAudioWorkletProcessorCreateOptions.numAudioParams, 'i32') }}};
252+
assert(numAudioParams == 0 && "Rebuild with -sAUDIO_WORKLET_SUPPORT_AUDIO_PARAMS to utilize AudioParams");
253+
#endif
249254

250255
#if WEBAUDIO_DEBUG
251256
console.log(`emscripten_create_wasm_audio_worklet_processor_async() creating a new AudioWorklet processor with name ${processorName}`);
@@ -257,7 +262,9 @@ var LibraryWebAudio = {
257262
// not get accidentally mixed with user submitted messages, the remainder
258263
// for space saving reasons, abbreviated from their variable names).
259264
'_wpn': processorName,
265+
#if AUDIO_WORKLET_SUPPORT_AUDIO_PARAMS
260266
audioParams,
267+
#endif
261268
contextHandle,
262269
callback,
263270
userData,

src/settings.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1642,6 +1642,13 @@ var WASM_WORKERS = 0;
16421642
// [link]
16431643
var AUDIO_WORKLET = 0;
16441644

1645+
// If true, enables utilizing k- and a-rate AudioParams based properties in
1646+
// Wasm Audio Worklet code. If false, AudioParams are not used. Set to false
1647+
// for a tiny improvement to code size and AudioWorklet CPU performance when
1648+
// audio synthesis is synchronized using custom WebAssembly Memory-based means.
1649+
// [link]
1650+
var AUDIO_WORKLET_SUPPORT_AUDIO_PARAMS = true;
1651+
16451652
// If true, enables deep debugging of Web Audio backend.
16461653
// [link]
16471654
var WEBAUDIO_DEBUG = 0;

test/codesize/audio_worklet_wasm.expected.js

Lines changed: 27 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -31,21 +31,21 @@ if (r) {
3131
this.K();
3232
}
3333
K() {
34-
for (var c = C(), f = D(this.B.length * this.s) >> 2, g = this.B.length - 1; 0 <= g; g--) this.B[g] = E.subarray(f, f += this.u);
34+
for (var c = C(), g = D(this.B.length * this.s) >> 2, f = this.B.length - 1; 0 <= f; f--) this.B[f] = E.subarray(g, g += this.u);
3535
F(c);
3636
}
3737
static get parameterDescriptors() {
3838
return e;
3939
}
40-
process(c, f, g) {
41-
var n = c.length, x = f.length, k, p, h = 12 * (n + x), l = 0;
40+
process(c, g, f) {
41+
var n = c.length, x = g.length, k, p, h = 12 * (n + x), l = 0;
4242
for (k of c) l += k.length;
4343
l *= this.s;
4444
var G = 0;
45-
for (k of f) G += k.length;
45+
for (k of g) G += k.length;
4646
l += G * this.s;
4747
var O = 0;
48-
for (k in g) ++O, h += 8, l += g[k].byteLength;
48+
for (k in f) ++O, h += 8, l += f[k].byteLength;
4949
var V = C(), B = h + l + 15 & -16;
5050
h = D(B);
5151
l = h + (B - l);
@@ -58,12 +58,12 @@ if (r) {
5858
for (p of k) E.set(p, l >> 2), l += this.s;
5959
}
6060
c = h;
61-
for (k = 0; p = g[k++]; ) H[h >> 2] = p.length, H[h + 4 >> 2] = l, h += 8, E.set(p, l >> 2),
61+
for (k = 0; p = f[k++]; ) H[h >> 2] = p.length, H[h + 4 >> 2] = l, h += 8, E.set(p, l >> 2),
6262
l += 4 * p.length;
63-
g = h;
64-
for (k of f) H[h >> 2] = k.length, H[h + 4 >> 2] = this.u, H[h + 8 >> 2] = l, h += 12,
63+
f = h;
64+
for (k of g) H[h >> 2] = k.length, H[h + 4 >> 2] = this.u, H[h + 8 >> 2] = l, h += 12,
6565
l += this.s * k.length;
66-
if (n = this.v(n, B, x, g, O, c, this.A)) for (k of f) for (p of k) p.set(this.B[--G]);
66+
if (n = this.v(n, B, x, f, O, c, this.A)) for (k of g) for (p of k) p.set(this.B[--G]);
6767
F(V);
6868
return !!n;
6969
}
@@ -119,10 +119,10 @@ var L = [], M = a => {
119119
for (d = ""; a < e; ) {
120120
var c = b[a++];
121121
if (c & 128) {
122-
var f = b[a++] & 63;
123-
if (192 == (c & 224)) d += String.fromCharCode((c & 31) << 6 | f); else {
124-
var g = b[a++] & 63;
125-
c = 224 == (c & 240) ? (c & 15) << 12 | f << 6 | g : (c & 7) << 18 | f << 12 | g << 6 | b[a++] & 63;
122+
var g = b[a++] & 63;
123+
if (192 == (c & 224)) d += String.fromCharCode((c & 31) << 6 | g); else {
124+
var f = b[a++] & 63;
125+
c = 224 == (c & 240) ? (c & 15) << 12 | g << 6 | f : (c & 7) << 18 | g << 12 | f << 6 | b[a++] & 63;
126126
65536 > c ? d += String.fromCharCode(c) : (c -= 65536, d += String.fromCharCode(55296 | c >> 10, 56320 | c & 1023));
127127
}
128128
} else d += String.fromCharCode(c);
@@ -140,19 +140,19 @@ var L = [], M = a => {
140140
P[++R] = a;
141141
return R;
142142
}, W = (a, b, e, d, c) => {
143-
var f = e ? K[e + 4 >> 2] : 0;
143+
var g = e ? K[e + 4 >> 2] : 0;
144144
if (e) {
145-
var g = K[e >> 2];
145+
var f = K[e >> 2];
146146
e = H[e + 8 >> 2];
147-
var n = f;
147+
var n = g;
148148
if (e) {
149149
e >>= 2;
150150
for (var x = []; n--; ) x.push(H[e++]);
151151
e = x;
152152
} else e = void 0;
153153
d = {
154-
numberOfInputs: g,
155-
numberOfOutputs: f,
154+
numberOfInputs: f,
155+
numberOfOutputs: g,
156156
outputChannelCount: e,
157157
processorOptions: {
158158
v: d,
@@ -165,18 +165,18 @@ var L = [], M = a => {
165165
P[++R] = a;
166166
return R;
167167
}, aa = (a, b, e, d) => {
168-
var c = [], f = (f = H[b >> 2]) ? T(f) : "", g = K[b + 4 >> 2];
168+
var c = (c = H[b >> 2]) ? T(c) : "", g = K[b + 4 >> 2];
169169
b = H[b + 8 >> 2];
170-
for (var n = 0; g--; ) c.push({
170+
for (var f = [], n = 0; g--; ) f.push({
171171
name: n++,
172172
defaultValue: E[b >> 2],
173173
minValue: E[b + 4 >> 2],
174174
maxValue: E[b + 8 >> 2],
175175
automationRate: (K[b + 12 >> 2] ? "k" : "a") + "-rate"
176176
}), b += 16;
177177
P[a].audioWorklet.D.port.postMessage({
178-
_wpn: f,
179-
H: c,
178+
_wpn: c,
179+
H: f,
180180
I: a,
181181
v: e,
182182
A: d
@@ -186,12 +186,12 @@ var L = [], M = a => {
186186
var b = a._wsc;
187187
b && A.get(b)(...a.C);
188188
}, ea = (a, b, e, d, c) => {
189-
var f = P[a], g = f.audioWorklet, n = () => {
189+
var g = P[a], f = g.audioWorklet, n = () => {
190190
A.get(d)(a, 0, c);
191191
};
192-
if (!g) return n();
193-
g.addModule(m.js).then((() => {
194-
g.D = new AudioWorkletNode(f, "em-bootstrap", {
192+
if (!f) return n();
193+
f.addModule(m.js).then((() => {
194+
f.D = new AudioWorkletNode(g, "em-bootstrap", {
195195
processorOptions: {
196196
N: ca++,
197197
G: m.wasm,
@@ -200,7 +200,7 @@ var L = [], M = a => {
200200
F: e
201201
}
202202
});
203-
g.D.port.onmessage = da;
203+
f.D.port.onmessage = da;
204204
A.get(d)(a, 1, c);
205205
})).catch(n);
206206
};

test/test_browser.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5459,6 +5459,7 @@ def test_full_js_library_strict(self):
54595459
'pthreads_es6': (['-pthread', '-sPTHREAD_POOL_SIZE=2', '-sEXPORT_ES6'],),
54605460
'es6': (['-sEXPORT_ES6'],),
54615461
'strict': (['-sSTRICT'],),
5462+
'audio_params_disabled': (['-sAUDIO_WORKLET_SUPPORT_AUDIO_PARAMS=0'],),
54625463
})
54635464
@requires_sound_hardware
54645465
def test_audio_worklet(self, args):

0 commit comments

Comments
 (0)