/*$Author: DCODY $*/ /*$Date: 06 Oct 1992 15:21:10 $*/ /*$Header: X:/sccs/pcmapps/recfile.c_v 1.12 06 Oct 1992 15:21:10 DCODY $*/ /*$Log: X:/sccs/pcmapps/recfile.c_v $ * * Rev 1.12 06 Oct 1992 15:21:10 DCODY * corrected a bug in writing the RIFF data size * * Rev 1.11 24 Sep 1992 08:59:04 DCODY * changed MVGetHardware to mvGetHardware * * Rev 1.10 18 Sep 1992 08:47:58 DCODY * added '+' option to the 'M' switch. * * Rev 1.9 14 Sep 1992 17:23:50 SHAO_M * Put all the text strings used in printf into rectext.h * * Rev 1.0 14 Sep 1992 17:02:20 unknown * Initial revision. * * Rev 1.8 02 Sep 1992 12:48:52 DCODY * made one simple change that now allows 44khz stereo 16bit recordings. * Took out the writting of the WAV header before starting the record * process. It is now done after the recording is finished. This allows * the data blocks to be written on sector boundaries. * * Rev 1.7 20 Aug 1992 14:36:28 DCODY * error exit now reports proper T&L product name. * * Rev 1.6 04 Aug 1992 11:39:42 DCODY * corrected t&l spelling * * Rev 1.5 28 Jul 1992 14:29:30 DCODY * updated for Thunderboard and Thunder&Lightning * * Rev 1.4 20 Jul 1992 11:39:18 DCODY * call to mvGetHWVersion now uses active I/O address detection. * * Rev 1.3 13 Jul 1992 18:54:00 DCODY * removed initmvsound call * * Rev 1.2 01 Jul 1992 11:57:16 DCODY * GaryL: Added OEM compiler flag checking for Welcome() * to use the generic board name and to not displau the MVI copyright. * Note that the copyright is still present, as an imbedded static string. * * Rev 1.1 23 Jun 1992 16:10:02 DCODY * pas2 update... * * Rev 1.0 15 Jun 1992 09:26:48 BCRANE * Initial revision. */ /*$Logfile: X:/sccs/pcmapps/recfile.c_v $*/ /*$Modtimes$*/ /*$Revision: 1.12 $*/ /*$Workfile: recfile.c $*/ /*\ |*|----====< RECFILE.C >====---- |*| |*| Record 8 bit PCM to disk in .WAV format |*| |*| Copyright (c) 1991, Media Vision, Inc. All rights reserved. |*| \*/ #ifndef OEM #define OEM 0 #endif #ifndef PROAS #define PROAS 0 #endif #ifndef THUNDER #define THUNDER 0 #endif #include #include #include #include #include "rectext.h" #if PROAS #include "play.h" #include "common.h" #include "pcmio.h" #include "binary.h" #endif #if THUNDER #include "proto.h" #include "play.h" #include "common.h" #include "pcmio.h" #endif /*\ |*|----====< Global Variables >====---- \*/ extern int ProcessedBlockCount; long mvGetHWVersion (int); /*\ |*|----====< Local Variables >====---- \*/ static FILE *ouf = 0; /* temp output file */ static long SampleRate = 11025L;/* default sample rate */ static int StereoMono = 0; /* default to mono */ static char TargetFile[100]; /* holds output file name */ static int FilterIndex = -1; /* -1 means no override */ static int DMAChannel = -1; /* default to standard DMA */ static int IRQChannel = -1; /* default to standard IRQ */ static int DebugFlag = FALSE; static int Compression = 0; /* no compression - 8 bits */ static int VoiceActivated = FALSE; static int VoiceActivatedNonStop = FALSE; static int NoiseLevel = 5; static int maxsize = 16; /* 16k DMA buffer size */ static int maxdiv = 4; /* 4k divisions on the DMA */ static int datasize= 8; /* 8 or 16 bit samples */ #define WAVEFILE 1 #define VOCFILE 2 static int FileType; /*\ |*|----====< Data Structures >====---- \*/ RiffWave fhd = { { "RIFF", 0L }, { "WAVE", { "fmt ", sizeof(WaveInfo) , { 1, 1, 11025L, 11025L, 1, 8}, }, { "data", 0L }, } }; /* .VOC simple (cheat) header definition */ typedef struct { VOCHDR vhdr; bVOCDATA vdta; } VOCHeader; /* our pre-defined data block */ static VOCHeader vhd = { { "Creative Voice File\x1a", 0x001a, 0x010a, 0x1129 }, { 0x01, 0x0,0x0,0x0, 0xa5, 0x0 } }; /*\ |*|-----------------=============================------------------- |*|-----------------====< Start of Exection >====------------------- |*|-----------------=============================------------------- \*/ /*\ |*|----====< Main >====---- |*| |*| Play the voice file out to the PCM hardware |*| \*/ main(argc,argv) int argc; char *argv[]; { char c; /* Give the welcome & checkout the hardware */ Welcome(); /* disable the ^C */ signal(SIGINT,SIG_IGN); /* set the runtime switches */ CommandLine (argc,argv); /* need a file name to play, exit if not found */ PreProcessFile (TargetFile); #if THUNDER /* last minute weirdness check... */ LastChanceStop(); #endif #if PROAS /* turn off the digital input mixer channel to avoid feedback */ TurnItOff(); #endif /* setup the DMA operations */ if (OpenPCMBuffering(DMAChannel,IRQChannel,maxsize,maxdiv)) { printf (TXT_MSG1); DoExit (-1); } /* setup how this file sounds */ #if PROAS ChooseFilter( SampleRate, FilterIndex ); #endif PCMState (SampleRate, StereoMono, Compression, datasize); /* Start the DMA & wait till an ESC is typed or data ends */ printf (TXT_MSG2); if (StartFileInput( ouf )) { while (1) { /* process some PCM data, if available */ if (VoiceActivated) { if (!ASpecialContinueFileInput(NoiseLevel,VoiceActivatedNonStop)) DoExit(PCMIOERR_FILEFULL); } else { if (!ContinueFileInput()) DoExit(PCMIOERR_FILEFULL); } /* 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 DoExit (PCMIOERR_OPENPCM); /* exit to DOS */ DoExit(0); } /*\ |*|--------------------=======================---------------------- |*|--------------------====< Subroutines >====---------------------- |*|--------------------=======================---------------------- \*/ /*\ |*|----====< BuildFileName( char *, char *, char *, int ); >====---- |*| |*| This routine takes the source name, scans it for an extension, |*| then may append the new extension. The entire file name is |*| returned in the callers target string. |*| \*/ void BuildFileName(trg,src,ext,force) char *trg; char *src; char *ext; int force; { int n; char *t,*o; // save a copy of the starting target address o = trg; // copy the source over to the target while ((*trg++ = *src++)) ; // move back to the terminator and save the pointer t = --trg; // search for an extension, if found, just return, we're all done... for (n=0;n<=4;n++) { // if no extension, go add one... if (o == trg) break; // if an extension... if (*trg == '.') { // and do not force it, just return. if (!force) return; // else point to this extension, and break out... else { t = trg; break; } } // move back to the prior character trg--; } // add the extension strcpy (t,ext); } /*\ |*|----====< CommandLine >====---- |*| |*| process the command line switches |*| \*/ int CommandLine(argc,argv) int argc; char *argv[]; { char *s; int n,temp; long l; /* 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 THUNDER case 'C': Compression = 01; /* 4 bit compression */ break; #endif #if PROAS case '8' & 0x5f: case '1' & 0x5f: if (*++s == '6') datasize = 16; break; case 'F': FilterIndex = *++s - 0x30; if ((FilterIndex<0) || (FilterIndex>6)) FilterIndex = -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; if (*++s == '+') maxdiv = 4; break; case 'R': if (sscanf (++s,"%ld",&SampleRate) != 1) { printf (TXT_MSG5,s); SampleRate = 11025L; } #if PROAS if ((SampleRate < 4000L) || (SampleRate > 44100L)) { printf (TXT_MSG5,s); SampleRate = 11025L; } #endif #if THUNDER if ((SampleRate < 4000L) || (SampleRate > 23300L)) { printf (TXT_MSG5,s); SampleRate = 11025L; } #endif break; case 'S': StereoMono = 1; break; case 'V': VoiceActivated = TRUE; if (*(s+1) == '+') { VoiceActivatedNonStop = TRUE; s++; } if (sscanf (++s,"%d",&temp) == 1) NoiseLevel = temp; break; case '+' & 0x5f: DebugFlag = TRUE; break; default: break; } } /* determine the type of output file */ BuildFileName (TargetFile,argv[1],".WAV",FALSE); /* scan the last portion of the name for the type */ FileType = WAVEFILE; s = TargetFile; while (*s) s++; if ((*(s-1) & 0x5f) == 'C') if ((*(s-2) & 0x5f) == 'O') if ((*(s-3) & 0x5f) == 'V') FileType = VOCFILE; /* if a bad sample rate, time to bomb out... */ if (FileType == WAVEFILE) { if ((SampleRate< 88200L) { printf (TXT_MSG6); DoExit(-1); } } else { if ((SampleRate< 23300L) { printf (TXT_MSG7,l); DoExit(-1); } } } /*\ |*|----====< DoExit() >====---- |*| |*| Exit to DOS |*| \*/ int DoExit(cc) int cc; { #if PROAS /* restore the PCM mixer channel */ TurnItOn(); #endif /* print any error messages */ switch (cc) { case PCMIOERR_SAMPLERATE: printf (TXT_MSG8); break; case PCMIOERR_OPENFILE: printf (TXT_MSG9); break; case PCMIOERR_OPENPCM: printf (TXT_MSG10); break; case PCMIOERR_NOMEM: printf (TXT_MSG11); break; case PCMIOERR_BADDMA: printf (TXT_MSG12); break; case PCMIOERR_BADIRQ: printf (TXT_MSG13); break; case PCMIOERR_FILEFULL: printf (TXT_MSG14); printf (TXT_MSG15); break; default: case PCMIOERR_HELPS: break; } /* if there is data, flush it and zip up the file */ if (ouf) { if (ProcessedBlockCount) { if (FileType == VOCFILE) fputc (0x00,ouf); /* set the terminating record */ fclose (ouf); if ((ouf = fopen(TargetFile,"r+b")) == 0) { printf (TXT_MSG16,TargetFile); ClosePCMBuffering(); exit(cc); } SetupHeader(); WriteBlockHeader(); } fclose (ouf); } /* shut down the hardware */ ClosePCMBuffering(); exit (cc); } /*\ |*|----====< GetKey() >====---- |*| |*| Get a new key |*| \*/ int GetKey() { char c; while (kbhit()) getch(); while (!kbhit()) ; if (getch() == 0) getch(); } /*\ |*|----====< GiveHelps >====---- |*| |*| Print the Help messages & returen |*| \*/ int GiveHelps() { /* print & return... */ #if PROAS printf (TXT_MSG17); printf (TXT_MSG18); printf (TXT_MSG19); printf (TXT_MSG20); printf (TXT_MSG21); printf (TXT_MSG22); printf (TXT_MSG23); printf (TXT_MSG24); printf (TXT_MSG25); printf (TXT_MSG26); printf (TXT_MSG27); printf (TXT_MSG28); #endif #if THUNDER printf (TXT_MSG29); printf (TXT_MSG30); printf (TXT_MSG31); printf (TXT_MSG32); #if THUNDER==2 printf (TXT_MSG33); printf (TXT_MSG34); #else printf (TXT_MSG35); #endif printf (TXT_MSG36); printf (TXT_MSG37); printf (TXT_MSG38); printf (TXT_MSG39); #endif } #if THUNDER /*\ |*|----====< LastChanceStop() >====---- |*| |*| Stop if there are some illegal setups |*| \*/ LastChanceStop() { /* .WAV cannot support compression... */ if ((FileType == WAVEFILE) && (Compression)) { printf (TXT_MSG40); GiveHelps(); DoExit(-1); } } #endif /*\ |*|----====< PreProcessFile >====---- |*| |*| Validate the User's output file & load the 1st header block |*| \*/ int PreProcessFile (fn) char *fn; { /* see if the file already exists */ if ((ouf = fopen(fn,"rb"))) { printf (TXT_MSG41,fn); while (!kbhit()) ; if ((getchar() & 0x5f) != 'Y') { #if PROAS TurnItOn(); #endif exit(1); } fclose (ouf); } /* attempt to open the users disk file */ if ((ouf = fopen(fn,"wb")) == 0) { printf (TXT_MSG42,fn); DoExit (-1); } /* send the header to disk */ ////////WriteBlockHeader(); } /*\ |*|----====< SetupHeader >====---- |*| |*| Load the RIFF header with the critical data |*| \*/ int SetupHeader() { long l,n; /* calculate the block size of each buffer division */ n = maxsize / maxdiv * 1024; /* get the # of processed blocks */ l = LONG(ProcessedBlockCount) * n - sizeof(RiffWave); /* set the data size */ fhd.wave.data.length = l; /* set the RIFF length */ fhd.riff.length = l + sizeof(WaveHeader); /* set the length of the FORMAT block */ fhd.wave.fmt.length = sizeof(WaveInfo); /* set up the sample rate, etc... */ fhd.wave.fmt.info.nChannels = StereoMono + 1; fhd.wave.fmt.info.nSamplesPerSec = SampleRate; fhd.wave.fmt.info.nAvgBytesPerSec = (SampleRate << StereoMono) << ((datasize == 8) ? 0 : 1); fhd.wave.fmt.info.nBlockAlign = (1 + ((datasize == 8) ? 0 : 1)) << StereoMono; fhd.wave.fmt.info.nBitsPerSample = datasize; /* setup the .VOC header */ l += 2; // .VOC wants a block length 2 bytes too long! vhd.vdta.bsize[0] = (char) (l & 0xff); vhd.vdta.bsize[1] = (char)((l>>8) & 0xff); vhd.vdta.bsize[2] = (char)((l>>16) & 0xff); vhd.vdta.sampler = (char)(256-(1000000L/SampleRate)) & 0xff; vhd.vdta.packtype = Compression; if (StereoMono) vhd.vdta.packtype = 5; } /*\ |*|----====< Welcome >====---- |*| |*| Print the logo & check for the appropriate hardware |*| \*/ Welcome() { long ver; /* give the normal stuff... */ #if OEM #if PROAS printf (TXT_MSG43); { static char zsCopyright[] = "Copyright (c) 1991,1992 Media Vision, Inc. All Rights Reserved\n\n"; } ver = mvGetHWVersion(USE_ACTIVE_ADDR);/* get the version */ if (ver == -1) { printf (TXT_MSG44); GiveHelps(); exit(-1); } #endif #if THUNDER printf (TXT_MSG45); { static char zsCopyright[] = "Copyright (c) 1991,1992 Media Vision, Inc. All Rights Reserved\n\n"; } ver = InitMVHardware(); /* get the version, or something.. */ if ((ver < 0) || ((ver & 0xffff0000) != 0x00010000)) { printf (TXT_MSG46); GiveHelps(); exit(-1); } #endif #else //OEM #if PROAS printf (TXT_MSG47); printf (TXT_MSG48); ver = mvGetHWVersion(USE_ACTIVE_ADDR);/* get the version */ if (ver == -1) { printf (TXT_MSG49); GiveHelps(); exit(-1); } #endif #if THUNDER #if THUNDER==2 printf (TXT_MSG50); #else printf (TXT_MSG51); #endif printf (TXT_MSG52); ver = mvGetHWVersion(0); /* get the version, or something.. */ if ((ver < 0) || ((ver & 0xffff0000) != 0x00010000)) { #if THUNDER==2 printf (TXT_MSG53); #else printf (TXT_MSG54); #endif GiveHelps(); exit(-1); } #endif #endif //OEM } /*\ |*|----====< WriteBlockHeader >====---- |*| |*| Output the one and only voice block header |*| \*/ int WriteBlockHeader() { long l; char *s; int n; WaveFormat wf; /* point to the start of the file */ fseek (ouf,0L,SEEK_SET); /* depending on the type of file, output the data... */ if (FileType == WAVEFILE) { s = (char*) &fhd; for (n=sizeof(RiffWave);n;n--) fputc(*s++,ouf); } else { s = (char*) &vhd; for (n=sizeof(VOCHeader);n;n--) fputc(*s++,ouf); } } /*\ |*| end of RECFILE.C \*/