home *** CD-ROM | disk | FTP | other *** search
-
- /**************************************************************************/
- /* DSound V1.20 */
- /* Copyright 1991-1992 by Dave Schreiber, All Rights Reserved */
- /* */
- /* To compile: */
- /* lc -Lcd -v -tr DSound Play Mem */
- /* or */
- /* lmk */
- /* */
- /* Revision history: */
- /* V1.20 - Added the ability to stop DSound by typing CTRL-C, and */
- /* added the switch '-w', which keeps the DSound window from */
- /* opening. */
- /* V1.10 - Added the ability to play a sound sample repeatedly (in a */
- /* loop). */
- /* July 11, 1992 */
- /* V1.00 - Added a new module (Mem.c) which allows a sample to be */
- /* loaded entirely into memory, so samples can be played from */
- /* floppy disk without first copying to a hard or RAM drive. */
- /* DSound also can now play a single channel of a stereo */
- /* out of two speakers. The small window, used to let the */
- /* user abort a playing sample, as been redone (DSound also */
- /* now responds instantly when the user clicks on the Close */
- /* gadget). DSound now checks a given 8SVX sample to make */
- /* sure that it is actually a valid sample. Finally, DSound */
- /* has been made pure (residentiable). */
- /* Second release (April 16, 1992) */
- /* V0.94a - Can now play a mono sample out of both speakers at the */
- /* same time (using the -2 switch). */
- /* March 27, 1992 (a little later) */
- /* V0.93a - Now handles stereo sound samples. Either the right or */
- /* left, or both, stereo channels can be played. Also split */
- /* off the code that actually plays the sound sample into a */
- /* separate source file (Play.c). */
- /* March 27, 1992 */
- /* V0.92a - Now gets the length of the sound sample from the head of */
- /* the BODY chunk, instead of the VHDR (a workaround to a bug */
- /* in the Perfect Sound software that would sometimes store */
- /* an incorrect length in the VHDR chunk of a sound sample). */
- /* November 4, 1991 */
- /* 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 <stdlib.h>
- #include <stdio.h>
-
- #include "dsound.h"
-
- #include <proto/intuition.h>
- #include <proto/exec.h>
- #include <proto/dos.h>
-
- char filename[140];
-
- #define DEF_BUF_SIZE 30000
-
- void InterpretArgs(int argc,char *argv[]);
- BOOL noFilter=FALSE;
- UBYTE volume=0;
- UWORD speed=0;
- ULONG bufSize=DEF_BUF_SIZE;
-
- void filter_on(void);
- void filter_off(void);
-
- char *version="$VER: DSound V1.20 (23.8.92)";
- char *copyright="Copyright 1991-1992 by Dave Schreiber, All Rights Reserved";
-
- struct IntuitionBase *IntuitionBase=NULL;
- struct GfxBase *GfxBase=NULL;
-
- struct Window *window=NULL;
-
- BPTR file=NULL;
-
- channel audioChannel=UNSPECIFIED;
- BOOL bothChan=FALSE;
- BOOL readAll=FALSE;
- BOOL loop=FALSE;
-
- /*The window definition*/
- struct NewWindow newWindow = {
- 124,31,
- 250,56,
- 0,1,
- CLOSEWINDOW,
- SMART_REFRESH|WINDOWDRAG|WINDOWDEPTH|WINDOWCLOSE,
- NULL,
- NULL,
- "DSound V1.20",
- NULL,
- NULL,
- 5,5,
- 640,200,
- WBENCHSCREEN
- };
-
- /*This determines whether or not the window will be opened*/
- BOOL openTheWdw=TRUE;
- ULONG signalMask=SIGBREAKF_CTRL_C;
-
- main(int argc,char *argv[])
- {
- struct Voice8Header vhdr;
- UBYTE foo2[5];
- UBYTE foo[5];
- ULONG chan;
- ULONG sampleLength;
- ULONG lock;
- char *chanStr;
-
- filename[0]=NULL;
-
- /*Get and interpret the command-line arguments*/
- InterpretArgs(argc,argv);
-
- /*Exit if there was no sound sample specified*/
- if(filename[0]==NULL)
- {
- WriteMsg("Please specify the name of a sound sample\n");
- cleanup(75);
- }
-
- /*Open the file*/
- file=Open(filename,MODE_OLDFILE);
- if(file==NULL)
- {
- WriteMsg("Couldn't open the file\n");
- cleanup(100);
- }
-
- /*If the user hasn't told us not to open the window*/
-
- if(openTheWdw)
- {
- /*Open libraries*/
- GfxBase=(struct GfxBase *)OpenLibrary("graphics.library",0L);
- IntuitionBase=(struct IntuitionBase *)OpenLibrary("intuition.library",0L);
-
- if(GfxBase==NULL || IntuitionBase==NULL)
- {
- WriteMsg("A shared library could not be opened\n");
- cleanup(50);
- }
-
- /*Get the size of the title bar font in a rather illegal way */
- /*Note: programmers at C= should put a GetDefTitleBarFontHeight() */
- /*function into Intuition before complaining to me about the following*/
- /*code. */
-
- lock=LockIBase(0L);
- newWindow.Height=IntuitionBase->ActiveScreen->Font->ta_YSize+3;
- UnlockIBase(lock);
-
- window=OpenWindow(&newWindow);
-
- if(window==NULL)
- cleanup(110);
- signalMask|=1<<window->UserPort->mp_SigBit;
- }
-
- /*Read the header*/
- Read(file,foo,4);
- Seek(file,4,OFFSET_CURRENT);
- Read(file,foo2,4);
-
- foo[4]=foo2[4]=NULL;
-
- /*Check the header's validity, more or less*/
- if((strcmp(foo,"FORM")!=0) || (strcmp(foo2,"8SVX")!=0))
- {
- WriteMsg("Not a valid IFF 8SVX sound sample file.\n");
- cleanup(120);
- }
-
- if(strcmp(FindChunk(file,"VHDR"),"VHDR")!=0)
- {
- WriteMsg("Couldn't find the 8SVX header (VHDR).\n");
- cleanup(130);
- }
-
- /*Skip past the chunk size*/
- Seek(file,4,OFFSET_CURRENT);
-
- /*Get the VHDR*/
- Read(file,&vhdr,sizeof(struct Voice8Header));
-
- /*Check for compression*/
- if(vhdr.sCompression!=0)
- {
- WriteMsg("Can't play a compressed sample!\n");
- cleanup(400);
- }
-
- /*Get the CHAN chunk (which will tell us if the sample is stereo, or,*/
- /*if it is mono, which speaker it should be played out of*/
- chanStr=FindChunk(file,"CHAN");
- if(strcmp(chanStr,"CHAN")==0)
- {
- /*Skip past chunk size*/
- Seek(file,4,OFFSET_CURRENT);
- Read(file,&chan,sizeof(long));
-
- /*The information we're looking for consists of one longword*/
- switch(chan)
- {
- case 2: /*Mono sample, left speaker*/
- if(bothChan)
- /*Play out of both channels if -2 used*/
- audioChannel=MONO_BOTH;
- else
- if(audioChannel==UNSPECIFIED)
- audioChannel=MONO_LEFT;
- break;
- case 4: /*Mono sample, right speaker*/
- if(bothChan)
- /*Play out of both channels if -2 used*/
- audioChannel=MONO_BOTH;
- else
- if(audioChannel==UNSPECIFIED)
- audioChannel=MONO_RIGHT;
- break;
- case 6: /*Stereo*/
- switch(audioChannel)
- {
- /*This reconciles a user's choice with the fact that the*/
- /*sample is in stereo*/
-
- /*Play left stereo channel*/
- case MONO_LEFT:
- if(bothChan)
- audioChannel=STEREO_LEFT_BOTH;
- else
- audioChannel=STEREO_LEFT;
- break;
-
- /*Play right stereo channel*/
- case MONO_RIGHT:
- if(bothChan)
- audioChannel=STEREO_RIGHT_BOTH;
- else
- audioChannel=STEREO_RIGHT;
- break;
-
- /*Play both channels*/
- case UNSPECIFIED:
- audioChannel=STEREO;
- break;
- }
- break;
- }
-
- /*Find the start of the BODY chunk*/
- chanStr=FindChunk(file,"BODY");
- }
- else
- {
- chan=0;
- if(bothChan)
- audioChannel=MONO_BOTH;
- }
-
- if(strcmp(chanStr,"BODY")!=0)
- {
- WriteMsg("Couldn't find body of sample.\n");
- cleanup(140);
- }
-
- if(noFilter)
- filter_off();
-
- /*Get the length of the sample*/
- Read(file,(char *)&sampleLength,4);
-
- SetSignal(0,0);
-
- /*Play the sample by choosing the appropriate player function*/
- switch(audioChannel)
- {
- case MONO_LEFT:
- case MONO_RIGHT:
- case UNSPECIFIED:
- /*Simple mono playback*/
- playMonoSample(file,audioChannel,&vhdr,sampleLength);
- break;
- case MONO_BOTH:
- /*Mono playback using both speakers*/
- playMonoTwice(file,audioChannel,&vhdr,sampleLength);
- break;
- case STEREO_RIGHT:
- /*Right stereo channel*/
- audioChannel=MONO_RIGHT;
- Seek(file,sampleLength/2,OFFSET_CURRENT);
- playMonoSample(file,audioChannel,&vhdr,sampleLength/2);
- break;
- case STEREO_RIGHT_BOTH:
- /*Right stereo channel out of both speakers*/
- audioChannel=MONO_RIGHT;
- Seek(file,sampleLength/2,OFFSET_CURRENT);
- playMonoTwice(file,audioChannel,&vhdr,sampleLength/2);
- break;
- case STEREO_LEFT:
- /*Left stereo channel*/
- audioChannel=MONO_LEFT;
- playMonoSample(file,audioChannel,&vhdr,sampleLength/2);
- break;
- case STEREO_LEFT_BOTH:
- /*Left stereo channel out of both speakers*/
- audioChannel=MONO_LEFT;
- playMonoTwice(file,audioChannel,&vhdr,sampleLength/2);
- break;
- case STEREO:
- /*Stereo sample (both channels)*/
- playStereoSample(file,audioChannel,&vhdr,sampleLength/2,filename);
- break;
- }
-
- if(noFilter)
- filter_on();
-
- /*Free allocated resources and exit*/
- cleanup(0);
- }
-
-
-
- /* Get an audio channel */
- struct IOAudio *GetAudioChannel(ULONG bufferSize,UBYTE *allocationMap)
- {
- 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=4;
- aIOB->ioa_Request.io_Command=ADCMD_ALLOCATE;
-
- /*Open the audio device*/
- OpenDevice("audio.device",0,(struct IORequest *)aIOB,0);
-
-
- if(aIOB->ioa_AllocKey==0)
- { /*There was an error*/
- 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);
-
- if(file==0L)
- getLeft(aIOB->ioa_Data);
- else if(file==4L)
- getRight(aIOB->ioa_Data);
- else
- aIOB->ioa_Length=Read(file,aIOB->ioa_Data,toRead);
- return(aIOB->ioa_Length);
- }
-
- /*Find the beginning of an IFF chunk. This routine will search for that*/
- /*chunk's name, and if found, will leave the file cursor at the chunk size*/
- /*field. If the chunk isn't found, the file cursor will be left at the*/
- /*size field of the BODY chunk, if there was one*/
- char *FindChunk(BPTR file,char *string)
- {
- static char buf[5];
- long len,actLen;
- buf[4]=NULL;
-
- actLen=Read(file,buf,4);
- while(strcmp(string,buf)!=0 && strcmp(buf,"BODY")!=0 && actLen > 0)
- {
- Read(file,(char *)&len,4);
- Seek(file,len,OFFSET_CURRENT);
- actLen=Read(file,buf,4);
- }
- return(buf);
- }
-
- /* 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])
- {
- /* Read the entire sample into memory before playing */
- case 'm':
- case 'M':
- readAll=TRUE;
- break;
-
- /* Use the left channel */
- case 'l':
- case 'L':
- audioChannel=MONO_LEFT;
- break;
-
- /* Use the right channel */
- case 'r':
- case 'R':
- audioChannel=MONO_RIGHT;
- break;
-
- /*Play a mono sample out of both speakers*/
- case '2':
- bothChan=TRUE;
- 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=DEF_BUF_SIZE;
- break;
-
- /* Loop the sample */
- case 'o':
- case 'O':
- loop=TRUE;
- break;
-
- case 'w':
- case 'W':
- openTheWdw=FALSE;
- break;
- }
- else if(argv[i][0]=='?')
- {
- /*On-line help*/
- WriteMsg("DSound V1.20 ©1991-1992 by Dave Schreiber\n");
- WriteMsg("Usage:\n");
- 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(" -2 -- Play the sample using both speakers\n");
- WriteMsg(" -f -- Shut off the low-pass filter\n");
- WriteMsg(" -m -- Load the entire sample into memory\n");
- WriteMsg(" -o -- Play the sample continuously (loop)\n");
- WriteMsg(" -w -- Do not open the DSound window\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));
- }
-
- /*Take a file handle and that handle's filename, and open that file again*/
- /*The position in the second file in set to the position in the first */
- /*file (so that the two file handles are essentially identical)*/
- /*This requires that the first file was opened in a shared mode, like */
- /*MODE_OLDFILE*/
- BPTR dupFileHandle(BPTR origFile,char *filename)
- {
- BPTR dupFile;
-
- dupFile=Open(filename,MODE_OLDFILE);
-
- if(dupFile==NULL)
- return(NULL);
-
- Seek(dupFile,getPosInFile(origFile),OFFSET_BEGINNING);
- return(dupFile);
- }
-
- /*Get the current position in a file*/
- ULONG getPosInFile(BPTR file)
- {
- LONG position;
-
- position=Seek(file,0,OFFSET_CURRENT);
- return((ULONG)position);
- }
-
- /* Free allocated resources */
- void cleanup(int err)
- {
- /*If the entire sample was read into memory, this will delete whatever*/
- /*part of the sample still remains in memory*/
- deleteLeft();
- deleteRight();
-
- 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);
- }
-
- #ifdef LATTICE
- int CXBRK(void) {return(0);}
- int chkabort(void) {return(0);}
- #endif
-
- /*End of DSound.c*/
-
-