home *** CD-ROM | disk | FTP | other *** search
- /*
- * FILE: sound.c
- * Support routines for reading IFF/8SVX files.
- *
- * Public Domain, but keep our names in it as the original authors.
- * 09-Dec-87 Rico Mariani original code (modified by JST)
- * 31-Aug-88 Jan Sven Trabandt first release version
- */
-
-
- #define I_AM_SOUND
- #include "gimmelib/gimmefuncs.h"
- #include "gimmelib/sound.h"
- #include <stdio.h>
-
-
- #define GET(iffile) getc( iffile )
-
- #define getId getLong
- #define getLen getLong
- #define getByte GET
- #define skip(len, file) fseek(file, (long)(len), 1)
-
- #define getV8H(v8h, file) fread(v8h, sizeof(Voice8Header), 1, file)
-
- /* requires an existent variable 'char *errmsg' and a label 'failure_return' */
- #define fail_and_return(msg) {errmsg = msg; goto failure_return;}
-
- /* forward declarations */
- static LONG getLong();
- static WORD getWord();
-
- static char noMemMsg[] = "insufficient memory\n";
- static char badFileMsg[] = "corrupt or incomplete file\n";
-
-
- SOUND *gimmeSound( filename )
- UBYTE *filename;
- {
- LONG len, id;
- SOUND *snd = NULL;
- BYTE *p;
- void *mh = NULL;
- FILE *file = NULL;
- char *errmsg = " ";
- SHORT i;
-
- if( !(file = fopen(filename, "r")) ) {
- fail_and_return( "unable to open iff sound file for read\n" );
- }
- if( getId(file) != ID_FORM ) {
- fail_and_return( "not IFF format\n" );
- }
- getLen( file );
- if( getId(file) != ID_8SVX ) {
- fail_and_return( "not 8SVX format\n" );
- }
- for( ;; ) {
- getChunk( &id, &len, file );
- if( ferror(file) || feof(file) ) {
- fail_and_return( badFileMsg );
- }
- switch( id ) {
- case ID_VHDR:
- snd = chainAllocMem( &mh, (ULONG)sizeof(SOUND),
- MEMF_PUBLIC | MEMF_CLEAR );
- if( !snd ) {
- fail_and_return( noMemMsg );
- }
- getV8H( &snd->vh, file );
- if( len & 1 ) {
- GET(file);
- }
- break;
- case ID_BODY:
- if( !snd ) {
- fail_and_return( "didn't find VHDR chunk\n" );
- }
- switch( snd->vh.sCompression ) {
- case sCmpNone:
- snd->bodylen = len;
- snd->body = chainAllocMem( &mh, len, MEMF_CHIP );
- if( !snd->body ) {
- fail_and_return( noMemMsg );
- }
- memget( snd->body, len, file );
- break;
- case sCmpFibDelta:
- snd->bodylen = len << 1;
- snd->body = chainAllocMem( &mh, (ULONG) snd->bodylen,
- MEMF_CHIP );
- if( !snd->body ) {
- fail_and_return( noMemMsg );
- }
- p = AllocMem( len, MEMF_PUBLIC );
- if( !p ) {
- fail_and_return( noMemMsg );
- }
- memget( p, len, file );
- DUnpack( p, len, snd->body );
- FreeMem( p, len );
- break;
- default:
- fail_and_return( "unknown compression form\n" );
- break;
- } /* switch */
- if( len & 1 ) {
- GET(file);
- }
- if( ferror(file) ) {
- fail_and_return( badFileMsg );
- }
- snd->memhead = mh;
- fclose( file );
- return( snd );
- break;
- case ID_NAME:
- case ID_AUTH:
- case ID_COPY:
- case ID_ANNO:
- case ID_ATAK:
- case ID_RLSE:
- default: /* unimplemented chunk type */
- skip( EVEN(len), file );
- break;
- } /* switch */
- } /* for */
- failure_return: {}
- if( Output() ) {
- Write( Output(), errmsg, (ULONG)strlen(errmsg) );
- }
- if( mh ) {
- chainFreeMem( mh );
- }
- if( file ) {
- fclose( file );
- }
- return( NULL );
- } /* gimmeSound */
-
-
- short getRidOfSound( sound )
- SOUND *sound;
- {
- #ifdef GIMME_WIMPY
- if( !sound ) {
- return( -1 );
- }
- #endif
- chainFreeMem( sound->memhead );
- return( 0 );
- } /* getRidOfSound */
-
-
- /* read an IFF Id */
- static LONG getLong( file )
- FILE *file;
- {
- register UBYTE p[4];
-
- p[0] = GET(file);
- p[1] = GET(file);
- p[2] = GET(file);
- p[3] = GET(file);
- return( (LONG) Mk(p[0],p[1],p[2],p[3]) );
- } /* getLong */
-
-
- /* read an IFF chunk header */
- static getChunk( id, len, file )
- LONG *id, *len;
- FILE *file;
- {
- *id = getId( file );
- *len = getLen( file );
- } /* getChunk */
-
-
- /* get len bytes from the file and put them into memory */
- static memget( p, len, file )
- UBYTE *p;
- LONG len;
- FILE *file;
- {
- for( ; len > 0L; len -= 0x07fffL, p += 0x07fffL ) {
- fread( p, (int) (len & 0x07fffL), 1, file );
- } /* for */
- } /* memget */
-
-
- /* get a word */
- static WORD getWord( file )
- FILE *file;
- {
- WORD v;
-
- v = GET(file) << 8;
- return( v | GET(file) );
- } /* getWord */
-
-
- /* get the EGPoint info */
- static getEGPoint( pnt, file )
- EGPoint *pnt;
- FILE *file;
- {
- pnt->duration = getWord( file );
- pnt->dest = getLong( file );
- } /* getEGPoint */
-
-
- static BYTE codeToDelta[] = {-34,-21,-13,-8,-5,-3,-2,-1,0,1,2,3,5,8,13,21};
-
- /* unpack a part of a fibonacci delta encoded sound sample */
- static BYTE D1Unpack( source, n, dest, x )
- BYTE *source;
- LONG n;
- BYTE *dest;
- BYTE x;
- {
- UBYTE d;
- LONG i, lim;
-
- lim = n << 1;
- for( i = 0; i < lim; ++i ) {
- d = source[i>>1];
- if( i & 1 ) {
- d &= 0xf;
- } else {
- d >>= 4;
- }
- x += codeToDelta[d];
- dest[i] = x;
- } /* for */
- return( x ); /* return last data value */
- } /* D1Unpack */
-
-
- /* unpack a fibonacci delta encoded sound sample */
- static DUnpack( source, n, dest )
- BYTE *source;
- LONG n;
- BYTE *dest;
- {
- D1Unpack( source + 2, n - 2, dest, source[1] );
- } /* DUnpack */
-