/*$Author: DCODY $*/ /*$Date: 06 Oct 1992 15:15:50 $*/ /*$Header: X:/sccs/pcmapps/playfile.c_v 1.10 06 Oct 1992 15:15:50 DCODY $*/ /*$Log: X:/sccs/pcmapps/playfile.c_v $ * * Rev 1.10 06 Oct 1992 15:15:50 DCODY * No change. * * Rev 1.9 24 Sep 1992 08:59:20 DCODY * changed MVGetHardware to mvGetHardware * * Rev 1.8 14 Sep 1992 17:22:38 SHAO_M * Put all the text strings used in printf into playtext.h * * Rev 1.0 14 Sep 1992 17:01:30 unknown * Initial revision. * * Rev 1.7 13 Aug 1992 08:26:18 DCODY * corrected #if/#endif and } placement for TB stuff... * * Rev 1.6 04 Aug 1992 11:39:54 DCODY * corrected t&l spelling * * Rev 1.5 28 Jul 1992 14:29:06 DCODY * updated for Thunderboard and Thunder&Lightning * * Rev 1.4 20 Jul 1992 11:39:02 DCODY * call to mvGetHWVersion now uses active I/O address detection. * * Rev 1.3 13 Jul 1992 18:54:14 DCODY * removed initmvsound call * * Rev 1.2 01 Jul 1992 11:55:16 DCODY * GaryL: Added OEM compiler flag checking for Welcome() * to use the generic board name and to not display the MVI copyright. * Note that the copyright is still present, as an imbedded static string. * * Rev 1.1 23 Jun 1992 16:09:50 DCODY * pas2 update... * * Rev 1.0 15 Jun 1992 09:26:40 BCRANE * Initial revision. */ /*$Logfile: X:/sccs/pcmapps/playfile.c_v $*/ /*$Modtimes$*/ /*$Revision: 1.10 $*/ /*$Workfile: playfile.c $*/ /*\ |*|----====< PLAYFILE.C >====---- |*| |*| Play the voice file from disk to the PCM hardware |*| |*| Copyright (c) 1991, Media Vision, Inc. All rights reserved. |*| \*/ #ifndef OEM #define OEM 0 /* OEM compile flag */ #endif #ifndef PROAS #define PROAS 0 /* Pro Audio Spectrum compile flag */ #endif #ifndef THUNDER #define THUNDER 0 /* Thunder Board compile flag */ #endif #include #include #include #include #include "playtext.h" #if PROAS #include "play.h" #include "common.h" #include "pcmio.h" #endif #if THUNDER #include "proto.h" #include "play.h" #include "common.h" #include "pcmio.h" #include "mvsound.h" #endif /*\ |*|----====< Global Variables >====---- \*/ extern int DMARunning; long mvGetHWVersion (int); /*\ |*|----====< Local Variables >====---- \*/ static FILE *inf; /* user input file */ static long SampleRate = 11025L;/* default sample rate */ static int StereoMono = 0; /* default to mono */ static int Filter = -1; /* filter override # */ static int Compression= FALSE; /* compressed data */ static int DMAChannel = -1; /* default to standard DMA */ static int IRQChannel = -1; /* default to standard IRQ */ static int speed = 100; /* 100 percent */ static int UserStereoMono = -1;/* user's override flag = mono */ static long UserSampleRate = -1;/* user's override = 11k */ static long DataLength = -1;/* -1 goes to EOF */ static int maxsize = 16; /* 16k DMA buffer size */ static int maxdiv = 4; /* 4k divisions on the DMA */ static int datasize = 8; /* 8 bit or 16 bit pcm */ static int dsoverride = FALSE; /* data size override */ #define ALLOTHERS 0 /* assume an 8 bit data file */ #define WAVEFILE 1 /* wave type of file */ #define VOCFILE 2 /* .voc 8 bit pcm file */ static int FileType; /* type of source file */ #define BUFFLEN 4096 static char vocbuffer[BUFFLEN]; /* 4k worth of data */ static long VOCBlockLength; /* current block length */ static char VOCBlockType; /* current block type */ static char VOCPackType; int CommandLine ( int, char *[] ); int DoExit ( int ); int FetchVOCData ( char * ); /* buffer of PCM data */ int PreProcessFile ( char * ); int SetupPlayRate ( ); void SetupSound ( ); /*\ |*|----====< Main >====---- |*| |*| Play the voice file out to the PCM hardware |*| \*/ main(argc,argv) int argc; char *argv[]; { char c; /* give the opening welcome & checkout the hardware */ Welcome(); /* set the runtime switches */ CommandLine (argc,argv); /* disable the ^C */ signal (SIGINT,SIG_IGN); /* need a file name to play, exit if not found */ PreProcessFile (argv[1]); if (OpenPCMBuffering(DMAChannel,IRQChannel,maxsize,maxdiv)) { printf (TXT_MSG1); DoExit (-1); } /* setup how this file sounds */ SetupSound(); /* Start the DMA & wait till an ESC is typed or data ends */ printf (TXT_MSG2); if (FileType <= WAVEFILE) { /* .WAV & all other files can go out using normal file I/O */ if (StartFileOutput( inf, DataLength )) { while (1) { /* if all done, then just break */ if (!ContinueFileOutput()) break; /* if ESC typed, kill the DMA & exit */ if (kbhit()) { if ((c = getch()) == 0x1b) { StopDMAIO(); break; } if (c == ' ') { PausePCM(); printf (TXT_MSG3); GetKey(); printf (TXT_MSG4); ResumePCM(); } } } } } else { /* if there is data available, play it... */ if (FetchVOCData(vocbuffer)) { /* start the output with the first block of data */ if (StartBlockOutput( vocbuffer )) { /* fetch the next block of data */ FetchVOCData(vocbuffer); while (1) { /* if the block can be passed, reload it */ if (ContinueBlockOutput(vocbuffer)) { if (!FetchVOCData(vocbuffer)) break; } /* if ESC typed, kill the DMA & exit */ if (kbhit()) { if ((c = getch()) == 0x1b) { StopDMAIO(); DoExit(0); } if (c == ' ') { PausePCM(); printf (TXT_MSG5); GetKey(); printf (TXT_MSG6); ResumePCM(); } } } /* wait till the DMA finishes */ while (DMARunning) ; } } } /* exit to DOS */ DoExit(0); } /*\ |*|----====< CommandLine >====---- |*| |*| process the command line switches |*| \*/ int CommandLine(argc,argv) int argc; char *argv[]; { char *s; int n,temp; long longtemp; /* exit if no additional parameters */ if (argc < 2) { GiveHelps(); DoExit (-1); } n = 2; while (n < argc) { s = argv[n++]; if (*s == '/') s++; if (*s == '-') s++; switch (*s & 0x5f) { #if PROAS case '1' & 0x5f: case '8' & 0x5f: if (*++s == '6') datasize = 16; dsoverride = TRUE; break; case 'F': Filter = *++s - 0x30; if ((Filter > 6) || (Filter < 0)) Filter = -1; break; #endif case 'D': temp = *++s - 0x30; if ((temp <= 7) && (temp >= 1)) { if (temp == 4) temp = 0; DMAChannel = temp; } break; case 'I': if (sscanf (++s,"%d",&temp) == 1) { if ((1 << temp) & 0x9CBC) IRQChannel = temp; } break; case 'M': maxsize = 64; maxdiv = 16; break; case 'R': if (sscanf (++s,"%ld",&longtemp) == 1) { if ((longtemp >4000L) && (longtemp < 88200L)) UserSampleRate = longtemp; } break; case 'S': s++; if (*s == '\0') UserStereoMono = 1; else { if (sscanf (s,"%d",&temp) == 1) { if ((temp >= 0) && ( temp <= 200)) speed = temp; } } break; default: break; } } } /*\ |*|----====< DoExit() >====---- |*| |*| Exit to DOS |*| \*/ int DoExit(cc) int cc; { ClosePCMBuffering(); exit (cc); } /*\ |*|----====< GiveHelps() >====---- |*| |*| print text helps & return |*| \*/ int GiveHelps() { /* print & return... */ #if PROAS printf (TXT_MSG7); printf (TXT_MSG8); printf (TXT_MSG9); printf (TXT_MSG10); printf (TXT_MSG11); printf (TXT_MSG12); printf (TXT_MSG13); printf (TXT_MSG14); printf (TXT_MSG15); printf (TXT_MSG16); printf (TXT_MSG17); #endif #if THUNDER printf (TXT_MSG18); printf (TXT_MSG19); printf (TXT_MSG20); #if THUNDER==2 printf (TXT_MSG21); printf (TXT_MSG22); #else printf (TXT_MSG23); #endif printf (TXT_MSG24); printf (TXT_MSG25); printf (TXT_MSG26); #endif } /*\ |*|----====< FetchVOCData >====---- |*| |*| Get a new key |*| \*/ int FetchVOCData(buff) char *buff; { int loaded = 0, n; int looping = TRUE; int remaining = BUFFLEN; /* grab the next block of data */ looping = 1; while (looping) { /* process the header */ switch (VOCBlockType) { case TERMINATOR: for (;remaining;remaining--) *buff++ = 0x80; remaining = 0; looping = 0; /* this will knock us out */ break; case VOICECONTINUE: case VOICEDATA: /* load the data, try to span blocks */ if (VOCBlockLength < remaining) { remaining -= VOCBlockLength; n = fread (buff,1,(size_t)VOCBlockLength,inf); loaded += n; buff += n; VOCBlockLength = 0; } else { n = fread(buff,1,remaining,inf); loaded += n; VOCBlockLength -= n; looping = remaining = 0; } break; case SILENCE: /* load the data, try to span blocks */ if (VOCBlockLength < remaining) { remaining -= VOCBlockLength; loaded += VOCBlockLength; for (;VOCBlockLength;VOCBlockLength--) *buff++ = 0x80; } else { loaded = remaining; VOCBlockLength -= remaining; for (;remaining;remaining--) *buff++ = 0x80; looping = remaining = 0; } break; case MARKER: case REPEAT: case ENDREPEAT: case ASCIITEXT: /* all the rest of the header were eaten by the */ /* "GetNextBlock" routine. We will continue till we */ /* find data, or the terminating record */ default: break; } /* span blocks, but exit on EOF */ if (remaining) { if (!GetNextBlock()) { for (;remaining;remaining--) *buff++ = 0x80; looping = FALSE; } } } /* return with data data block */ return(loaded); } /*\ |*|----====< GetKey() >====---- |*| |*| Get a new key |*| \*/ int GetKey() { char c; while (kbhit()) getch(); while (!kbhit()) ; if (getch() == 0) getch(); } /*\ |*|----====< GetNextBlock() >====---- |*| |*| Process the header to the next block, & return TRUE if data is |*| pointed to. |*| \*/ int GetNextBlock() { int looping = TRUE; long l; /* get the record type & process to get the sample rate */ VOCBlockLength = 0; /* we must end up with data! */ while (looping) { switch (VOCBlockType = fgetc(inf)) { case TERMINATOR: return(0); /* if at the end, just exit */ case SILENCE: fgetc(inf);fgetc(inf);fgetc(inf); VOCBlockLength = fgetc(inf) & 0xff; VOCBlockLength += ((long)(fgetc(inf) & 0xff)) << 8; SetupPlayRate(fgetc(inf) & 0xff); VOCBlockLength -= 3; /* 3 less for header data */ looping = FALSE; break; case VOICEDATA: VOCBlockLength = fgetc(inf) & 0xff; VOCBlockLength += ((long)(fgetc(inf) & 0xff)) << 8; VOCBlockLength += ((long)(fgetc(inf) & 0xff)) << 16; SetupPlayRate(fgetc(inf) & 0xff); /* determine mono/stereo */ StereoMono = 0; if (((VOCPackType = fgetc(inf)) & 0xff) == 5) { StereoMono = 1; VOCPackType = 0; } #if THUNDER /* determine compression */ if (VOCPackType <= 3) /* types 0 - 3 */ Compression = VOCPackType; #endif VOCBlockLength -= 2; /* 2 less for header data */ looping = FALSE; break; case ASCIITEXT: l = fgetc(inf) & 0xff; l += ((long)(fgetc(inf) & 0xff)) << 8; l += ((long)(fgetc(inf) & 0xff)) << 16; for (;l;l--) fgetc(inf); break; case MARKER: case REPEAT: fgetc(inf);fgetc(inf); case ENDREPEAT: fgetc(inf);fgetc(inf);fgetc(inf); break; default: printf (TXT_MSG27); DoExit(-1); break; } } /* we leave the file pointing to the first data byte */ return(1); } /*\ |*|----====< PreProcessFile >====---- |*| |*| Fill the play buffer with the contents of the disk file |*| \*/ int PreProcessFile (fn) char *fn; { char buff[100]; int n,looping; long psize,l; char *p,*b; long* ptr; FILE *wf; /* attempt to open the users disk file */ if ((inf = fopen(fn,"rb")) == 0) { strcpy (buff,fn); strcat (buff,".WAV"); if ((inf = fopen(buff,"rb")) == 0) { strcpy (buff,fn); strcat (buff,".VOC"); if ((inf = fopen(buff,"rb")) == 0) { printf (TXT_MSG28,fn); DoExit (-1); } } } /* get the 1st 2 characters in the file */ n = fgetc(inf) & 0xff; n = n + ((fgetc(inf) & 0xff) << 8); fseek (inf,0L,SEEK_SET); /* rewind to the start */ /* special case a .WAV file */ if (n == 0x4952) { ProcessWAVFile(); return(0); } /* special case anything else than a .VOC file */ if (n != 0x7243) { /* if NE to Creative..., then it's PCM */ ProcessPCMFile(); return(0); } /* .VOC type of source file */ FileType = VOCFILE; /* get the header of the voice file */ b = &buff[0]; fseek(inf,0L,SEEK_SET); /* move to the first byte */ for (n=0;n<(sizeof (VOCHDR));n++) *b++ = fgetc(inf); if (feof(inf)) { printf (TXT_MSG29); DoExit (-1); } /* Make sure it's a legit file */ if (strncmp (buff,"Creative Voice File",0x13) != 0) { printf (TXT_MSG30); DoExit (-1); } p = &buff[0x14]; /* get a pointer to the offset */ psize = LONG(*p) & 0xffff; /* get the 16 bit word */ fseek(inf,psize,SEEK_SET); /* move to the first byte */ if (!GetNextBlock()) /* process the next header */ DoExit(0); } /*\ |*|----====< ProcessWAVFile >====---- |*| |*| load the header from our WAV file format |*| \*/ int ProcessWAVFile(f) { int n; char *b,c; WaveInfo whd; DataHeader dhd; /* We are a WAVE file */ FileType = WAVEFILE; /* type of source file */ /* eat the RIFF portion of the header */ c = fgetc(inf); if (c == 'R') { for (n=7;n;n--) fgetc(inf); c = fgetc(inf); } /* pas up the wave block header name */ if (c != 'W') { printf (TXT_MSG31); DoExit(-1); } fgetc(inf); fgetc(inf); fgetc(inf); /* move past the data */ /* pass up the format section name */ c = fgetc(inf); if (c != 'f') { printf (TXT_MSG32); DoExit(-1); } for (n=7;n;n--) fgetc(inf); /* move past the data */ /* load the actual header data */ b = (char *) &whd; for (n=0;n====---- |*| |*| load the header from our PCM file format |*| \*/ int ProcessPCMFile() { int n; char *b; /* we are some unknown data type */ FileType = ALLOTHERS; /* type of source file */ /* ask for the sample rate */ if (UserSampleRate != -1) { SampleRate = UserSampleRate; if (UserStereoMono == -1) UserStereoMono = 0; StereoMono = UserStereoMono; } else { SampleRate = 11025L; printf (TXT_MSG34); while (1) { if (scanf ("%ld",&SampleRate) == 1) break; } printf (TXT_MSG35); while (1) { if (scanf ("%d",&StereoMono) == 1) { StereoMono--; /* make it zero based */ break; } } } if ((StereoMono < 0) || (StereoMono > 1)) StereoMono = 0; } /*\ |*|----====< SetupPlayRate >====---- |*| |*| Setup the playing rate of the interrupt routine. |*| \*/ int SetupPlayRate(n) int n; { /* we will use a default rate */ SampleRate = 11025L; /* search for the real rate */ while (1) { if (n <= 6) { SampleRate = 4000L; /* 4000 kh sampling */ break; } if (n <= 56) { SampleRate = 5000L; /* 5000 kh sampling */ break; } if (n <= 90) { SampleRate = 6000L; /* 6000 kh sampling */ break; } if (n <= 114) { SampleRate = 7000L; /* 7000 kh sampling */ break; } if (n <= 131) { SampleRate = 8000L; /* 8000 kh sampling */ break; } if (n <= 145) { SampleRate = 9000L; /* 9000 kh sampling */ break; } if (n <= 156) { SampleRate = 10000L; /* 10000 kh sampling */ break; } if (n <= 166) { SampleRate = 11000L; /* 11000 kh sampling */ break; } if (n <= 173) { SampleRate = 12000L; /* 11000 kh sampling */ break; } if (n <= 180) { SampleRate = 13000L; /* 11000 kh sampling */ break; } if (n <= 185) { SampleRate = 14000L; /* 11000 kh sampling */ break; } if (n <= 190) { SampleRate = 15000L; /* 11000 kh sampling */ break; } if (n <= 194) { SampleRate = 16000L; /* 11000 kh sampling */ break; } if (n <= 198) { SampleRate = 17000L; /* 11000 kh sampling */ break; } if (n <= 201) { SampleRate = 18000L; /* 11000 kh sampling */ break; } if (n <= 204) { SampleRate = 19000L; /* 11000 kh sampling */ break; } if (n <= 206) { SampleRate = 20000L; /* 11000 kh sampling */ break; } if (n <= 209) { SampleRate = 21000L; /* 11000 kh sampling */ break; } if (n <= 211) { SampleRate = 22000L; /* 11000 kh sampling */ break; } if (n <= 215) { SampleRate = 23000L; /* 11000 kh sampling */ break; } /* if unknown value, bomb out... */ printf (TXT_MSG36); DoExit(0); } } /*\ |*|----====< SetupSound() >====---- |*| |*| Setup the sample rate, stereo/mono. |*| \*/ void SetupSound() { /* if the user wants it different... */ if (UserSampleRate != -1) SampleRate = UserSampleRate; if (UserStereoMono != -1) StereoMono = UserStereoMono; /* speed is the user's %. from 0 to 200 % */ SampleRate = ((SampleRate * speed) + 50) / 100; #if PROAS ChooseFilter( SampleRate, Filter ); #endif PCMState (SampleRate, StereoMono, Compression, datasize ); } /*\ |*|----====< Welcome >====---- |*| |*| Print the logo & check for the appropriate hardware |*| \*/ Welcome() { long ver; /* give the normal stuff... */ #if OEM #if PROAS printf (TXT_MSG37); #endif #if THUNDER printf (TXT_MSG38); #endif { static char zsCopyright[] = "Copyright (c) 1991,1992 Media Vision, Inc. All Rights Reserved\n\n"; } #else #if PROAS printf (TXT_MSG39); #endif #if THUNDER #if THUNDER==2 printf (TXT_MSG40); #else printf (TXT_MSG41); #endif #endif printf (TXT_MSG42); #endif //OEM /* check for the hardware */ #if PROAS ver = mvGetHWVersion(USE_ACTIVE_ADDR); /* get the version */ if (ver == -1) { #if OEM printf (TXT_MSG43); #else //OEM printf (TXT_MSG44); #endif //OEM GiveHelps(); exit(-1); } #endif #if THUNDER ver = mvGetHWVersion(0); /* get the version, or something.. */ if ((ver < 0) || ((ver & 0xffff0000) != 0x00010000)) { #if OEM printf (TXT_MSG45); #else //OEM #if THUNDER==2 printf (TXT_MSG46); #else printf (TXT_MSG47); #endif #endif GiveHelps(); exit(-1); } #endif //THUNDER } /*\ |*| end of PLAYFILE.C \*/