Skip to content

Commit a041945

Browse files
committed
Split out the test changes from emscripten-core#23508
This mostly adds an Audio Worklet parameter test, but also tidies a little the related tests and shared code.
1 parent 3f29dc6 commit a041945

7 files changed

+314
-38
lines changed

test/test_interactive.py

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -334,10 +334,32 @@ def test_audio_worklet_2x_hard_pan_io(self):
334334
shutil.copy(test_file('webaudio/audio_files/emscripten-bass-mono.mp3'), 'audio_files/')
335335
self.btest_exit('webaudio/audioworklet_2x_in_hard_pan.c', args=['-sAUDIO_WORKLET', '-sWASM_WORKERS'])
336336

337+
# Tests an AudioWorklet with multiple stereo inputs mixing in the processor via a parameter to a single stereo output (6kB stack)
338+
def test_audio_worklet_params_mixing(self):
339+
os.mkdir('audio_files')
340+
shutil.copy(test_file('webaudio/audio_files/emscripten-beat.mp3'), 'audio_files/')
341+
shutil.copy(test_file('webaudio/audio_files/emscripten-bass.mp3'), 'audio_files/')
342+
self.btest_exit('webaudio/audioworklet_params_mixing.c', args=['-sAUDIO_WORKLET', '-sWASM_WORKERS'])
343+
337344

338345
class interactive64(interactive):
339346
def setUp(self):
340347
super().setUp()
341348
self.set_setting('MEMORY64')
342-
self.emcc_args.append('-Wno-experimental')
343349
self.require_wasm64()
350+
351+
352+
class interactive64_4gb(interactive):
353+
def setUp(self):
354+
super().setUp()
355+
self.set_setting('MEMORY64')
356+
self.set_setting('INITIAL_MEMORY', '4200mb')
357+
self.set_setting('GLOBAL_BASE', '4gb')
358+
self.require_wasm64()
359+
360+
361+
class interactive_2gb(interactive):
362+
def setUp(self):
363+
super().setUp()
364+
self.set_setting('INITIAL_MEMORY', '2200mb')
365+
self.set_setting('GLOBAL_BASE', '2gb')

test/webaudio/audioworklet_2x_in_hard_pan.c

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,25 +15,37 @@
1515
#include "audioworklet_test_shared.inc"
1616

1717
// Callback to process and copy the audio tracks
18-
bool process(int numInputs, const AudioSampleFrame* inputs, int numOutputs, AudioSampleFrame* outputs, int numParams, const AudioParamFrame* params, void* data) {
18+
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

3547
// Audio processor created, now register the audio callback
36-
void processorCreated(EMSCRIPTEN_WEBAUDIO_T context, bool success, void* data) {
48+
void processorCreated(EMSCRIPTEN_WEBAUDIO_T context, bool success, void* __unused data) {
3749
if (!success) {
3850
printf("Audio worklet node creation failed\n");
3951
return;
@@ -68,3 +80,8 @@ void processorCreated(EMSCRIPTEN_WEBAUDIO_T context, bool success, void* data) {
6880
// Register the counter that exits the test after one second of mixing
6981
emscripten_set_timeout_loop(&playedAndMixed, 16, NULL);
7082
}
83+
84+
// This implementation has no custom start-up requirements
85+
EmscriptenStartWebAudioWorkletCallback getStartCallback(void) {
86+
return &initialised;
87+
}

test/webaudio/audioworklet_2x_in_out_stereo.c

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,26 +14,37 @@
1414
#include "audioworklet_test_shared.inc"
1515

1616
// Callback to process and copy the audio tracks
17-
bool process(int numInputs, const AudioSampleFrame* inputs, int numOutputs, AudioSampleFrame* outputs, int numParams, const AudioParamFrame* params, void* data) {
17+
bool process(int numInputs, const AudioSampleFrame* inputs, int numOutputs, AudioSampleFrame* outputs, int __unused numParams, const AudioParamFrame* __unused params, void* __unused data) {
1818
audioProcessedCount++;
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

3546
// Audio processor created, now register the audio callback
36-
void processorCreated(EMSCRIPTEN_WEBAUDIO_T context, bool success, void* data) {
47+
void processorCreated(EMSCRIPTEN_WEBAUDIO_T context, bool success, void* __unused data) {
3748
if (!success) {
3849
printf("Audio worklet node creation failed\n");
3950
return;
@@ -70,3 +81,8 @@ void processorCreated(EMSCRIPTEN_WEBAUDIO_T context, bool success, void* data) {
7081
// Register the counter that exits the test after one second of mixing
7182
emscripten_set_timeout_loop(&playedAndMixed, 16, NULL);
7283
}
84+
85+
// This implementation has no custom start-up requirements
86+
EmscriptenStartWebAudioWorkletCallback getStartCallback(void) {
87+
return &initialised;
88+
}

test/webaudio/audioworklet_in_out_mono.c

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
#include "audioworklet_test_shared.inc"
1616

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

2121
// Single mono output
@@ -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 the first input's audio data, checking that we have
33+
// channels (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];
@@ -45,7 +52,7 @@ bool process(int numInputs, const AudioSampleFrame* inputs, int numOutputs, Audi
4552
}
4653

4754
// Audio processor created, now register the audio callback
48-
void processorCreated(EMSCRIPTEN_WEBAUDIO_T context, bool success, void* data) {
55+
void processorCreated(EMSCRIPTEN_WEBAUDIO_T context, bool success, void* __unused data) {
4956
if (!success) {
5057
printf("Audio worklet node creation failed\n");
5158
return;
@@ -80,3 +87,9 @@ void processorCreated(EMSCRIPTEN_WEBAUDIO_T context, bool success, void* data) {
8087
// Register the counter that exits the test after one second of mixing
8188
emscripten_set_timeout_loop(&playedAndMixed, 16, NULL);
8289
}
90+
91+
// This implementation has no custom start-up requirements
92+
EmscriptenStartWebAudioWorkletCallback getStartCallback(void) {
93+
return &initialised;
94+
}
95+

test/webaudio/audioworklet_in_out_stereo.c

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
#include "audioworklet_test_shared.inc"
1616

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

2121
// Single stereo output
@@ -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 the first input's audio data, checking that we have
33+
// channels (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];
@@ -45,7 +52,7 @@ bool process(int numInputs, const AudioSampleFrame* inputs, int numOutputs, Audi
4552
}
4653

4754
// Audio processor created, now register the audio callback
48-
void processorCreated(EMSCRIPTEN_WEBAUDIO_T context, bool success, void* data) {
55+
void processorCreated(EMSCRIPTEN_WEBAUDIO_T context, bool success, void* __unused data) {
4956
if (!success) {
5057
printf("Audio worklet node creation failed\n");
5158
return;
@@ -80,3 +87,8 @@ void processorCreated(EMSCRIPTEN_WEBAUDIO_T context, bool success, void* data) {
8087
// Register the counter that exits the test after one second of mixing
8188
emscripten_set_timeout_loop(&playedAndMixed, 16, NULL);
8289
}
90+
91+
// This implementation has no custom start-up requirements
92+
EmscriptenStartWebAudioWorkletCallback getStartCallback(void) {
93+
return &initialised;
94+
}

0 commit comments

Comments
 (0)