//========================================================================= #define PROGRAMMER "SOLUTIONS, Nofrills" #define PROG_CODE "soln" #define COURSE "ECE-1021" #define YEAR (2004) #define TERM "Spring" #define SECTION (0) #define ASSIGNMENT "HW #8B" #define REVISION (0) #define TITLE "WAV <-> TXT Converter" #define SUBTITLE "Last Modified on 22 APR 04" #define EMAIL "ece1021@eas.uccs.edu" #define FILENAME "08b0soln.txt" //========================================================================= //========================================================================= // PROBLEM //========================================================================= // // Get a file name from the User that has either a TXT or a WAV extension. // If (TXT) // Read the text file and generate a wave file. // If (WAV) // Read the wave file and generate a text file. // //========================================================================= // PSEUDOCODE //========================================================================= // // 1) TASK: Get filename from User // 2) TASK: Determine type of file (TXT or WAV or neither) // 3) TASK: Open and verify files in appropriate modes // 4) IF: Both files successfully opened // 4.1) IF: (Input file is TXT) // 4.1.1) TASK: Read header // 4.1.2) TASK: Determine amount of data in file // 4.1.3) TASK: Write WAV file (except for actual data) // 4.1.4) TASK: Translate data from TXT to WAV // 4.2) IF: (Input file is WAV) // 4.2.1) TASK: Read Format Chunk // 4.2.2) TASK: Write TXT header // 4.2.3) TASK: Translate data from WAV to TXT //========================================================================= // DEVIATIONS FROM SUBMITTED PSEUDOCODE //========================================================================= // // In this section you should list any differences between the pseudocode // you submitted for grading and the program as you implemented it. // // If you did not submit any pseudocode, then you must put your entire // pseudocode here or lose even more points. //========================================================================= // WAIVED COMPILER WARNINGS //========================================================================= // // In this section you should list any compiler warnings that remain and // why you are accepting them. It is acceptable to indicate that the // the reason is that you don't know how to get rid of it. // // Linker Warning: No module definition file specified: using defaults // Reason for Waiver: Can't suppress. Does not have adverse impact. //========================================================================= // CODE SECTION //========================================================================= //== INCLUDE FILES ======================================================== #include // printf(), scanf(), fprintf(), fscanf() // fopen(), fclose(), fseek(), fread(), fwrite() #include // pow() #include // strcmp(), strlen(), strlwr() //== MACRO DEFINITIONS ==================================================== #define FALSE (0) #define TRUE (!FALSE) #define BLANKLINE printf("\n") #define TXT (0) #define WAV (1) #define NEITHER (2) //========================================================================= //== WAVEFILE STRUCTURE DEFINITION ======================================== //========================================================================= struct wavfile { long RIFF_FileSize; long FMT_Offset; // Offset from beginning of file to FORMAT chunk long FMT_ChunkSize; int FMT_AudioFormat; int FMT_NumChannels; long FMT_SampleRate; long FMT_ByteRate; int FMT_BlockAlign; int FMT_BitsPerSample; long DATA_Offset; // Offset from beginning of file to DATA chunk long DATA_ChunkSize; }; typedef struct wavfile WAVFILE; // --- OFFSETS within WAV File ------------------------------------------- // Chunk Offsets common to all chunk types #define CHUNK_ID ( 0) #define CHUNK_SIZE ( 4) #define FIRSTSUBCHUNK (12) // RIFF Chunk Offsets (From beginning of RIFF Chunk) #define RIFFTYPE ( 8) // FMT Chunk Offsets (from beginning of FORMAT chunk) #define AUDIOFORMAT ( 8) #define NUMCHANNELS (10) #define SAMPLERATE (12) #define BYTERATE (16) #define BLOCKALIGN (20) #define BITSPERSAMPLE (22) // DATA Chunk Offsets (from beginning of DATA chunk) #define DATASTART ( 8) // --- WAVFILE Structure Primitive Function Prototypes -------------------- long GetWAVFILE_RIFF_Filesize(WAVFILE *wav); long SetWAVFILE_RIFF_Filesize(WAVFILE *wav, long v); long GetWAVFILE_FMT_Offset(WAVFILE *wav); long SetWAVFILE_FMT_Offset(WAVFILE *wav, long v); long GetWAVFILE_FMT_ChunkSize(WAVFILE *wav); long SetWAVFILE_FMT_ChunkSize(WAVFILE *wav, long v); int GetWAVFILE_FMT_AudioFormat(WAVFILE *wav); int SetWAVFILE_FMT_AudioFormat(WAVFILE *wav, int v); int GetWAVFILE_FMT_NumChannels(WAVFILE *wav); int SetWAVFILE_FMT_NumChannels(WAVFILE *wav, int v); long GetWAVFILE_FMT_SampleRate(WAVFILE *wav); long SetWAVFILE_FMT_SampleRate(WAVFILE *wav, long v); long GetWAVFILE_FMT_ByteRate(WAVFILE *wav); long SetWAVFILE_FMT_ByteRate(WAVFILE *wav, long v); int GetWAVFILE_FMT_BlockAlign(WAVFILE *wav); int SetWAVFILE_FMT_BlockAlign(WAVFILE *wav, int v); int GetWAVFILE_FMT_BitsPerSample(WAVFILE *wav); int SetWAVFILE_FMT_BitsPerSample(WAVFILE *wav, int v); long GetWAVFILE_DATA_Offset(WAVFILE *wav); long SetWAVFILE_DATA_Offset(WAVFILE *wav, long v); long GetWAVFILE_DATA_ChunkSize(WAVFILE *wav); long SetWAVFILE_DATA_ChunkSize(WAVFILE *wav, long v); //========================================================================= //== FUNCTION PROTOTYPES (for Primary Functions) ========================== void PrintHeader(void); void GetFileNameFromUser(char *filename, int max); int TypeOfFile(char *filename); FILE *fopenTXT(char *filename, int InputType); FILE *fopenWAV(char *filename, int InputType); long CountSampleFrames(FILE *fpTXT, double *min, double *max); void WriteWAVparams(FILE *fpWAV, int channels, int bits, long rate, long frames); int WriteWAV2TXTdata(WAVFILE *wav, FILE *fpTXT, FILE *fpWAV); int WriteTXT2WAVdata(WAVFILE *wav, FILE *fpWAV, FILE *fpTXT, double min, double max); int GetWAVchannels(FILE *fpWAV); int GetWAVbits(FILE *fpWAV); long GetWAVrate(FILE *fpWAV); WAVFILE *WriteWAVEFILE_Header(WAVFILE *wav, FILE *fp); WAVFILE *ReadWAVEFILE_Header(WAVFILE *wav, FILE *fp); int BytesPerSample(int bits); int PrepWAVFILE(WAVFILE *wav, int chan, int bits, long rate, long frames); WAVFILE *DisplayWAVEFILE(WAVFILE *wav); //== MAIN FUNCTION ======================================================== int main(void) { char filename[81]; int InputType; FILE *fpTXT, *fpWAV; int chan, bits; long rate, frames; WAVFILE WaveFile, *wav; double min, max; PrintHeader(); BLANKLINE; wav = &WaveFile; // For convenience in function calls // 1) TASK: Get filename from User GetFileNameFromUser(filename, 81); // 2) TASK: Determine type of file (TXT or WAV or neither) InputType = TypeOfFile(filename); // 3) TASK: Open and verify files in appropriate modes fpTXT = fopenTXT(filename, InputType); fpWAV = fopenWAV(filename, InputType); // 4) IF: Both files successfully opened if( (NULL != fpTXT) && (NULL != fpWAV) ) { // 4.1) IF: (Input file is TXT) if(TXT == InputType) { // 4.1.1) TASK: Read header fscanf(fpTXT, "%i,", &chan); fscanf(fpTXT, "%i,", &bits); fscanf(fpTXT, "%li,", &rate); // 4.1.2) TASK: Determine amount of data in file frames = CountSampleFrames(fpTXT, &min, &max); // 4.1.3) TASK: Write WAV file (except for actual data) PrepWAVFILE(wav, chan, bits, rate, frames); DisplayWAVEFILE(wav); WriteWAVEFILE_Header(wav, fpWAV); // 4.1.4) TASK: Translate data from TXT to WAV WriteTXT2WAVdata(wav, fpTXT, fpWAV, min, max); printf("Text File Generated. Program Finished.\n"); } // 4.2) IF: (Input file is WAV) if(WAV == InputType) { // 4.2.1) TASK: Read Format Chunk if(NULL == ReadWAVEFILE_Header(wav, fpWAV)) { printf("Failed to read WAV Header.\n"); return(2); } DisplayWAVEFILE(wav); // 4.2.2) TASK: Write TXT header chan = GetWAVFILE_FMT_NumChannels(wav); bits = GetWAVFILE_FMT_BitsPerSample(wav); rate = GetWAVFILE_FMT_SampleRate(wav); fprintf(fpTXT, "%i,%i,%li\n", chan, bits, rate); // 4.1.4) TASK: Translate data from TXT to WAV WriteWAV2TXTdata(wav, fpWAV, fpTXT); printf("Wave File Generated. Program Finished.\n"); } fclose(fpTXT); fclose(fpWAV); } return(0); } //========================================================================= // PRIMARY FUNCTIONS (functions called directly by main() ) //========================================================================= //== FUNCTION PROTOTYPES (for Support Functions) ========================== int printc(char c, int n); int fwritelong(FILE *fp, long offset, long value); int fwriteint(FILE *fp, long offset, int value); int fwritebytes(FILE *fp, long offset, char *value, int n); //== PRIMARY FUNCTIONS ==================================================== void PrintHeader(void) { printc('=', 79); printf("\n"); printf("Course....... %s-%i (%s %i)\n", COURSE, SECTION, TERM, YEAR); printf("Programmer... %s (%s)\n", PROGRAMMER, PROG_CODE); printf("Assignment... %s (Rev %i) (Source Code in %s)\n", ASSIGNMENT, REVISION, FILENAME); printf("Description.. %s\n", TITLE); printf(" %s\n", SUBTITLE); printc('=', 79); printf("\n"); return; } //========================================================================= // SUPPORT FUNCTIONS (functions not called directly by main() ) //========================================================================= int printc(char c, int n) { while(0 < n--) printf("%c", c); return(n); } char *StripCR(char *s) { int i; i = 0; do { switch(s[i]) { case '\0': break; case '\n': case '\r': s[i] = '\0'; break; default : i++; } } while(s[i] != '\0'); return(s); } void GetFileNameFromUser(char *filename, int max) { printf("Enter filename with extension: "); fgets(filename, max, stdin); StripCR(filename); return; } int TypeOfFile(char *s) { char *ext; int i; int type = NEITHER; ext = s; i = 0; do { switch(s[i]) { case '\0': break; case '.': ext = s+i+1; s[i] = '\0'; break; default : i++; } } while(s[i] != '\0'); if(ext > s) // A '.' was found { strlwr(ext); if(0 == strcmp(ext, "txt")) type = TXT; if(0 == strcmp(ext, "wav")) type = WAV; } return(type); } FILE *fopenTXT(char *filename, int InputType) { char fullname[256]; FILE *fp; strcpy(fullname, filename); strcat(fullname, ".txt"); switch(InputType) { case TXT: fp = fopen(fullname, "rt"); break; case WAV: fp = fopen(fullname, "wt"); break; default : fp = NULL; break; } return(fp); } FILE *fopenWAV(char *filename, int InputType) { char fullname[256]; FILE *fp; strcpy(fullname, filename); strcat(fullname, ".wav"); switch(InputType) { case TXT: fp = fopen(fullname, "wb"); break; case WAV: fp = fopen(fullname, "rb"); break; default : fp = NULL; break; } return(fp); } long CountSampleFrames(FILE *fpTXT, double *min, double *max) { long frames; char buffer[256]; double value; // Pass 1: Determine min and max: rewind(fpTXT); fgets(buffer, 256, fpTXT); // Skip first line; fscanf(fpTXT, "%lf", &value); *min = *max = value; while(1 == fscanf(fpTXT, "%lf", &value) ) { if(value < *min) *min = value; if(value > *max) *max = value; } // Pass 2: Count sample frames: rewind(fpTXT); fgets(buffer, 256, fpTXT); // Skip first line; frames = 0; while( NULL != fgets(buffer, 256, fpTXT) ) frames++; return(frames); } int fwritelong(FILE *fp, long offset, long value) { if( fseek(fp, offset, SEEK_SET) ) // returns zero upon success return(1); if(1 != fwrite(&value, 4, 1, fp) ) // returns number of items written return(2); return(0); } int fwriteint(FILE *fp, long offset, int value) { if( fseek(fp, offset, SEEK_SET) ) // returns zero upon success return(1); if(1 != fwrite(&value, 2, 1, fp) ) // returns number of items written return(2); return(0); } int fwritebytes(FILE *fp, long offset, char *value, int n) { if( fseek(fp, offset, SEEK_SET) ) // returns zero upon success return(1); if(n != fwrite(value, 1, n, fp) ) // returns number of items written return(2); return(0); } long freadlong(FILE *fp, long offset) { long value; if( fseek(fp, offset, SEEK_SET) ) // returns zero upon success return(-1); if(1 != fread(&value, 4, 1, fp) ) // returns number of items read return(-1); return(value); } int freadint(FILE *fp, long offset) { int value; if( fseek(fp, offset, SEEK_SET) ) // returns zero upon success return(-1); if(1 != fread(&value, 2, 1, fp) ) // returns number of items read return(-1); return(value); } int freadbytes(FILE *fp, long offset, char *value, int n) { if( fseek(fp, offset, SEEK_SET) ) // returns zero upon success return(1); if(n != fread(value, 1, n, fp) ) // returns number of items read return(2); return(0); } //========================================================================= // WAVFILE STRUCTURE FUNCTIONS //========================================================================= // --- WAV File Organization ---------------------------------------------- // RIFF Chunk // 4 GroupID 'RIFF' // 4 FileSize Bytes Remaining in File // 4 RIFFtype 'WAVE' // FORMAT Chunk // 4 ChunkID 'fmt ' // 4 ChunkSize Bytes Remaining in Chunk // 2 AudioFormat PCM=1 for uncompressed // 2 NumChannels // 4 SampleRate Sample Frames per Second // 4 ByteRate Bytes per Second // 2 BlockAlign Bytes per Frame // 2 BitsPerSample // DATA Chunk // 4 ChunkID 'data' // 4 ChunkSize Bytes Remaining in Chunk // x Data // --- WAVFILE Structure Primitive Functions ------------------------------ // RIFF_FileSize long GetWAVFILE_RIFF_Filesize(WAVFILE *wav) { if(NULL == wav) return(-1); return(wav->RIFF_FileSize); } long SetWAVFILE_RIFF_Filesize(WAVFILE *wav, long v) { if(NULL == wav) return(-1); wav->RIFF_FileSize = v; return(GetWAVFILE_RIFF_Filesize(wav)); } // FMT_Offset long GetWAVFILE_FMT_Offset(WAVFILE *wav) { if(NULL == wav) return(-1); return(wav->FMT_Offset); } long SetWAVFILE_FMT_Offset(WAVFILE *wav, long v) { if(NULL == wav) return(-1); wav->FMT_Offset = v; return(GetWAVFILE_FMT_Offset(wav)); } // FMT_ChunkSize long GetWAVFILE_FMT_ChunkSize(WAVFILE *wav) { if(NULL == wav) return(-1); return(wav->FMT_ChunkSize); } long SetWAVFILE_FMT_ChunkSize(WAVFILE *wav, long v) { if(NULL == wav) return(-1); wav->FMT_ChunkSize = v; return(GetWAVFILE_FMT_ChunkSize(wav)); } // FMT_AudioFormat int GetWAVFILE_FMT_AudioFormat(WAVFILE *wav) { if(NULL == wav) return(-1); return(wav->FMT_AudioFormat); } int SetWAVFILE_FMT_AudioFormat(WAVFILE *wav, int v) { if(NULL == wav) return(-1); wav->FMT_AudioFormat = v; return(GetWAVFILE_FMT_AudioFormat(wav)); } // FMT_NumChannels int GetWAVFILE_FMT_NumChannels(WAVFILE *wav) { if(NULL == wav) return(-1); return(wav->FMT_NumChannels); } int SetWAVFILE_FMT_NumChannels(WAVFILE *wav, int v) { if(NULL == wav) return(-1); wav->FMT_NumChannels = v; return(GetWAVFILE_FMT_NumChannels(wav)); } //FMT_SampleRate long GetWAVFILE_FMT_SampleRate(WAVFILE *wav) { if(NULL == wav) return(-1); return(wav->FMT_SampleRate); } long SetWAVFILE_FMT_SampleRate(WAVFILE *wav, long v) { if(NULL == wav) return(-1); wav->FMT_SampleRate = v; return(GetWAVFILE_FMT_SampleRate(wav)); } // FMT_ByteRate long GetWAVFILE_FMT_ByteRate(WAVFILE *wav) { if(NULL == wav) return(-1); return(wav->FMT_ByteRate); } long SetWAVFILE_FMT_ByteRate(WAVFILE *wav, long v) { if(NULL == wav) return(-1); wav->FMT_ByteRate = v; return(GetWAVFILE_FMT_ByteRate(wav)); } // FMT_BlockAlign int GetWAVFILE_FMT_BlockAlign(WAVFILE *wav) { if(NULL == wav) return(-1); return(wav->FMT_BlockAlign); } int SetWAVFILE_FMT_BlockAlign(WAVFILE *wav, int v) { if(NULL == wav) return(-1); wav->FMT_BlockAlign = v; return(GetWAVFILE_FMT_BlockAlign(wav)); } // FMT_BitsPerSample int GetWAVFILE_FMT_BitsPerSample(WAVFILE *wav) { if(NULL == wav) return(-1); return(wav->FMT_BitsPerSample); } int SetWAVFILE_FMT_BitsPerSample(WAVFILE *wav, int v) { if(NULL == wav) return(-1); wav->FMT_BitsPerSample = v; return(GetWAVFILE_FMT_BitsPerSample(wav)); } // DATA_Offset long GetWAVFILE_DATA_Offset(WAVFILE *wav) { if(NULL == wav) return(-1); return(wav->DATA_Offset); } long SetWAVFILE_DATA_Offset(WAVFILE *wav, long v) { if(NULL == wav) return(-1); wav->DATA_Offset = v; return(GetWAVFILE_DATA_Offset(wav)); } // DATA_ChunkSize long GetWAVFILE_DATA_ChunkSize(WAVFILE *wav) { if(NULL == wav) return(-1); return(wav->DATA_ChunkSize); } long SetWAVFILE_DATA_ChunkSize(WAVFILE *wav, long v) { if(NULL == wav) return(-1); wav->DATA_ChunkSize = v; return(GetWAVFILE_DATA_ChunkSize(wav)); } int IsRIFFWAVE(FILE *fp) { char IDstring[5]; if(NULL == fp) return(FALSE); IDstring[4] = '\0'; freadbytes(fp, 0, IDstring, 4); if(0 != strcmp(IDstring, "RIFF")) return(FALSE); freadbytes(fp, RIFFTYPE, IDstring, 4); if(0 != strcmp(IDstring, "WAVE")) return(FALSE); return(TRUE); } long FindChunk(FILE *fp, char *ChunkType) { long offset; long filesize; int NotFound; char IDstring[5]; // Verify the RIFF/WAVE Header if(!IsRIFFWAVE(fp)) return(0); filesize = 8 + freadlong(fp, CHUNK_SIZE); // If ChunkType is 'RIFF', function returns filesize. if(0 == strcmp(ChunkType, "RIFF")) return(filesize); // Loop Initialization IDstring[4] = '\0'; offset = FIRSTSUBCHUNK; NotFound = TRUE; // Loop until Chunk is found or no more chunks in file do { freadbytes(fp, offset, IDstring, 4); if(0 == strcmp(ChunkType, IDstring)) NotFound = FALSE; else offset += 8 + freadlong(fp, offset + CHUNK_SIZE); } while( (offset < filesize) && NotFound); return(NotFound? 0 : offset); } WAVFILE *WriteWAVEFILE_Header(WAVFILE *wav, FILE *fp) { long cs; // Chunk Start if( (NULL == fp) || (NULL == wav) ) return(NULL); // Write RIFF Header cs = 0; fwritebytes(fp, cs + CHUNK_ID, "RIFF", 4); fwritelong (fp, cs + CHUNK_SIZE, GetWAVFILE_RIFF_Filesize(wav)); fwritebytes(fp, cs + RIFFTYPE, "WAVE", 4); // Write FORMAT Chunk cs = GetWAVFILE_FMT_Offset(wav); fwritebytes(fp, cs + CHUNK_ID, "fmt ", 4); fwritelong (fp, cs + CHUNK_SIZE, GetWAVFILE_FMT_ChunkSize(wav)); fwriteint (fp, cs + AUDIOFORMAT, GetWAVFILE_FMT_AudioFormat(wav)); fwriteint (fp, cs + NUMCHANNELS, GetWAVFILE_FMT_NumChannels(wav)); fwritelong (fp, cs + SAMPLERATE, GetWAVFILE_FMT_SampleRate(wav)); fwritelong (fp, cs + BYTERATE, GetWAVFILE_FMT_ByteRate(wav)); fwriteint (fp, cs + BLOCKALIGN, GetWAVFILE_FMT_BlockAlign(wav)); fwriteint (fp, cs + BITSPERSAMPLE, GetWAVFILE_FMT_BitsPerSample(wav)); // Write DATA Chunk (Header only) cs = GetWAVFILE_DATA_Offset(wav); fwritebytes(fp, cs + CHUNK_ID, "data", 4); fwritelong (fp, cs + CHUNK_SIZE, GetWAVFILE_DATA_ChunkSize(wav)); return(wav); } WAVFILE *ReadWAVEFILE_Header(WAVFILE *wav, FILE *fp) { long cs; // Chunk Start if( (NULL == fp) || (NULL == wav) ) return(NULL); // Read RIFF Header if(0 == FindChunk(fp, "RIFF")) return(NULL); cs = 0; SetWAVFILE_RIFF_Filesize(wav, freadlong(fp, cs + CHUNK_SIZE)); // Read FORMAT Chunk cs = SetWAVFILE_FMT_Offset(wav, FindChunk(fp, "fmt ")); if(0 == cs) return(NULL); SetWAVFILE_FMT_ChunkSize(wav, freadlong (fp, cs + CHUNK_SIZE)); SetWAVFILE_FMT_AudioFormat(wav, freadint (fp, cs + AUDIOFORMAT)); SetWAVFILE_FMT_NumChannels(wav, freadint (fp, cs + NUMCHANNELS)); SetWAVFILE_FMT_SampleRate(wav, freadlong (fp, cs + SAMPLERATE)); SetWAVFILE_FMT_ByteRate(wav, freadlong (fp, cs + BYTERATE)); SetWAVFILE_FMT_BlockAlign(wav, freadint (fp, cs + BLOCKALIGN)); SetWAVFILE_FMT_BitsPerSample(wav, freadint (fp, cs + BITSPERSAMPLE)); // Write DATA Chunk (Header only) cs = SetWAVFILE_DATA_Offset(wav, FindChunk(fp, "data")); if(0 == cs) return(NULL); SetWAVFILE_DATA_ChunkSize(wav, freadlong (fp, cs + CHUNK_SIZE)); return(wav); } int BytesPerSample(int bits) { return( (bits/8) + (0 != bits%8) ); } int PrepWAVFILE(WAVFILE *wav, int chan, int bits, long rate, long frames) { int SampleSize, BlockAlign; long ByteRate, DataBytes; if( NULL == wav ) return(NULL); SampleSize = BytesPerSample(bits); BlockAlign = chan * SampleSize; ByteRate = rate * BlockAlign; DataBytes = frames * BlockAlign; // Prepare RIFF Chunk SetWAVFILE_RIFF_Filesize(wav, (36 + DataBytes)); // Prepare FORMAT Chunk SetWAVFILE_FMT_Offset(wav, 12); SetWAVFILE_FMT_ChunkSize(wav, 16); SetWAVFILE_FMT_AudioFormat(wav, 1); SetWAVFILE_FMT_NumChannels(wav, chan); SetWAVFILE_FMT_SampleRate(wav, rate); SetWAVFILE_FMT_ByteRate(wav, ByteRate); SetWAVFILE_FMT_BlockAlign(wav, BlockAlign); SetWAVFILE_FMT_BitsPerSample(wav, bits); // Prepare DATA Chunk (Header Only) SetWAVFILE_DATA_Offset(wav, 36); SetWAVFILE_DATA_ChunkSize(wav, DataBytes); return(0); } WAVFILE *DisplayWAVEFILE(WAVFILE *wav) { BLANKLINE; printf("Data stored in wavefile structure:\n"); if(NULL == wav) { printf(" - WAVFILE pointer NULL.\n"); return(NULL); } BLANKLINE; printf(" RIFF Header:\n"); printf(" File Size: 8 + %li bytes\n", GetWAVFILE_RIFF_Filesize(wav)); BLANKLINE; printf(" FORMAT Chunk:\n"); printf(" Offset in file: %li bytes\n", GetWAVFILE_FMT_Offset(wav)); printf(" Chunk Size: 8 + %li bytes\n", GetWAVFILE_FMT_ChunkSize(wav)); printf(" Audio Format: %i \n", GetWAVFILE_FMT_AudioFormat(wav)); printf(" Channels: %i\n", GetWAVFILE_FMT_NumChannels(wav)); printf(" Sample Rate : %li Hz\n", GetWAVFILE_FMT_SampleRate(wav)); printf(" Byte Rate: %li bytes/sec\n", GetWAVFILE_FMT_ByteRate(wav)); printf(" Block Alignment: %i bytes\n", GetWAVFILE_FMT_BlockAlign(wav)); printf(" Bits per Sample: %i\n", GetWAVFILE_FMT_BitsPerSample(wav)); BLANKLINE; printf(" DATA Chunk:\n"); printf(" Offset in file: %li bytes\n", GetWAVFILE_DATA_Offset(wav)); printf(" Total Data: %li bytes\n", GetWAVFILE_DATA_ChunkSize(wav)); return(wav); } int WriteWAV2TXTdata(WAVFILE *wav, FILE *fpWAV, FILE *fpTXT) { long BlockStart; int bits; int SampleSize, BlockAlign; long frame, frames; int channel, channels; long data; int shift; if( NULL == wav ) return(1); if( NULL == fpTXT ) return(2); if( NULL == fpWAV ) return(3); bits = GetWAVFILE_FMT_BitsPerSample(wav); channels = GetWAVFILE_FMT_NumChannels(wav); BlockAlign = GetWAVFILE_FMT_BlockAlign(wav); frames = GetWAVFILE_DATA_ChunkSize(wav)/BlockAlign; SampleSize = BytesPerSample(bits); shift = (8-bits%8)%8; BlockStart = 8 + GetWAVFILE_DATA_Offset(wav); for(frame = 0; frame < frames; frame++) { printf("\rWriting %li frames: %li", frames, frame); for(channel = 0; channel < channels; channel++) { data = freadlong(fpWAV, BlockStart + channel*SampleSize); data >>= shift; fprintf(fpTXT, "%li ", data); } fprintf(fpTXT, "\n"); BlockStart += BlockAlign; } printf("\rWriting %li frames: %li (done)\n", frames, frame); return(0); } int WriteTXT2WAVdata(WAVFILE *wav, FILE *fpTXT, FILE *fpWAV, double min, double max) { long BlockStart; int bits; int SampleSize, BlockAlign; long frame, frames; int channel, channels; long data, minsig, maxsig, margin; int shift; double value; double slope, intercept; if( NULL == wav ) return(1); if( NULL == fpTXT ) return(2); if( NULL == fpWAV ) return(3); bits = GetWAVFILE_FMT_BitsPerSample(wav); maxsig = (bits>8)? bits-1 : bits; maxsig = -1 + pow(2, maxsig); minsig = (bits>8)? -maxsig-1 : 0; margin = (long) (0.1*(maxsig - minsig)); maxsig -= margin; minsig += margin; slope = (double)(maxsig - minsig) / (max - min); intercept = (double) minsig - slope*min; channels = GetWAVFILE_FMT_NumChannels(wav); BlockAlign = GetWAVFILE_FMT_BlockAlign(wav); frames = GetWAVFILE_DATA_ChunkSize(wav)/BlockAlign; SampleSize = BytesPerSample(bits); shift = (8-bits%8)%8; rewind(fpTXT); while('\n' != fgetc(fpTXT)); // Skip first line; BlockStart = 8 + GetWAVFILE_DATA_Offset(wav); for(frame = 0; frame < frames; frame++) { printf("\rWriting %li frames: %li", frames, frame); for(channel = 0; channel < channels; channel++) { fscanf(fpTXT, "%lf", &value); data = slope*value + intercept; data <<= shift; fwritebytes(fpWAV, BlockStart + channel*SampleSize, (char *) &data, SampleSize); } BlockStart += BlockAlign; } printf("\rWriting %li frames: %li (done)\n", frames, frame); return(0); }