Skip to content

Commit abcf6bc

Browse files
committed
Fix audio leaking in builtin SDL_mixer
1 parent bf910d6 commit abcf6bc

File tree

3 files changed

+57
-0
lines changed

3 files changed

+57
-0
lines changed

src/library_sdl.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2817,6 +2817,7 @@ var LibrarySDL = {
28172817
Mix_ReserveChannels: (num) => {
28182818
SDL.channelMinimumNumber = num;
28192819
},
2820+
Mix_PlayChannelTimed__deps: ['Mix_HaltChannel'],
28202821
Mix_PlayChannelTimed__proxy: 'sync',
28212822
Mix_PlayChannelTimed: (channel, id, loops, ticks) => {
28222823
// TODO: handle fixed amount of N loops. Currently loops either 0 or infinite times.
@@ -2863,6 +2864,9 @@ var LibrarySDL = {
28632864
if (channelInfo.audio == this) { channelInfo.audio.paused = true; channelInfo.audio = null; }
28642865
if (SDL.channelFinished) {{{ makeDynCall('vi', 'SDL.channelFinished') }}}(channel);
28652866
}
2867+
if (channelInfo.audio) {
2868+
_Mix_HaltChannel(channel);
2869+
}
28662870
channelInfo.audio = audio;
28672871
// TODO: handle N loops. Behavior matches Mix_PlayMusic
28682872
audio.loop = loops != 0;
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
#include <SDL/SDL_mixer.h>
2+
#include <chrono>
3+
#include <emscripten.h>
4+
5+
using namespace std::chrono;
6+
7+
Mix_Chunk* chunk = nullptr;
8+
uint64_t started = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
9+
uint64_t lastRun = 0;
10+
11+
void loop() {
12+
uint64_t now = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
13+
if (now - lastRun > 300) {
14+
Mix_PlayChannel(0, chunk, -1);
15+
lastRun = now;
16+
}
17+
if (now - started > 3000) {
18+
emscripten_force_exit(0);
19+
}
20+
}
21+
22+
int main(int argc, char** argv) {
23+
if ((Mix_Init(MIX_INIT_OGG) & MIX_INIT_OGG) != MIX_INIT_OGG) {
24+
printf("ERR! Mix_Init: Failed to init with required flags support!\n");
25+
printf("ERR! Mix_Init: %s\n", Mix_GetError());
26+
return -1;
27+
}
28+
29+
if (Mix_OpenAudio(MIX_DEFAULT_FREQUENCY, MIX_DEFAULT_FORMAT, 1, 1024) == -1) {
30+
printf("ERR! Mix_OpenAudio: %s\n", Mix_GetError());
31+
return -1;
32+
}
33+
34+
Mix_AllocateChannels(1);
35+
chunk = Mix_LoadWAV("/the_entertainer.ogg");
36+
if (!chunk) {
37+
printf("ERR! Mix_LoadWAV: %s\n", Mix_GetError());
38+
return -1;
39+
}
40+
41+
printf("The sound should reset to start every 300ms, if you hear overapplied music then the test has failed.\n");
42+
emscripten_set_main_loop(loop, 0, 0);
43+
return 0;
44+
}

test/test_interactive.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,15 @@ def test_sdl_audio_mix_channels(self, args):
8282

8383
self.btest_exit('test_sdl_audio_mix_channels.c', args=['-O2', '--minify=0', '--preload-file', 'sound.ogg'] + args)
8484

85+
@parameterized({
86+
'': ([],),
87+
'wasmfs': (['-sWASMFS'],),
88+
})
89+
def test_sdl_audio_mix_channels_halt(self, args):
90+
shutil.copyfile(test_file('sounds/the_entertainer.ogg'), self.in_dir('the_entertainer.ogg'))
91+
92+
self.btest_exit('test_sdl_audio_mix_channels_halt.cpp', args=['-O2', '--minify=0', '--preload-file', 'the_entertainer.ogg'] + args)
93+
8594
@parameterized({
8695
'': ([],),
8796
'wasmfs': (['-sWASMFS'],),

0 commit comments

Comments
 (0)