src/audio/SDL_wave.c
author Sam Lantinga <slouken@lokigames.com>
Thu, 26 Apr 2001 16:45:43 +0000
changeset 0 74212992fb08
child 171 02e27b705645
permissions -rw-r--r--
Initial revision
     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$";
    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]))
    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)
    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,
    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)
   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)
   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)
   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,
   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)
   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,
   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)
   568 {
   569 	if ( audio_buf != NULL ) {
   570 		free(audio_buf);
   571 	}
   572 }
   573 
   574 static int ReadChunk(SDL_RWops *src, Chunk *chunk)
   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 */