src/audio/SDL_wave.c
author Sam Lantinga
Sat, 31 Dec 2011 09:28:07 -0500
changeset 6138 4c64952a58fb
parent 5535 96594ac5fd1a
child 6389 43a190ad60a7
permissions -rwxr-xr-x
Happy New Year!
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
     4 
     5   This software is provided 'as-is', without any express or implied
     6   warranty.  In no event will the authors be held liable for any damages
     7   arising from the use of this software.
     8 
     9   Permission is granted to anyone to use this software for any purpose,
    10   including commercial applications, and to alter it and redistribute it
    11   freely, subject to the following restrictions:
    12 
    13   1. The origin of this software must not be misrepresented; you must not
    14      claim that you wrote the original software. If you use this software
    15      in a product, an acknowledgment in the product documentation would be
    16      appreciated but is not required.
    17   2. Altered source versions must be plainly marked as such, and must not be
    18      misrepresented as being the original software.
    19   3. This notice may not be removed or altered from any source distribution.
    20 */
    21 #include "SDL_config.h"
    22 
    23 /* Microsoft WAVE file loading routines */
    24 
    25 #include "SDL_audio.h"
    26 #include "SDL_wave.h"
    27 
    28 
    29 static int ReadChunk(SDL_RWops * src, Chunk * chunk);
    30 
    31 struct MS_ADPCM_decodestate
    32 {
    33     Uint8 hPredictor;
    34     Uint16 iDelta;
    35     Sint16 iSamp1;
    36     Sint16 iSamp2;
    37 };
    38 static struct MS_ADPCM_decoder
    39 {
    40     WaveFMT wavefmt;
    41     Uint16 wSamplesPerBlock;
    42     Uint16 wNumCoef;
    43     Sint16 aCoeff[7][2];
    44     /* * * */
    45     struct MS_ADPCM_decodestate state[2];
    46 } MS_ADPCM_state;
    47 
    48 static int
    49 InitMS_ADPCM(WaveFMT * format)
    50 {
    51     Uint8 *rogue_feel;
    52     Uint16 extra_info;
    53     int i;
    54 
    55     /* Set the rogue pointer to the MS_ADPCM specific data */
    56     MS_ADPCM_state.wavefmt.encoding = SDL_SwapLE16(format->encoding);
    57     MS_ADPCM_state.wavefmt.channels = SDL_SwapLE16(format->channels);
    58     MS_ADPCM_state.wavefmt.frequency = SDL_SwapLE32(format->frequency);
    59     MS_ADPCM_state.wavefmt.byterate = SDL_SwapLE32(format->byterate);
    60     MS_ADPCM_state.wavefmt.blockalign = SDL_SwapLE16(format->blockalign);
    61     MS_ADPCM_state.wavefmt.bitspersample =
    62         SDL_SwapLE16(format->bitspersample);
    63     rogue_feel = (Uint8 *) format + sizeof(*format);
    64     if (sizeof(*format) == 16) {
    65         extra_info = ((rogue_feel[1] << 8) | rogue_feel[0]);
    66         rogue_feel += sizeof(Uint16);
    67     }
    68     MS_ADPCM_state.wSamplesPerBlock = ((rogue_feel[1] << 8) | rogue_feel[0]);
    69     rogue_feel += sizeof(Uint16);
    70     MS_ADPCM_state.wNumCoef = ((rogue_feel[1] << 8) | rogue_feel[0]);
    71     rogue_feel += sizeof(Uint16);
    72     if (MS_ADPCM_state.wNumCoef != 7) {
    73         SDL_SetError("Unknown set of MS_ADPCM coefficients");
    74         return (-1);
    75     }
    76     for (i = 0; i < MS_ADPCM_state.wNumCoef; ++i) {
    77         MS_ADPCM_state.aCoeff[i][0] = ((rogue_feel[1] << 8) | rogue_feel[0]);
    78         rogue_feel += sizeof(Uint16);
    79         MS_ADPCM_state.aCoeff[i][1] = ((rogue_feel[1] << 8) | rogue_feel[0]);
    80         rogue_feel += sizeof(Uint16);
    81     }
    82     return (0);
    83 }
    84 
    85 static Sint32
    86 MS_ADPCM_nibble(struct MS_ADPCM_decodestate *state,
    87                 Uint8 nybble, Sint16 * coeff)
    88 {
    89     const Sint32 max_audioval = ((1 << (16 - 1)) - 1);
    90     const Sint32 min_audioval = -(1 << (16 - 1));
    91     const Sint32 adaptive[] = {
    92         230, 230, 230, 230, 307, 409, 512, 614,
    93         768, 614, 512, 409, 307, 230, 230, 230
    94     };
    95     Sint32 new_sample, delta;
    96 
    97     new_sample = ((state->iSamp1 * coeff[0]) +
    98                   (state->iSamp2 * coeff[1])) / 256;
    99     if (nybble & 0x08) {
   100         new_sample += state->iDelta * (nybble - 0x10);
   101     } else {
   102         new_sample += state->iDelta * nybble;
   103     }
   104     if (new_sample < min_audioval) {
   105         new_sample = min_audioval;
   106     } else if (new_sample > max_audioval) {
   107         new_sample = max_audioval;
   108     }
   109     delta = ((Sint32) state->iDelta * adaptive[nybble]) / 256;
   110     if (delta < 16) {
   111         delta = 16;
   112     }
   113     state->iDelta = (Uint16) delta;
   114     state->iSamp2 = state->iSamp1;
   115     state->iSamp1 = (Sint16) new_sample;
   116     return (new_sample);
   117 }
   118 
   119 static int
   120 MS_ADPCM_decode(Uint8 ** audio_buf, Uint32 * audio_len)
   121 {
   122     struct MS_ADPCM_decodestate *state[2];
   123     Uint8 *freeable, *encoded, *decoded;
   124     Sint32 encoded_len, samplesleft;
   125     Sint8 nybble, stereo;
   126     Sint16 *coeff[2];
   127     Sint32 new_sample;
   128 
   129     /* Allocate the proper sized output buffer */
   130     encoded_len = *audio_len;
   131     encoded = *audio_buf;
   132     freeable = *audio_buf;
   133     *audio_len = (encoded_len / MS_ADPCM_state.wavefmt.blockalign) *
   134         MS_ADPCM_state.wSamplesPerBlock *
   135         MS_ADPCM_state.wavefmt.channels * sizeof(Sint16);
   136     *audio_buf = (Uint8 *) SDL_malloc(*audio_len);
   137     if (*audio_buf == NULL) {
   138         SDL_Error(SDL_ENOMEM);
   139         return (-1);
   140     }
   141     decoded = *audio_buf;
   142 
   143     /* Get ready... Go! */
   144     stereo = (MS_ADPCM_state.wavefmt.channels == 2);
   145     state[0] = &MS_ADPCM_state.state[0];
   146     state[1] = &MS_ADPCM_state.state[stereo];
   147     while (encoded_len >= MS_ADPCM_state.wavefmt.blockalign) {
   148         /* Grab the initial information for this block */
   149         state[0]->hPredictor = *encoded++;
   150         if (stereo) {
   151             state[1]->hPredictor = *encoded++;
   152         }
   153         state[0]->iDelta = ((encoded[1] << 8) | encoded[0]);
   154         encoded += sizeof(Sint16);
   155         if (stereo) {
   156             state[1]->iDelta = ((encoded[1] << 8) | encoded[0]);
   157             encoded += sizeof(Sint16);
   158         }
   159         state[0]->iSamp1 = ((encoded[1] << 8) | encoded[0]);
   160         encoded += sizeof(Sint16);
   161         if (stereo) {
   162             state[1]->iSamp1 = ((encoded[1] << 8) | encoded[0]);
   163             encoded += sizeof(Sint16);
   164         }
   165         state[0]->iSamp2 = ((encoded[1] << 8) | encoded[0]);
   166         encoded += sizeof(Sint16);
   167         if (stereo) {
   168             state[1]->iSamp2 = ((encoded[1] << 8) | encoded[0]);
   169             encoded += sizeof(Sint16);
   170         }
   171         coeff[0] = MS_ADPCM_state.aCoeff[state[0]->hPredictor];
   172         coeff[1] = MS_ADPCM_state.aCoeff[state[1]->hPredictor];
   173 
   174         /* Store the two initial samples we start with */
   175         decoded[0] = state[0]->iSamp2 & 0xFF;
   176         decoded[1] = state[0]->iSamp2 >> 8;
   177         decoded += 2;
   178         if (stereo) {
   179             decoded[0] = state[1]->iSamp2 & 0xFF;
   180             decoded[1] = state[1]->iSamp2 >> 8;
   181             decoded += 2;
   182         }
   183         decoded[0] = state[0]->iSamp1 & 0xFF;
   184         decoded[1] = state[0]->iSamp1 >> 8;
   185         decoded += 2;
   186         if (stereo) {
   187             decoded[0] = state[1]->iSamp1 & 0xFF;
   188             decoded[1] = state[1]->iSamp1 >> 8;
   189             decoded += 2;
   190         }
   191 
   192         /* Decode and store the other samples in this block */
   193         samplesleft = (MS_ADPCM_state.wSamplesPerBlock - 2) *
   194             MS_ADPCM_state.wavefmt.channels;
   195         while (samplesleft > 0) {
   196             nybble = (*encoded) >> 4;
   197             new_sample = MS_ADPCM_nibble(state[0], nybble, coeff[0]);
   198             decoded[0] = new_sample & 0xFF;
   199             new_sample >>= 8;
   200             decoded[1] = new_sample & 0xFF;
   201             decoded += 2;
   202 
   203             nybble = (*encoded) & 0x0F;
   204             new_sample = MS_ADPCM_nibble(state[1], nybble, coeff[1]);
   205             decoded[0] = new_sample & 0xFF;
   206             new_sample >>= 8;
   207             decoded[1] = new_sample & 0xFF;
   208             decoded += 2;
   209 
   210             ++encoded;
   211             samplesleft -= 2;
   212         }
   213         encoded_len -= MS_ADPCM_state.wavefmt.blockalign;
   214     }
   215     SDL_free(freeable);
   216     return (0);
   217 }
   218 
   219 struct IMA_ADPCM_decodestate
   220 {
   221     Sint32 sample;
   222     Sint8 index;
   223 };
   224 static struct IMA_ADPCM_decoder
   225 {
   226     WaveFMT wavefmt;
   227     Uint16 wSamplesPerBlock;
   228     /* * * */
   229     struct IMA_ADPCM_decodestate state[2];
   230 } IMA_ADPCM_state;
   231 
   232 static int
   233 InitIMA_ADPCM(WaveFMT * format)
   234 {
   235     Uint8 *rogue_feel;
   236     Uint16 extra_info;
   237 
   238     /* Set the rogue pointer to the IMA_ADPCM specific data */
   239     IMA_ADPCM_state.wavefmt.encoding = SDL_SwapLE16(format->encoding);
   240     IMA_ADPCM_state.wavefmt.channels = SDL_SwapLE16(format->channels);
   241     IMA_ADPCM_state.wavefmt.frequency = SDL_SwapLE32(format->frequency);
   242     IMA_ADPCM_state.wavefmt.byterate = SDL_SwapLE32(format->byterate);
   243     IMA_ADPCM_state.wavefmt.blockalign = SDL_SwapLE16(format->blockalign);
   244     IMA_ADPCM_state.wavefmt.bitspersample =
   245         SDL_SwapLE16(format->bitspersample);
   246     rogue_feel = (Uint8 *) format + sizeof(*format);
   247     if (sizeof(*format) == 16) {
   248         extra_info = ((rogue_feel[1] << 8) | rogue_feel[0]);
   249         rogue_feel += sizeof(Uint16);
   250     }
   251     IMA_ADPCM_state.wSamplesPerBlock = ((rogue_feel[1] << 8) | rogue_feel[0]);
   252     return (0);
   253 }
   254 
   255 static Sint32
   256 IMA_ADPCM_nibble(struct IMA_ADPCM_decodestate *state, Uint8 nybble)
   257 {
   258     const Sint32 max_audioval = ((1 << (16 - 1)) - 1);
   259     const Sint32 min_audioval = -(1 << (16 - 1));
   260     const int index_table[16] = {
   261         -1, -1, -1, -1,
   262         2, 4, 6, 8,
   263         -1, -1, -1, -1,
   264         2, 4, 6, 8
   265     };
   266     const Sint32 step_table[89] = {
   267         7, 8, 9, 10, 11, 12, 13, 14, 16, 17, 19, 21, 23, 25, 28, 31,
   268         34, 37, 41, 45, 50, 55, 60, 66, 73, 80, 88, 97, 107, 118, 130,
   269         143, 157, 173, 190, 209, 230, 253, 279, 307, 337, 371, 408,
   270         449, 494, 544, 598, 658, 724, 796, 876, 963, 1060, 1166, 1282,
   271         1411, 1552, 1707, 1878, 2066, 2272, 2499, 2749, 3024, 3327,
   272         3660, 4026, 4428, 4871, 5358, 5894, 6484, 7132, 7845, 8630,
   273         9493, 10442, 11487, 12635, 13899, 15289, 16818, 18500, 20350,
   274         22385, 24623, 27086, 29794, 32767
   275     };
   276     Sint32 delta, step;
   277 
   278     /* Compute difference and new sample value */
   279     step = step_table[state->index];
   280     delta = step >> 3;
   281     if (nybble & 0x04)
   282         delta += step;
   283     if (nybble & 0x02)
   284         delta += (step >> 1);
   285     if (nybble & 0x01)
   286         delta += (step >> 2);
   287     if (nybble & 0x08)
   288         delta = -delta;
   289     state->sample += delta;
   290 
   291     /* Update index value */
   292     state->index += index_table[nybble];
   293     if (state->index > 88) {
   294         state->index = 88;
   295     } else if (state->index < 0) {
   296         state->index = 0;
   297     }
   298 
   299     /* Clamp output sample */
   300     if (state->sample > max_audioval) {
   301         state->sample = max_audioval;
   302     } else if (state->sample < min_audioval) {
   303         state->sample = min_audioval;
   304     }
   305     return (state->sample);
   306 }
   307 
   308 /* Fill the decode buffer with a channel block of data (8 samples) */
   309 static void
   310 Fill_IMA_ADPCM_block(Uint8 * decoded, Uint8 * encoded,
   311                      int channel, int numchannels,
   312                      struct IMA_ADPCM_decodestate *state)
   313 {
   314     int i;
   315     Sint8 nybble;
   316     Sint32 new_sample;
   317 
   318     decoded += (channel * 2);
   319     for (i = 0; i < 4; ++i) {
   320         nybble = (*encoded) & 0x0F;
   321         new_sample = IMA_ADPCM_nibble(state, nybble);
   322         decoded[0] = new_sample & 0xFF;
   323         new_sample >>= 8;
   324         decoded[1] = new_sample & 0xFF;
   325         decoded += 2 * numchannels;
   326 
   327         nybble = (*encoded) >> 4;
   328         new_sample = IMA_ADPCM_nibble(state, nybble);
   329         decoded[0] = new_sample & 0xFF;
   330         new_sample >>= 8;
   331         decoded[1] = new_sample & 0xFF;
   332         decoded += 2 * numchannels;
   333 
   334         ++encoded;
   335     }
   336 }
   337 
   338 static int
   339 IMA_ADPCM_decode(Uint8 ** audio_buf, Uint32 * audio_len)
   340 {
   341     struct IMA_ADPCM_decodestate *state;
   342     Uint8 *freeable, *encoded, *decoded;
   343     Sint32 encoded_len, samplesleft;
   344     unsigned int c, channels;
   345 
   346     /* Check to make sure we have enough variables in the state array */
   347     channels = IMA_ADPCM_state.wavefmt.channels;
   348     if (channels > SDL_arraysize(IMA_ADPCM_state.state)) {
   349         SDL_SetError("IMA ADPCM decoder can only handle %d channels",
   350                      SDL_arraysize(IMA_ADPCM_state.state));
   351         return (-1);
   352     }
   353     state = IMA_ADPCM_state.state;
   354 
   355     /* Allocate the proper sized output buffer */
   356     encoded_len = *audio_len;
   357     encoded = *audio_buf;
   358     freeable = *audio_buf;
   359     *audio_len = (encoded_len / IMA_ADPCM_state.wavefmt.blockalign) *
   360         IMA_ADPCM_state.wSamplesPerBlock *
   361         IMA_ADPCM_state.wavefmt.channels * sizeof(Sint16);
   362     *audio_buf = (Uint8 *) SDL_malloc(*audio_len);
   363     if (*audio_buf == NULL) {
   364         SDL_Error(SDL_ENOMEM);
   365         return (-1);
   366     }
   367     decoded = *audio_buf;
   368 
   369     /* Get ready... Go! */
   370     while (encoded_len >= IMA_ADPCM_state.wavefmt.blockalign) {
   371         /* Grab the initial information for this block */
   372         for (c = 0; c < channels; ++c) {
   373             /* Fill the state information for this block */
   374             state[c].sample = ((encoded[1] << 8) | encoded[0]);
   375             encoded += 2;
   376             if (state[c].sample & 0x8000) {
   377                 state[c].sample -= 0x10000;
   378             }
   379             state[c].index = *encoded++;
   380             /* Reserved byte in buffer header, should be 0 */
   381             if (*encoded++ != 0) {
   382                 /* Uh oh, corrupt data?  Buggy code? */ ;
   383             }
   384 
   385             /* Store the initial sample we start with */
   386             decoded[0] = (Uint8) (state[c].sample & 0xFF);
   387             decoded[1] = (Uint8) (state[c].sample >> 8);
   388             decoded += 2;
   389         }
   390 
   391         /* Decode and store the other samples in this block */
   392         samplesleft = (IMA_ADPCM_state.wSamplesPerBlock - 1) * channels;
   393         while (samplesleft > 0) {
   394             for (c = 0; c < channels; ++c) {
   395                 Fill_IMA_ADPCM_block(decoded, encoded,
   396                                      c, channels, &state[c]);
   397                 encoded += 4;
   398                 samplesleft -= 8;
   399             }
   400             decoded += (channels * 8 * 2);
   401         }
   402         encoded_len -= IMA_ADPCM_state.wavefmt.blockalign;
   403     }
   404     SDL_free(freeable);
   405     return (0);
   406 }
   407 
   408 SDL_AudioSpec *
   409 SDL_LoadWAV_RW(SDL_RWops * src, int freesrc,
   410                SDL_AudioSpec * spec, Uint8 ** audio_buf, Uint32 * audio_len)
   411 {
   412     int was_error;
   413     Chunk chunk;
   414     int lenread;
   415     int IEEE_float_encoded, MS_ADPCM_encoded, IMA_ADPCM_encoded;
   416     int samplesize;
   417 
   418     /* WAV magic header */
   419     Uint32 RIFFchunk;
   420     Uint32 wavelen = 0;
   421     Uint32 WAVEmagic;
   422     Uint32 headerDiff = 0;
   423 
   424     /* FMT chunk */
   425     WaveFMT *format = NULL;
   426 
   427     /* Make sure we are passed a valid data source */
   428     was_error = 0;
   429     if (src == NULL) {
   430         was_error = 1;
   431         goto done;
   432     }
   433 
   434     /* Check the magic header */
   435     RIFFchunk = SDL_ReadLE32(src);
   436     wavelen = SDL_ReadLE32(src);
   437     if (wavelen == WAVE) {      /* The RIFFchunk has already been read */
   438         WAVEmagic = wavelen;
   439         wavelen = RIFFchunk;
   440         RIFFchunk = RIFF;
   441     } else {
   442         WAVEmagic = SDL_ReadLE32(src);
   443     }
   444     if ((RIFFchunk != RIFF) || (WAVEmagic != WAVE)) {
   445         SDL_SetError("Unrecognized file type (not WAVE)");
   446         was_error = 1;
   447         goto done;
   448     }
   449     headerDiff += sizeof(Uint32);       /* for WAVE */
   450 
   451     /* Read the audio data format chunk */
   452     chunk.data = NULL;
   453     do {
   454         if (chunk.data != NULL) {
   455             SDL_free(chunk.data);
   456             chunk.data = NULL;
   457         }
   458         lenread = ReadChunk(src, &chunk);
   459         if (lenread < 0) {
   460             was_error = 1;
   461             goto done;
   462         }
   463         /* 2 Uint32's for chunk header+len, plus the lenread */
   464         headerDiff += lenread + 2 * sizeof(Uint32);
   465     } while ((chunk.magic == FACT) || (chunk.magic == LIST));
   466 
   467     /* Decode the audio data format */
   468     format = (WaveFMT *) chunk.data;
   469     if (chunk.magic != FMT) {
   470         SDL_SetError("Complex WAVE files not supported");
   471         was_error = 1;
   472         goto done;
   473     }
   474     IEEE_float_encoded = MS_ADPCM_encoded = IMA_ADPCM_encoded = 0;
   475     switch (SDL_SwapLE16(format->encoding)) {
   476     case PCM_CODE:
   477         /* We can understand this */
   478         break;
   479     case IEEE_FLOAT_CODE:
   480         IEEE_float_encoded = 1;
   481         /* We can understand this */
   482         break;
   483     case MS_ADPCM_CODE:
   484         /* Try to understand this */
   485         if (InitMS_ADPCM(format) < 0) {
   486             was_error = 1;
   487             goto done;
   488         }
   489         MS_ADPCM_encoded = 1;
   490         break;
   491     case IMA_ADPCM_CODE:
   492         /* Try to understand this */
   493         if (InitIMA_ADPCM(format) < 0) {
   494             was_error = 1;
   495             goto done;
   496         }
   497         IMA_ADPCM_encoded = 1;
   498         break;
   499     case MP3_CODE:
   500         SDL_SetError("MPEG Layer 3 data not supported",
   501                      SDL_SwapLE16(format->encoding));
   502         was_error = 1;
   503         goto done;
   504     default:
   505         SDL_SetError("Unknown WAVE data format: 0x%.4x",
   506                      SDL_SwapLE16(format->encoding));
   507         was_error = 1;
   508         goto done;
   509     }
   510     SDL_memset(spec, 0, (sizeof *spec));
   511     spec->freq = SDL_SwapLE32(format->frequency);
   512 
   513     if (IEEE_float_encoded) {
   514         if ((SDL_SwapLE16(format->bitspersample)) != 32) {
   515             was_error = 1;
   516         } else {
   517             spec->format = AUDIO_F32;
   518         }
   519     } else {
   520         switch (SDL_SwapLE16(format->bitspersample)) {
   521         case 4:
   522             if (MS_ADPCM_encoded || IMA_ADPCM_encoded) {
   523                 spec->format = AUDIO_S16;
   524             } else {
   525                 was_error = 1;
   526             }
   527             break;
   528         case 8:
   529             spec->format = AUDIO_U8;
   530             break;
   531         case 16:
   532             spec->format = AUDIO_S16;
   533             break;
   534         case 32:
   535             spec->format = AUDIO_S32;
   536             break;
   537         default:
   538             was_error = 1;
   539             break;
   540         }
   541     }
   542 
   543     if (was_error) {
   544         SDL_SetError("Unknown %d-bit PCM data format",
   545                      SDL_SwapLE16(format->bitspersample));
   546         goto done;
   547     }
   548     spec->channels = (Uint8) SDL_SwapLE16(format->channels);
   549     spec->samples = 4096;       /* Good default buffer size */
   550 
   551     /* Read the audio data chunk */
   552     *audio_buf = NULL;
   553     do {
   554         if (*audio_buf != NULL) {
   555             SDL_free(*audio_buf);
   556             *audio_buf = NULL;
   557         }
   558         lenread = ReadChunk(src, &chunk);
   559         if (lenread < 0) {
   560             was_error = 1;
   561             goto done;
   562         }
   563         *audio_len = lenread;
   564         *audio_buf = chunk.data;
   565         if (chunk.magic != DATA)
   566             headerDiff += lenread + 2 * sizeof(Uint32);
   567     } while (chunk.magic != DATA);
   568     headerDiff += 2 * sizeof(Uint32);   /* for the data chunk and len */
   569 
   570     if (MS_ADPCM_encoded) {
   571         if (MS_ADPCM_decode(audio_buf, audio_len) < 0) {
   572             was_error = 1;
   573             goto done;
   574         }
   575     }
   576     if (IMA_ADPCM_encoded) {
   577         if (IMA_ADPCM_decode(audio_buf, audio_len) < 0) {
   578             was_error = 1;
   579             goto done;
   580         }
   581     }
   582 
   583     /* Don't return a buffer that isn't a multiple of samplesize */
   584     samplesize = ((SDL_AUDIO_BITSIZE(spec->format)) / 8) * spec->channels;
   585     *audio_len &= ~(samplesize - 1);
   586 
   587   done:
   588     if (format != NULL) {
   589         SDL_free(format);
   590     }
   591     if (src) {
   592         if (freesrc) {
   593             SDL_RWclose(src);
   594         } else {
   595             /* seek to the end of the file (given by the RIFF chunk) */
   596             SDL_RWseek(src, wavelen - chunk.length - headerDiff, RW_SEEK_CUR);
   597         }
   598     }
   599     if (was_error) {
   600         spec = NULL;
   601     }
   602     return (spec);
   603 }
   604 
   605 /* Since the WAV memory is allocated in the shared library, it must also
   606    be freed here.  (Necessary under Win32, VC++)
   607  */
   608 void
   609 SDL_FreeWAV(Uint8 * audio_buf)
   610 {
   611     if (audio_buf != NULL) {
   612         SDL_free(audio_buf);
   613     }
   614 }
   615 
   616 static int
   617 ReadChunk(SDL_RWops * src, Chunk * chunk)
   618 {
   619     chunk->magic = SDL_ReadLE32(src);
   620     chunk->length = SDL_ReadLE32(src);
   621     chunk->data = (Uint8 *) SDL_malloc(chunk->length);
   622     if (chunk->data == NULL) {
   623         SDL_Error(SDL_ENOMEM);
   624         return (-1);
   625     }
   626     if (SDL_RWread(src, chunk->data, chunk->length, 1) != 1) {
   627         SDL_Error(SDL_EFREAD);
   628         SDL_free(chunk->data);
   629         chunk->data = NULL;
   630         return (-1);
   631     }
   632     return (chunk->length);
   633 }
   634 
   635 /* vi: set ts=4 sw=4 expandtab: */