Skip to content

Commit ccdb089

Browse files
committed
Initial work to playback audio
1 parent 0eb80c5 commit ccdb089

File tree

2 files changed

+29
-22
lines changed

2 files changed

+29
-22
lines changed

src/audio_worklet.js

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@ function createWasmAudioWorkletProcessor(audioParams) {
2525
assert(opts.callback)
2626
assert(opts.samplesPerChannel)
2727
#endif
28-
this.callback = getWasmTableEntry(opts.callback);
29-
this.userData = opts.userData;
28+
this.callback = getWasmTableEntry({{{ toIndexType("opts.callback") }}});
29+
this.userData = {{{ toIndexType("opts.userData") }}};
3030
// Then the samples per channel to process, fixed for the lifetime of the
3131
// context that created this processor. Note for when moving to Web Audio
3232
// 1.1: the typed array passed to process() should be the same size as this
@@ -82,13 +82,16 @@ function createWasmAudioWorkletProcessor(audioParams) {
8282

8383
// Copy output audio descriptor structs to Wasm
8484
outputsPtr = dataPtr;
85-
k = outputsPtr >> 2;
86-
outputDataPtr = (dataPtr += numOutputs * {{{ C_STRUCTS.AudioSampleFrame.__size__ }}}) >> 2;
85+
k = {{{ getHeapOffset('outputsPtr', 'u32') }}};
86+
outputDataPtr = (dataPtr += numOutputs * {{{ C_STRUCTS.AudioSampleFrame.__size__ }}});
8787
for (i of outputList) {
8888
// Write the AudioSampleFrame struct instance
8989
HEAPU32[k + {{{ C_STRUCTS.AudioSampleFrame.numberOfChannels / 4 }}}] = i.length;
9090
HEAPU32[k + {{{ C_STRUCTS.AudioSampleFrame.samplesPerChannel / 4 }}}] = this.samplesPerChannel;
9191
HEAPU32[k + {{{ C_STRUCTS.AudioSampleFrame.data / 4 }}}] = dataPtr;
92+
#if MEMORY64
93+
HEAPU32[k + {{{ C_STRUCTS.AudioSampleFrame.data / 4 + 1 }}}] = dataPtr / 0x100000000;
94+
#endif
9295
k += {{{ C_STRUCTS.AudioSampleFrame.__size__ / 4 }}};
9396
// Reserve space for the output data
9497
dataPtr += bytesPerChannel * i.length;
@@ -110,11 +113,12 @@ function createWasmAudioWorkletProcessor(audioParams) {
110113
}
111114

112115
// Call out to Wasm callback to perform audio processing
113-
if (didProduceAudio = this.callback(numInputs, inputsPtr, numOutputs, outputsPtr, numParams, paramsPtr, this.userData)) {
116+
if (didProduceAudio = this.callback(numInputs, {{{ toIndexType('inputsPtr') }}}, numOutputs, {{{ toIndexType('outputsPtr') }}}, numParams, {{{ toIndexType('paramsPtr') }}}, this.userData)) {
114117
// Read back the produced audio data to all outputs and their channels.
115118
// (A garbage-free function TypedArray.copy(dstTypedArray, dstOffset,
116119
// srcTypedArray, srcOffset, count) would sure be handy.. but web does
117120
// not have one, so manually copy all bytes in)
121+
outputDataPtr = {{{ getHeapOffset('outputDataPtr', 'float') }}};
118122
for (i of outputList) {
119123
for (j of i) {
120124
for (k = 0; k < this.samplesPerChannel; ++k) {
@@ -168,9 +172,9 @@ class BootstrapMessages extends AudioWorkletProcessor {
168172
//
169173
// '_wsc' is short for 'wasm call', using an identifier that will never
170174
// conflict with user messages
171-
messagePort.postMessage({'_wsc': d.callback, args: [d.contextHandle, 1/*EM_TRUE*/, d.userData] });
175+
messagePort.postMessage({'_wsc': {{{ toIndexType("d.callback") }}}, args: [d.contextHandle, 1/*EM_TRUE*/, {{{ toIndexType("d.userData") }}}] });
172176
} else if (d['_wsc']) {
173-
getWasmTableEntry(d['_wsc'])(...d.args);
177+
getWasmTableEntry({{{ toIndexType("d['_wsc']") }}})(...d.args);
174178
};
175179
}
176180
}

src/lib/libwebaudio.js

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ let LibraryWebAudio = {
7878
#if WEBAUDIO_DEBUG
7979
console.log(`emscripten_resume_audio_context_async() callback: New audio state="${EmAudio[contextHandle].state}", ID=${state}`);
8080
#endif
81-
{{{ makeDynCall('viii', 'callback') }}}(contextHandle, state, userData);
81+
{{{ makeDynCall('viip', 'callback') }}}(contextHandle, state, userData);
8282
}
8383
#if WEBAUDIO_DEBUG
8484
console.log(`emscripten_resume_audio_context_async() resuming...`);
@@ -202,7 +202,7 @@ let LibraryWebAudio = {
202202
}
203203
});
204204
audioWorklet.bootstrapMessage.port.onmessage = _EmAudioDispatchProcessorCallback;
205-
{{{ makeDynCall('viii', 'callback') }}}(contextHandle, 1/*EM_TRUE*/, userData);
205+
{{{ makeDynCall('viip', 'callback') }}}(contextHandle, 1/*EM_TRUE*/, userData);
206206
}).catch(audioWorkletCreationFailed);
207207
},
208208

@@ -222,32 +222,33 @@ let LibraryWebAudio = {
222222
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]}`);
223223
#endif
224224

225-
options >>= 2;
226225
let audioParams = [],
227-
numAudioParams = HEAPU32[options+1],
228-
audioParamDescriptors = HEAPU32[options+2] >> 2,
226+
processorName = UTF8ToString({{{ makeGetValue('options', C_STRUCTS.WebAudioWorkletProcessorCreateOptions.name, '*') }}}),
227+
numAudioParams = {{{ makeGetValue('options', C_STRUCTS.WebAudioWorkletProcessorCreateOptions.numAudioParams, 'i32') }}},
228+
audioParamDescriptors = {{{ makeGetValue('options', C_STRUCTS.WebAudioWorkletProcessorCreateOptions.audioParamDescriptors, '*') }}},
229229
i = 0;
230230

231231
while (numAudioParams--) {
232232
audioParams.push({
233233
name: i++,
234-
defaultValue: HEAPF32[audioParamDescriptors++],
235-
minValue: HEAPF32[audioParamDescriptors++],
236-
maxValue: HEAPF32[audioParamDescriptors++],
237-
automationRate: ['a','k'][HEAPU32[audioParamDescriptors++]] + '-rate',
234+
defaultValue: {{{ makeGetValue('audioParamDescriptors', C_STRUCTS.WebAudioParamDescriptor.defaultValue, 'float') }}},
235+
minValue: {{{ makeGetValue('audioParamDescriptors', C_STRUCTS.WebAudioParamDescriptor.minValue, 'float') }}},
236+
maxValue: {{{ makeGetValue('audioParamDescriptors', C_STRUCTS.WebAudioParamDescriptor.maxValue, 'float') }}},
237+
automationRate: ({{{ makeGetValue('audioParamDescriptors', C_STRUCTS.WebAudioParamDescriptor.automationRate, 'i32') }}} ? 'k' : 'a') + '-rate'
238238
});
239+
audioParamDescriptors += {{{ C_STRUCTS.WebAudioParamDescriptor.__size__ }}};
239240
}
240241

241242
#if WEBAUDIO_DEBUG
242-
console.log(`emscripten_create_wasm_audio_worklet_processor_async() creating a new AudioWorklet processor with name ${UTF8ToString(HEAPU32[options])}`);
243+
console.log(`emscripten_create_wasm_audio_worklet_processor_async() creating a new AudioWorklet processor with name ${processorName}`);
243244
#endif
244245

245246
EmAudio[contextHandle].audioWorklet.bootstrapMessage.port.postMessage({
246247
// Deliberately mangled and short names used here ('_wpn', the 'Worklet
247248
// Processor Name' used as a 'key' to verify the message type so as to
248249
// not get accidentally mixed with user submitted messages, the remainder
249250
// for space saving reasons, abbreviated from their variable names).
250-
'_wpn': UTF8ToString(HEAPU32[options]),
251+
'_wpn': processorName,
251252
audioParams,
252253
contextHandle,
253254
callback,
@@ -262,18 +263,20 @@ let LibraryWebAudio = {
262263
assert(EmAudio[contextHandle], `Called emscripten_create_wasm_audio_worklet_node() with a nonexisting/already freed Web Audio Context handle ${contextHandle}!`);
263264
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]}`);
264265
#endif
265-
options >>= 2;
266266

267267
function readChannelCountArray(heapIndex, numOutputs) {
268+
if (!heapIndex) return void 0;
269+
heapIndex = {{{ getHeapOffset('heapIndex', 'i32') }}};
268270
let channelCounts = [];
269271
while (numOutputs--) channelCounts.push(HEAPU32[heapIndex++]);
270272
return channelCounts;
271273
}
272274

275+
let optionsOutputs = options ? {{{ makeGetValue('options', C_STRUCTS.EmscriptenAudioWorkletNodeCreateOptions.numberOfOutputs, 'i32') }}} : 0;
273276
let opts = options ? {
274-
numberOfInputs: HEAP32[options],
275-
numberOfOutputs: HEAP32[options+1],
276-
outputChannelCount: HEAPU32[options+2] ? readChannelCountArray(HEAPU32[options+2]>>2, HEAP32[options+1]) : void 0,
277+
numberOfInputs: {{{ makeGetValue('options', C_STRUCTS.EmscriptenAudioWorkletNodeCreateOptions.numberOfInputs, 'i32') }}},
278+
numberOfOutputs: optionsOutputs,
279+
outputChannelCount: readChannelCountArray({{{ makeGetValue('options', C_STRUCTS.EmscriptenAudioWorkletNodeCreateOptions.outputChannelCounts, 'i32*') }}}, optionsOutputs),
277280
processorOptions: {
278281
callback,
279282
userData,

0 commit comments

Comments
 (0)