home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Club Amiga de Montreal - CAM
/
CAM_CD_1.iso
/
files
/
199.lha
/
GimmeLib
/
sound.c
< prev
next >
Wrap
C/C++ Source or Header
|
1988-12-27
|
5KB
|
247 lines
/*
* 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 */