wavestream.c
 changeset 95 871a7c1b93fb parent 64 00b28153c609 child 97 2bf733171d56
```     1.1 --- a/wavestream.c	Sat Aug 18 11:14:31 2001 +0000
1.2 +++ b/wavestream.c	Sun Aug 19 19:13:09 2001 +0000
1.3 @@ -337,49 +337,58 @@
1.4  	return(wavefp);
1.5  }
1.6
1.7 -static double SANE_to_double(Uint32 l1, Uint32 l2, Uint16 s1)
1.8 +/* I couldn't get SANE_to_double() to work, so I stole this from libsndfile.
1.9 + * I don't pretend to fully understand it.
1.10 + */
1.11 +
1.12 +static Uint32 SANE_to_Uint32 (Uint8 *sanebuf)
1.13  {
1.14 -	double d;
1.15 -	struct almost_double {
1.16 -		Uint32 hi, lo;
1.17 -	} *dp = (struct almost_double *)&d;
1.18 +	/* Negative number? */
1.19 +	if (sanebuf[0] & 0x80)
1.20 +		return 0;
1.21
1.22 -	dp->hi = ((l1 << 4) & 0x3ff00000) | (l1 & 0xc0000000);
1.23 -	dp->hi |= (l1 << 5) & 0xffff0;
1.24 -	dp->hi |= (l2 >> 27) & 0x1f;
1.25 -	dp->lo = (l2 << 5) & 0xffffffe0;
1.26 -	dp->lo |= ((s1 >> 11) & 0x1f);
1.27 -	return(d);
1.28 +	/* Less than 1? */
1.29 +	if (sanebuf[0] <= 0x3F)
1.30 +		return 1;
1.31 +
1.32 +	/* Way too big? */
1.33 +	if (sanebuf[0] > 0x40)
1.34 +		return 0x4000000;
1.35 +
1.36 +	/* Still too big? */
1.37 +	if (sanebuf[0] == 0x40 && sanebuf[1] > 0x1C)
1.38 +		return 800000000;
1.39 +
1.40 +	return ((sanebuf[2] << 23) | (sanebuf[3] << 15) | (sanebuf[4] << 7)
1.41 +		| (sanebuf[5] >> 1)) >> (29 - sanebuf[1]);
1.42  }
1.43
1.44  static FILE *LoadAIFFStream (const char *file, SDL_AudioSpec *spec,
1.45  					long *start, long *stop)
1.46  {
1.47  	int was_error;
1.48 +	int found_SSND;
1.49 +	int found_COMM;
1.50  	FILE *wavefp;
1.51  	SDL_RWops *src;
1.52
1.53 +	Uint32 chunk_type;
1.54 +	Uint32 chunk_length;
1.55 +	long next_chunk;
1.56 +
1.57  	/* AIFF magic header */
1.58  	Uint32 FORMchunk;
1.59 -	Uint32 chunklen;
1.60  	Uint32 AIFFmagic;
1.61  	/* SSND chunk        */
1.62  	Uint32 SSNDchunk;
1.63 -	Uint32 ssndlen;
1.64  	Uint32 offset;
1.65  	Uint32 blocksize;
1.66  	/* COMM format chunk */
1.67  	Uint32 COMMchunk;
1.68 -	Uint32 commlen;
1.69  	Uint16 channels;
1.70  	Uint32 numsamples;
1.71  	Uint16 samplesize;
1.72 -	struct { /* plus a SANE format double precision number */
1.73 -		Uint32 l1;
1.74 -		Uint32 l2;
1.75 -		Uint16 s1;
1.76 -	} sane_freq;
1.77 -
1.78 +	Uint8 sane_freq[10];
1.79  	Uint32 frequency;
1.80
1.81
1.82 @@ -397,7 +406,7 @@
1.83
1.84  	/* Check the magic header */
1.85  	FORMchunk	= SDL_ReadLE32(src);
1.86 -	chunklen	= SDL_ReadLE32(src);
1.87 +	chunk_length	= SDL_ReadBE32(src);
1.88  	AIFFmagic	= SDL_ReadLE32(src);
1.89  	if ( (FORMchunk != FORM) || (AIFFmagic != AIFF) ) {
1.90  		SDL_SetError("Unrecognized file type (not AIFF)");
1.91 @@ -405,39 +414,60 @@
1.92  		goto done;
1.93  	}
1.94
1.95 -	/* Read the SSND data chunk */
1.96 -	SSNDchunk	= SDL_ReadLE32(src);
1.97 -	if ( SSNDchunk != SSND ) {
1.98 -		SDL_SetError("Unrecognized AIFF chunk (not SSND)");
1.99 -		was_error = 1;
1.100 -		goto done;
1.101 +	/* From what I understand of the specification, chunks may appear in
1.102 +         * any order, and we should just ignore unknown ones.
1.103 +         */
1.104 +
1.105 +	found_SSND = 0;
1.106 +	found_COMM = 0;
1.107 +
1.108 +	do {
1.109 +	    chunk_type		= SDL_ReadLE32(src);
1.110 +	    chunk_length	= SDL_ReadBE32(src);
1.111 +	    next_chunk		= SDL_RWtell(src) + chunk_length;
1.112 +
1.113 +	    /* Paranoia to avoid infinite loops */
1.114 +	    if (chunk_length == 0)
1.115 +		break;
1.116 +
1.117 +            switch (chunk_type) {
1.118 +		case SSND:
1.119 +		    found_SSND		= 1;
1.120 +		    offset		= SDL_ReadBE32(src);
1.121 +		    blocksize		= SDL_ReadBE32(src);
1.122 +		    *start		= SDL_RWtell(src) + offset;
1.123 +		    break;
1.124 +
1.125 +		case COMM:
1.126 +		    found_COMM		= 1;
1.127 +
1.128 +		    /* Read the audio data format chunk */
1.129 +		    channels		= SDL_ReadBE16(src);
1.130 +		    numsamples		= SDL_ReadBE32(src);
1.131 +		    samplesize		= SDL_ReadBE16(src);
1.132 +		    SDL_RWread(src, sane_freq, sizeof(sane_freq), 1);
1.133 +		    frequency		= SANE_to_Uint32(sane_freq);
1.134 +		    break;
1.135 +
1.136 +		default:
1.137 +		    break;
1.138 +	    }
1.139 +	} while ((!found_SSND || !found_COMM)
1.140 +		 && SDL_RWseek(src, next_chunk, SEEK_SET) != -1);
1.141 +
1.142 +	if (!found_SSND) {
1.143 +	    SDL_SetError("Bad AIFF file (no SSND chunk)");
1.144 +	    was_error = 1;
1.145 +	    goto done;
1.146  	}
1.147 -	ssndlen		= SDL_ReadLE32(src);
1.148 -	offset		= SDL_ReadLE32(src);
1.149 -	blocksize	= SDL_ReadLE32(src);
1.150 +
1.151 +	if (!found_COMM) {
1.152 +	    SDL_SetError("Bad AIFF file (no COMM chunk)");
1.153 +	    was_error = 1;
1.154 +	    goto done;
1.155 +	}
1.156
1.157 -	/* Fill in start and stop pointers, then seek to format chunk */
1.158 -	ssndlen -= (2*sizeof(Uint32));
1.159 -	*start = SDL_RWtell(src) + offset;
1.160 -	*stop = SDL_RWtell(src) + ssndlen;
1.161 -	SDL_RWseek(src, *stop, SEEK_SET);
1.162 -
1.163 -	/* Read the audio data format chunk */
1.164 -	COMMchunk	= SDL_ReadLE32(src);
1.165 -	if ( COMMchunk != COMM ) {
1.166 -		SDL_SetError("Unrecognized AIFF chunk (not COMM)");
1.167 -		was_error = 1;
1.168 -		goto done;
1.169 -	}
1.170 -	commlen		= SDL_ReadLE32(src);
1.171 -	channels	= SDL_ReadLE16(src);
1.172 -	numsamples	= SDL_ReadLE32(src);
1.173 -	samplesize	= SDL_ReadLE16(src);
1.174 -	sane_freq.l1	= SDL_ReadLE32(src);
1.175 -	sane_freq.l2	= SDL_ReadLE32(src);
1.176 -	sane_freq.s1	= SDL_ReadLE16(src);
1.177 -	frequency	= (Uint32)SANE_to_double(sane_freq.l1, sane_freq.l2,
1.178 -								sane_freq.s1);
1.179 +	*stop = *start + channels * numsamples * (samplesize / 8) - 1;
1.180
1.181  	/* Decode the audio data format */
1.182  	memset(spec, 0, (sizeof *spec));
1.183 @@ -447,7 +477,7 @@
1.184  			spec->format = AUDIO_U8;
1.185  			break;
1.186  		case 16:
1.187 -			spec->format = AUDIO_S16;
1.188 +			spec->format = AUDIO_S16MSB;
1.189  			break;
1.190  		default:
1.191  			SDL_SetError("Unknown samplesize in data format");
```