src/audio/SDL_wave.c
changeset 0 74212992fb08
child 171 02e27b705645
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/audio/SDL_wave.c	Thu Apr 26 16:45:43 2001 +0000
     1.3 @@ -0,0 +1,591 @@
     1.4 +/*
     1.5 +    SDL - Simple DirectMedia Layer
     1.6 +    Copyright (C) 1997, 1998, 1999, 2000, 2001  Sam Lantinga
     1.7 +
     1.8 +    This library is free software; you can redistribute it and/or
     1.9 +    modify it under the terms of the GNU Library General Public
    1.10 +    License as published by the Free Software Foundation; either
    1.11 +    version 2 of the License, or (at your option) any later version.
    1.12 +
    1.13 +    This library is distributed in the hope that it will be useful,
    1.14 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
    1.15 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    1.16 +    Library General Public License for more details.
    1.17 +
    1.18 +    You should have received a copy of the GNU Library General Public
    1.19 +    License along with this library; if not, write to the Free
    1.20 +    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    1.21 +
    1.22 +    Sam Lantinga
    1.23 +    slouken@devolution.com
    1.24 +*/
    1.25 +
    1.26 +#ifdef SAVE_RCSID
    1.27 +static char rcsid =
    1.28 + "@(#) $Id$";
    1.29 +#endif
    1.30 +
    1.31 +#ifndef DISABLE_FILE
    1.32 +
    1.33 +/* Microsoft WAVE file loading routines */
    1.34 +
    1.35 +#include <stdlib.h>
    1.36 +#include <string.h>
    1.37 +
    1.38 +#include "SDL_error.h"
    1.39 +#include "SDL_audio.h"
    1.40 +#include "SDL_wave.h"
    1.41 +#include "SDL_endian.h"
    1.42 +
    1.43 +#ifndef NELEMS
    1.44 +#define NELEMS(array)	((sizeof array)/(sizeof array[0]))
    1.45 +#endif
    1.46 +
    1.47 +static int ReadChunk(SDL_RWops *src, Chunk *chunk);
    1.48 +
    1.49 +struct MS_ADPCM_decodestate {
    1.50 +	Uint8 hPredictor;
    1.51 +	Uint16 iDelta;
    1.52 +	Sint16 iSamp1;
    1.53 +	Sint16 iSamp2;
    1.54 +};
    1.55 +static struct MS_ADPCM_decoder {
    1.56 +	WaveFMT wavefmt;
    1.57 +	Uint16 wSamplesPerBlock;
    1.58 +	Uint16 wNumCoef;
    1.59 +	Sint16 aCoeff[7][2];
    1.60 +	/* * * */
    1.61 +	struct MS_ADPCM_decodestate state[2];
    1.62 +} MS_ADPCM_state;
    1.63 +
    1.64 +static int InitMS_ADPCM(WaveFMT *format)
    1.65 +{
    1.66 +	Uint8 *rogue_feel;
    1.67 +	Uint16 extra_info;
    1.68 +	int i;
    1.69 +
    1.70 +	/* Set the rogue pointer to the MS_ADPCM specific data */
    1.71 +	MS_ADPCM_state.wavefmt.encoding = SDL_SwapLE16(format->encoding);
    1.72 +	MS_ADPCM_state.wavefmt.channels = SDL_SwapLE16(format->channels);
    1.73 +	MS_ADPCM_state.wavefmt.frequency = SDL_SwapLE32(format->frequency);
    1.74 +	MS_ADPCM_state.wavefmt.byterate = SDL_SwapLE32(format->byterate);
    1.75 +	MS_ADPCM_state.wavefmt.blockalign = SDL_SwapLE16(format->blockalign);
    1.76 +	MS_ADPCM_state.wavefmt.bitspersample =
    1.77 +					 SDL_SwapLE16(format->bitspersample);
    1.78 +	rogue_feel = (Uint8 *)format+sizeof(*format);
    1.79 +	if ( sizeof(*format) == 16 ) {
    1.80 +		extra_info = ((rogue_feel[1]<<8)|rogue_feel[0]);
    1.81 +		rogue_feel += sizeof(Uint16);
    1.82 +	}
    1.83 +	MS_ADPCM_state.wSamplesPerBlock = ((rogue_feel[1]<<8)|rogue_feel[0]);
    1.84 +	rogue_feel += sizeof(Uint16);
    1.85 +	MS_ADPCM_state.wNumCoef = ((rogue_feel[1]<<8)|rogue_feel[0]);
    1.86 +	rogue_feel += sizeof(Uint16);
    1.87 +	if ( MS_ADPCM_state.wNumCoef != 7 ) {
    1.88 +		SDL_SetError("Unknown set of MS_ADPCM coefficients");
    1.89 +		return(-1);
    1.90 +	}
    1.91 +	for ( i=0; i<MS_ADPCM_state.wNumCoef; ++i ) {
    1.92 +		MS_ADPCM_state.aCoeff[i][0] = ((rogue_feel[1]<<8)|rogue_feel[0]);
    1.93 +		rogue_feel += sizeof(Uint16);
    1.94 +		MS_ADPCM_state.aCoeff[i][1] = ((rogue_feel[1]<<8)|rogue_feel[0]);
    1.95 +		rogue_feel += sizeof(Uint16);
    1.96 +	}
    1.97 +	return(0);
    1.98 +}
    1.99 +
   1.100 +static Sint32 MS_ADPCM_nibble(struct MS_ADPCM_decodestate *state,
   1.101 +					Uint8 nybble, Sint16 *coeff)
   1.102 +{
   1.103 +	const Sint32 max_audioval = ((1<<(16-1))-1);
   1.104 +	const Sint32 min_audioval = -(1<<(16-1));
   1.105 +	const Sint32 adaptive[] = {
   1.106 +		230, 230, 230, 230, 307, 409, 512, 614,
   1.107 +		768, 614, 512, 409, 307, 230, 230, 230
   1.108 +	};
   1.109 +	Sint32 new_sample, delta;
   1.110 +
   1.111 +	new_sample = ((state->iSamp1 * coeff[0]) +
   1.112 +		      (state->iSamp2 * coeff[1]))/256;
   1.113 +	if ( nybble & 0x08 ) {
   1.114 +		new_sample += state->iDelta * (nybble-0x10);
   1.115 +	} else {
   1.116 +		new_sample += state->iDelta * nybble;
   1.117 +	}
   1.118 +	if ( new_sample < min_audioval ) {
   1.119 +		new_sample = min_audioval;
   1.120 +	} else
   1.121 +	if ( new_sample > max_audioval ) {
   1.122 +		new_sample = max_audioval;
   1.123 +	}
   1.124 +	delta = ((Sint32)state->iDelta * adaptive[nybble])/256;
   1.125 +	if ( delta < 16 ) {
   1.126 +		delta = 16;
   1.127 +	}
   1.128 +	state->iDelta = delta;
   1.129 +	state->iSamp2 = state->iSamp1;
   1.130 +	state->iSamp1 = new_sample;
   1.131 +	return(new_sample);
   1.132 +}
   1.133 +
   1.134 +static int MS_ADPCM_decode(Uint8 **audio_buf, Uint32 *audio_len)
   1.135 +{
   1.136 +	struct MS_ADPCM_decodestate *state[2];
   1.137 +	Uint8 *freeable, *encoded, *decoded;
   1.138 +	Sint32 encoded_len, samplesleft;
   1.139 +	Sint8 nybble, stereo;
   1.140 +	Sint16 *coeff[2];
   1.141 +	Sint32 new_sample;
   1.142 +
   1.143 +	/* Allocate the proper sized output buffer */
   1.144 +	encoded_len = *audio_len;
   1.145 +	encoded = *audio_buf;
   1.146 +	freeable = *audio_buf;
   1.147 +	*audio_len = (encoded_len/MS_ADPCM_state.wavefmt.blockalign) * 
   1.148 +				MS_ADPCM_state.wSamplesPerBlock*
   1.149 +				MS_ADPCM_state.wavefmt.channels*sizeof(Sint16);
   1.150 +	*audio_buf = (Uint8 *)malloc(*audio_len);
   1.151 +	if ( *audio_buf == NULL ) {
   1.152 +		SDL_Error(SDL_ENOMEM);
   1.153 +		return(-1);
   1.154 +	}
   1.155 +	decoded = *audio_buf;
   1.156 +
   1.157 +	/* Get ready... Go! */
   1.158 +	stereo = (MS_ADPCM_state.wavefmt.channels == 2);
   1.159 +	state[0] = &MS_ADPCM_state.state[0];
   1.160 +	state[1] = &MS_ADPCM_state.state[stereo];
   1.161 +	while ( encoded_len >= MS_ADPCM_state.wavefmt.blockalign ) {
   1.162 +		/* Grab the initial information for this block */
   1.163 +		state[0]->hPredictor = *encoded++;
   1.164 +		if ( stereo ) {
   1.165 +			state[1]->hPredictor = *encoded++;
   1.166 +		}
   1.167 +		state[0]->iDelta = ((encoded[1]<<8)|encoded[0]);
   1.168 +		encoded += sizeof(Sint16);
   1.169 +		if ( stereo ) {
   1.170 +			state[1]->iDelta = ((encoded[1]<<8)|encoded[0]);
   1.171 +			encoded += sizeof(Sint16);
   1.172 +		}
   1.173 +		state[0]->iSamp1 = ((encoded[1]<<8)|encoded[0]);
   1.174 +		encoded += sizeof(Sint16);
   1.175 +		if ( stereo ) {
   1.176 +			state[1]->iSamp1 = ((encoded[1]<<8)|encoded[0]);
   1.177 +			encoded += sizeof(Sint16);
   1.178 +		}
   1.179 +		state[0]->iSamp2 = ((encoded[1]<<8)|encoded[0]);
   1.180 +		encoded += sizeof(Sint16);
   1.181 +		if ( stereo ) {
   1.182 +			state[1]->iSamp2 = ((encoded[1]<<8)|encoded[0]);
   1.183 +			encoded += sizeof(Sint16);
   1.184 +		}
   1.185 +		coeff[0] = MS_ADPCM_state.aCoeff[state[0]->hPredictor];
   1.186 +		coeff[1] = MS_ADPCM_state.aCoeff[state[1]->hPredictor];
   1.187 +
   1.188 +		/* Store the two initial samples we start with */
   1.189 +		decoded[0] = state[0]->iSamp2&0xFF;
   1.190 +		decoded[1] = state[0]->iSamp2>>8;
   1.191 +		decoded += 2;
   1.192 +		if ( stereo ) {
   1.193 +			decoded[0] = state[1]->iSamp2&0xFF;
   1.194 +			decoded[1] = state[1]->iSamp2>>8;
   1.195 +			decoded += 2;
   1.196 +		}
   1.197 +		decoded[0] = state[0]->iSamp1&0xFF;
   1.198 +		decoded[1] = state[0]->iSamp1>>8;
   1.199 +		decoded += 2;
   1.200 +		if ( stereo ) {
   1.201 +			decoded[0] = state[1]->iSamp1&0xFF;
   1.202 +			decoded[1] = state[1]->iSamp1>>8;
   1.203 +			decoded += 2;
   1.204 +		}
   1.205 +
   1.206 +		/* Decode and store the other samples in this block */
   1.207 +		samplesleft = (MS_ADPCM_state.wSamplesPerBlock-2)*
   1.208 +					MS_ADPCM_state.wavefmt.channels;
   1.209 +		while ( samplesleft > 0 ) {
   1.210 +			nybble = (*encoded)>>4;
   1.211 +			new_sample = MS_ADPCM_nibble(state[0],nybble,coeff[0]);
   1.212 +			decoded[0] = new_sample&0xFF;
   1.213 +			new_sample >>= 8;
   1.214 +			decoded[1] = new_sample&0xFF;
   1.215 +			decoded += 2;
   1.216 +
   1.217 +			nybble = (*encoded)&0x0F;
   1.218 +			new_sample = MS_ADPCM_nibble(state[1],nybble,coeff[1]);
   1.219 +			decoded[0] = new_sample&0xFF;
   1.220 +			new_sample >>= 8;
   1.221 +			decoded[1] = new_sample&0xFF;
   1.222 +			decoded += 2;
   1.223 +
   1.224 +			++encoded;
   1.225 +			samplesleft -= 2;
   1.226 +		}
   1.227 +		encoded_len -= MS_ADPCM_state.wavefmt.blockalign;
   1.228 +	}
   1.229 +	free(freeable);
   1.230 +	return(0);
   1.231 +}
   1.232 +
   1.233 +struct IMA_ADPCM_decodestate {
   1.234 +	Sint32 sample;
   1.235 +	Sint8 index;
   1.236 +};
   1.237 +static struct IMA_ADPCM_decoder {
   1.238 +	WaveFMT wavefmt;
   1.239 +	Uint16 wSamplesPerBlock;
   1.240 +	/* * * */
   1.241 +	struct IMA_ADPCM_decodestate state[2];
   1.242 +} IMA_ADPCM_state;
   1.243 +
   1.244 +static int InitIMA_ADPCM(WaveFMT *format)
   1.245 +{
   1.246 +	Uint8 *rogue_feel;
   1.247 +	Uint16 extra_info;
   1.248 +
   1.249 +	/* Set the rogue pointer to the IMA_ADPCM specific data */
   1.250 +	IMA_ADPCM_state.wavefmt.encoding = SDL_SwapLE16(format->encoding);
   1.251 +	IMA_ADPCM_state.wavefmt.channels = SDL_SwapLE16(format->channels);
   1.252 +	IMA_ADPCM_state.wavefmt.frequency = SDL_SwapLE32(format->frequency);
   1.253 +	IMA_ADPCM_state.wavefmt.byterate = SDL_SwapLE32(format->byterate);
   1.254 +	IMA_ADPCM_state.wavefmt.blockalign = SDL_SwapLE16(format->blockalign);
   1.255 +	IMA_ADPCM_state.wavefmt.bitspersample =
   1.256 +					 SDL_SwapLE16(format->bitspersample);
   1.257 +	rogue_feel = (Uint8 *)format+sizeof(*format);
   1.258 +	if ( sizeof(*format) == 16 ) {
   1.259 +		extra_info = ((rogue_feel[1]<<8)|rogue_feel[0]);
   1.260 +		rogue_feel += sizeof(Uint16);
   1.261 +	}
   1.262 +	IMA_ADPCM_state.wSamplesPerBlock = ((rogue_feel[1]<<8)|rogue_feel[0]);
   1.263 +	return(0);
   1.264 +}
   1.265 +
   1.266 +static Sint32 IMA_ADPCM_nibble(struct IMA_ADPCM_decodestate *state,Uint8 nybble)
   1.267 +{
   1.268 +	const Sint32 max_audioval = ((1<<(16-1))-1);
   1.269 +	const Sint32 min_audioval = -(1<<(16-1));
   1.270 +	const int index_table[16] = {
   1.271 +		-1, -1, -1, -1,
   1.272 +		 2,  4,  6,  8,
   1.273 +		-1, -1, -1, -1,
   1.274 +		 2,  4,  6,  8
   1.275 +	};
   1.276 +	const Sint32 step_table[89] = {
   1.277 +		7, 8, 9, 10, 11, 12, 13, 14, 16, 17, 19, 21, 23, 25, 28, 31,
   1.278 +		34, 37, 41, 45, 50, 55, 60, 66, 73, 80, 88, 97, 107, 118, 130,
   1.279 +		143, 157, 173, 190, 209, 230, 253, 279, 307, 337, 371, 408,
   1.280 +		449, 494, 544, 598, 658, 724, 796, 876, 963, 1060, 1166, 1282,
   1.281 +		1411, 1552, 1707, 1878, 2066, 2272, 2499, 2749, 3024, 3327,
   1.282 +		3660, 4026, 4428, 4871, 5358, 5894, 6484, 7132, 7845, 8630,
   1.283 +		9493, 10442, 11487, 12635, 13899, 15289, 16818, 18500, 20350,
   1.284 +		22385, 24623, 27086, 29794, 32767
   1.285 +	};
   1.286 +	Sint32 delta, step;
   1.287 +
   1.288 +	/* Compute difference and new sample value */
   1.289 +	step = step_table[state->index];
   1.290 +	delta = step >> 3;
   1.291 +	if ( nybble & 0x04 ) delta += step;
   1.292 +	if ( nybble & 0x02 ) delta += (step >> 1);
   1.293 +	if ( nybble & 0x01 ) delta += (step >> 2);
   1.294 +	if ( nybble & 0x08 ) delta = -delta;
   1.295 +	state->sample += delta;
   1.296 +
   1.297 +	/* Update index value */
   1.298 +	state->index += index_table[nybble];
   1.299 +	if ( state->index > 88 ) {
   1.300 +		state->index = 88;
   1.301 +	} else
   1.302 +	if ( state->index < 0 ) {
   1.303 +		state->index = 0;
   1.304 +	}
   1.305 +
   1.306 +	/* Clamp output sample */
   1.307 +	if ( state->sample > max_audioval ) {
   1.308 +		state->sample = max_audioval;
   1.309 +	} else
   1.310 +	if ( state->sample < min_audioval ) {
   1.311 +		state->sample = min_audioval;
   1.312 +	}
   1.313 +	return(state->sample);
   1.314 +}
   1.315 +
   1.316 +/* Fill the decode buffer with a channel block of data (8 samples) */
   1.317 +static void Fill_IMA_ADPCM_block(Uint8 *decoded, Uint8 *encoded,
   1.318 +	int channel, int numchannels, struct IMA_ADPCM_decodestate *state)
   1.319 +{
   1.320 +	int i;
   1.321 +	Sint8 nybble;
   1.322 +	Sint32 new_sample;
   1.323 +
   1.324 +	decoded += (channel * 2);
   1.325 +	for ( i=0; i<4; ++i ) {
   1.326 +		nybble = (*encoded)&0x0F;
   1.327 +		new_sample = IMA_ADPCM_nibble(state, nybble);
   1.328 +		decoded[0] = new_sample&0xFF;
   1.329 +		new_sample >>= 8;
   1.330 +		decoded[1] = new_sample&0xFF;
   1.331 +		decoded += 2 * numchannels;
   1.332 +
   1.333 +		nybble = (*encoded)>>4;
   1.334 +		new_sample = IMA_ADPCM_nibble(state, nybble);
   1.335 +		decoded[0] = new_sample&0xFF;
   1.336 +		new_sample >>= 8;
   1.337 +		decoded[1] = new_sample&0xFF;
   1.338 +		decoded += 2 * numchannels;
   1.339 +
   1.340 +		++encoded;
   1.341 +	}
   1.342 +}
   1.343 +
   1.344 +static int IMA_ADPCM_decode(Uint8 **audio_buf, Uint32 *audio_len)
   1.345 +{
   1.346 +	struct IMA_ADPCM_decodestate *state;
   1.347 +	Uint8 *freeable, *encoded, *decoded;
   1.348 +	Sint32 encoded_len, samplesleft;
   1.349 +	int c, channels;
   1.350 +
   1.351 +	/* Check to make sure we have enough variables in the state array */
   1.352 +	channels = IMA_ADPCM_state.wavefmt.channels;
   1.353 +	if ( channels > NELEMS(IMA_ADPCM_state.state) ) {
   1.354 +		SDL_SetError("IMA ADPCM decoder can only handle %d channels",
   1.355 +						NELEMS(IMA_ADPCM_state.state));
   1.356 +		return(-1);
   1.357 +	}
   1.358 +	state = IMA_ADPCM_state.state;
   1.359 +
   1.360 +	/* Allocate the proper sized output buffer */
   1.361 +	encoded_len = *audio_len;
   1.362 +	encoded = *audio_buf;
   1.363 +	freeable = *audio_buf;
   1.364 +	*audio_len = (encoded_len/IMA_ADPCM_state.wavefmt.blockalign) * 
   1.365 +				IMA_ADPCM_state.wSamplesPerBlock*
   1.366 +				IMA_ADPCM_state.wavefmt.channels*sizeof(Sint16);
   1.367 +	*audio_buf = (Uint8 *)malloc(*audio_len);
   1.368 +	if ( *audio_buf == NULL ) {
   1.369 +		SDL_Error(SDL_ENOMEM);
   1.370 +		return(-1);
   1.371 +	}
   1.372 +	decoded = *audio_buf;
   1.373 +
   1.374 +	/* Get ready... Go! */
   1.375 +	while ( encoded_len >= IMA_ADPCM_state.wavefmt.blockalign ) {
   1.376 +		/* Grab the initial information for this block */
   1.377 +		for ( c=0; c<channels; ++c ) {
   1.378 +			/* Fill the state information for this block */
   1.379 +			state[c].sample = ((encoded[1]<<8)|encoded[0]);
   1.380 +			encoded += 2;
   1.381 +			if ( state[c].sample & 0x8000 ) {
   1.382 +				state[c].sample -= 0x10000;
   1.383 +			}
   1.384 +			state[c].index = *encoded++;
   1.385 +			/* Reserved byte in buffer header, should be 0 */
   1.386 +			if ( *encoded++ != 0 ) {
   1.387 +				/* Uh oh, corrupt data?  Buggy code? */;
   1.388 +			}
   1.389 +
   1.390 +			/* Store the initial sample we start with */
   1.391 +			decoded[0] = state[c].sample&0xFF;
   1.392 +			decoded[1] = state[c].sample>>8;
   1.393 +			decoded += 2;
   1.394 +		}
   1.395 +
   1.396 +		/* Decode and store the other samples in this block */
   1.397 +		samplesleft = (IMA_ADPCM_state.wSamplesPerBlock-1)*channels;
   1.398 +		while ( samplesleft > 0 ) {
   1.399 +			for ( c=0; c<channels; ++c ) {
   1.400 +				Fill_IMA_ADPCM_block(decoded, encoded,
   1.401 +						c, channels, &state[c]);
   1.402 +				encoded += 4;
   1.403 +				samplesleft -= 8;
   1.404 +			}
   1.405 +			decoded += (channels * 8 * 2);
   1.406 +		}
   1.407 +		encoded_len -= IMA_ADPCM_state.wavefmt.blockalign;
   1.408 +	}
   1.409 +	free(freeable);
   1.410 +	return(0);
   1.411 +}
   1.412 +
   1.413 +SDL_AudioSpec * SDL_LoadWAV_RW (SDL_RWops *src, int freesrc,
   1.414 +		SDL_AudioSpec *spec, Uint8 **audio_buf, Uint32 *audio_len)
   1.415 +{
   1.416 +	int was_error;
   1.417 +	Chunk chunk;
   1.418 +	int lenread;
   1.419 +	int MS_ADPCM_encoded, IMA_ADPCM_encoded;
   1.420 +	int samplesize;
   1.421 +
   1.422 +	/* WAV magic header */
   1.423 +	Uint32 RIFFchunk;
   1.424 +	Uint32 wavelen;
   1.425 +	Uint32 WAVEmagic;
   1.426 +
   1.427 +	/* FMT chunk */
   1.428 +	WaveFMT *format = NULL;
   1.429 +
   1.430 +	/* Make sure we are passed a valid data source */
   1.431 +	was_error = 0;
   1.432 +	if ( src == NULL ) {
   1.433 +		was_error = 1;
   1.434 +		goto done;
   1.435 +	}
   1.436 +		
   1.437 +	/* Check the magic header */
   1.438 +	RIFFchunk	= SDL_ReadLE32(src);
   1.439 +	wavelen		= SDL_ReadLE32(src);
   1.440 +	WAVEmagic	= SDL_ReadLE32(src);
   1.441 +	if ( (RIFFchunk != RIFF) || (WAVEmagic != WAVE) ) {
   1.442 +		SDL_SetError("Unrecognized file type (not WAVE)");
   1.443 +		was_error = 1;
   1.444 +		goto done;
   1.445 +	}
   1.446 +
   1.447 +	/* Read the audio data format chunk */
   1.448 +	chunk.data = NULL;
   1.449 +	do {
   1.450 +		if ( chunk.data != NULL ) {
   1.451 +			free(chunk.data);
   1.452 +		}
   1.453 +		lenread = ReadChunk(src, &chunk);
   1.454 +		if ( lenread < 0 ) {
   1.455 +			was_error = 1;
   1.456 +			goto done;
   1.457 +		}
   1.458 +	} while ( (chunk.magic == FACT) || (chunk.magic == LIST) );
   1.459 +
   1.460 +	/* Decode the audio data format */
   1.461 +	format = (WaveFMT *)chunk.data;
   1.462 +	if ( chunk.magic != FMT ) {
   1.463 +		SDL_SetError("Complex WAVE files not supported");
   1.464 +		was_error = 1;
   1.465 +		goto done;
   1.466 +	}
   1.467 +	MS_ADPCM_encoded = IMA_ADPCM_encoded = 0;
   1.468 +	switch (SDL_SwapLE16(format->encoding)) {
   1.469 +		case PCM_CODE:
   1.470 +			/* We can understand this */
   1.471 +			break;
   1.472 +		case MS_ADPCM_CODE:
   1.473 +			/* Try to understand this */
   1.474 +			if ( InitMS_ADPCM(format) < 0 ) {
   1.475 +				was_error = 1;
   1.476 +				goto done;
   1.477 +			}
   1.478 +			MS_ADPCM_encoded = 1;
   1.479 +			break;
   1.480 +		case IMA_ADPCM_CODE:
   1.481 +			/* Try to understand this */
   1.482 +			if ( InitIMA_ADPCM(format) < 0 ) {
   1.483 +				was_error = 1;
   1.484 +				goto done;
   1.485 +			}
   1.486 +			IMA_ADPCM_encoded = 1;
   1.487 +			break;
   1.488 +		default:
   1.489 +			SDL_SetError("Unknown WAVE data format: 0x%.4x",
   1.490 +					SDL_SwapLE16(format->encoding));
   1.491 +			was_error = 1;
   1.492 +			goto done;
   1.493 +	}
   1.494 +	memset(spec, 0, (sizeof *spec));
   1.495 +	spec->freq = SDL_SwapLE32(format->frequency);
   1.496 +	switch (SDL_SwapLE16(format->bitspersample)) {
   1.497 +		case 4:
   1.498 +			if ( MS_ADPCM_encoded || IMA_ADPCM_encoded ) {
   1.499 +				spec->format = AUDIO_S16;
   1.500 +			} else {
   1.501 +				was_error = 1;
   1.502 +			}
   1.503 +			break;
   1.504 +		case 8:
   1.505 +			spec->format = AUDIO_U8;
   1.506 +			break;
   1.507 +		case 16:
   1.508 +			spec->format = AUDIO_S16;
   1.509 +			break;
   1.510 +		default:
   1.511 +			was_error = 1;
   1.512 +			break;
   1.513 +	}
   1.514 +	if ( was_error ) {
   1.515 +		SDL_SetError("Unknown %d-bit PCM data format",
   1.516 +			SDL_SwapLE16(format->bitspersample));
   1.517 +		goto done;
   1.518 +	}
   1.519 +	spec->channels = (Uint8)SDL_SwapLE16(format->channels);
   1.520 +	spec->samples = 4096;		/* Good default buffer size */
   1.521 +
   1.522 +	/* Read the audio data chunk */
   1.523 +	*audio_buf = NULL;
   1.524 +	do {
   1.525 +		if ( *audio_buf != NULL ) {
   1.526 +			free(*audio_buf);
   1.527 +		}
   1.528 +		lenread = ReadChunk(src, &chunk);
   1.529 +		if ( lenread < 0 ) {
   1.530 +			was_error = 1;
   1.531 +			goto done;
   1.532 +		}
   1.533 +		*audio_len = lenread;
   1.534 +		*audio_buf = chunk.data;
   1.535 +	} while ( chunk.magic != DATA );
   1.536 +
   1.537 +	if ( MS_ADPCM_encoded ) {
   1.538 +		if ( MS_ADPCM_decode(audio_buf, audio_len) < 0 ) {
   1.539 +			was_error = 1;
   1.540 +			goto done;
   1.541 +		}
   1.542 +	}
   1.543 +	if ( IMA_ADPCM_encoded ) {
   1.544 +		if ( IMA_ADPCM_decode(audio_buf, audio_len) < 0 ) {
   1.545 +			was_error = 1;
   1.546 +			goto done;
   1.547 +		}
   1.548 +	}
   1.549 +
   1.550 +	/* Don't return a buffer that isn't a multiple of samplesize */
   1.551 +	samplesize = ((spec->format & 0xFF)/8)*spec->channels;
   1.552 +	*audio_len &= ~(samplesize-1);
   1.553 +
   1.554 +done:
   1.555 +	if ( format != NULL ) {
   1.556 +		free(format);
   1.557 +	}
   1.558 +	if ( freesrc && src ) {
   1.559 +		SDL_RWclose(src);
   1.560 +	}
   1.561 +	if ( was_error ) {
   1.562 +		spec = NULL;
   1.563 +	}
   1.564 +	return(spec);
   1.565 +}
   1.566 +
   1.567 +/* Since the WAV memory is allocated in the shared library, it must also
   1.568 +   be freed here.  (Necessary under Win32, VC++)
   1.569 + */
   1.570 +void SDL_FreeWAV(Uint8 *audio_buf)
   1.571 +{
   1.572 +	if ( audio_buf != NULL ) {
   1.573 +		free(audio_buf);
   1.574 +	}
   1.575 +}
   1.576 +
   1.577 +static int ReadChunk(SDL_RWops *src, Chunk *chunk)
   1.578 +{
   1.579 +	chunk->magic	= SDL_ReadLE32(src);
   1.580 +	chunk->length	= SDL_ReadLE32(src);
   1.581 +	chunk->data = (Uint8 *)malloc(chunk->length);
   1.582 +	if ( chunk->data == NULL ) {
   1.583 +		SDL_Error(SDL_ENOMEM);
   1.584 +		return(-1);
   1.585 +	}
   1.586 +	if ( SDL_RWread(src, chunk->data, chunk->length, 1) != 1 ) {
   1.587 +		SDL_Error(SDL_EFREAD);
   1.588 +		free(chunk->data);
   1.589 +		return(-1);
   1.590 +	}
   1.591 +	return(chunk->length);
   1.592 +}
   1.593 +
   1.594 +#endif /* ENABLE_FILE */