src/audio/SDL_wave.c
author Darren Alton <dalton@stevens.edu>
Tue, 10 Jun 2008 06:45:39 +0000
branchgsoc2008_nds
changeset 2669 e27bdcc80744
parent 2012 575d5c9d4db8
child 2859 99210400e8b9
permissions -rw-r--r--
First commit. Added header configs for DS as well as a Makefile. Initial work on framebuffer video driver, currently not functioning as desired.
     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     } while ((chunk.magic == FACT) || (chunk.magic == LIST));
   466 
   467     /* Decode the audio data format */
   468     format = (WaveFMT *) chunk.data;
   469     if (chunk.magic != FMT) {
   470         SDL_SetError("Complex WAVE files not supported");
   471         was_error = 1;
   472         goto done;
   473     }
   474     IEEE_float_encoded = MS_ADPCM_encoded = IMA_ADPCM_encoded = 0;
   475     switch (SDL_SwapLE16(format->encoding)) {
   476     case PCM_CODE:
   477         /* We can understand this */
   478         break;
   479     case IEEE_FLOAT_CODE:
   480         IEEE_float_encoded = 1;
   481         /* We can understand this */
   482         break;
   483     case MS_ADPCM_CODE:
   484         /* Try to understand this */
   485         if (InitMS_ADPCM(format) < 0) {
   486             was_error = 1;
   487             goto done;
   488         }
   489         MS_ADPCM_encoded = 1;
   490         break;
   491     case IMA_ADPCM_CODE:
   492         /* Try to understand this */
   493         if (InitIMA_ADPCM(format) < 0) {
   494             was_error = 1;
   495             goto done;
   496         }
   497         IMA_ADPCM_encoded = 1;
   498         break;
   499     case MP3_CODE:
   500         SDL_SetError("MPEG Layer 3 data not supported",
   501                      SDL_SwapLE16(format->encoding));
   502         was_error = 1;
   503         goto done;
   504     default:
   505         SDL_SetError("Unknown WAVE data format: 0x%.4x",
   506                      SDL_SwapLE16(format->encoding));
   507         was_error = 1;
   508         goto done;
   509     }
   510     SDL_memset(spec, 0, (sizeof *spec));
   511     spec->freq = SDL_SwapLE32(format->frequency);
   512 
   513     if (IEEE_float_encoded) {
   514         if ((SDL_SwapLE16(format->bitspersample)) != 32) {
   515             was_error = 1;
   516         } else {
   517             spec->format = AUDIO_F32;
   518         }
   519     } else {
   520         switch (SDL_SwapLE16(format->bitspersample)) {
   521         case 4:
   522             if (MS_ADPCM_encoded || IMA_ADPCM_encoded) {
   523                 spec->format = AUDIO_S16;
   524             } else {
   525                 was_error = 1;
   526             }
   527             break;
   528         case 8:
   529             spec->format = AUDIO_U8;
   530             break;
   531         case 16:
   532             spec->format = AUDIO_S16;
   533             break;
   534         case 32:
   535             spec->format = AUDIO_S32;
   536             break;
   537         default:
   538             was_error = 1;
   539             break;
   540         }
   541     }
   542 
   543     if (was_error) {
   544         SDL_SetError("Unknown %d-bit PCM data format",
   545                      SDL_SwapLE16(format->bitspersample));
   546         goto done;
   547     }
   548     spec->channels = (Uint8) SDL_SwapLE16(format->channels);
   549     spec->samples = 4096;       /* Good default buffer size */
   550 
   551     /* Read the audio data chunk */
   552     *audio_buf = NULL;
   553     do {
   554         if (*audio_buf != NULL) {
   555             SDL_free(*audio_buf);
   556         }
   557         lenread = ReadChunk(src, &chunk);
   558         if (lenread < 0) {
   559             was_error = 1;
   560             goto done;
   561         }
   562         *audio_len = lenread;
   563         *audio_buf = chunk.data;
   564         if (chunk.magic != DATA)
   565             headerDiff += lenread + 2 * sizeof(Uint32);
   566     } while (chunk.magic != DATA);
   567     headerDiff += 2 * sizeof(Uint32);   /* for the data chunk and len */
   568 
   569     if (MS_ADPCM_encoded) {
   570         if (MS_ADPCM_decode(audio_buf, audio_len) < 0) {
   571             was_error = 1;
   572             goto done;
   573         }
   574     }
   575     if (IMA_ADPCM_encoded) {
   576         if (IMA_ADPCM_decode(audio_buf, audio_len) < 0) {
   577             was_error = 1;
   578             goto done;
   579         }
   580     }
   581 
   582     /* Don't return a buffer that isn't a multiple of samplesize */
   583     samplesize = ((SDL_AUDIO_BITSIZE(spec->format)) / 8) * spec->channels;
   584     *audio_len &= ~(samplesize - 1);
   585 
   586   done:
   587     if (format != NULL) {
   588         SDL_free(format);
   589     }
   590     if (src) {
   591         if (freesrc) {
   592             SDL_RWclose(src);
   593         } else {
   594             /* seek to the end of the file (given by the RIFF chunk) */
   595             SDL_RWseek(src, wavelen - chunk.length - headerDiff, RW_SEEK_CUR);
   596         }
   597     }
   598     if (was_error) {
   599         spec = NULL;
   600     }
   601     return (spec);
   602 }
   603 
   604 /* Since the WAV memory is allocated in the shared library, it must also
   605    be freed here.  (Necessary under Win32, VC++)
   606  */
   607 void
   608 SDL_FreeWAV(Uint8 * audio_buf)
   609 {
   610     if (audio_buf != NULL) {
   611         SDL_free(audio_buf);
   612     }
   613 }
   614 
   615 static int
   616 ReadChunk(SDL_RWops * src, Chunk * chunk)
   617 {
   618     chunk->magic = SDL_ReadLE32(src);
   619     chunk->length = SDL_ReadLE32(src);
   620     chunk->data = (Uint8 *) SDL_malloc(chunk->length);
   621     if (chunk->data == NULL) {
   622         SDL_Error(SDL_ENOMEM);
   623         return (-1);
   624     }
   625     if (SDL_RWread(src, chunk->data, chunk->length, 1) != 1) {
   626         SDL_Error(SDL_EFREAD);
   627         SDL_free(chunk->data);
   628         return (-1);
   629     }
   630     return (chunk->length);
   631 }
   632 
   633 /* vi: set ts=4 sw=4 expandtab: */