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