Skip to content

Commit f78eb81

Browse files
committed
Work-in-progress: using a single stack allocation
The code has also been brought back closer to the original for comparison.
1 parent df48b6e commit f78eb81

File tree

1 file changed

+35
-39
lines changed

1 file changed

+35
-39
lines changed

src/audio_worklet.js

Lines changed: 35 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -73,42 +73,28 @@ function createWasmAudioWorkletProcessor(audioParams) {
7373
numOutputs = outputList.length,
7474
numParams = 0, i, j, k, dataPtr,
7575
bytesPerChannel = this.samplesPerChannel * 4,
76-
outputStackNeeded = 0, outputViewsNeeded = 0,
76+
outputViewsNeeded = 0,
7777
stackMemoryNeeded = (numInputs + numOutputs) * {{{ C_STRUCTS.AudioSampleFrame.__size__ }}},
7878
oldStackPtr = stackSave(),
79-
inputsPtr, outputsPtr, outputDataPtr, paramsPtr,
79+
inputsPtr, outputsPtr, paramsPtr,
80+
outputDataPtr,
8081
didProduceAudio, paramArray;
8182

82-
// Calculate how much stack space is needed, first for the outputs
83-
// pre-allocated in the constructor from the stack top.
84-
for (i of outputList) {
85-
outputStackNeeded += i.length * bytesPerChannel;
86-
outputViewsNeeded += i.length;
87-
#if ASSERTIONS
88-
for (/*which channel*/ j of i) {
89-
console.assert(j.byteLength === bytesPerChannel, `Unexpected AudioWorklet output buffer size (expected ${bytesPerChannel} got ${j.byteLength})`);
90-
}
91-
#endif
92-
}
93-
// Then the remaining space all together
83+
// Calculate how much stack space is needed
9484
for (i of inputList) stackMemoryNeeded += i.length * bytesPerChannel;
85+
for (i of outputList) outputViewsNeeded += i.length;
86+
stackMemoryNeeded += outputViewsNeeded * bytesPerChannel;
9587
for (i in parameters) stackMemoryNeeded += parameters[i].byteLength + {{{ C_STRUCTS.AudioParamFrame.__size__ }}}, ++numParams;
9688

97-
outputDataPtr = stackAlloc(outputStackNeeded);
98-
//#if ASSERTIONS
89+
#if ASSERTIONS
9990
console.assert(outputViewsNeeded <= this.outputViews.length, `Too many AudioWorklet outputs (need ${outputViewsNeeded} but have stack space for ${this.outputViews.length})`);
100-
k = outputDataPtr;
101-
for (i = outputViewsNeeded - 1; i >= 0; i--) {
102-
console.assert(this.outputViews[i].byteOffset == k, 'Internal error in addresses of the output array views');
103-
k += bytesPerChannel;
104-
}
105-
//#endif
91+
#endif
10692

10793
// Allocate the necessary stack space (dataPtr is always in bytes, and
10894
// advances as space for structs as data is taken, but note the switching
109-
// between bytes and indices into the various heaps).
110-
95+
// between bytes and indices into the various heaps, usually in 'k').
11196
dataPtr = stackAlloc(stackMemoryNeeded);
97+
11298
// Copy input audio descriptor structs and data to Wasm
11399
inputsPtr = dataPtr;
114100
k = inputsPtr >> 2;
@@ -126,21 +112,6 @@ function createWasmAudioWorkletProcessor(audioParams) {
126112
}
127113
}
128114

129-
// Copy output audio descriptor structs to Wasm
130-
// TODO: now dataPtr tracks the next address, move this above
131-
outputsPtr = dataPtr;
132-
k = outputsPtr >> 2;
133-
dataPtr += numOutputs * {{{ C_STRUCTS.AudioSampleFrame.__size__ }}};
134-
for (i of outputList) {
135-
// Write the AudioSampleFrame struct instance
136-
HEAPU32[k + {{{ C_STRUCTS.AudioSampleFrame.numberOfChannels / 4 }}}] = i.length;
137-
HEAPU32[k + {{{ C_STRUCTS.AudioSampleFrame.samplesPerChannel / 4 }}}] = this.samplesPerChannel;
138-
HEAPU32[k + {{{ C_STRUCTS.AudioSampleFrame.data / 4 }}}] = outputDataPtr;
139-
k += {{{ C_STRUCTS.AudioSampleFrame.__size__ / 4 }}};
140-
// Advance the output pointer to the next output
141-
outputDataPtr += bytesPerChannel * i.length;
142-
}
143-
144115
// Copy parameters descriptor structs and data to Wasm
145116
paramsPtr = dataPtr;
146117
k = paramsPtr >> 2;
@@ -155,6 +126,31 @@ function createWasmAudioWorkletProcessor(audioParams) {
155126
dataPtr += paramArray.length*4;
156127
}
157128

129+
// Copy output audio descriptor structs to Wasm
130+
outputsPtr = dataPtr;
131+
k = outputsPtr >> 2;
132+
dataPtr += numOutputs * {{{ C_STRUCTS.AudioSampleFrame.__size__ }}};
133+
#if ASSERTIONS
134+
outputDataPtr = dataPtr;
135+
#endif
136+
for (i of outputList) {
137+
// Write the AudioSampleFrame struct instance
138+
HEAPU32[k + {{{ C_STRUCTS.AudioSampleFrame.numberOfChannels / 4 }}}] = i.length;
139+
HEAPU32[k + {{{ C_STRUCTS.AudioSampleFrame.samplesPerChannel / 4 }}}] = this.samplesPerChannel;
140+
HEAPU32[k + {{{ C_STRUCTS.AudioSampleFrame.data / 4 }}}] = dataPtr;
141+
k += {{{ C_STRUCTS.AudioSampleFrame.__size__ / 4 }}};
142+
// Advance the output pointer to the next output (matching the pre-allocated views)
143+
dataPtr += bytesPerChannel * i.length;
144+
}
145+
146+
#if ASSERTIONS
147+
k = outputDataPtr;
148+
for (i = outputViewsNeeded - 1; i >= 0; i--) {
149+
console.assert(this.outputViews[i].byteOffset == k, 'Internal error in addresses of the output array views');
150+
k += bytesPerChannel;
151+
}
152+
#endif
153+
158154
// Call out to Wasm callback to perform audio processing
159155
if (didProduceAudio = this.callbackFunction(numInputs, inputsPtr, numOutputs, outputsPtr, numParams, paramsPtr, this.userData)) {
160156
// Read back the produced audio data to all outputs and their channels.

0 commit comments

Comments
 (0)