Skip to content

Commit b9a7742

Browse files
committed
Tidy, bullet-proof and document
1 parent 37db147 commit b9a7742

6 files changed

+80
-39
lines changed

test/webaudio/audioworklet_2x_in_hard_pan.c

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,29 @@
1818
bool process(int numInputs, const AudioSampleFrame* inputs, int numOutputs, AudioSampleFrame* outputs, int __unused numParams, const AudioParamFrame* __unused params, void* __unused data) {
1919
audioProcessedCount++;
2020

21-
// Twin mono in, single stereo out
21+
// Twin mono in (or disabled), single stereo out
2222
assert(numInputs == 2 && numOutputs == 1);
23-
assert(inputs[0].numberOfChannels == 1 && inputs[1].numberOfChannels == 1);
23+
assert(inputs[0].numberOfChannels == 0 || inputs[0].numberOfChannels == 1);
24+
assert(inputs[1].numberOfChannels == 0 || inputs[1].numberOfChannels == 1);
2425
assert(outputs[0].numberOfChannels == 2);
2526
// All with the same number of samples
2627
assert(inputs[0].samplesPerChannel == inputs[1].samplesPerChannel);
2728
assert(inputs[0].samplesPerChannel == outputs[0].samplesPerChannel);
28-
// Now with all known quantities we can memcpy the data
29-
int samplesPerChannel = inputs[0].samplesPerChannel;
30-
memcpy(outputs[0].data, inputs[0].data, samplesPerChannel * sizeof(float));
31-
memcpy(outputs[0].data + samplesPerChannel, inputs[1].data, samplesPerChannel * sizeof(float));
29+
// Now with all known quantities we can memcpy the L&R data (or zero it if the
30+
// channels are disabled)
31+
int bytesPerChannel = outputs[0].samplesPerChannel * sizeof(float);
32+
float* outputData = outputs[0].data;
33+
if (inputs[0].numberOfChannels > 0) {
34+
memcpy(outputData, inputs[0].data, bytesPerChannel);
35+
} else {
36+
memset(outputData, 0, bytesPerChannel);
37+
}
38+
outputData += outputs[0].samplesPerChannel;
39+
if (inputs[1].numberOfChannels > 0) {
40+
memcpy(outputData, inputs[1].data, bytesPerChannel);
41+
} else {
42+
memset(outputData, 0, bytesPerChannel);
43+
}
3244
return true;
3345
}
3446

@@ -70,6 +82,6 @@ void processorCreated(EMSCRIPTEN_WEBAUDIO_T context, bool success, void* __unuse
7082
}
7183

7284
// This implementation has no custom start-up requirements
73-
EmscriptenStartWebAudioWorkletCallback getStartCallback() {
85+
EmscriptenStartWebAudioWorkletCallback getStartCallback(void) {
7486
return &initialised;
7587
}

test/webaudio/audioworklet_2x_in_out_stereo.c

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,16 +19,27 @@ bool process(int numInputs, const AudioSampleFrame* inputs, int numOutputs, Audi
1919

2020
// Twin stereo in and out
2121
assert(numInputs == 2 && numOutputs == 2);
22-
assert(inputs[0].numberOfChannels == 2 && inputs[1].numberOfChannels == 2);
23-
assert(outputs[0].numberOfChannels == 2 && outputs[1].numberOfChannels == 2);
22+
assert(inputs[0].numberOfChannels == 0 || inputs[0].numberOfChannels == 2);
23+
assert(inputs[1].numberOfChannels == 0 || inputs[1].numberOfChannels == 2);
24+
assert(outputs[0].numberOfChannels == 2);
25+
assert(outputs[1].numberOfChannels == 2);
2426
// All with the same number of samples
2527
assert(inputs[0].samplesPerChannel == inputs[1].samplesPerChannel);
2628
assert(inputs[0].samplesPerChannel == outputs[0].samplesPerChannel);
2729
assert(outputs[0].samplesPerChannel == outputs[1].samplesPerChannel);
28-
// Now with all known quantities we can memcpy the data
29-
int totalSamples = outputs[0].samplesPerChannel * outputs[0].numberOfChannels;
30-
memcpy(outputs[0].data, inputs[0].data, totalSamples * sizeof(float));
31-
memcpy(outputs[1].data, inputs[1].data, totalSamples * sizeof(float));
30+
// Now with all known quantities we can memcpy all the data (or zero it if the
31+
// channels are disabled)
32+
int totalBytes = outputs[0].samplesPerChannel * outputs[0].numberOfChannels * sizeof(float);
33+
if (inputs[0].numberOfChannels > 0) {
34+
memcpy(outputs[0].data, inputs[0].data, totalBytes);
35+
} else {
36+
memset(outputs[0].data, 0, totalBytes);
37+
}
38+
if (inputs[1].numberOfChannels > 0) {
39+
memcpy(outputs[1].data, inputs[1].data, totalBytes);
40+
} else {
41+
memset(outputs[1].data, 0, totalBytes);
42+
}
3243
return true;
3344
}
3445

@@ -72,6 +83,6 @@ void processorCreated(EMSCRIPTEN_WEBAUDIO_T context, bool success, void* __unuse
7283
}
7384

7485
// This implementation has no custom start-up requirements
75-
EmscriptenStartWebAudioWorkletCallback getStartCallback() {
86+
EmscriptenStartWebAudioWorkletCallback getStartCallback(void) {
7687
return &initialised;
7788
}

test/webaudio/audioworklet_in_out_mono.c

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,18 @@ bool process(int numInputs, const AudioSampleFrame* inputs, int numOutputs, Audi
2929
// We can now do a quick mix since we know the layouts
3030
if (numInputs > 0) {
3131
int totalSamples = outputs[0].samplesPerChannel * outputs[0].numberOfChannels;
32+
// Simple copy of single input's audio data, checking that we have channels
33+
// (since a muted input has zero channels)
3234
float* outputData = outputs[0].data;
33-
memcpy(outputData, inputs[0].data, totalSamples * sizeof(float));
35+
if (inputs[0].numberOfChannels > 0) {
36+
memcpy(outputData, inputs[0].data, totalSamples * sizeof(float));
37+
} else {
38+
// And for muted we need to fill the buffer with zeroes otherwise it repeats the last frame
39+
memset(outputData, 0, totalSamples * sizeof(float));
40+
}
41+
// Now add another inputs
3442
for (int n = 1; n < numInputs; n++) {
35-
// It's possible to have an input with no channels
36-
if (inputs[n].numberOfChannels == 1) {
43+
if (inputs[n].numberOfChannels > 0) {
3744
float* inputData = inputs[n].data;
3845
for (int i = totalSamples - 1; i >= 0; i--) {
3946
outputData[i] += inputData[i];
@@ -82,7 +89,7 @@ void processorCreated(EMSCRIPTEN_WEBAUDIO_T context, bool success, void* __unuse
8289
}
8390

8491
// This implementation has no custom start-up requirements
85-
EmscriptenStartWebAudioWorkletCallback getStartCallback() {
92+
EmscriptenStartWebAudioWorkletCallback getStartCallback(void) {
8693
return &initialised;
8794
}
8895

test/webaudio/audioworklet_in_out_stereo.c

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,18 @@ bool process(int numInputs, const AudioSampleFrame* inputs, int numOutputs, Audi
2929
// We can now do a quick mix since we know the layouts
3030
if (numInputs > 0) {
3131
int totalSamples = outputs[0].samplesPerChannel * outputs[0].numberOfChannels;
32+
// Simple copy of single input's audio data, checking that we have channels
33+
// (since a muted input has zero channels)
3234
float* outputData = outputs[0].data;
33-
memcpy(outputData, inputs[0].data, totalSamples * sizeof(float));
35+
if (inputs[0].numberOfChannels > 0) {
36+
memcpy(outputData, inputs[0].data, totalSamples * sizeof(float));
37+
} else {
38+
// And for muted we need to fill the buffer with zeroes otherwise it repeats the last frame
39+
memset(outputData, 0, totalSamples * sizeof(float));
40+
}
41+
// Now add another inputs
3442
for (int n = 1; n < numInputs; n++) {
35-
// It's possible to have an input with no channels
36-
if (inputs[n].numberOfChannels == 2) {
43+
if (inputs[n].numberOfChannels > 0) {
3744
float* inputData = inputs[n].data;
3845
for (int i = totalSamples - 1; i >= 0; i--) {
3946
outputData[i] += inputData[i];
@@ -82,6 +89,6 @@ void processorCreated(EMSCRIPTEN_WEBAUDIO_T context, bool success, void* __unuse
8289
}
8390

8491
// This implementation has no custom start-up requirements
85-
EmscriptenStartWebAudioWorkletCallback getStartCallback() {
92+
EmscriptenStartWebAudioWorkletCallback getStartCallback(void) {
8693
return &initialised;
8794
}

test/webaudio/audioworklet_params_mixing.c

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,30 +6,32 @@
66
#include <emscripten/webaudio.h>
77

88
// Tests processing two stereo audio inputs being mixed to a single stereo audio
9-
// output in process() (by adding the inputs together).
9+
// output in process(), then applying a fade from the parameters.
1010

11-
// This needs to be big enough for the stereo output, 2x inputs, 2x params and the worker stack
11+
// This needs to be big enough for the stereo output, 2x inputs, 2x params and
12+
// the worker stack. To note that different browsers have different stack size
13+
// requirement (see notes in process()).
1214
#define AUDIO_STACK_SIZE 5120
1315

1416
// Shared file playback and bootstrap
1517
#include "audioworklet_test_shared.inc"
1618

1719
// Callback to process and mix the audio tracks
18-
bool process(int numInputs, const AudioSampleFrame* inputs, int numOutputs, AudioSampleFrame* outputs, int numParams, const AudioParamFrame* __unused params, void* __unused data) {
20+
bool process(int numInputs, const AudioSampleFrame* inputs, int numOutputs, AudioSampleFrame* outputs, int numParams, const AudioParamFrame* params, void* __unused data) {
1921
audioProcessedCount++;
2022

2123
// Single stereo output
2224
assert(numOutputs == 1 && outputs[0].numberOfChannels == 2);
2325
int outSamplesPerChannel = outputs[0].samplesPerChannel;
2426
for (int n = 0; n < numInputs; n++) {
25-
// And all inputs are also stereo
27+
// And all inputs are also stereo (or disabled)
2628
assert(inputs[n].numberOfChannels == 2 || inputs[n].numberOfChannels == 0);
2729
// This should always be the case
2830
assert(inputs[n].samplesPerChannel == outSamplesPerChannel);
2931
}
3032
// Interestingly, params varies per browser. Chrome won't have a length > 1
31-
// unless the value changes, and FF has all the samples even for a k-rate
32-
// parameter. The only given is that two params are incoming.
33+
// unless the value changes, and FF has all 128 entries even for a k-rate
34+
// parameter. The only given is that two params are incoming:
3335
assert(numParams = 2);
3436
assert(params[0].length == 1 || params[0].length == outSamplesPerChannel);
3537
assert(params[1].length == 1 || params[1].length == outSamplesPerChannel);
@@ -39,16 +41,17 @@ bool process(int numInputs, const AudioSampleFrame* inputs, int numOutputs, Audi
3941
// Simple copy of single input's audio data, checking that we have channels
4042
// (since a muted input has zero channels)
4143
float* outputData = outputs[0].data;
42-
if (inputs[0].numberOfChannels != 0) {
44+
if (inputs[0].numberOfChannels > 0) {
4345
memcpy(outputData, inputs[0].data, totalSamples * sizeof(float));
4446
} else {
45-
// And for muted we need to full the buffer with zeroes otherwise it play the previous frame
47+
// And for muted we need to fill the buffer with zeroes otherwise it repeats the last frame
4648
memset(outputData, 0, totalSamples * sizeof(float));
4749
}
48-
// Grab the mix level parameter (with either a length of 1 or the samples per channel)
50+
// Grab the mix level parameter (with either a length of 1 or the samples
51+
// per channel) and add any other inputs
4952
const AudioParamFrame* mixLevel = &params[0];
5053
for (int n = 1; n < numInputs; n++) {
51-
if (inputs[n].numberOfChannels != 0) {
54+
if (inputs[n].numberOfChannels > 0) {
5255
float* inputData = inputs[n].data;
5356
for (int i = totalSamples - 1; i >= 0; i--) {
5457
// Output and input buffers are stereo planar in this example so we
@@ -76,7 +79,7 @@ EM_JS(void, doFade, (EMSCRIPTEN_AUDIO_WORKLET_NODE_T workletID), {
7679
param.setTargetAtTime((param.value > 0.5) ? 0 : 1, 0 /* same as context.currentTime */, 0.5);
7780
}
7881
}
79-
});
82+
})
8083

8184
// Registered keypress event to call the JS doFade()
8285
bool onPress(int __unused type, const EmscriptenKeyboardEvent* e, void* data) {
@@ -160,6 +163,6 @@ void initialisedWithParams(EMSCRIPTEN_WEBAUDIO_T context, bool success, void* __
160163
}
161164

162165
// This implementation has no custom start-up requirements
163-
EmscriptenStartWebAudioWorkletCallback getStartCallback() {
166+
EmscriptenStartWebAudioWorkletCallback getStartCallback(void) {
164167
return &initialisedWithParams;
165168
}

test/webaudio/audioworklet_test_shared.inc

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@ EM_JS(EMSCRIPTEN_WEBAUDIO_T, createTrack, (EMSCRIPTEN_WEBAUDIO_T ctxID, const ch
3535
if (context) {
3636
var audio = document.createElement('audio');
3737
#if __wasm64__
38-
// Workaround for UTF8ToString() needing a JS number and from64() not working in EM_JS
38+
// Number() wrapper is a workaround for UTF8ToString() needing a JS number
39+
// and from64() not being available in EM_JS macros. Fix in UTF8ToString?
3940
url = Number(url);
4041
#endif
4142
audio.src = UTF8ToString(url);
@@ -44,7 +45,7 @@ EM_JS(EMSCRIPTEN_WEBAUDIO_T, createTrack, (EMSCRIPTEN_WEBAUDIO_T ctxID, const ch
4445
return emscriptenRegisterAudioObject(track);
4546
}
4647
return 0;
47-
});
48+
})
4849

4950
// Toggles the play/pause of a MediaElementAudioSourceNode given its ID
5051
EM_JS(void, toggleTrack, (EMSCRIPTEN_WEBAUDIO_T srcID), {
@@ -60,7 +61,7 @@ EM_JS(void, toggleTrack, (EMSCRIPTEN_WEBAUDIO_T srcID), {
6061
}
6162
}
6263
}
63-
});
64+
})
6465

6566
// Registered click event to (1) enable audio playback and (2) toggle playing the tracks
6667
bool onClick(int __unused type, const EmscriptenMouseEvent* __unused e, void* data) {
@@ -93,10 +94,10 @@ void initialised(EMSCRIPTEN_WEBAUDIO_T context, bool success, void* __unused dat
9394
}
9495

9596
// To be implemented by the test code, allowing initialised() to be changed.
96-
EmscriptenStartWebAudioWorkletCallback getStartCallback();
97+
EmscriptenStartWebAudioWorkletCallback getStartCallback(void);
9798

9899
// Common entry point for the mixer tests
99-
int main() {
100+
int main(void) {
100101
char* const workletStack = memalign(16, AUDIO_STACK_SIZE);
101102
printf("Audio worklet stack at 0x%p\n", workletStack);
102103
assert(workletStack);

0 commit comments

Comments
 (0)