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