/*$Author:   DCODY  $*/
/*$Date:   24 Sep 1992 08:59:04  $*/
/*$Header:   X:/sccs/pcmapps/recfile.c_v   1.11   24 Sep 1992 08:59:04   DCODY  $*/
/*$Log:   X:/sccs/pcmapps/recfile.c_v  $
 * 
 *    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.11  $*/
/*$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 <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <signal.h>
#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<<StereoMono) > 88200L) {
				printf (TXT_MSG6);
				DoExit(-1);
			}
		}
		else {
			if ((SampleRate<<StereoMono) > 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
    \*/

