home *** CD-ROM | disk | FTP | other *** search
-
- /**************************************************************************/
- /* DSound V0.91a */
- /* Copyright 1991 by Dave Schreiber, All Rights Reserved */
- /* */
- /* To compile: */
- /* lc -Lcd -v DSound */
- /* */
- /* Revision history: */
- /* V0.91a - First release (September 11, 1991) */
- /**************************************************************************/
-
- #include <exec/types.h>
- #include <exec/exec.h>
- #include <devices/audio.h>
- #include <dos/dos.h>
- #include <intuition/intuition.h>
- #include <intuition/intuitionbase.h>
- #include <graphics/gfxbase.h>
- #include "dsound.h"
-
- #include <clib/intuition_protos.h>
- #include <clib/exec_protos.h>
-
- UBYTE rightAMap[]={2,4};
- UBYTE leftAMap[]={1,8};
- UBYTE eitherAMap[]={1,2,4,8};
- UBYTE *allocationMap=eitherAMap;
- char filename[140];
-
- #define BUF_SIZE 30000
-
- void InterpretArgs(int argc,char *argv[]);
- BOOL noFilter=FALSE;
- UBYTE volume=0;
- UWORD speed=0;
- ULONG bufSize=BUF_SIZE;
-
- void filter_on(void);
- void filter_off(void);
-
- char *version="$VER: DSound V0.91a (11.9.91)";
- char *copyright="Copyright 1991 by Dave Schreiber, All Rights Reserved";
-
- struct IntuitionBase *IntuitionBase=NULL;
- struct GfxBase *GfxBase=NULL;
-
- struct Window *window=NULL;
-
- struct NewWindow newWindow=
- {
- 100,50,300,10,-1,-1,CLOSEWINDOW,WINDOWCLOSE|WINDOWDRAG|WINDOWDEPTH,
- NULL,NULL,"<-- Click to stop (DSound V0.91)",NULL,NULL,1,1,1000,1000,
- WBENCHSCREEN
- };
-
- BPTR file=NULL;
-
- main(int argc,char *argv[])
- {
- struct IOAudio *iob1,*iob2;
- struct Voice8Header vhdr;
- UBYTE foo2[5];
- ULONG len;
- ULONG toRead;
- BOOL done=FALSE;
-
- filename[0]=NULL;
-
- GfxBase=(struct GfxBase *)OpenLibrary("graphics.library",0L);
-
- IntuitionBase=(struct IntuitionBase *)OpenLibrary("intuition.library",0L);
-
- if(GfxBase==NULL || IntuitionBase==NULL)
- cleanup(50);
-
- InterpretArgs(argc,argv);
-
- if(filename[0]==NULL)
- {
- WriteMsg("Please specify a filename\n");
- cleanup(75);
- }
-
- /*Open the file*/
- file=Open(filename,MODE_OLDFILE);
- if(file==NULL)
- {
- WriteMsg("Couldn't open the file\n");
- cleanup(100);
- }
-
- newWindow.Height=IntuitionBase->ActiveScreen->Font->ta_YSize+3;
-
- window=OpenWindow(&newWindow);
-
- if(window==NULL)
- cleanup(110);
-
- /*Read the header*/
- Position(file,"VHDR");
- Read(file,foo2,4);
- Read(file,&vhdr,sizeof(struct Voice8Header));
-
- /*Check for compression*/
- if(vhdr.sCompression!=0)
- {
- WriteMsg("The sound sample is compressed\n");
- cleanup(400);
- }
-
- /*Find the BODY*/
- Position(file,"BODY");
- Read(file,foo2,4);
-
- /*Get the length of the sample*/
- len=vhdr.oneShotHiSamples;
-
- /*Get the first audio channel*/
- iob1=GetAudioChannel(bufSize);
- if(iob1==NULL)
- {
- WriteMsg("Couldn't create the first buffer\n");
- cleanup(150);
- }
-
- /* If the user didn't specify a volume, get it from the VHDR */
- if(volume==0)
- volume=(vhdr.volume>>10);
-
- /* If the VHDR gave a volume of zero, use maximum volume*/
- if(volume==0)
- volume=64;
-
- /* Get the samples/sec rate (either the rate given by the user, or the*/
- /* rate found in the VHDR) */
- if(speed==0)
- speed=1000000000/(vhdr.samplesPerSec*279);
- else
- speed=1000000000/(speed*279);
-
- InitAudioChannel(iob1,volume,speed);
-
- /*Get the 2nd audio channel*/
- iob2=DuplicateAudioChannel(iob1);
-
- if(iob2==NULL)
- {
- FreeAudioChannel(iob1);
- WriteMsg("Couldn't create the second buffer");
- cleanup(175);
- }
-
- /* Load the first buffer*/
- toRead=MIN(len,bufSize);
- LoadAudioBuffer(file,iob1,toRead);
- len-=toRead;
- iob1->ioa_Length=toRead;
-
- /* Make sure there's enough data so that we have something to put in */
- /* the second buffer */
- if(len!=0)
- {
- toRead=MIN(len,bufSize);
- LoadAudioBuffer(file,iob2,toRead);
- len-=toRead;
- iob2->ioa_Length=toRead;
- }
- else
- /* It appears that the entire sound sample is small enough to */
- /* fit into the first buffer, so don't play the second */
- iob2->ioa_Length=0;
-
- /*Switch off the filter, if necessary */
- if(noFilter)
- filter_off();
-
- /*And queue up the play requests*/
- BeginIO((struct ioRequest *)iob1);
- if(iob2->ioa_Length!=0)
- BeginIO((struct ioRequest *)iob2);
-
- /* If the sound sample was small enough to fit into the two buffers, */
- /* play them then finish up */
- if(len==0 || GetMsg(window->UserPort)!=NULL)
- {
- WaitIO((struct ioRequest *)iob1);
- if(iob2->ioa_Length!=0)
- WaitIO((struct ioRequest *)iob2);
- done=TRUE;
- }
- /*Otherwise, play those samples then read more from disk*/
-
- /*Loop while there's stuff to read*/
- while(!done)
- {
- /*Fill the first buffer*/
- WaitIO((struct ioRequest *)iob1);
-
- toRead=MIN(len,bufSize);
-
- if(toRead==0 || GetMsg(window->UserPort)!=NULL)
- {
- /*If there's no stuff left to read, wait 'till the second buffer*/
- /*finishes, then quit*/
- WaitIO((struct ioRequest *)iob2);
- done=TRUE;
- break;
- }
-
- LoadAudioBuffer(file,iob1,toRead);
- len-=toRead;
-
- /*Play the first buffer*/
- BeginIO((struct ioRequest *)iob1);
-
- /*Wait for the second buffer to finish*/
- WaitIO((struct ioRequest *)iob2);
-
- toRead=MIN(len,bufSize);
-
- if(toRead==0 || GetMsg(window->UserPort)!=NULL)
- {
- /*If there's no stuff left to read, wait 'till the first buffer*/
- /*finishes, then quit*/
- WaitIO((struct ioRequest *)iob1);
- done=TRUE;
- break;
- }
-
- /*Reload it*/
- LoadAudioBuffer(file,iob2,toRead);
- len-=toRead;
-
- /*Play it*/
- BeginIO((struct ioRequest *)iob2);
- }
-
- /*Switch the filter off if it was switched off*/
- if(noFilter)
- filter_on();
-
- /*Restore the buffer lengths, so that FreeAudio() channel, etc., knows*/
- /*how much memory to free*/
- iob1->ioa_Length=iob2->ioa_Length=bufSize;
- FreeAudioChannel(iob1);
- DeleteDuplication(iob2);
-
- /*Free allocated resources and exit*/
- cleanup(0);
- }
-
-
- // Get an audio channel
- struct IOAudio *GetAudioChannel(ULONG bufferSize)
- {
- struct IOAudio *aIOB;
- void *audioBuf;
- struct Port *aPort;
-
- aPort=(struct Port *)CreatePort("dsound",0);
- if(aPort==NULL)
- return(NULL);
-
- /* Allocate the chip memory buffer for the channel */
- audioBuf=(void *)AllocMem(bufferSize,MEMF_CHIP);
- if(audioBuf==NULL)
- {
- DeletePort(aPort);
- return(NULL);
- }
-
- /* Allocate an IOAudio structure*/
- aIOB=(struct IOAudio *)AllocMem(sizeof(struct IOAudio),MEMF_PUBLIC|MEMF_CLEAR);
- if(aIOB==NULL)
- {
- DeletePort(aPort);
- FreeMem(audioBuf,bufferSize);
- return(NULL);
- }
-
- /* Set up the IOAudio to allocate the command channel */
- aIOB->ioa_Request.io_Message.mn_Node.ln_Pri=0;
- aIOB->ioa_Request.io_Message.mn_ReplyPort=aPort;
-
- aIOB->ioa_Data=allocationMap;
- aIOB->ioa_Length=2;
- aIOB->ioa_Request.io_Command=ADCMD_ALLOCATE;
-
- OpenDevice("audio.device",0,(struct ioRequest *)aIOB,0);
- if(aIOB->ioa_AllocKey==0)
- {
- DeletePort(aPort);
- FreeMem(audioBuf,bufferSize);
- FreeMem(aIOB,sizeof(struct IOAudio));
- return(NULL);
- }
- else
- {
- /* Set up the IOAudio for writes */
- aIOB->ioa_Request.io_Command=CMD_WRITE;
- aIOB->ioa_Request.io_Flags=ADIOF_PERVOL;
- aIOB->ioa_Data=audioBuf;
- aIOB->ioa_Length=bufferSize;
- return(aIOB);
- }
- }
-
- /* Free an allocated audio channel */
- void FreeAudioChannel(struct IOAudio *aIOB)
- {
- if(aIOB==NULL)
- return;
-
- /* Free the audi obuffer */
- if(aIOB->ioa_Data!=NULL)
- FreeMem(aIOB->ioa_Data,aIOB->ioa_Length);
-
- /* Free the audio channel */
- aIOB->ioa_Request.io_Command=ADCMD_FREE;
- BeginIO((struct ioRequest *)aIOB);
- WaitIO((struct ioRequest *)aIOB);
- DeletePort(aIOB->ioa_Request.io_Message.mn_ReplyPort);
-
- /* Close the audio channel */
- CloseDevice((struct ioRequest *)aIOB);
-
- /* Free the IOAudio structure */
- FreeMem(aIOB,sizeof(struct IOAudio));
- return;
- }
-
- /* Initialize an IOAudio's volume, period, and set the number of cycles */
- /* to one */
- void InitAudioChannel(struct IOAudio *aIOB,UWORD volume,UWORD period)
- {
- aIOB->ioa_Period=period;
- aIOB->ioa_Volume=volume;
- aIOB->ioa_Cycles=1;
- return;
- }
-
- /* Duplicate an IOAudio structure */
- struct IOAudio *DuplicateAudioChannel(struct IOAudio *OrigIOB)
- {
- struct IOAudio *aIOB;
- void *audioBuf;
-
- if(OrigIOB==NULL)
- return(NULL);
-
- /* Allocate the alternate buffer */
- audioBuf=(void *)AllocMem(OrigIOB->ioa_Length,MEMF_CHIP);
- if(audioBuf==NULL)
- return(NULL);
-
- /*Allocate the IOAudio structure*/
- aIOB=(struct IOAudio *)AllocMem(sizeof(struct IOAudio),MEMF_PUBLIC|MEMF_CLEAR);
- if(aIOB==NULL)
- {
- FreeMem(audioBuf,OrigIOB->ioa_Length);
- return(NULL);
- }
-
- /*Copy the original IOAudio's contents to the new one*/
- CopyMem(OrigIOB,aIOB,sizeof(struct IOAudio));
-
- /*Except for the buffer pointer, of course*/
- aIOB->ioa_Data=audioBuf;
-
- return(aIOB);
- }
-
- /*Delete a duplicated IOAudio*/
- void DeleteDuplication(struct IOAudio *aIOB)
- {
- if(aIOB != NULL)
- {
- /* Free the memory for the buffer and IOAudio */
- if(aIOB->ioa_Data != NULL)
- FreeMem(aIOB->ioa_Data,aIOB->ioa_Length);
- FreeMem(aIOB,sizeof(struct IOAudio));
- }
- return;
- }
-
- /* Load an IOAudio's buffer from an open file */
- ULONG LoadAudioBuffer(BPTR file,struct IOAudio *aIOB,ULONG toRead)
- {
- if(toRead==0)
- return(0);
- aIOB->ioa_Length=Read(file,aIOB->ioa_Data,toRead);
- return(aIOB->ioa_Length);
- }
-
- /* Seek forward in a file until the given string is found (useful for */
- /* finding chunk in IFF files */
- void Position(BPTR file,char *string)
- {
- UBYTE len;
- char chr;
- UBYTE i;
-
- len=strlen(string);
-
- for(;;)
- {
- Read(file,&chr,1);
- if(chr==string[0])
- {
- Read(file,&chr,1);
- for(i=1;i<4 && string[i]==chr;i++)
- {
- if(i!=3)
- Read(file,&chr,1);
- }
- if(i==4)
- return;
- }
- }
- }
-
-
- /* Interpret the command line arguments */
- void InterpretArgs(int argc,char *argv[])
- {
- int i;
-
- for(i=1;i<argc;i++)
- {
- if(argv[i][0]=='-')
- switch(argv[i][1])
- {
- /* Use the left channel */
- case 'l':
- case 'L':
- allocationMap=leftAMap;
- break;
-
- /* Use the right channel */
- case 'r':
- case 'R':
- allocationMap=rightAMap;
- break;
-
- /* Switch off the low-pass filter while the sample is playing */
- case 'f':
- case 'F':
- noFilter=TRUE;
- break;
-
- /* Play a sample at a given speed */
- case 's':
- case 'S':
- speed=atol(&argv[i][2]);
- if(speed > 28000)
- speed=0;
- break;
-
- /* The volume at which the sample should be played */
- case 'v':
- case 'V':
- volume=atol(&argv[i][2]);
- if(volume > 64)
- volume=0;
- break;
-
- /* The size of the chip RAM buffers */
- case 'b':
- case 'B':
- bufSize=(atol(&argv[i][2])+1)&(~1);
- if(bufSize==0)
- bufSize=BUF_SIZE;
- break;
- }
- else if(argv[i][0]=='?')
- {
- /*On-line help*/
- WriteMsg("DSound V0.91a ©1991 by Dave Schreiber\n");
- WriteMsg("Usage:\m");
- WriteMsg(" DSound <options> <filename>\n");
- WriteMsg("Where the options are:\n");
- WriteMsg(" -l -- Play the sample using the left speaker\n");
- WriteMsg(" -r -- Play the sample using the right speaker\n");
- WriteMsg(" -f -- Shut off the low-pass filter\n");
- WriteMsg(" -s<speed> -- Play the sample at the given speed (samples/sec)\n");
- WriteMsg(" -v<volume> -- Play the sample at the given volume (0-64)\n");
- WriteMsg(" -b<bufsize> -- Use a buffer of size <bufsize> (default is 30K)\n");
- exit(0);
- }
- else /*Otherwise, the argument is a filename */
- strcpy(filename,argv[i]);
- }
- }
-
- /*Switch on the low-pass filter */
- void filter_on()
- {
- *((char *)0x0bfe001)&=0xFD;
- }
-
- /*Switch off the low-pass filter*/
- void filter_off()
- {
- *((char *)0x0bfe001)|=0x02;
- }
-
- /*Write a message to the CLI*/
- void WriteMsg(char *errMsg)
- {
- Write(Output(),errMsg,strlen(errMsg));
- }
-
- /* Free allocated resources */
- void cleanup(int err)
- {
- if(file!=NULL)
- Close(file);
-
- if(window!=NULL)
- CloseWindow(window);
-
- if(GfxBase!=NULL)
- CloseLibrary((struct Library *)GfxBase);
-
- if(IntuitionBase!=NULL)
- CloseLibrary((struct Library *)IntuitionBase);
-
- exit(err);
- }
-
-
-