src/audio/SDL_wave.c

/* [<][>]
[^][v][top][bottom][index][help] */

FUNCTIONS

This source file includes following functions.
  1. NELEMS
  2. InitMS_ADPCM
  3. MS_ADPCM_nibble
  4. MS_ADPCM_decode
  5. InitIMA_ADPCM
  6. IMA_ADPCM_nibble
  7. Fill_IMA_ADPCM_block
  8. IMA_ADPCM_decode
  9. SDL_LoadWAV_RW
  10. SDL_FreeWAV
  11. ReadChunk

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

/* [<][>][^][v][top][bottom][index][help] */