2
\$\begingroup\$

I have WAV files of this format:

Opening audio decoder: [pcm] Uncompressed PCM audio decoder
AUDIO: 48000 Hz, 2 ch, s24le, 2304.0 kbit/100.00% (ratio: 288000->288000)
ID_AUDIO_BITRATE=2304000
ID_AUDIO_RATE=48000
ID_AUDIO_NCH=2
Selected audio codec: [pcm] afm: pcm (Uncompressed PCM)

mplayer plays them at 16bit, and I can convert them to pcm_s16le with ffmpeg very easily, and they do play in SDL2 fine.

The Problem

These files are 24bit, so we lose some audio converting them to 16bit I'd assume. Since SDL2 only supports 16bit (signed, unsigned, float) and 32bit, I figured I'd convert up to 32bit if that's possible, using this:

ffmpeg -i input.wav -filter:a asetrate="48k" -ac 2 -c:a pcm_s32le output.wav

If I try to use pcm_s32be I get: pcm_s32be codec not supported in WAVE format so I have to use little endian with Float, signed or unsigned...

FFmpeg converts it correctly, but SDL2 won't play the 32bit audio, it gives: Unknown WAVE data format: 0xfffe


Here are the valid SDL2 audio formats: https://wiki.libsdl.org/SDL_AudioFormat we're looking at AUDIO_S32LSB specifically, and yes I am using SDL2 2.0.X

Note this error message comes from https://github.com/spurious/SDL-mirror/blob/13666b37a08a78bb209b5c584f74846f7e7b5cf2/src/audio/SDL_wave.c#L473 Where it seems to be comparing to Swap16LE? and notices it's not pcm_16 and dies.

Here is the definition for the constant we're using: https://github.com/spurious/SDL-mirror/blob/e04f23c7eaa7da672a8904b59001eff09da8db92/include/SDL_audio.h#L103 note that the number given is not 0xfffe

Note: This is related to SDL2 specifically, so I believe it fits gamedev, I don't think posting to an audio related SA would garner as much intimate knowledge on the subject.

TL;DR Question

Does anyone have any insight on how I can get SDL2 to play my 24bit WAV, possibly by converting them to 32bit and getting them to play in SDL2


EDIT #2: Forget the last Edit (I removed).

I've implemented the LoadWav functionality locally and am getting the 0x0001 vs 0xfffe between 32bit wav and 16bit, so we're getting closer...

I'm inspecting how SDL2 is reading the WAV Header, and the difference between 32bit vs 16bit header is and why it's dying.

EDIT #3:

Here are some values from the two files:

32BIT WAVE:
RIFF: 1179011410, WAVELEN: 52043438
WAVE Magic: 1163280727
headerDiff: 4
Start of Chunk Loop:
Chunk Data: 254
headerDiff: 52
Chunk Magic: 544501094
0x000000000000fffe

16BIT WAVE:
RIFF: 1179011410, WAVELEN: 99312
WAVE Magic: 1163280727
headerDiff: 4
Start of Chunk Loop:
Chunk Data: 1
headerDiff: 28
Chunk Magic: 544501094
0x0000000000000001

So it seems the issue is when reading the chunks, note how the Header is double the size and returns the non-0x0001 value...


Edit #4:

Here are the two files each printed 1 byte at a time, and diffed (0-248 bits) 160-168 are where we're having issues. I need to learn the WAV format header information to proceed past this part.

@@ -2,10 +2,10 @@
   8 SRC Bytes: 0x49
  16 SRC Bytes: 0x46
  24 SRC Bytes: 0x46
- 32 SRC Bytes: 0xf0
- 40 SRC Bytes: 0x83
- 48 SRC Bytes: 0x1
- 56 SRC Bytes: 0x0
+ 32 SRC Bytes: 0xae
+ 40 SRC Bytes: 0x1e
+ 48 SRC Bytes: 0x1a
+ 56 SRC Bytes: 0x3
  64 SRC Bytes: 0x57
  72 SRC Bytes: 0x41
  80 SRC Bytes: 0x56
@@ -14,12 +14,12 @@
 104 SRC Bytes: 0x6d
 112 SRC Bytes: 0x74
 120 SRC Bytes: 0x20
-128 SRC Bytes: 0x10
+128 SRC Bytes: 0x28
 136 SRC Bytes: 0x0
 144 SRC Bytes: 0x0
 152 SRC Bytes: 0x0
-160 SRC Bytes: 0x1
-168 SRC Bytes: 0x0
+160 SRC Bytes: 0xfe
+168 SRC Bytes: 0xff
 176 SRC Bytes: 0x2
 184 SRC Bytes: 0x0
 192 SRC Bytes: 0x80
@@ -27,6 +27,6 @@
 208 SRC Bytes: 0x0
 216 SRC Bytes: 0x0
 224 SRC Bytes: 0x0
-232 SRC Bytes: 0xee
-240 SRC Bytes: 0x2
+232 SRC Bytes: 0xdc
+240 SRC Bytes: 0x5
 248 SRC Bytes: 0x0

EDIT #5:

Going off of this: http://soundfile.sapp.org/doc/WaveFormat/

We have

Subchunk1Size 16 for PCM. This is the size of the rest of the Subchunk which follows this number.

AudioFormat PCM = 1 (i.e. Linear quantization) Values other than 1 indicate some form of compression.

So Clearly there's some issue with how I'm converting it to 32bit, as it has a 40 chunk size, rather than 16, and 0xfffe rather than 1.

\$\endgroup\$
1
\$\begingroup\$

As of EDIT #5, we can conclude that the Audio Format section of the header is 0xfffe and SDL2 only allows 0x0001 (as of PCM standard).

With this post: https://stackoverflow.com/a/42048916/5698848

It's come to understand that ffmpeg (and sox apparently) add a "wave format extensible" flag which is 0xfffe but is not needed and can be replaced manually with 0x0001

With this replacement, SDL2 will play the audio file flawlessly, assuming one uses the proper flag (AUDIO_S32LSB in my case)

\$\endgroup\$
1
\$\begingroup\$

Just as a heads up, this was just fixed in SDL: https://hg.libsdl.org/SDL/rev/748bedefb03f

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.