wavestream.c
changeset 95 871a7c1b93fb
parent 64 00b28153c609
child 97 2bf733171d56
equal deleted inserted replaced
94:57a263c7f503 95:871a7c1b93fb
   335 		}
   335 		}
   336 	}
   336 	}
   337 	return(wavefp);
   337 	return(wavefp);
   338 }
   338 }
   339 
   339 
   340 static double SANE_to_double(Uint32 l1, Uint32 l2, Uint16 s1)
   340 /* I couldn't get SANE_to_double() to work, so I stole this from libsndfile.
   341 {
   341  * I don't pretend to fully understand it.
   342 	double d;
   342  */
   343 	struct almost_double {
   343 
   344 		Uint32 hi, lo;
   344 static Uint32 SANE_to_Uint32 (Uint8 *sanebuf)
   345 	} *dp = (struct almost_double *)&d;
   345 {
   346 
   346 	/* Negative number? */
   347 	dp->hi = ((l1 << 4) & 0x3ff00000) | (l1 & 0xc0000000);
   347 	if (sanebuf[0] & 0x80)
   348 	dp->hi |= (l1 << 5) & 0xffff0;
   348 		return 0;
   349 	dp->hi |= (l2 >> 27) & 0x1f;
   349 
   350 	dp->lo = (l2 << 5) & 0xffffffe0;
   350 	/* Less than 1? */
   351 	dp->lo |= ((s1 >> 11) & 0x1f);
   351 	if (sanebuf[0] <= 0x3F)
   352 	return(d);
   352 		return 1;
       
   353 
       
   354 	/* Way too big? */
       
   355 	if (sanebuf[0] > 0x40)
       
   356 		return 0x4000000;
       
   357 
       
   358 	/* Still too big? */
       
   359 	if (sanebuf[0] == 0x40 && sanebuf[1] > 0x1C)
       
   360 		return 800000000;
       
   361 
       
   362 	return ((sanebuf[2] << 23) | (sanebuf[3] << 15) | (sanebuf[4] << 7)
       
   363 		| (sanebuf[5] >> 1)) >> (29 - sanebuf[1]);
   353 }
   364 }
   354 
   365 
   355 static FILE *LoadAIFFStream (const char *file, SDL_AudioSpec *spec,
   366 static FILE *LoadAIFFStream (const char *file, SDL_AudioSpec *spec,
   356 					long *start, long *stop)
   367 					long *start, long *stop)
   357 {
   368 {
   358 	int was_error;
   369 	int was_error;
       
   370 	int found_SSND;
       
   371 	int found_COMM;
   359 	FILE *wavefp;
   372 	FILE *wavefp;
   360 	SDL_RWops *src;
   373 	SDL_RWops *src;
   361 
   374 
       
   375 	Uint32 chunk_type;
       
   376 	Uint32 chunk_length;
       
   377 	long next_chunk;
       
   378 
   362 	/* AIFF magic header */
   379 	/* AIFF magic header */
   363 	Uint32 FORMchunk;
   380 	Uint32 FORMchunk;
   364 	Uint32 chunklen;
       
   365 	Uint32 AIFFmagic;
   381 	Uint32 AIFFmagic;
   366 	/* SSND chunk        */
   382 	/* SSND chunk        */
   367 	Uint32 SSNDchunk;
   383 	Uint32 SSNDchunk;
   368 	Uint32 ssndlen;
       
   369 	Uint32 offset;
   384 	Uint32 offset;
   370 	Uint32 blocksize;
   385 	Uint32 blocksize;
   371 	/* COMM format chunk */
   386 	/* COMM format chunk */
   372 	Uint32 COMMchunk;
   387 	Uint32 COMMchunk;
   373 	Uint32 commlen;
       
   374 	Uint16 channels;
   388 	Uint16 channels;
   375 	Uint32 numsamples;
   389 	Uint32 numsamples;
   376 	Uint16 samplesize;
   390 	Uint16 samplesize;
   377 	struct { /* plus a SANE format double precision number */
   391 	Uint8 sane_freq[10];
   378 		Uint32 l1;
       
   379 		Uint32 l2;
       
   380 		Uint16 s1;
       
   381 	} sane_freq;
       
   382 
       
   383 	Uint32 frequency;
   392 	Uint32 frequency;
   384 
   393 
   385 
   394 
   386 	/* Make sure we are passed a valid data source */
   395 	/* Make sure we are passed a valid data source */
   387 	was_error = 0;
   396 	was_error = 0;
   395 		goto done;
   404 		goto done;
   396 	}
   405 	}
   397 
   406 
   398 	/* Check the magic header */
   407 	/* Check the magic header */
   399 	FORMchunk	= SDL_ReadLE32(src);
   408 	FORMchunk	= SDL_ReadLE32(src);
   400 	chunklen	= SDL_ReadLE32(src);
   409 	chunk_length	= SDL_ReadBE32(src);
   401 	AIFFmagic	= SDL_ReadLE32(src);
   410 	AIFFmagic	= SDL_ReadLE32(src);
   402 	if ( (FORMchunk != FORM) || (AIFFmagic != AIFF) ) {
   411 	if ( (FORMchunk != FORM) || (AIFFmagic != AIFF) ) {
   403 		SDL_SetError("Unrecognized file type (not AIFF)");
   412 		SDL_SetError("Unrecognized file type (not AIFF)");
   404 		was_error = 1;
   413 		was_error = 1;
   405 		goto done;
   414 		goto done;
   406 	}
   415 	}
   407 
   416 
   408 	/* Read the SSND data chunk */
   417 	/* From what I understand of the specification, chunks may appear in
   409 	SSNDchunk	= SDL_ReadLE32(src);
   418          * any order, and we should just ignore unknown ones.
   410 	if ( SSNDchunk != SSND ) {
   419          */
   411 		SDL_SetError("Unrecognized AIFF chunk (not SSND)");
   420 
   412 		was_error = 1;
   421 	found_SSND = 0;
   413 		goto done;
   422 	found_COMM = 0;
   414 	}
   423 
   415 	ssndlen		= SDL_ReadLE32(src);
   424 	do {
   416 	offset		= SDL_ReadLE32(src);
   425 	    chunk_type		= SDL_ReadLE32(src);
   417 	blocksize	= SDL_ReadLE32(src);
   426 	    chunk_length	= SDL_ReadBE32(src);
   418 
   427 	    next_chunk		= SDL_RWtell(src) + chunk_length;
   419 	/* Fill in start and stop pointers, then seek to format chunk */
   428 
   420 	ssndlen -= (2*sizeof(Uint32));
   429 	    /* Paranoia to avoid infinite loops */
   421 	*start = SDL_RWtell(src) + offset;
   430 	    if (chunk_length == 0)
   422 	*stop = SDL_RWtell(src) + ssndlen;
   431 		break;
   423 	SDL_RWseek(src, *stop, SEEK_SET);
   432 
   424 
   433             switch (chunk_type) {
   425 	/* Read the audio data format chunk */
   434 		case SSND:
   426 	COMMchunk	= SDL_ReadLE32(src);
   435 		    found_SSND		= 1;
   427 	if ( COMMchunk != COMM ) {
   436 		    offset		= SDL_ReadBE32(src);
   428 		SDL_SetError("Unrecognized AIFF chunk (not COMM)");
   437 		    blocksize		= SDL_ReadBE32(src);
   429 		was_error = 1;
   438 		    *start		= SDL_RWtell(src) + offset;
   430 		goto done;
   439 		    break;
   431 	}
   440 
   432 	commlen		= SDL_ReadLE32(src);
   441 		case COMM:
   433 	channels	= SDL_ReadLE16(src);
   442 		    found_COMM		= 1;
   434 	numsamples	= SDL_ReadLE32(src);
   443 
   435 	samplesize	= SDL_ReadLE16(src);
   444 		    /* Read the audio data format chunk */
   436 	sane_freq.l1	= SDL_ReadLE32(src);
   445 		    channels		= SDL_ReadBE16(src);
   437 	sane_freq.l2	= SDL_ReadLE32(src);
   446 		    numsamples		= SDL_ReadBE32(src);
   438 	sane_freq.s1	= SDL_ReadLE16(src);
   447 		    samplesize		= SDL_ReadBE16(src);
   439 	frequency	= (Uint32)SANE_to_double(sane_freq.l1, sane_freq.l2,
   448 		    SDL_RWread(src, sane_freq, sizeof(sane_freq), 1);
   440 								sane_freq.s1);
   449 		    frequency		= SANE_to_Uint32(sane_freq);
       
   450 		    break;
       
   451 
       
   452 		default:
       
   453 		    break;
       
   454 	    }
       
   455 	} while ((!found_SSND || !found_COMM)
       
   456 		 && SDL_RWseek(src, next_chunk, SEEK_SET) != -1);
       
   457 
       
   458 	if (!found_SSND) {
       
   459 	    SDL_SetError("Bad AIFF file (no SSND chunk)");
       
   460 	    was_error = 1;
       
   461 	    goto done;
       
   462 	}
       
   463 		    
       
   464 	if (!found_COMM) {
       
   465 	    SDL_SetError("Bad AIFF file (no COMM chunk)");
       
   466 	    was_error = 1;
       
   467 	    goto done;
       
   468 	}
       
   469 
       
   470 	*stop = *start + channels * numsamples * (samplesize / 8) - 1;
   441 
   471 
   442 	/* Decode the audio data format */
   472 	/* Decode the audio data format */
   443 	memset(spec, 0, (sizeof *spec));
   473 	memset(spec, 0, (sizeof *spec));
   444 	spec->freq = frequency;
   474 	spec->freq = frequency;
   445 	switch (samplesize) {
   475 	switch (samplesize) {
   446 		case 8:
   476 		case 8:
   447 			spec->format = AUDIO_U8;
   477 			spec->format = AUDIO_U8;
   448 			break;
   478 			break;
   449 		case 16:
   479 		case 16:
   450 			spec->format = AUDIO_S16;
   480 			spec->format = AUDIO_S16MSB;
   451 			break;
   481 			break;
   452 		default:
   482 		default:
   453 			SDL_SetError("Unknown samplesize in data format");
   483 			SDL_SetError("Unknown samplesize in data format");
   454 			was_error = 1;
   484 			was_error = 1;
   455 			goto done;
   485 			goto done;