From e8677a1bd2f3b277503c5e1d1dab6df56f3744aa Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Fri, 17 Feb 2017 02:25:37 -0500 Subject: [PATCH] audio: Added basic WAVE_FORMAT_EXTENSIBLE support to .wav loader. This is just enough to get you through a file that just used the extended header for float or int data. It doesn't handle all the other things that you expect from this header, like 24-bit samples inside a 32-bit container or speaker masks. --- src/audio/SDL_wave.c | 23 +++++++++++++++++++++++ src/audio/SDL_wave.h | 10 ++++++++++ 2 files changed, 33 insertions(+) diff --git a/src/audio/SDL_wave.c b/src/audio/SDL_wave.c index 7ce00a51031a0..a9e905c1ccb9d 100644 --- a/src/audio/SDL_wave.c +++ b/src/audio/SDL_wave.c @@ -403,6 +403,10 @@ IMA_ADPCM_decode(Uint8 ** audio_buf, Uint32 * audio_len) return (0); } +/* GUIDs that are used by WAVE_FORMAT_EXTENSIBLE */ +static const Uint8 extensible_pcm_guid[16] = { 1, 0, 0, 0, 0, 0, 16, 0, 128, 0, 0, 170, 0, 56, 155, 113 }; +static const Uint8 extensible_ieee_guid[16] = { 3, 0, 0, 0, 0, 0, 16, 0, 128, 0, 0, 170, 0, 56, 155, 113 }; + SDL_AudioSpec * SDL_LoadWAV_RW(SDL_RWops * src, int freesrc, SDL_AudioSpec * spec, Uint8 ** audio_buf, Uint32 * audio_len) @@ -421,6 +425,7 @@ SDL_LoadWAV_RW(SDL_RWops * src, int freesrc, /* FMT chunk */ WaveFMT *format = NULL; + WaveExtensibleFMT *ext = NULL; SDL_zero(chunk); @@ -494,6 +499,24 @@ SDL_LoadWAV_RW(SDL_RWops * src, int freesrc, } IMA_ADPCM_encoded = 1; break; + case EXTENSIBLE_CODE: + /* note that this ignores channel masks, smaller valid bit counts + inside a larger container, and most subtypes. This is just enough + to get things that didn't really _need_ WAVE_FORMAT_EXTENSIBLE + to be useful working when they use this format flag. */ + ext = (WaveExtensibleFMT *) format; + if (SDL_SwapLE16(ext->size) < 22) { + SDL_SetError("bogus extended .wav header"); + was_error = 1; + goto done; + } + if (SDL_memcmp(ext->subformat, extensible_pcm_guid, 16) == 0) { + break; /* cool. */ + } else if (SDL_memcmp(ext->subformat, extensible_ieee_guid, 16) == 0) { + IEEE_float_encoded = 1; + break; + } + break; case MP3_CODE: SDL_SetError("MPEG Layer 3 data not supported"); was_error = 1; diff --git a/src/audio/SDL_wave.h b/src/audio/SDL_wave.h index fe55b4ac3fd12..5762f519ae7d3 100644 --- a/src/audio/SDL_wave.h +++ b/src/audio/SDL_wave.h @@ -38,6 +38,7 @@ #define IEEE_FLOAT_CODE 0x0003 #define IMA_ADPCM_CODE 0x0011 #define MP3_CODE 0x0055 +#define EXTENSIBLE_CODE 0xFFFE #define WAVE_MONO 1 #define WAVE_STEREO 2 @@ -64,4 +65,13 @@ typedef struct Chunk Uint8 *data; } Chunk; +typedef struct WaveExtensibleFMT +{ + WaveFMT format; + Uint16 size; + Uint16 validbits; + Uint32 channelmask; + Uint8 subformat[16]; /* a GUID. */ +} WaveExtensibleFMT; + /* vi: set ts=4 sw=4 expandtab: */