libsdl-org / SDL_mixer

An audio mixer that supports various file formats for Simple Directmedia Layer.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

playmus no longer recognising WAV files since the SDL_RWops API change

smcv opened this issue · comments

After upgrading from a few days ago's SDL3 and SDL_mixer to libsdl-org/SDL@a2d5942 and mixer 139b748, I can still play a simple stereo WAV file with playwave:

$ .../playwave /usr/share/sounds/alsa/Front_Center.wav
INFO: Opened audio at 48000 Hz 32 bit stereo

but the same with playmus no longer works:

$ .../playmus /usr/share/sounds/alsa/Front_Center.wav
INFO: Opened audio at 48000 Hz 32 bit stereo audio buffer
INFO: Couldn't load /usr/share/sounds/alsa/Front_Center.wav: Unrecognized audio format

It fails during chunk_type and chunk_length read in LoadWAVMusic():
https://github.com/libsdl-org/SDL_mixer/blob/main/src/codecs/music_wav.c#L1655-L1658

It is supposed to break out of the for loop if it hits chunk_length == 0:
https://github.com/libsdl-org/SDL_mixer/blob/main/src/codecs/music_wav.c#L1655-L1658

It was possible before because with the old SDL_ReadLE32 we didn't care
about read success: I guess we shouldn't now either, or change the logic.

EDIT: Possible similar issues elsewhere in music_wav.c (possibly in other
places too???)

CC: @slouken

For what it's worth, patching like the following cures the reported issue with WAVE files:

diff --git a/src/codecs/music_wav.c b/src/codecs/music_wav.c
index e04d7fe..7cf277a 100644
--- a/src/codecs/music_wav.c
+++ b/src/codecs/music_wav.c
@@ -1652,10 +1652,8 @@ static SDL_bool LoadWAVMusic(WAV_Music *wave)
 
     /* Read the chunks */
     for (; ;) {
-        if (!SDL_ReadU32LE(src, &chunk_type) ||
-            !SDL_ReadU32LE(src, &chunk_length)) {
-            return SDL_FALSE;
-        }
+        SDL_ReadU32LE(src, &chunk_type);  /* not checking success for these two. */
+        SDL_ReadU32LE(src, &chunk_length);
 
         if (chunk_length == 0)
             break;

How about this?

diff --git a/src/codecs/music_wav.c b/src/codecs/music_wav.c
index e04d7fe2..1889bb32 100644
--- a/src/codecs/music_wav.c
+++ b/src/codecs/music_wav.c
@@ -1654,6 +1654,9 @@ static SDL_bool LoadWAVMusic(WAV_Music *wave)
     for (; ;) {
         if (!SDL_ReadU32LE(src, &chunk_type) ||
             !SDL_ReadU32LE(src, &chunk_length)) {
+            if (src->status == SDL_RWOPS_STATUS_EOF) {
+                break;
+            }
             return SDL_FALSE;
         }

Tested to work.

I wonder whether there are any other such places that need this kind of care (and not just in SDL_mixer but SDL_image and SDL_ttf too.)

Possibly. If people continue to ignore the return value it'll work the way it always had. It's not great practice, but it was the only option in the previous API. I think this is an improvement, we just have to keep an eye out for this kind of thing.

Fixed in 14f1eb2