home *** CD-ROM | disk | FTP | other *** search
- /* quasi-minimal IFF 8SVX sample file loader for Karl's Audio Stuff
- * by Karl Lehenbauer, based originally on public domain IFF code from
- * Electronic Arts
- * rewritten 2/25/88 KEL to support chaining of samples through a
- * central sample store and to support music (it's now carrying
- * around octave and one-shot info)
-
- *
- * this version for the sound effect player has had the octave stuff
- * hacked back out but the central sample store is still there
- *
- */
-
- #include <exec/types.h>
- #include <functions.h>
- #include <exec/memory.h>
- #include <exec/nodes.h>
- #include <exec/lists.h>
- #include <stdio.h>
- #include <fcntl.h>
- #include "assert.h"
-
- #include "iff.h"
- #include "8svx.h"
-
- #include "sample.h"
-
- struct List SampleStore;
- struct List *SampleList = &SampleStore;
-
- /* this is a global variable that is set by Load8SVX to indicate whether
- * it found the sample in memory already or not. When we're playing
- * sounds for the timer and noload is selected, it's a good thing to know
- * and we already return a value (bleah, C is a bit restrictive in this
- * case)
- */
- int sample_was_in_cache;
-
- char *SamplePath = "ChatterBox:";
-
- void UnloadAllSamples()
- {
- #ifdef DEBUG
- fprintf(stderr,"UnloadAllSamples cleanup routine executing\n");
- #endif
- while (SampleList->lh_TailPred != SampleList)
- {
- UnloadSampleAt(SampleList->lh_Head);
- }
- #ifdef DEBUG
- fprintf(stderr,"UnloadAllSamples cleanup routine complete\n");
- #endif
- }
-
-
- Init8SVX()
- {
- NewList(SampleList);
- add_cleanup(UnloadAllSamples);
- }
-
- Sample *Load8SVX(fname)
- char *fname;
- {
- int iffile;
- ChunkHeader chunkhead;
- Voice8Header voicehead;
- LONG samplebytes, fibbytes;
- LONG formtype;
- char *sampbufp, *fibbufp;
- register Sample *samptr;
- LONG headsize;
- short flags = 0;
- char fnamebuf[256];
-
- assert(sizeof(chunkhead) == 8);
-
- #ifndef NOAUDIT
- if (SampleList->lh_Head == (struct Node *)NULL)
- panic("called Load8SVX without calling Init8SVX\n");
- #endif
-
- #ifdef DEBUG
- printf("checking sample store for %s - ",fname);
- #endif
- if ((samptr = (Sample *)FindName(SampleList, fname)) != NULL)
- {
- #ifdef DEBUG
- printf("request for %s satisfied from sample store\n",fname);
- #endif
- sample_was_in_cache = YES;
- return(samptr);
- }
-
- sample_was_in_cache = NO;
-
- #ifdef DEBUG
- printf("didn't find it\n");
- #endif
-
- sprintf(fnamebuf,"%s%s",SamplePath,fname);
- #ifdef DEBUG
- printf("looking for IFF file, name of %s\n",fnamebuf);
- fflush(stdout);
- #endif
- if ((iffile = OpenIFF(fnamebuf, ID_8SVX)) < 0)
- {
- fprintf(stderr,"Load8SVX: can't open IFF sample file %s\n",fnamebuf);
- return((Sample *)NULL);
- }
-
- if ((headsize = chunkuntil(iffile,ID_VHDR)) == -1)
- {
- fputs("Load8SVX: IFF 8SVX VHDR chunk search failed\n",stderr);
- return((Sample *)NULL);
- }
-
- if (!readchunk(iffile,&voicehead,headsize))
- {
- fputs("Load8SVX: read of IFF VHDR chunk failed\n",stderr);
- return((Sample *)NULL);
- }
- #ifdef DEBUG
- DumpVoiceHead(&voicehead);
- #endif
-
- if ((samplebytes = chunkuntil(iffile,ID_BODY)) < 0)
- {
- fputs("Load8SVX: IFF 8SVX BODY chunk search failed\n",stderr);
- return((Sample *)NULL);
- }
-
- if (voicehead.sCompression == sCmpFibDelta)
- {
- #ifdef DEBUG
- fprintf(stderr,"Load8SVX: sample uses Fibonacci Delta Encoding\n");
- #endif
- fibbytes = samplebytes;
- samplebytes = (fibbytes - 2) * 2;
- }
-
- if ((sampbufp = (char *)AllocMem(samplebytes,MEMF_FAST)) == (char *)NULL)
- {
- if ((sampbufp = (char *)AllocMem(samplebytes,MEMF_CHIP)) == (char *)NULL)
- {
- fputs("Load8SVX: unable to allocate memory for waveform\n",stderr);
- return((Sample *)NULL);
- }
- else
- flags = SAMPLE_ALLOCATED_IN_CHIP_RAM;
-
- }
- else
- flags = SAMPLE_ALLOCATED_IN_FAST_RAM;
-
- if (voicehead.sCompression == sCmpFibDelta)
- {
-
- /* load the delta compressed data into the back half of the sample
- * buffer just allocated. We will decompress the data into the
- * same sample memory, without overwriting the compressed data.
- * It'll work. Trust me, I know what I'm doing.
- */
-
- fibbufp = &sampbufp[samplebytes / 2];
-
- if (!readchunk(iffile,fibbufp,fibbytes))
- {
- fputs("Read of fib sample data failed!\n",stderr);
- FreeMem(sampbufp,samplebytes);
- return((Sample *)NULL);
- }
- FibUnpack(fibbufp+2,fibbytes-2,sampbufp,fibbufp[1]);
- }
- else if (!readchunk(iffile,sampbufp,samplebytes))
- {
- fputs("Read of sample data failed!\n",stderr);
- FreeMem(sampbufp,samplebytes);
- return((Sample *)NULL);
- }
-
- close(iffile);
-
- if ((samptr = (Sample *)AllocMem(sizeof(Sample),0L)) == (Sample *)NULL)
- {
- fputs("Load8SVX: unable to allocate memory for Sample structure\n",stderr);
- FreeMem(sampbufp,samplebytes);
- return((Sample *)NULL);
- }
-
- /* allocate memory for sample name */
- if ((samptr->node.ln_Name = (char *)AllocMem(strlen(fname) + 1,0)) == (char *)NULL)
- {
- fputs("Load8SVX: unable to allocate memory for Sample name\n",stderr);
- FreeMem(sampbufp,samplebytes);
- FreeMem(samptr,sizeof(Sample));
- return((Sample *)NULL);
- }
-
- /* structure copy in Voice8Header info */
- samptr->sampleheader = voicehead;
-
- /* set up pointer to sample data and store length */
- if (flags & SAMPLE_ALLOCATED_IN_FAST_RAM)
- {
- samptr->fastsampledata = sampbufp;
- samptr->sampledata = NULL;
- }
- else if (flags & SAMPLE_ALLOCATED_IN_CHIP_RAM)
- {
- samptr->fastsampledata = NULL;
- samptr->sampledata = sampbufp;
- }
- samptr->samplebytes = samplebytes;
-
- /* copy in the voice name */
- strcpy(samptr->node.ln_Name,fname);
-
- /* ...and set up the flags */
- samptr->sample_flags = flags;
-
- /* set the number of current "users" of the sample in chip RAM to zero */
- samptr->chip_use_count = 0;
-
- /* initialize the rest of the node fields */
- samptr->node.ln_Type = samptr->node.ln_Pri = 0;
-
- /* stick this new sample onto the end of the sample list */
- AddTail(SampleList,&samptr->node);
-
- #ifndef NOAUDIT
- samptr->magic = SAMPLE_MAGIC;
- #endif
-
- #ifdef DEBUG
- fprintf(stderr,"Load8SVX: waveform bytes %ld, samples/second %d\n",samplebytes,voicehead.samplesPerSec);
- fprintf(stderr,"Load8SVX: samptr %lx, sampledata %lx\n",samptr,sampbufp);
- #endif
- return(samptr);
- }
-
- /* FibUnpack - unpack Fibonacci Delta Compressed audio sample
- * see IFF file formats in the ROM Kernel Exec manual
- * or on one of the Fred Fish disks
- */
-
- char FibToDelta[16] = {-34,-21,-13,-8,-5,-3,-2,-1,0,1,2,3,5,8,13,21};
-
- FibUnpack(inp,n,outp,val)
- char *inp, *outp;
- long n;
- char val;
- {
- register char pair;
- #ifdef DEBUG
- fprintf(stderr,"FibUnpack: inp %lx, n %ld, outp %lx, val %d\n",inp,n,outp,val);
- #endif
- while (n--)
- {
- pair = *inp++; /* get a pair of compressed samples */
- val += FibToDelta[(pair >> 4) & 0xf]; /* uncompress first sample */
- *outp++ = val;
- val += FibToDelta[pair & 0xf]; /* uncompress second sample */
- *outp++ = val;
- }
- }
-
- /* unload sample at address */
- UnloadSampleAt(samptr)
- Sample *samptr;
- {
- ASSERT_SAMPLE_MAGIC(samptr);
-
- #ifdef DEBUG
- printf("UnloadSampleAt: Unloading Sample %s\n",samptr->node.ln_Name);
- #endif
-
- /* remove the sample from the sample list */
- Remove(&samptr->node);
-
- /* free the space allocated for the sample's name */
- FreeMem(samptr->node.ln_Name,strlen(samptr->node.ln_Name)+1);
-
- /* free the sample data itself */
- if (samptr->sample_flags & SAMPLE_ALLOCATED_IN_CHIP_RAM)
- {
- FreeMem(samptr->sampledata,samptr->samplebytes);
- }
- else
- {
- assert(samptr->sample_flags & SAMPLE_ALLOCATED_IN_FAST_RAM);
- FreeMem(samptr->fastsampledata,samptr->samplebytes);
- }
- #ifndef NOAUDIT
- samptr->magic = 0;
- #endif
- samptr->sample_flags = 0;
-
- /* free the sample structure */
- FreeMem(samptr,sizeof(Sample));
- }
-
- UnloadSample(name)
- char *name;
- {
- Sample *samptr;
-
- #ifdef DEBUG
- printf("UnloadSample(%s)\n",name);
- #endif
-
- if ((samptr = (Sample *)FindName(SampleList,name)) != NULL)
- UnloadSampleAt(samptr);
- else
- fprintf(stderr,"couldn't find sample %s to unload it\n",name);
- }
-
- #ifdef DEBUG
- DumpVoiceHead(vptr)
- Voice8Header *vptr;
- {
- printf("oneShotHiSamples %d, repeatHiSamples %d\n",
- vptr->oneShotHiSamples, vptr->repeatHiSamples);
- printf("samplesPerHiCycle %ld, samplesPerSec %d\n",
- vptr->samplesPerHiCycle, vptr->samplesPerSec);
- printf("ctOctave %d, sCompression %d, volume %d\n",
- vptr->ctOctave, vptr->sCompression, vptr->volume);
- }
- #endif
-
- /* end of 8svx.c */
-