music_wav.c: Extended support for WAV files (bug #4878):
authorVitaly Novichkov <admin@wohlnet.ru>
Wed, 04 Dec 2019 18:50:02 +0300
changeset 1054ae77864d2fa7
parent 1053 a7d2efcbc36c
child 1055 df723393f0cf
music_wav.c: Extended support for WAV files (bug #4878):

- Support for uLAW and ALAW encodings
- Better support of AIFF files
- Support Float32 and Float64 both big and little endian, all variants
of integer (8, 16, 24 and 32) both little and big endian as a sample
format
- Added WAV_Seek() call to allow seeking inside of WAV or AIFF files
src/codecs/music_wav.c
     1.1 --- a/src/codecs/music_wav.c	Sun Dec 01 21:50:02 2019 +0300
     1.2 +++ b/src/codecs/music_wav.c	Wed Dec 04 18:50:02 2019 +0300
     1.3 @@ -42,10 +42,13 @@
     1.4      int play_count;
     1.5      Sint64 start;
     1.6      Sint64 stop;
     1.7 +    Sint64 samplesize;
     1.8      Uint8 *buffer;
     1.9      SDL_AudioStream *stream;
    1.10      unsigned int numloops;
    1.11      WAVLoopPoint *loops;
    1.12 +    Uint16 encoding;
    1.13 +    int (*decode)(void *music, int length);
    1.14  } WAV_Music;
    1.15  
    1.16  /*
    1.17 @@ -64,8 +67,14 @@
    1.18  #define FMT         0x20746D66      /* "fmt " */
    1.19  #define DATA        0x61746164      /* "data" */
    1.20  #define SMPL        0x6c706d73      /* "smpl" */
    1.21 -#define PCM_CODE    1
    1.22 -#define ADPCM_CODE  2
    1.23 +#define LIST        0x5453494c      /* "LIST" */
    1.24 +#define ID3_        0x20336469      /* "id3 " */
    1.25 +#define PCM_CODE    1               /* WAVE_FORMAT_PCM */
    1.26 +#define ADPCM_CODE  2               /* WAVE_FORMAT_ADPCM */
    1.27 +#define FLOAT_CODE  3               /* WAVE_FORMAT_IEEE_FLOAT */
    1.28 +#define ALAW_CODE   6               /* WAVE_FORMAT_ALAW */
    1.29 +#define uLAW_CODE   7               /* WAVE_FORMAT_MULAW */
    1.30 +#define EXT_CODE    0xFFFE          /* WAVE_FORMAT_EXTENSIBLE */
    1.31  #define WAVE_MONO   1
    1.32  #define WAVE_STEREO 2
    1.33  
    1.34 @@ -83,6 +92,21 @@
    1.35  } WaveFMT;
    1.36  
    1.37  typedef struct {
    1.38 +    Uint16  cbSize;
    1.39 +    union {
    1.40 +        Uint16 validbitspersample; /* bits of precision */
    1.41 +        Uint16 samplesperblock;   /* valid if wBitsPerSample==0 */
    1.42 +        Uint16 reserved;         /* If neither applies, set to zero. */
    1.43 +    } Samples;
    1.44 +    Uint32 channelsmask;
    1.45 +    /* GUID subFormat 16 bytes */
    1.46 +    Uint32 subencoding;
    1.47 +    Uint16 sub_data2;
    1.48 +    Uint16 sub_data3;
    1.49 +    Uint8  sub_data[8];
    1.50 +} WaveFMTex;
    1.51 +
    1.52 +typedef struct {
    1.53      Uint32 identifier;
    1.54      Uint32 type;
    1.55      Uint32 start;
    1.56 @@ -113,9 +137,28 @@
    1.57  /*********************************************/
    1.58  #define FORM        0x4d524f46      /* "FORM" */
    1.59  #define AIFF        0x46464941      /* "AIFF" */
    1.60 +#define AIFC        0x43464941      /* "AIF–°" */
    1.61 +#define FVER        0x52455646      /* "FVER" */
    1.62  #define SSND        0x444e5353      /* "SSND" */
    1.63  #define COMM        0x4d4d4f43      /* "COMM" */
    1.64 +#define AIFF_ID3_   0x20334449      /* "ID3 " */
    1.65 +#define MARK        0x4B52414D      /* "MARK" */
    1.66 +#define INST        0x54534E49      /* "INST" */
    1.67 +#define AUTH        0x48545541      /* "AUTH" */
    1.68 +#define NAME        0x454D414E      /* "NAME" */
    1.69 +#define _c__        0x20296328      /* "(c) " */
    1.70  
    1.71 +/* Supported compression types */
    1.72 +#define NONE        0x454E4F4E      /* "NONE" */
    1.73 +#define sowt        0x74776F73      /* "sowt" */
    1.74 +#define raw_        0x20776172      /* "raw " */
    1.75 +#define ulaw        0x77616C75      /* "ulaw" */
    1.76 +#define alaw        0x77616C61      /* "alaw" */
    1.77 +#define ULAW        0x57414C55      /* "ULAW" */
    1.78 +#define ALAW        0x57414C41      /* "ALAW" */
    1.79 +#define fl32        0x32336C66      /* "fl32" */
    1.80 +#define fl64        0x34366C66      /* "fl64" */
    1.81 +#define FL32        0x32334C46      /* "FL32" */
    1.82  
    1.83  /* Function to load the WAV/AIFF stream */
    1.84  static SDL_bool LoadWAVMusic(WAV_Music *wave);
    1.85 @@ -123,6 +166,8 @@
    1.86  
    1.87  static void WAV_Delete(void *context);
    1.88  
    1.89 +static int fetch_pcm(void *context, int length);
    1.90 +
    1.91  /* Load a WAV stream from the given RWops object */
    1.92  static void *WAV_CreateFromRW(SDL_RWops *src, int freesrc)
    1.93  {
    1.94 @@ -137,6 +182,9 @@
    1.95      }
    1.96      music->src = src;
    1.97      music->volume = MIX_MAX_VOLUME;
    1.98 +    /* Default decoder is PCM */
    1.99 +    music->decode = fetch_pcm;
   1.100 +    music->encoding = PCM_CODE;
   1.101  
   1.102      magic = SDL_ReadLE32(src);
   1.103      if (magic == RIFF || magic == WAVE) {
   1.104 @@ -190,15 +238,250 @@
   1.105      return 0;
   1.106  }
   1.107  
   1.108 +static int fetch_pcm(void *context, int length)
   1.109 +{
   1.110 +    WAV_Music *music = (WAV_Music *)context;
   1.111 +    return (int)SDL_RWread(music->src, music->buffer, 1, (size_t)length);
   1.112 +}
   1.113 +
   1.114 +static Uint32 PCM_S24_to_S32_BE(Uint8 *x) {
   1.115 +    const Uint32 bits = 24;
   1.116 +    Uint32 in = (((Uint32)x[0] << 0)  & 0x0000FF) |
   1.117 +                (((Uint32)x[1] << 8)  & 0x00FF00) |
   1.118 +                (((Uint32)x[2] << 16) & 0xFF0000);
   1.119 +    Uint32 m = 1u << (bits - 1);
   1.120 +    return (in ^ m) - m;
   1.121 +}
   1.122 +
   1.123 +static Uint32 PCM_S24_to_S32_LE(Uint8 *x) {
   1.124 +    const Uint32 bits = 24;
   1.125 +    Uint32 in = (((Uint32)x[2] << 0)  & 0x0000FF) |
   1.126 +                (((Uint32)x[1] << 8)  & 0x00FF00) |
   1.127 +                (((Uint32)x[0] << 16) & 0xFF0000);
   1.128 +    Uint32 m = 1u << (bits - 1);
   1.129 +    return (in ^ m) - m;
   1.130 +}
   1.131 +
   1.132 +static int fetch_pcm24be(void *context, int length)
   1.133 +{
   1.134 +    WAV_Music *music = (WAV_Music *)context;
   1.135 +    int i = 0, o = 0;
   1.136 +    length = (int)SDL_RWread(music->src, music->buffer, 1, (size_t)((length / 4) * 3));
   1.137 +    if (length % music->samplesize != 0) {
   1.138 +        length -= length % music->samplesize;
   1.139 +    }
   1.140 +    for (i = length - 3, o = ((length - 3) / 3) * 4; i >= 0; i -= 3, o -= 4) {
   1.141 +        Uint32 decoded = PCM_S24_to_S32_BE(music->buffer + i);
   1.142 +        music->buffer[o + 0] = (decoded >> 0) & 0xFF;
   1.143 +        music->buffer[o + 1] = (decoded >> 8) & 0xFF;
   1.144 +        music->buffer[o + 2] = (decoded >> 16) & 0xFF;
   1.145 +        music->buffer[o + 3] = (decoded >> 24) & 0xFF;
   1.146 +    }
   1.147 +    return (length / 3) * 4;
   1.148 +}
   1.149 +
   1.150 +static int fetch_pcm24le(void *context, int length)
   1.151 +{
   1.152 +    WAV_Music *music = (WAV_Music *)context;
   1.153 +    int i = 0, o = 0;
   1.154 +    length = (int)SDL_RWread(music->src, music->buffer, 1, (size_t)((length / 4) * 3));
   1.155 +    if (length % music->samplesize != 0) {
   1.156 +        length -= length % music->samplesize;
   1.157 +    }
   1.158 +    for (i = length - 3, o = ((length - 3) / 3) * 4; i >= 0; i -= 3, o -= 4) {
   1.159 +        Uint32 decoded = PCM_S24_to_S32_LE(music->buffer + i);
   1.160 +        music->buffer[o + 3] = (decoded >> 0) & 0xFF;
   1.161 +        music->buffer[o + 2] = (decoded >> 8) & 0xFF;
   1.162 +        music->buffer[o + 1] = (decoded >> 16) & 0xFF;
   1.163 +        music->buffer[o + 0] = (decoded >> 24) & 0xFF;
   1.164 +    }
   1.165 +    return (length / 3) * 4;
   1.166 +}
   1.167 +
   1.168 +SDL_FORCE_INLINE double
   1.169 +Mix_SwapDouble(double x)
   1.170 +{
   1.171 +    union
   1.172 +    {
   1.173 +        double f;
   1.174 +        Uint64 ui64;
   1.175 +    } swapper;
   1.176 +    swapper.f = x;
   1.177 +    swapper.ui64 = SDL_Swap64(swapper.ui64);
   1.178 +    return swapper.f;
   1.179 +}
   1.180 +
   1.181 +#if SDL_BYTEORDER == SDL_LIL_ENDIAN
   1.182 +#define Mix_SwapDoubleLE(X)  (X)
   1.183 +#define Mix_SwapDoubleBE(X)  Mix_SwapDouble(X)
   1.184 +#else
   1.185 +#define Mix_SwapDoubleLE(X)  Mix_SwapDouble(X)
   1.186 +#define Mix_SwapDoubleBE(X)  (X)
   1.187 +#endif
   1.188 +
   1.189 +static int fetch_float64be(void *context, int length)
   1.190 +{
   1.191 +    WAV_Music *music = (WAV_Music *)context;
   1.192 +    int i = 0, o = 0;
   1.193 +    length = (int)SDL_RWread(music->src, music->buffer, 1, (size_t)(length));
   1.194 +    if (length % music->samplesize != 0) {
   1.195 +        length -= length % music->samplesize;
   1.196 +    }
   1.197 +    for (i = 0, o = 0; i <= length; i += 8, o += 4) {
   1.198 +        union
   1.199 +        {
   1.200 +            float f;
   1.201 +            Uint32 ui32;
   1.202 +        } sample;
   1.203 +        sample.f = (float)Mix_SwapDoubleBE(*(double*)(music->buffer + i));
   1.204 +        music->buffer[o + 0] = (sample.ui32 >> 0) & 0xFF;
   1.205 +        music->buffer[o + 1] = (sample.ui32 >> 8) & 0xFF;
   1.206 +        music->buffer[o + 2] = (sample.ui32 >> 16) & 0xFF;
   1.207 +        music->buffer[o + 3] = (sample.ui32 >> 24) & 0xFF;
   1.208 +    }
   1.209 +    return length / 2;
   1.210 +}
   1.211 +
   1.212 +static int fetch_float64le(void *context, int length)
   1.213 +{
   1.214 +    WAV_Music *music = (WAV_Music *)context;
   1.215 +    int i = 0, o = 0;
   1.216 +    length = (int)SDL_RWread(music->src, music->buffer, 1, (size_t)(length));
   1.217 +    if (length % music->samplesize != 0) {
   1.218 +        length -= length % music->samplesize;
   1.219 +    }
   1.220 +    for (i = 0, o = 0; i <= length; i += 8, o += 4) {
   1.221 +        union
   1.222 +        {
   1.223 +            float f;
   1.224 +            Uint32 ui32;
   1.225 +        } sample;
   1.226 +        sample.f = (float)Mix_SwapDoubleLE(*(double*)(music->buffer + i));
   1.227 +        music->buffer[o + 0] = (sample.ui32 >> 0) & 0xFF;
   1.228 +        music->buffer[o + 1] = (sample.ui32 >> 8) & 0xFF;
   1.229 +        music->buffer[o + 2] = (sample.ui32 >> 16) & 0xFF;
   1.230 +        music->buffer[o + 3] = (sample.ui32 >> 24) & 0xFF;
   1.231 +    }
   1.232 +    return length / 2;
   1.233 +}
   1.234 +
   1.235 +/*
   1.236 +    G711 decode tables taken from SDL2 (src/audio/SDL_wave.c)
   1.237 +*/
   1.238 +#ifdef SDL_WAVE_LAW_LUT
   1.239 +static const Sint16 alaw_lut[256] = {
   1.240 +    -5504, -5248, -6016, -5760, -4480, -4224, -4992, -4736, -7552, -7296, -8064, -7808, -6528, -6272, -7040, -6784, -2752,
   1.241 +    -2624, -3008, -2880, -2240, -2112, -2496, -2368, -3776, -3648, -4032, -3904, -3264, -3136, -3520, -3392, -22016,
   1.242 +    -20992, -24064, -23040, -17920, -16896, -19968, -18944, -30208, -29184, -32256, -31232, -26112, -25088, -28160, -27136, -11008,
   1.243 +    -10496, -12032, -11520, -8960, -8448, -9984, -9472, -15104, -14592, -16128, -15616, -13056, -12544, -14080, -13568, -344,
   1.244 +    -328, -376, -360, -280, -264, -312, -296, -472, -456, -504, -488, -408, -392, -440, -424, -88,
   1.245 +    -72, -120, -104, -24, -8, -56, -40, -216, -200, -248, -232, -152, -136, -184, -168, -1376,
   1.246 +    -1312, -1504, -1440, -1120, -1056, -1248, -1184, -1888, -1824, -2016, -1952, -1632, -1568, -1760, -1696, -688,
   1.247 +    -656, -752, -720, -560, -528, -624, -592, -944, -912, -1008, -976, -816, -784, -880, -848, 5504,
   1.248 +    5248, 6016, 5760, 4480, 4224, 4992, 4736, 7552, 7296, 8064, 7808, 6528, 6272, 7040, 6784, 2752,
   1.249 +    2624, 3008, 2880, 2240, 2112, 2496, 2368, 3776, 3648, 4032, 3904, 3264, 3136, 3520, 3392, 22016,
   1.250 +    20992, 24064, 23040, 17920, 16896, 19968, 18944, 30208, 29184, 32256, 31232, 26112, 25088, 28160, 27136, 11008,
   1.251 +    10496, 12032, 11520, 8960, 8448, 9984, 9472, 15104, 14592, 16128, 15616, 13056, 12544, 14080, 13568, 344,
   1.252 +    328, 376, 360, 280, 264, 312, 296, 472, 456, 504, 488, 408, 392, 440, 424, 88,
   1.253 +    72, 120, 104, 24, 8, 56, 40, 216, 200, 248, 232, 152, 136, 184, 168, 1376,
   1.254 +    1312, 1504, 1440, 1120, 1056, 1248, 1184, 1888, 1824, 2016, 1952, 1632, 1568, 1760, 1696, 688,
   1.255 +    656, 752, 720, 560, 528, 624, 592, 944, 912, 1008, 976, 816, 784, 880, 848
   1.256 +};
   1.257 +
   1.258 +static const Sint16 mulaw_lut[256] = {
   1.259 +    -32124, -31100, -30076, -29052, -28028, -27004, -25980, -24956, -23932, -22908, -21884, -20860, -19836, -18812, -17788, -16764, -15996,
   1.260 +    -15484, -14972, -14460, -13948, -13436, -12924, -12412, -11900, -11388, -10876, -10364, -9852, -9340, -8828, -8316, -7932,
   1.261 +    -7676, -7420, -7164, -6908, -6652, -6396, -6140, -5884, -5628, -5372, -5116, -4860, -4604, -4348, -4092, -3900,
   1.262 +    -3772, -3644, -3516, -3388, -3260, -3132, -3004, -2876, -2748, -2620, -2492, -2364, -2236, -2108, -1980, -1884,
   1.263 +    -1820, -1756, -1692, -1628, -1564, -1500, -1436, -1372, -1308, -1244, -1180, -1116, -1052, -988, -924, -876,
   1.264 +    -844, -812, -780, -748, -716, -684, -652, -620, -588, -556, -524, -492, -460, -428, -396, -372,
   1.265 +    -356, -340, -324, -308, -292, -276, -260, -244, -228, -212, -196, -180, -164, -148, -132, -120,
   1.266 +    -112, -104, -96, -88, -80, -72, -64, -56, -48, -40, -32, -24, -16, -8, 0, 32124,
   1.267 +    31100, 30076, 29052, 28028, 27004, 25980, 24956, 23932, 22908, 21884, 20860, 19836, 18812, 17788, 16764, 15996,
   1.268 +    15484, 14972, 14460, 13948, 13436, 12924, 12412, 11900, 11388, 10876, 10364, 9852, 9340, 8828, 8316, 7932,
   1.269 +    7676, 7420, 7164, 6908, 6652, 6396, 6140, 5884, 5628, 5372, 5116, 4860, 4604, 4348, 4092, 3900,
   1.270 +    3772, 3644, 3516, 3388, 3260, 3132, 3004, 2876, 2748, 2620, 2492, 2364, 2236, 2108, 1980, 1884,
   1.271 +    1820, 1756, 1692, 1628, 1564, 1500, 1436, 1372, 1308, 1244, 1180, 1116, 1052, 988, 924, 876,
   1.272 +    844, 812, 780, 748, 716, 684, 652, 620, 588, 556, 524, 492, 460, 428, 396, 372,
   1.273 +    356, 340, 324, 308, 292, 276, 260, 244, 228, 212, 196, 180, 164, 148, 132, 120,
   1.274 +    112, 104, 96, 88, 80, 72, 64, 56, 48, 40, 32, 24, 16, 8, 0
   1.275 +};
   1.276 +#endif
   1.277 +
   1.278 +static Sint16 uLAW_To_PCM16(Uint8 u_val)
   1.279 +{
   1.280 +#ifdef SDL_WAVE_LAW_LUT
   1.281 +    return mulaw_lut[u_val];
   1.282 +#else
   1.283 +    Uint8 nibble = ~u_val;
   1.284 +    Sint16 mantissa = nibble & 0xf;
   1.285 +    Uint8 exponent = (nibble >> 4) & 0x7;
   1.286 +    Sint16 step = (Sint16)(4 << (exponent + 1));
   1.287 +
   1.288 +    mantissa = (Sint16)(0x80 << exponent) + step * mantissa + step / 2 - 132;
   1.289 +
   1.290 +    return nibble & 0x80 ? -mantissa : mantissa;
   1.291 +#endif
   1.292 +}
   1.293 +
   1.294 +static Sint16 ALAW_To_PCM16(Uint8 a_val)
   1.295 +{
   1.296 +#ifdef SDL_WAVE_LAW_LUT
   1.297 +    return alaw_lut[a_val];
   1.298 +#else
   1.299 +    Uint8 nibble = a_val;
   1.300 +    Uint8 exponent = (nibble & 0x7f) ^ 0x55;
   1.301 +    Sint16 mantissa = exponent & 0xf;
   1.302 +
   1.303 +    exponent >>= 4;
   1.304 +    if (exponent > 0) {
   1.305 +        mantissa |= 0x10;
   1.306 +    }
   1.307 +    mantissa = (Sint16)(mantissa << 4) | 0x8;
   1.308 +    if (exponent > 1) {
   1.309 +        mantissa <<= exponent - 1;
   1.310 +    }
   1.311 +
   1.312 +    return nibble & 0x80 ? mantissa : -mantissa;
   1.313 +#endif
   1.314 +}
   1.315 +
   1.316 +static int fetch_xlaw(Sint16 (*decode_sample)(Uint8), void *context, int length)
   1.317 +{
   1.318 +    WAV_Music *music = (WAV_Music *)context;
   1.319 +    int i = 0, o = 0;
   1.320 +    length = (int)SDL_RWread(music->src, music->buffer, 1, (size_t)(length / 2));
   1.321 +    if (length % music->samplesize != 0) {
   1.322 +        length -= length % music->samplesize;
   1.323 +    }
   1.324 +    for (i = length - 1, o = (length - 1) * 2; i >= 0; i--, o -= 2) {
   1.325 +        Uint16 decoded = (Uint16)decode_sample(music->buffer[i]);
   1.326 +        music->buffer[o] = decoded & 0xFF;
   1.327 +        music->buffer[o + 1] = (decoded >> 8) & 0xFF;
   1.328 +    }
   1.329 +    return length * 2;
   1.330 +}
   1.331 +
   1.332 +static int fetch_ulaw(void *context, int length)
   1.333 +{
   1.334 +    return fetch_xlaw(uLAW_To_PCM16, context, length);
   1.335 +}
   1.336 +
   1.337 +static int fetch_alaw(void *context, int length)
   1.338 +{
   1.339 +    return fetch_xlaw(ALAW_To_PCM16, context, length);
   1.340 +}
   1.341 +
   1.342  /* Play some of a stream previously started with WAV_Play() */
   1.343  static int WAV_GetSome(void *context, void *data, int bytes, SDL_bool *done)
   1.344  {
   1.345      WAV_Music *music = (WAV_Music *)context;
   1.346      Sint64 pos, stop;
   1.347      WAVLoopPoint *loop;
   1.348 -    Sint64 loop_start;
   1.349 -    Sint64 loop_stop;
   1.350 +    Sint64 loop_start = music->start;
   1.351 +    Sint64 loop_stop = music->stop;
   1.352      SDL_bool looped = SDL_FALSE;
   1.353 +    SDL_bool at_end = SDL_FALSE;
   1.354      unsigned int i;
   1.355      int filled, amount, result;
   1.356  
   1.357 @@ -216,13 +499,12 @@
   1.358      pos = SDL_RWtell(music->src);
   1.359      stop = music->stop;
   1.360      loop = NULL;
   1.361 -    loop_start = 0; /* silence warnings */
   1.362      for (i = 0; i < music->numloops; ++i) {
   1.363          loop = &music->loops[i];
   1.364          if (loop->active) {
   1.365              const int bytes_per_sample = (SDL_AUDIO_BITSIZE(music->spec.format) / 8) * music->spec.channels;
   1.366 -            loop_start = music->start + loop->start * bytes_per_sample;
   1.367 -            loop_stop = music->start + (loop->stop + 1) * bytes_per_sample;
   1.368 +            loop_start = music->start + loop->start * (Uint32)bytes_per_sample;
   1.369 +            loop_stop = music->start + (loop->stop + 1) * (Uint32)bytes_per_sample;
   1.370              if (pos >= loop_start && pos < loop_stop) {
   1.371                  stop = loop_stop;
   1.372                  break;
   1.373 @@ -231,11 +513,12 @@
   1.374          loop = NULL;
   1.375      }
   1.376  
   1.377 -    amount = music->spec.size;
   1.378 +    amount = (int)music->spec.size;
   1.379      if ((stop - pos) < amount) {
   1.380          amount = (int)(stop - pos);
   1.381      }
   1.382 -    amount = (int)SDL_RWread(music->src, music->buffer, 1, amount);
   1.383 +
   1.384 +    amount = music->decode(music, amount);
   1.385      if (amount > 0) {
   1.386          result = SDL_AudioStreamPut(music->stream, music->buffer, amount);
   1.387          if (result < 0) {
   1.388 @@ -243,6 +526,7 @@
   1.389          }
   1.390      } else {
   1.391          /* We might be looping, continue */
   1.392 +        at_end = SDL_TRUE;
   1.393      }
   1.394  
   1.395      if (loop && SDL_RWtell(music->src) >= stop) {
   1.396 @@ -257,7 +541,7 @@
   1.397          }
   1.398      }
   1.399  
   1.400 -    if (!looped && SDL_RWtell(music->src) >= music->stop) {
   1.401 +    if (!looped && (at_end || SDL_RWtell(music->src) >= music->stop)) {
   1.402          if (music->play_count == 1) {
   1.403              music->play_count = 0;
   1.404              SDL_AudioStreamFlush(music->stream);
   1.405 @@ -282,6 +566,19 @@
   1.406      return music_pcm_getaudio(context, data, bytes, music->volume, WAV_GetSome);
   1.407  }
   1.408  
   1.409 +static int WAV_Seek(void *context, double position)
   1.410 +{
   1.411 +    WAV_Music *music = (WAV_Music *)context;
   1.412 +    Sint64 sample_size = music->spec.freq * music->samplesize;
   1.413 +    Sint64 dest_offset = (Sint64)(position * (double)music->spec.freq * music->samplesize);
   1.414 +    Sint64 destpos = music->start + dest_offset;
   1.415 +    destpos -= dest_offset % sample_size;
   1.416 +    if (destpos > music->stop)
   1.417 +        return -1;
   1.418 +    SDL_RWseek(music->src, destpos, RW_SEEK_SET);
   1.419 +    return 0;
   1.420 +}
   1.421 +
   1.422  /* Close the given WAV stream */
   1.423  static void WAV_Delete(void *context)
   1.424  {
   1.425 @@ -307,7 +604,9 @@
   1.426  {
   1.427      SDL_AudioSpec *spec = &wave->spec;
   1.428      WaveFMT *format;
   1.429 +    WaveFMTex *formatEx = NULL;
   1.430      Uint8 *data;
   1.431 +    Uint16 bitsamplerate;
   1.432      SDL_bool loaded = SDL_FALSE;
   1.433  
   1.434      if (chunk_length < sizeof(*format)) {
   1.435 @@ -326,29 +625,82 @@
   1.436      }
   1.437      format = (WaveFMT *)data;
   1.438  
   1.439 +    wave->encoding = SDL_SwapLE16(format->encoding);
   1.440 +
   1.441 +    if (wave->encoding == EXT_CODE) {
   1.442 +        formatEx = (WaveFMTex*)(data + sizeof(WaveFMT));
   1.443 +        wave->encoding = (Uint16)SDL_SwapLE32(formatEx->subencoding);
   1.444 +    }
   1.445 +
   1.446      /* Decode the audio data format */
   1.447 -    switch (SDL_SwapLE16(format->encoding)) {
   1.448 +    switch (wave->encoding) {
   1.449          case PCM_CODE:
   1.450 +        case FLOAT_CODE:
   1.451              /* We can understand this */
   1.452 +            wave->decode = fetch_pcm;
   1.453 +            break;
   1.454 +        case uLAW_CODE:
   1.455 +            /* , this */
   1.456 +            wave->decode = fetch_ulaw;
   1.457 +            break;
   1.458 +        case ALAW_CODE:
   1.459 +            /* , and this */
   1.460 +            wave->decode = fetch_alaw;
   1.461              break;
   1.462          default:
   1.463 +            /* but NOT this */
   1.464              Mix_SetError("Unknown WAVE data format");
   1.465              goto done;
   1.466      }
   1.467 -    spec->freq = SDL_SwapLE32(format->frequency);
   1.468 -    switch (SDL_SwapLE16(format->bitspersample)) {
   1.469 +    spec->freq = (int)SDL_SwapLE32(format->frequency);
   1.470 +    bitsamplerate = SDL_SwapLE16(format->bitspersample);
   1.471 +    switch (bitsamplerate) {
   1.472          case 8:
   1.473 -            spec->format = AUDIO_U8;
   1.474 +            switch(wave->encoding) {
   1.475 +            case PCM_CODE:  spec->format = AUDIO_U8; break;
   1.476 +            case ALAW_CODE: spec->format = AUDIO_S16; break;
   1.477 +            case uLAW_CODE: spec->format = AUDIO_S16; break;
   1.478 +            default: goto unknown_length;
   1.479 +            }
   1.480              break;
   1.481          case 16:
   1.482 -            spec->format = AUDIO_S16;
   1.483 +            switch(wave->encoding) {
   1.484 +            case PCM_CODE: spec->format = AUDIO_S16; break;
   1.485 +            default: goto unknown_length;
   1.486 +            }
   1.487 +            break;
   1.488 +        case 24:
   1.489 +            switch(wave->encoding) {
   1.490 +            case PCM_CODE:
   1.491 +                wave->decode = fetch_pcm24le;
   1.492 +                spec->format = AUDIO_S32;
   1.493 +                break;
   1.494 +            default: goto unknown_length;
   1.495 +            }
   1.496 +        case 32:
   1.497 +            switch(wave->encoding) {
   1.498 +            case PCM_CODE:   spec->format = AUDIO_S32; break;
   1.499 +            case FLOAT_CODE: spec->format = AUDIO_F32; break;
   1.500 +            default: goto unknown_length;
   1.501 +            }
   1.502 +            break;
   1.503 +        case 64:
   1.504 +            switch(wave->encoding) {
   1.505 +            case FLOAT_CODE:
   1.506 +                wave->decode = fetch_float64le;
   1.507 +                spec->format = AUDIO_F32;
   1.508 +                break;
   1.509 +            default: goto unknown_length;
   1.510 +            }
   1.511              break;
   1.512          default:
   1.513 -            Mix_SetError("Unknown PCM data format");
   1.514 +            unknown_length:
   1.515 +            Mix_SetError("Unknown PCM data format of %d-bit length", (int)bitsamplerate);
   1.516              goto done;
   1.517      }
   1.518      spec->channels = (Uint8) SDL_SwapLE16(format->channels);
   1.519      spec->samples = 4096;       /* Good default buffer size */
   1.520 +    wave->samplesize = spec->channels * (bitsamplerate / 8);
   1.521      /* SDL_CalculateAudioSpec */
   1.522      spec->size = SDL_AUDIO_BITSIZE(spec->format) / 8;
   1.523      spec->size *= spec->channels;
   1.524 @@ -513,10 +865,15 @@
   1.525      SDL_AudioSpec *spec = &wave->spec;
   1.526      SDL_bool found_SSND = SDL_FALSE;
   1.527      SDL_bool found_COMM = SDL_FALSE;
   1.528 +    SDL_bool found_FVER = SDL_FALSE;
   1.529 +    SDL_bool is_AIFC = SDL_FALSE;
   1.530  
   1.531      Uint32 chunk_type;
   1.532      Uint32 chunk_length;
   1.533 -    Sint64 next_chunk;
   1.534 +    Sint64 next_chunk = 0;
   1.535 +    Sint64 file_length;
   1.536 +
   1.537 +    file_length = SDL_RWsize(src);
   1.538  
   1.539      /* AIFF magic header */
   1.540      Uint32 AIFFmagic;
   1.541 @@ -529,14 +886,19 @@
   1.542      Uint16 samplesize = 0;
   1.543      Uint8 sane_freq[10];
   1.544      Uint32 frequency = 0;
   1.545 +    Uint32 AIFCVersion1 = 0;
   1.546 +    Uint32 compressionType = 0;
   1.547  
   1.548      /* Check the magic header */
   1.549      chunk_length = SDL_ReadBE32(src);
   1.550      AIFFmagic = SDL_ReadLE32(src);
   1.551 -    if (AIFFmagic != AIFF) {
   1.552 -        Mix_SetError("Unrecognized file type (not AIFF)");
   1.553 +    if (AIFFmagic != AIFF && AIFFmagic != AIFC) {
   1.554 +        Mix_SetError("Unrecognized file type (not AIFF or AIFC)");
   1.555          return SDL_FALSE;
   1.556      }
   1.557 +    if (AIFFmagic == AIFC) {
   1.558 +        is_AIFC = SDL_TRUE;
   1.559 +    }
   1.560  
   1.561      /* From what I understand of the specification, chunks may appear in
   1.562       * any order, and we should just ignore unknown ones.
   1.563 @@ -549,9 +911,9 @@
   1.564          chunk_length    = SDL_ReadBE32(src);
   1.565          next_chunk      = SDL_RWtell(src) + chunk_length;
   1.566  
   1.567 -        /* Paranoia to avoid infinite loops */
   1.568 -        if (chunk_length == 0)
   1.569 -            break;
   1.570 +        if (chunk_length % 2) {
   1.571 +            next_chunk++;
   1.572 +        }
   1.573  
   1.574          switch (chunk_type) {
   1.575          case SSND:
   1.576 @@ -559,6 +921,24 @@
   1.577              offset = SDL_ReadBE32(src);
   1.578              blocksize = SDL_ReadBE32(src);
   1.579              wave->start = SDL_RWtell(src) + offset;
   1.580 +            (void)blocksize; /* unused */
   1.581 +            break;
   1.582 +
   1.583 +        case FVER:
   1.584 +            found_FVER = SDL_TRUE;
   1.585 +            AIFCVersion1 = SDL_ReadBE32(src);
   1.586 +            (void)AIFCVersion1; /* unused */
   1.587 +            break;
   1.588 +
   1.589 +        case MARK:
   1.590 +        case INST:
   1.591 +            /* Just skip those chunks */
   1.592 +            break;
   1.593 +
   1.594 +        case NAME:
   1.595 +        case AUTH:
   1.596 +        case _c__:
   1.597 +            /* Just skip those chunks */
   1.598              break;
   1.599  
   1.600          case COMM:
   1.601 @@ -570,42 +950,123 @@
   1.602              samplesize = SDL_ReadBE16(src);
   1.603              SDL_RWread(src, sane_freq, sizeof(sane_freq), 1);
   1.604              frequency = SANE_to_Uint32(sane_freq);
   1.605 +            if (is_AIFC) {
   1.606 +                compressionType = SDL_ReadLE32(src);
   1.607 +                /* here must be a "compressionName" which is a padded string */
   1.608 +            }
   1.609              break;
   1.610  
   1.611          default:
   1.612 +            /* Unknown/unsupported chunk: we just skip over */
   1.613              break;
   1.614          }
   1.615 -    } while ((!found_SSND || !found_COMM)
   1.616 -         && SDL_RWseek(src, next_chunk, RW_SEEK_SET) != -1);
   1.617 +    } while (next_chunk < file_length && SDL_RWseek(src, next_chunk, RW_SEEK_SET) != -1);
   1.618  
   1.619      if (!found_SSND) {
   1.620 -        Mix_SetError("Bad AIFF file (no SSND chunk)");
   1.621 +        Mix_SetError("Bad AIFF/AIFF-C file (no SSND chunk)");
   1.622          return SDL_FALSE;
   1.623      }
   1.624  
   1.625      if (!found_COMM) {
   1.626 -        Mix_SetError("Bad AIFF file (no COMM chunk)");
   1.627 +        Mix_SetError("Bad AIFF/AIFF-C file (no COMM chunk)");
   1.628          return SDL_FALSE;
   1.629      }
   1.630  
   1.631 +    if (is_AIFC && !found_FVER) {
   1.632 +        Mix_SetError("Bad AIFF-C file (no FVER chunk)");
   1.633 +        return SDL_FALSE;
   1.634 +    }
   1.635 +
   1.636 +
   1.637 +    wave->samplesize = channels * (samplesize / 8);
   1.638      wave->stop = wave->start + channels * numsamples * (samplesize / 8);
   1.639  
   1.640      /* Decode the audio data format */
   1.641      SDL_memset(spec, 0, (sizeof *spec));
   1.642 -    spec->freq = frequency;
   1.643 +    spec->freq = (int)frequency;
   1.644      switch (samplesize) {
   1.645      case 8:
   1.646 -        spec->format = AUDIO_S8;
   1.647 +        if (!is_AIFC)
   1.648 +            spec->format = AUDIO_S8;
   1.649 +        else switch (compressionType) {
   1.650 +        case raw_: spec->format = AUDIO_U8; break;
   1.651 +        case sowt: spec->format = AUDIO_S8; break;
   1.652 +        case ulaw:
   1.653 +            spec->format = AUDIO_S16LSB;
   1.654 +            wave->encoding = uLAW_CODE;
   1.655 +            wave->decode = fetch_ulaw;
   1.656 +            break;
   1.657 +        case alaw:
   1.658 +            spec->format = AUDIO_S16LSB;
   1.659 +            wave->encoding = ALAW_CODE;
   1.660 +            wave->decode = fetch_alaw;
   1.661 +            break;
   1.662 +        default: goto unsupported_format;
   1.663 +        }
   1.664          break;
   1.665      case 16:
   1.666 -        spec->format = AUDIO_S16MSB;
   1.667 +        if (!is_AIFC)
   1.668 +            spec->format = AUDIO_S16MSB;
   1.669 +        else switch (compressionType) {
   1.670 +        case sowt: spec->format = AUDIO_S16LSB; break;
   1.671 +        case NONE: spec->format = AUDIO_S16MSB; break;
   1.672 +        case ULAW:
   1.673 +            spec->format = AUDIO_S16LSB;
   1.674 +            wave->encoding = uLAW_CODE;
   1.675 +            wave->decode = fetch_ulaw;
   1.676 +            break;
   1.677 +        case ALAW:
   1.678 +            spec->format = AUDIO_S16LSB;
   1.679 +            wave->encoding = ALAW_CODE;
   1.680 +            wave->decode = fetch_alaw;
   1.681 +            break;
   1.682 +        default: goto unsupported_format;
   1.683 +        }
   1.684 +        break;
   1.685 +    case 24:
   1.686 +        wave->encoding = PCM_CODE;
   1.687 +        wave->decode = fetch_pcm24be;
   1.688 +        if (!is_AIFC)
   1.689 +            spec->format = AUDIO_S32MSB;
   1.690 +        else switch (compressionType) {
   1.691 +        case sowt: spec->format = AUDIO_S32LSB; break;
   1.692 +        case NONE: spec->format = AUDIO_S32MSB; break;
   1.693 +        default: goto unsupported_format;
   1.694 +        }
   1.695 +        break;
   1.696 +    case 32:
   1.697 +        if (!is_AIFC)
   1.698 +            spec->format = AUDIO_S32MSB;
   1.699 +        else switch (compressionType) {
   1.700 +        case sowt: spec->format = AUDIO_S32LSB; break;
   1.701 +        case NONE: spec->format = AUDIO_S32MSB; break;
   1.702 +        case fl32:
   1.703 +        case FL32: spec->format = AUDIO_F32MSB; break;
   1.704 +        default: goto unsupported_format;
   1.705 +        }
   1.706 +        break;
   1.707 +    case 64:
   1.708 +        wave->encoding = FLOAT_CODE;
   1.709 +        wave->decode = fetch_float64be;
   1.710 +        if (!is_AIFC)
   1.711 +            spec->format = AUDIO_F32;
   1.712 +        else switch (compressionType) {
   1.713 +        case fl64:
   1.714 +            spec->format = AUDIO_F32;
   1.715 +            break;
   1.716 +        default: goto unsupported_format;
   1.717 +        }
   1.718          break;
   1.719      default:
   1.720 +    unsupported_format:
   1.721          Mix_SetError("Unknown samplesize in data format");
   1.722          return SDL_FALSE;
   1.723      }
   1.724      spec->channels = (Uint8) channels;
   1.725      spec->samples = 4096;       /* Good default buffer size */
   1.726 +    spec->size = SDL_AUDIO_BITSIZE(spec->format) / 8;
   1.727 +    spec->size *= spec->channels;
   1.728 +    spec->size *= spec->samples;
   1.729  
   1.730      return SDL_TRUE;
   1.731  }
   1.732 @@ -626,7 +1087,7 @@
   1.733      WAV_Play,
   1.734      NULL,   /* IsPlaying */
   1.735      WAV_GetAudio,
   1.736 -    NULL,   /* Seek */
   1.737 +    WAV_Seek,   /* Seek */
   1.738      NULL,   /* Pause */
   1.739      NULL,   /* Resume */
   1.740      NULL,   /* Stop */