Browse Source

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.
Ryan C. Gordon 8 years ago
parent
commit
e8677a1bd2
2 changed files with 33 additions and 0 deletions
  1. 23 0
      src/audio/SDL_wave.c
  2. 10 0
      src/audio/SDL_wave.h

+ 23 - 0
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;

+ 10 - 0
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: */