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