#include "hacks.h" #define UWORD unsigned short /* --------------------- forward references --------------------- */ void usage(); void usage_exit(); int write_intel_long(unsigned long, FILE *); int write_intel_word(unsigned int, FILE *); int read_motorola_word(int *, FILE *); int write_wav_header(FILE *, int, int); int get_file_size(FILE *, int *); int r_rewind(FILE *); /* -------------------- start of actual code -------------------- */ void usage() { fprintf(stderr,"\ Usage: sample_to_wav [sample_rate \ in Hz]\n"); } void usage_exit() { usage(); exit(DOOPS); } int write_intel_long(l, f) /* slower but more portable version */ unsigned long l; FILE *f; { int status; unsigned long x; x = l mod 256; if ((status = fputc(x, f)) eq EOF) { fprintf(stderr, "write_intel_long: write error\n"); return(DOOPS); } x = l / 256; x = x mod 256; if ((status = fputc(x, f)) eq EOF) { fprintf(stderr, "write_intel_long: write error\n"); return(DOOPS); } x = l / 256; x = x / 256; x = x mod 256; if ((status = fputc(x, f)) eq EOF) { fprintf(stderr, "write_intel_long: write error\n"); return(DOOPS); } x = l / 256; x = x / 256; x = x / 256; x = x mod 256; if ((status = fputc(x, f)) eq EOF) { fprintf(stderr, "write_intel_long: write error\n"); return(DOOPS); } return(OKDOKEY); } int write_intel_word(w, f) unsigned int w; FILE *f; { int status; unsigned int x; x = w mod 256; if ((status = fputc(x, f)) eq EOF) { fprintf(stderr, "write_intel_long: write error\n"); return(DOOPS); } x = w / 256; x = x mod 256; if ((status = fputc(x, f)) eq EOF) { fprintf(stderr, "write_intel_long: write error\n"); return(DOOPS); } return(OKDOKEY); } /* read sample from file into the int */ int read_motorola_word(wtr, f) int *wtr; FILE *f; { int c; unsigned int x; /* read motorola high byte first */ c = fgetc(f); if (c eq EOF) return(EOF); x = c; /* read motorola low byte next */ c = fgetc(f); if (c eq EOF) return(c); x = (x * 256) + c; *wtr = x; return(OKDOKEY); } int write_wav_header(f, sample_length, sample_rate) FILE *f; int sample_length; int sample_rate; { int temp; /* all ints are assumed to be four bytes!!!! */ fprintf(f, "RIFF"); sample_length *= 2; /* cause it is 16-bit, which is 2 bytes */ temp = sample_length; temp += 36; /* header size */ write_intel_long(temp, f); /* this is length of entire .WAV file. */ fprintf(f, "WAVE"); /* now the format chunk "" */ fprintf(f, "fmt "); /* padded with space (not underline!) on end */ write_intel_long(16 ,f); /* size of WAVE section (16 bytes) */ write_intel_word(1, f); /* "formatTag" aka "Format catagory" is "PCM" */ write_intel_word(1, f); /* number of channels (1 for mono, 2 for stereo) */ write_intel_long(sample_rate, f);/* samples per second (sample rate) */ write_intel_long((sample_rate * 2), f); /* ? avg bytes per second. "for buffer" */ write_intel_word(2, f); /* nBlockAlign: number of bytes per sample * number of channels */ /* start of "PCM-format-specific: 2 bytes */ write_intel_word(16, f); /* bits per sample */ /* start of data chunk ... */ fprintf(f, "data"); write_intel_long(sample_length, f); return(OKDOKEY); } /* get_file_size. This function does not rewind the file! It leaves the file pointer at the end of the file. The file must have already been opened. */ /* -------------------------------------------------------------------------- */ int get_file_size(f, file_size) FILE *f; int *file_size; { int status; status = fseek(f,0,2); /* seek to end of file */ if (status neq 0) { fprintf(stderr, "get_file_size: file seek error\n"); return(DOOPS); } status = ftell(f); if (status eq -1L) { fprintf(stderr, "get_file_size: file ftell error\n"); return(DOOPS); } *file_size = status; return(OKDOKEY); } int r_rewind(f) FILE *f; { int status; status = fseek(f, 0, SEEK_SET); if (status eq -1) return(status); return(0); } main(argc, argv) int argc; char *argv[]; { int status, sample_length, sample_rate, x, s; FILE *f1, *f2; if (argc eq 0) exit(DOOPS); if (argc < 3) usage_exit(); if (argc eq 4) { sample_rate = atoi(argv[3]); if (sample_rate < 1) { fprintf(stderr,"error: bad sample rate! %\n", sample_rate); exit(DOOPS); } } else { sample_rate = 44100; } if ((f1 = fopen(argv[1], "rb")) eq NULL) { fprintf(stderr,"can't open input file %s\n", argv[1]); exit(DOOPS); } if ((status = setvbuf(f1, NULL, _IOFBF, 16384)) neq 0) { fprintf(stderr, "setvbuf error on input file\n"); exit(DOOPS); } status = get_file_size(f1, &sample_length); /* we need this info to make a proper WAV header */ if (status eq DOOPS) { fprintf(stderr,"seek error on input file\n"); exit(DOOPS); } /* rewind file */ status = r_rewind(f1); if (status neq 0) { fprintf(stderr,"rewind error on input file\n"); exit(DOOPS); } sample_length /= 2; /* change from byte count to word count */ if ((f2 = fopen(argv[2], "wb")) eq NULL) { fprintf(stderr,"can't create output file %s\n", argv[2]); exit(DOOPS); } if ((status = setvbuf(f2, NULL, _IOFBF, 16384)) neq 0) { fprintf(stderr, "setvbuf error on output file\n"); exit(DOOPS); } if ((status = write_wav_header(f2, sample_length, sample_rate)) eq DOOPS) { fprintf(stderr,"error writing header to wave file %s\n", argv[2]); exit(DOOPS); } printf("file is %d samples long ", sample_length); for (x = 0; x neq sample_length; x++) { if ((status = read_motorola_word(&s, f1)) eq EOF) { fprintf(stderr,"error reading from .sample file\n"); exit(DOOPS); } s -= 32768; /* convert from unisgned (0-65535) range to signed (-32768-32767) range */ if ((status = write_intel_word(s, f2)) eq EOF) { fprintf(stderr,"error writing to .WAV file\n"); exit(DOOPS); } } fclose(f2); fclose(f1); printf("\033[7mDone\033[m\n"); exit(OKDOKEY); } /* actual end of this file */