Skip to content

Commit a6d1c87

Browse files
authored
[AUDIO_WORKLET] Tidy and document the worklet processing code. NFC (#24878)
This renames some of the single-letter variables and documents their use. Since I've spent a lot of time in this code it's extra work to keep remembering that `k` is the struct address (previously the heap index), `j` is the audio channel, etc. I also removed some of the code that had side effects, e.g. `c = (a += b)`; some but not all). The end result (IMO) is readable and even saves a few bytes after Closure. (This is the only planned change like this ahead of the optimisation PR)
1 parent 6aff524 commit a6d1c87

File tree

3 files changed

+163
-154
lines changed

3 files changed

+163
-154
lines changed

src/audio_worklet.js

Lines changed: 53 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -47,79 +47,86 @@ function createWasmAudioWorkletProcessor(audioParams) {
4747
// then perform the wasm audio worklet call,
4848
// and finally marshal audio output data back.
4949

50-
let numInputs = inputList.length,
51-
numOutputs = outputList.length,
52-
numParams = 0, i, j, k, dataPtr,
53-
bytesPerChannel = this.samplesPerChannel * 4,
54-
stackMemoryNeeded = (numInputs + numOutputs) * {{{ C_STRUCTS.AudioSampleFrame.__size__ }}},
55-
oldStackPtr = stackSave(),
56-
inputsPtr, outputsPtr, outputDataPtr, paramsPtr,
57-
didProduceAudio, paramArray;
50+
var numInputs = inputList.length;
51+
var numOutputs = outputList.length;
52+
53+
var entry; // reused list entry or index
54+
var subentry; // reused channel or other array in each list entry or index
5855

5956
// Calculate how much stack space is needed.
60-
for (i of inputList) stackMemoryNeeded += i.length * bytesPerChannel;
61-
for (i of outputList) stackMemoryNeeded += i.length * bytesPerChannel;
62-
for (i in parameters) stackMemoryNeeded += parameters[i].byteLength + {{{ C_STRUCTS.AudioParamFrame.__size__ }}}, ++numParams;
57+
var bytesPerChannel = this.samplesPerChannel * {{{ getNativeTypeSize('float') }}};
58+
var stackMemoryNeeded = (numInputs + numOutputs) * {{{ C_STRUCTS.AudioSampleFrame.__size__ }}};
59+
var numParams = 0;
60+
for (entry of inputList) stackMemoryNeeded += entry.length * bytesPerChannel;
61+
for (entry of outputList) stackMemoryNeeded += entry.length * bytesPerChannel;
62+
for (entry in parameters) {
63+
stackMemoryNeeded += parameters[entry].byteLength + {{{ C_STRUCTS.AudioParamFrame.__size__ }}};
64+
++numParams;
65+
}
6366

6467
// Allocate the necessary stack space.
65-
inputsPtr = stackAlloc(stackMemoryNeeded);
66-
67-
// Copy input audio descriptor structs and data to Wasm
68-
k = inputsPtr;
69-
dataPtr = inputsPtr + numInputs * {{{ C_STRUCTS.AudioSampleFrame.__size__ }}};
70-
for (i of inputList) {
68+
var oldStackPtr = stackSave();
69+
var inputsPtr = stackAlloc(stackMemoryNeeded);
70+
71+
// Copy input audio descriptor structs and data to Wasm ('structPtr' is
72+
// reused as the working start to each struct record, 'dataPtr' start of
73+
// the data section, usually after all structs).
74+
var structPtr = inputsPtr;
75+
var dataPtr = inputsPtr + numInputs * {{{ C_STRUCTS.AudioSampleFrame.__size__ }}};
76+
for (entry of inputList) {
7177
// Write the AudioSampleFrame struct instance
72-
{{{ makeSetValue('k', C_STRUCTS.AudioSampleFrame.numberOfChannels, 'i.length', 'u32') }}};
73-
{{{ makeSetValue('k', C_STRUCTS.AudioSampleFrame.samplesPerChannel, 'this.samplesPerChannel', 'u32') }}};
74-
{{{ makeSetValue('k', C_STRUCTS.AudioSampleFrame.data, 'dataPtr', '*') }}};
75-
k += {{{ C_STRUCTS.AudioSampleFrame.__size__ }}};
78+
{{{ makeSetValue('structPtr', C_STRUCTS.AudioSampleFrame.numberOfChannels, 'entry.length', 'u32') }}};
79+
{{{ makeSetValue('structPtr', C_STRUCTS.AudioSampleFrame.samplesPerChannel, 'this.samplesPerChannel', 'u32') }}};
80+
{{{ makeSetValue('structPtr', C_STRUCTS.AudioSampleFrame.data, 'dataPtr', '*') }}};
81+
structPtr += {{{ C_STRUCTS.AudioSampleFrame.__size__ }}};
7682
// Marshal the input audio sample data for each audio channel of this input
77-
for (j of i) {
78-
HEAPF32.set(j, {{{ getHeapOffset('dataPtr', 'float') }}});
83+
for (subentry of entry) {
84+
HEAPF32.set(subentry, {{{ getHeapOffset('dataPtr', 'float') }}});
7985
dataPtr += bytesPerChannel;
8086
}
8187
}
8288

8389
// Copy output audio descriptor structs to Wasm
84-
outputsPtr = dataPtr;
85-
k = outputsPtr;
86-
outputDataPtr = (dataPtr += numOutputs * {{{ C_STRUCTS.AudioSampleFrame.__size__ }}});
87-
for (i of outputList) {
90+
var outputsPtr = dataPtr;
91+
structPtr = outputsPtr;
92+
var outputDataPtr = (dataPtr += numOutputs * {{{ C_STRUCTS.AudioSampleFrame.__size__ }}});
93+
for (entry of outputList) {
8894
// Write the AudioSampleFrame struct instance
89-
{{{ makeSetValue('k', C_STRUCTS.AudioSampleFrame.numberOfChannels, 'i.length', 'u32') }}};
90-
{{{ makeSetValue('k', C_STRUCTS.AudioSampleFrame.samplesPerChannel, 'this.samplesPerChannel', 'u32') }}};
91-
{{{ makeSetValue('k', C_STRUCTS.AudioSampleFrame.data, 'dataPtr', '*') }}};
92-
k += {{{ C_STRUCTS.AudioSampleFrame.__size__ }}};
95+
{{{ makeSetValue('structPtr', C_STRUCTS.AudioSampleFrame.numberOfChannels, 'entry.length', 'u32') }}};
96+
{{{ makeSetValue('structPtr', C_STRUCTS.AudioSampleFrame.samplesPerChannel, 'this.samplesPerChannel', 'u32') }}};
97+
{{{ makeSetValue('structPtr', C_STRUCTS.AudioSampleFrame.data, 'dataPtr', '*') }}};
98+
structPtr += {{{ C_STRUCTS.AudioSampleFrame.__size__ }}};
9399
// Reserve space for the output data
94-
dataPtr += bytesPerChannel * i.length;
100+
dataPtr += bytesPerChannel * entry.length;
95101
}
96102

97103
// Copy parameters descriptor structs and data to Wasm
98-
paramsPtr = dataPtr;
99-
k = paramsPtr;
104+
var paramsPtr = dataPtr;
105+
structPtr = paramsPtr;
100106
dataPtr += numParams * {{{ C_STRUCTS.AudioParamFrame.__size__ }}};
101-
102-
for (i = 0; paramArray = parameters[i++];) {
107+
for (entry = 0; subentry = parameters[entry++];) {
103108
// Write the AudioParamFrame struct instance
104-
{{{ makeSetValue('k', C_STRUCTS.AudioParamFrame.length, 'paramArray.length', 'u32') }}};
105-
{{{ makeSetValue('k', C_STRUCTS.AudioParamFrame.data, 'dataPtr', '*') }}};
106-
k += {{{ C_STRUCTS.AudioParamFrame.__size__ }}};
109+
{{{ makeSetValue('structPtr', C_STRUCTS.AudioParamFrame.length, 'subentry.length', 'u32') }}};
110+
{{{ makeSetValue('structPtr', C_STRUCTS.AudioParamFrame.data, 'dataPtr', '*') }}};
111+
structPtr += {{{ C_STRUCTS.AudioParamFrame.__size__ }}};
107112
// Marshal the audio parameters array
108-
HEAPF32.set(paramArray, {{{ getHeapOffset('dataPtr', 'float') }}});
109-
dataPtr += paramArray.length * {{{ getNativeTypeSize('float') }}};
113+
HEAPF32.set(subentry, {{{ getHeapOffset('dataPtr', 'float') }}});
114+
dataPtr += subentry.length * {{{ getNativeTypeSize('float') }}};
110115
}
111116

112117
// Call out to Wasm callback to perform audio processing
113-
if (didProduceAudio = this.callback(numInputs, inputsPtr, numOutputs, outputsPtr, numParams, paramsPtr, this.userData)) {
118+
var didProduceAudio = this.callback(numInputs, inputsPtr, numOutputs, outputsPtr, numParams, paramsPtr, this.userData);
119+
if (didProduceAudio) {
114120
// Read back the produced audio data to all outputs and their channels.
115121
// (A garbage-free function TypedArray.copy(dstTypedArray, dstOffset,
116122
// srcTypedArray, srcOffset, count) would sure be handy.. but web does
117123
// not have one, so manually copy all bytes in)
118124
outputDataPtr = {{{ getHeapOffset('outputDataPtr', 'float') }}};
119-
for (i of outputList) {
120-
for (j of i) {
121-
for (k = 0; k < this.samplesPerChannel; ++k) {
122-
j[k] = HEAPF32[outputDataPtr++];
125+
for (entry of outputList) {
126+
for (subentry of entry) {
127+
// repurposing structPtr for now
128+
for (structPtr = 0; structPtr < this.samplesPerChannel; ++structPtr) {
129+
subentry[structPtr] = HEAPF32[outputDataPtr++];
123130
}
124131
}
125132
}

0 commit comments

Comments
 (0)