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");