/*=======================================================================*/
#define PROGRAMMER "SOLUTIONS, Nofrills"
#define PROG_CODE  "SOLN"
#define COURSE     "ECE-1021"
#define YEAR       (2004)
#define TERM       "Fall"
#define SECTION    (0)
#define ASSIGNMENT "HW9"
#define REVISION   (0)
#define TITLE      "WAV Data Extractor"
#define SUBTITLE   "Last Modified on 23 NOV 04"
#define EMAIL      "ece1021@eas.uccs.edu"
#define FILENAME   "9_0SOLN0.c"
/*=======================================================================*/

/*=======================================================================*/
/* WAIVED COMPILER WARNINGS                                              */
/*=======================================================================*/
/*
	Linker Warning: No module definition file specified: using defaults
	Reason for Waiver: Can't suppress. Does not have adverse impact.
*/
/*=======================================================================*/
/* NOTES TO THE USER/GRADER                                              */
/*=======================================================================*/
/*
*/
/*=======================================================================*/
/* PROBLEM STATEMENT                                                     */
/*=======================================================================*/
/*
*/
/*=======================================================================*/
/* DEVELOPMENT NOTES                                                     */
/*=======================================================================*/
/*
*/
/*=======================================================================*/
/* PSEUDOCODE                                                            */
/*=======================================================================*/
/*
*/
/*=======================================================================*/
/* DEVIATIONS FROM SUBMITTED PSEUDOCODE                                  */
/*=======================================================================*/
/*
*/
/*=======================================================================*/
/*=======================================================================*/
/* CODE SECTION                                                          */
/*=======================================================================*/
/*=======================================================================*/

/*== INCLUDE FILES ======================================================*/
#include <stdio.h>  /* stdout, putc(), printf(), scanf() */
						  /* FILE, fopen(), fread(), fwrite() */
						  /* SEEK_END, SEEK_SET, SEEK_CUR, ftell(), fseek() */
#include <stdlib.h> /* EXIT_SUCCESS, EXIT_FAILURE */

/*== MACRO DEFINITIONS (OBJECT-LIKE) ====================================*/
#define FALSE (0)
#define TRUE (!FALSE)
#define BLANKLINE printf("\n")
#define MARGIN (2)                       /* Left Margin in PrintHeader() */
#define INDENT_SIZE (2)                  /* Indent relative to           */

#define LMARG printc(' ', MARGIN)        /* Print Left Margin            */
#define INDENT printc(' ', INDENT_SIZE)  /* Indent relative to margin    */
#define EMPTYLOOP {}

/*== MACRO DEFINITIONS (FUNCTION-LIKE) ==================================*/

/*=======================================================================*/
/* SUPPORT FUNCTIONS ( functions not called directly by main() )         */
/*=======================================================================*/

int printc(char c, int n)
{
	while ( (n--) && (c == putc(c, stdout)) ); /* EMPTY LOOP */
	return n;
}

/*=======================================================================*/
/* PRIMARY FUNCTIONS ( functions called directly by main() )             */
/*=======================================================================*/

/*== FUNCTION PROTOTYPES (to Document Support Functions) ================*/
int printc(char c, int n);

/*== PRIMARY FUNCTIONS ==================================================*/
void PrintHeader(void)
{
	LMARG; printc('=', (78 - MARGIN)); putc('\n', stdout);
	LMARG; printf("Course....... %s-%i (%s %i)\n",COURSE,SECTION,TERM,YEAR);
	LMARG; printf("Programmer... %s (%s)\n", PROGRAMMER, PROG_CODE);
	LMARG; printf("Assignment... %s (Rev %i)", ASSIGNMENT, REVISION);
	LMARG; printf("(Source Code in %s)\n", FILENAME);
	LMARG; printf("Description.. %s\n", TITLE);
	LMARG; printf("              %s\n", SUBTITLE);
	LMARG; printc('=', (78 - MARGIN)); putc('\n', stdout);
}

/*=======================================================================*/
/* MAIN FUNCTION                                                         */
/*=======================================================================*/

/*== FUNCTION PROTOTYPES (to Document Primary Functions) ================*/
void PrintHeader(void);

int main(void)
{
	FILE *fp, *fp_out;
	char filename[81];
	char textfilename[81];

	char RIFF_ID[4];
	long RIFF_Size;
	char RIFF_Format[4];

	char FMT_ID[4];
	long FMT_Size;
	int  AudioFormat;
	int  Channels;
	long SampleRate;
	long ByteRate;
	int  BlockSize;
	int  Bits;

	/* Read DATA Chunk */
	char DATA_ID[4];
	long DATA_Size;

	long sample, samples;
	long BytesRead;
	int bytespersample;
	int i;
	double t, dt;
	int channel;
   int data;

	PrintHeader();
	BLANKLINE;

	/*	1) TASK: Get Data From User */
	printf("  Enter the WAV file name (with extension): ");
	scanf("%s", &filename);

	if (NULL == (fp = fopen(filename, "rb")))
	{
		printf("Failed to open file [%s] for binary reading\n", filename);
		return EXIT_FAILURE;
	}

	printf("  Enter the file name to dump to (with extension): ");
	scanf("%s", &textfilename);

	if (NULL == (fp_out = fopen(textfilename, "wt")))
	{
		printf("Failed to open file [%s] for text writing\n", textfilename);
		return EXIT_FAILURE;
	}

	/* Read RIFF Chunk */
	fread(RIFF_ID, 4, 1, fp);         /* Should be "RIFF" */
	fread(&RIFF_Size, 4, 1, fp);      /* Filesize - 8 */
	fread(&RIFF_Format, 4, 1, fp);    /* Should be "WAVE" */

	/* Read FORMAT Chunk */
	fread(FMT_ID, 4, 1, fp);          /* Should be "fmt " */
	fread(&FMT_Size, 4, 1, fp);       /* Should be 16 (AudioFormat = 1) */
	fread(&AudioFormat, 2, 1, fp);    /* Should be 1 (linear) */
	fread(&Channels, 2, 1, fp);
	fread(&SampleRate, 4, 1, fp);
	fread(&ByteRate, 4, 1, fp);
	fread(&BlockSize, 2, 1, fp);
	fread(&Bits, 2, 1, fp);           /* Should be 16 */

	/* Read DATA Chunk */
	fread(DATA_ID, 4, 1, fp);          /* Should be "data " */
	fread(&DATA_Size, 4, 1, fp);       /* Should be bytes of sound data */

	/* Print out Wave File Summary */
	printf("  WAVE FILE SUMMARY:\n");
	printf("  Filename:.............. %s\n", filename);

	BLANKLINE;
	printf("  RIFF CHUNK:\n");
	printf("    ID:.................. \"");
	for (i = 0; i < 4; i++)
		printf("%c", RIFF_ID[i]);
	printf("\"\n");
	printf("    SIZE:................ %li bytes\n", RIFF_Size);
	printf("    Format:.............. \"");
	for (i = 0; i < 4; i++)
		printf("%c", RIFF_Format[i]);
	printf("\"\n");

	BLANKLINE;
	printf("  FORMAT CHUNK:\n");
	printf("    ID:.................. \"");
	for (i = 0; i < 4; i++)
		printf("%c", FMT_ID[i]);
	printf("\"\n");
	printf("    SIZE:................ %li bytes\n", FMT_Size);
	printf("    Audio Format:........ %i \n",  AudioFormat);
	printf("    Channels:............ %i channel(s)\n",  Channels);
	printf("    Sample Rate:......... %li samples per second\n",SampleRate);
	printf("    Byte Rate:........... %li bytes per second\n",  ByteRate);
	printf("    Block Size:.......... %i byte(s)\n",  BlockSize);
	printf("    Bits Per Sample:..... %i bits\n",  Bits);

	BLANKLINE;
	printf("  DATA CHUNK:\n");
	printf("    ID:.................. \"");
	for (i = 0; i < 4; i++)
		printf("%c", DATA_ID[i]);
	printf("\"\n");
	printf("    SIZE:................ %li bytes\n", DATA_Size);

	BLANKLINE;
	printf("  DERIVED PARAMETERS:\n");
	samples = DATA_Size / BlockSize;
	printf("    Total Samples:....... %li sample(s)\n", samples);
	bytespersample = Bits/8 + (Bits%8)? 1 : 0;
	printf("    Bytes Per Sample:.... %i byte(s)\n", bytespersample);
	dt = 1.0/SampleRate;
	printf("    Time Increment:...... %.3f ms\n", 1000.0*dt);
	t = samples * dt;
	printf("    Total Run Time:...... %.3f sec\n", t);

	BLANKLINE;
	printf("  Dumping sample data to file [%s]:\n", textfilename);
	BytesRead = 0;
	sample = 0;
	t = 0.0;
	while ( (!feof(fp)) && (BytesRead < DATA_Size))
	{
		fprintf(fp_out, "%f", t);
		for (channel = 0; channel < Channels; channel++)
		{
			fread(&data, 2, 1, fp);
			fprintf(fp_out, ",%i", data);
			BytesRead += 2;
		}
		fprintf(fp_out, "\n");
		if (!(sample%1000))
			printf("  Sample: %li\r", sample++);
		sample++;
      t += dt;
	}
	printf("  Sample: %li\n", sample++);
	printf("  Dump complete\n");

	fclose(fp);
	fclose(fp_out);

	return EXIT_SUCCESS;
}

/*=======================================================================*/
/* END OF SOURCE CODE FILE                                               */
/*=======================================================================*/