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