/*$Author:   DCODY  $*/
/*$Date:   23 Jun 1992 16:09:36  $*/
/*$Header:   W:/sccs/pcmapps/fixwave.c_v   1.1   23 Jun 1992 16:09:36   DCODY  $*/
/*$Log:   W:/sccs/pcmapps/fixwave.c_v  $
 * 
 *    Rev 1.1   23 Jun 1992 16:09:36   DCODY
 * pas2 update...
 * 
 *    Rev 1.0   15 Jun 1992 09:26:32   BCRANE
 * Initial revision.
*/
/*$Logfile:   W:/sccs/pcmapps/fixwave.c_v  $*/
/*$Modtimes$*/
/*$Revision:   1.1  $*/
/*$Workfile:   fixwave.c  $*/


	/*\
	|*|----====< FIXWAVE.C >====----
	|*|
	|*| This program Corrects the average # of samples in a stereo file.
    |*|
    \*/

#include <stdio.h>
#include <stdlib.h>
#include <dos.h>

#include "play.h"


	/*\
	|*|----====< Global Variables >====----
	\*/

#define TRUE	-1
#define FALSE	 0

		struct find_t  w_file;			/* wave file stuff				*/
		static FILE *inf;				/* user input file				*/
		fpos_t pos1;
		fpos_t pos2;
		fpos_t pos3;
		fpos_t pos4;


        RiffWave fhd = {
            { "RIFF", 0L },
            { "WAVE",
                { "fmt ", sizeof(WaveInfo) , { 1, 1, 11025L, 11025L, 1, 8}, },
                { "data", 0L },
            }
        };

		int align;
		int fixed;
		int rdhead;
		int bitspersample;

		unsigned long rate;
		unsigned long ave;

		int DoSave = FALSE; 			// save-the-changes flag


	/*\
	|*|
	|*|----====< Main >====----
	|*|
	|*| Play the voice file out to the PCM hardware
	|*|
	\*/

main(argc,argv)
	int  argc;
	char *argv[];
{
int n,ch,work;
unsigned long lwork;
unsigned long l;
char c;

	/* we have not fixed any fields 									*/

		fixed = FALSE;

	/* Check parameters 												*/

		CommandLine (argc,argv);

	/* 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) {
			printf ("this is not a .wav file!\n");
			exit(1);
		}

	/* print the RIFF portion of the header 							*/

		printf ("RIFF header information:\n\n");

		for (n=4;n;n--)
			putch (fgetc(inf));
		printf ("\n");

		fgetpos (inf,&pos3);
		l  =  (unsigned long) fgetc(inf) & 0xff;
		l += ((unsigned long) fgetc(inf) & 0xff) << 8;
		l += ((unsigned long) fgetc(inf) & 0xff) <<16;
		l += ((unsigned long) fgetc(inf) & 0xff) <<24;

		fhd.riff.length = l;

		printf ("  length=%lu\n",l);

	/* pas up the wave block header name								*/

		if ((unsigned long) fgetc(inf) != 'W') {
			printf ("\aUnknown header in the .WAV file! (should be 'WAVE')\n");
			exit(1);
		}

		putch ('W');
		for (n=3;n;n--)
			putch ((unsigned long) fgetc(inf));
		printf ("\n");

	/* pass up the format section name									*/

		c = (unsigned long) fgetc(inf);
		if (c != 'f') {
			printf ("\aUnknown header in the .WAV file! (should be 'fmt ')\n");
			exit(1);
		}
		putch (c);
		for (n=3;n;n--)
			putch((unsigned long) fgetc(inf));	/* move past the data	*/
        printf ("\n");

		// fmt <length>

        l  =  (unsigned long) fgetc(inf) & 0xff;
		l += ((unsigned long) fgetc(inf) & 0xff) << 8;
		l += ((unsigned long) fgetc(inf) & 0xff) <<16;
		l += ((unsigned long) fgetc(inf) & 0xff) <<24;

		printf ("  length =%lu\n",l);

		// format tag

		l  = (unsigned long) fgetc(inf)  & 0xff;
		l += ((unsigned long) fgetc(inf) & 0xff) << 8;

		printf ("  format =%lu\n",l);

		// # of channel

        ch =  (unsigned long) fgetc(inf) & 0xff;
		ch += ((unsigned long) fgetc(inf) & 0xff) << 8;

		printf ("  channel=%d\n",ch);

		// Samples per second

		l  =  (unsigned long) fgetc(inf) & 0xff;
		l += ((unsigned long) fgetc(inf) & 0xff) << 8;
		l += ((unsigned long) fgetc(inf) & 0xff) <<16;
		l += ((unsigned long) fgetc(inf) & 0xff) <<24;

		rate = l;
		printf ("  s-rate =%lu\n",rate);

		fgetpos (inf,&pos1);
        l  =  (unsigned long) fgetc(inf) & 0xff;
		l += ((unsigned long) fgetc(inf) & 0xff) << 8;
		l += ((unsigned long) fgetc(inf) & 0xff) <<16;
		l += ((unsigned long) fgetc(inf) & 0xff) <<24;

		// Average Samples per second

		ave = l;
		printf ("  average=%lu\n",ave);

		// Block Alignment

		fgetpos (inf,&pos2);
		align  =  (unsigned long) fgetc(inf) & 0xff;
		align += ((unsigned long) fgetc(inf) & 0xff) << 8;

		printf ("  align  =%d\n",align);

		// Bits per sample

		l  = (unsigned long) fgetc(inf)  & 0xff;
		l += ((unsigned long) fgetc(inf) & 0xff) << 8;
		bitspersample = l & 0xff;

		printf ("  bits   =%lu\n",l);

		c = (unsigned long) fgetc(inf);
		if (c != 'd') {
			printf ("\aUnknown header in the .WAV file! (should be 'fmt ')\n");
			exit(1);
		}
		putch (c);
		for (n=3;n;n--)
			putch((unsigned long) fgetc(inf));	/* move past the data	*/
		printf ("\n");

		fgetpos (inf,&pos4);
		l  =  (unsigned long) fgetc(inf) & 0xff;
		l += ((unsigned long) fgetc(inf) & 0xff) << 8;
		l += ((unsigned long) fgetc(inf) & 0xff) <<16;
		l += ((unsigned long) fgetc(inf) & 0xff) <<24;

		fhd.wave.data.length = l;

		printf ("  length =%lu\n\n",l);

		///// This is the average sample count for stereo file errors /////

		if (ch == 2) {
			lwork = rate << (((bitspersample==16)?1:0) + ch-1);
			if (lwork != ave) {
				printf ("This stereo file average sample count is incorrect,\n");
				if (DoSave) {
					printf ("now saving the average samples as %lu\n",lwork );
					fsetpos (inf,&pos1);
					fputc (( lwork		& 0xff),inf);
					fputc (((lwork>> 8) & 0xff),inf);
					fputc (((lwork>>16) & 0xff),inf);
					fputc (((lwork>>24) & 0xff),inf);
					fixed = TRUE;
				}
			}
			else
				printf ("This stereo file average sample count is correct...\n");
        }
		else
			printf ("This is a mono file. The average sample count is correct...\n");

		///// This is the alignment size error created by FIXWAVE.EXE /////

		if (bitspersample == 16) {
			work = 1 << (((ch == 1) ? 0 : 1) + 1);
			if (align != work) {
				align = work & 0xff;
				printf ("This file's sample alignment is incorrect,\n");

				if (DoSave) {
					printf ("now saving the alignment as %d\n",work);
					fsetpos (inf,&pos2);
					fputc (( work		& 0xff),inf);
					fputc (((work >> 8) & 0xff),inf);
					fixed = TRUE;
				}

            }
			else
				printf ("This file's alignment is correct...\n");
		}

        ///// This is the alignment size error /////

        if (ch == 2) {
			work = 1 << (((bitspersample == 8) ? 0 : 1) + ch-1);
			if (align != work) {
				printf ("This stereo file alignment is incorrect,\n");

                if (DoSave) {
					printf ("now saving the alignment as %d\n",work);
					fsetpos (inf,&pos2);
					fputc (( work		& 0xff),inf);
					fputc (((work >> 8) & 0xff),inf);
					fixed = TRUE;
				}
            }
			else
				printf ("This stereo file alignment count is correct...\n");
		}
		else
			printf ("This is a mono file. The alignment count sample count is correct...\n");

		///// This is the 2-off error in the RIFF and DATA lengths	/////

		rdhead = 0;
        if ((w_file.size - fhd.riff.length) == 6) {

			printf ("The RIFF and DATA lengths are incorrect,\n");

			if (DoSave) {

				printf ("now correcting...\n");

				// correct the RIFF size

				l = fhd.riff.length - 2;
				fsetpos (inf,&pos3);
				fputc (( l		 & 0xff),inf);
				fputc (((l >> 8) & 0xff),inf);
				fputc (((l >>16) & 0xff),inf);
				fputc (((l >>24) & 0xff),inf);

				// correct the DATA size

				l = fhd.wave.data.length - 2;
				fsetpos (inf,&pos4);
				fputc (( l		 & 0xff),inf);
				fputc (((l >> 8) & 0xff),inf);
				fputc (((l >>16) & 0xff),inf);
				fputc (((l >>24) & 0xff),inf);
				rdhead = fixed = TRUE;

			}
        }

		if (w_file.size < fhd.riff.length) {

			printf ("The RIFF and DATA lengths are greater than the file length,\n");

            if (DoSave) {

				printf ("now correcting...\n");

				// correct the RIFF size

				l = w_file.size - sizeof (RiffHeader);
				fsetpos (inf,&pos3);
				fputc (( l		 & 0xff),inf);
				fputc (((l >> 8) & 0xff),inf);
				fputc (((l >>16) & 0xff),inf);
				fputc (((l >>24) & 0xff),inf);

				rdhead = fixed = TRUE;

				if (w_file.size < fhd.wave.data.length) {

					// correct the DATA size

					l = w_file.size -
						(sizeof (RiffHeader) + sizeof(WaveHeader) - sizeof (long));
					fsetpos (inf,&pos4);
					fputc (( l		 & 0xff),inf);
					fputc (((l >> 8) & 0xff),inf);
					fputc (((l >>16) & 0xff),inf);
					fputc (((l >>24) & 0xff),inf);
				}
			}
        }

		if (!rdhead)
			printf ("This RIFF and DATA size are correct...\n");

    /* save the changes, if any were made...                                */

        if (fixed)
			fclose (inf);

}

;	/*\
;---|*|----====< CommandLine >====----
;---|*|
;---|*| Check the parameters
;---|*|
;	\*/

CommandLine (argc,argv)
	int argc;
	char *argv[];
{
int n;
char *s;

	// say hello...

		printf ("\nFIXWAVE, Version 1.04 - Checks/Fixes .WAV header errors from RECFILE.EXE.\n");
		printf ("Courtesy of Media Vision, Inc.\n\n");

	// stop if there are no more parameters

        if (argc < 2) {
			printf ("To Use: DOS>FIXWAVE FILE.WAV [/C] \n\n");
			printf ("Where:  [/C] corrects detected errors.\n\n");
			exit(1);
		}

	// open the file and get the file size.

		if ((inf = fopen(argv[1],"r+b")) == 0) {
			printf ("\aBad File Name, \"%s\" Try Again!\n",argv[1]);
			exit(1);
		}
		_dos_findfirst (argv[1],_A_ARCH|_A_NORMAL,&w_file);

	// process any switches

		n = 2;
		while (n < argc) {

			s = argv[n++];

			if (*s == '/') s++;
			if (*s == '-') s++;

			switch (*s & 0x5f) {

				case 'C':
					DoSave = TRUE;
                    break;

				default:
					break;

            }
		}
}

	/*\
	|*| end of FIXWAVE.C
	\*/

