src/audio/SDL_wave.c
author Sam Lantinga <slouken@libsdl.org>
Mon, 10 Jul 2006 21:04:37 +0000
changeset 1895 c121d94672cb
parent 1818 7995cc87b777
child 1994 6abc7e6f9817
permissions -rw-r--r--
SDL 1.2 is moving to a branch, and SDL 1.3 is becoming the head.
     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 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     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 MS_ADPCM_CODE:
   481         /* Try to understand this */
   482         if (InitMS_ADPCM(format) < 0) {
   483             was_error = 1;
   484             goto done;
   485         }
   486         MS_ADPCM_encoded = 1;
   487         break;
   488     case IMA_ADPCM_CODE:
   489         /* Try to understand this */
   490         if (InitIMA_ADPCM(format) < 0) {
   491             was_error = 1;
   492             goto done;
   493         }
   494         IMA_ADPCM_encoded = 1;
   495         break;
   496     case MP3_CODE:
   497         SDL_SetError("MPEG Layer 3 data not supported",
   498                      SDL_SwapLE16(format->encoding));
   499         was_error = 1;
   500         goto done;
   501     default:
   502         SDL_SetError("Unknown WAVE data format: 0x%.4x",
   503                      SDL_SwapLE16(format->encoding));
   504         was_error = 1;
   505         goto done;
   506     }
   507     SDL_memset(spec, 0, (sizeof *spec));
   508     spec->freq = SDL_SwapLE32(format->frequency);
   509     switch (SDL_SwapLE16(format->bitspersample)) {
   510     case 4:
   511         if (MS_ADPCM_encoded || IMA_ADPCM_encoded) {
   512             spec->format = AUDIO_S16;
   513         } else {
   514             was_error = 1;
   515         }
   516         break;
   517     case 8:
   518         spec->format = AUDIO_U8;
   519         break;
   520     case 16:
   521         spec->format = AUDIO_S16;
   522         break;
   523     default:
   524         was_error = 1;
   525         break;
   526     }
   527     if (was_error) {
   528         SDL_SetError("Unknown %d-bit PCM data format",
   529                      SDL_SwapLE16(format->bitspersample));
   530         goto done;
   531     }
   532     spec->channels = (Uint8) SDL_SwapLE16(format->channels);
   533     spec->samples = 4096;       /* Good default buffer size */
   534 
   535     /* Read the audio data chunk */
   536     *audio_buf = NULL;
   537     do {
   538         if (*audio_buf != NULL) {
   539             SDL_free(*audio_buf);
   540         }
   541         lenread = ReadChunk(src, &chunk);
   542         if (lenread < 0) {
   543             was_error = 1;
   544             goto done;
   545         }
   546         *audio_len = lenread;
   547         *audio_buf = chunk.data;
   548         if (chunk.magic != DATA)
   549             headerDiff += lenread + 2 * sizeof(Uint32);
   550     }
   551     while (chunk.magic != DATA);
   552     headerDiff += 2 * sizeof(Uint32);   /* for the data chunk and len */
   553 
   554     if (MS_ADPCM_encoded) {
   555         if (MS_ADPCM_decode(audio_buf, audio_len) < 0) {
   556             was_error = 1;
   557             goto done;
   558         }
   559     }
   560     if (IMA_ADPCM_encoded) {
   561         if (IMA_ADPCM_decode(audio_buf, audio_len) < 0) {
   562             was_error = 1;
   563             goto done;
   564         }
   565     }
   566 
   567     /* Don't return a buffer that isn't a multiple of samplesize */
   568     samplesize = ((spec->format & 0xFF) / 8) * spec->channels;
   569     *audio_len &= ~(samplesize - 1);
   570 
   571   done:
   572     if (format != NULL) {
   573         SDL_free(format);
   574     }
   575     if (src) {
   576         if (freesrc) {
   577             SDL_RWclose(src);
   578         } else {
   579             /* seek to the end of the file (given by the RIFF chunk) */
   580             SDL_RWseek(src, wavelen - chunk.length - headerDiff, RW_SEEK_CUR);
   581         }
   582     }
   583     if (was_error) {
   584         spec = NULL;
   585     }
   586     return (spec);
   587 }
   588 
   589 /* Since the WAV memory is allocated in the shared library, it must also
   590    be freed here.  (Necessary under Win32, VC++)
   591  */
   592 void
   593 SDL_FreeWAV(Uint8 * audio_buf)
   594 {
   595     if (audio_buf != NULL) {
   596         SDL_free(audio_buf);
   597     }
   598 }
   599 
   600 static int
   601 ReadChunk(SDL_RWops * src, Chunk * chunk)
   602 {
   603     chunk->magic = SDL_ReadLE32(src);
   604     chunk->length = SDL_ReadLE32(src);
   605     chunk->data = (Uint8 *) SDL_malloc(chunk->length);
   606     if (chunk->data == NULL) {
   607         SDL_Error(SDL_ENOMEM);
   608         return (-1);
   609     }
   610     if (SDL_RWread(src, chunk->data, chunk->length, 1) != 1) {
   611         SDL_Error(SDL_EFREAD);
   612         SDL_free(chunk->data);
   613         return (-1);
   614     }
   615     return (chunk->length);
   616 }
   617 
   618 /* vi: set ts=4 sw=4 expandtab: */