/* * April 15, 1992 * Copyright 1992 Rick Richardson * Copyright 1991 Lance Norskog And Sundry Contributors * This source code is freely redistributable and may be used for * any purpose. This copyright notice must be maintained. * Lance Norskog And Sundry Contributors are not responsible for * the consequences of using this software. */ /* * Windows 3.0 .wav format driver */ #include "st.h" /* Private data for .wav file */ typedef struct wavstuff { long samples; } *wav_t; extern float volume, amplitude; extern long summary, verbose; /* * Do anything required before you start reading samples. * Read file header. * Find out sampling rate, * size and style of samples, * mono/stereo/quad. */ wavstartread(ft) ft_t ft; { wav_t wav = (wav_t) ft->priv; char magic[4]; long len; /* If you need to seek around the input file. */ if (0 && ! ft->seekable) fail(".wav input file must be a file, not a pipe"); fread(magic, 4, 1, ft->fp); if (strncmp("RIFF", magic, 4)) fail("Not a RIFF file"); len = rllong(ft); fread(magic, 4, 1, ft->fp); if (strncmp("WAVE", magic, 4)) fail("Not a WAVE file"); fread(magic, 4, 1, ft->fp); if (strncmp("fmt ", magic, 4)) fail("Missing fmt spec"); len = rllong(ft); switch (rlshort(ft)) { case 1: ft->info.style = UNSIGNED; break; default: fail("Don't understand format"); } ft->info.channels = rlshort(ft); ft->info.rate = rllong(ft); rllong(ft); /* Average bytes/second */ rlshort(ft); /* Block align */ switch (rlshort(ft)) { case 8: ft->info.size = BYTE; break; case 16: ft->info.size = WORD; break; case 32: ft->info.size = LONG; break; default: fail("Don't understand size"); } len -= 16; while (len) getc(ft->fp); fread(magic, 4, 1, ft->fp); if (strncmp("data", magic, 4)) fail("Missing data portion"); wav->samples = rllong(ft); } /* * Read up to len samples from file. * Convert to signed longs. * Place in buf[]. * Return number of samples read. */ wavread(ft, buf, len) ft_t ft; long *buf, len; { wav_t wav = (wav_t) ft->priv; int done; if (len > wav->samples) len = wav->samples; if (len == 0) return 0; done = rawread(ft, buf, len); wav->samples -= len; return done; } /* * Do anything required when you stop reading samples. * Don't close input file! */ wavstopread(ft) ft_t ft; { } wavstartwrite(ft) ft_t ft; { wav_t wav = (wav_t) ft->priv; int littlendian = 0; char *endptr; if (! ft->seekable) fail("Output .wav file must be a file, not a pipe"); endptr = (char *) &littlendian; *endptr = 1; if (!littlendian) ft->swap = 1; wav->samples = 0; wavwritehdr(ft); } wavwritehdr(ft) ft_t ft; { wav_t wav = (wav_t) ft->priv; int samsize; long datasize; switch (ft->info.size) { case BYTE: samsize = 8; break; case WORD: samsize = 16; break; default: case LONG: ft->info.size = LONG; samsize = 32; break; } ft->info.style = UNSIGNED; datasize = samsize/8 * ft->info.channels * wav->samples; fputs("RIFF", ft->fp); wllong(ft, datasize + 8+16+12); /* Waveform chunk size: FIXUP(4) */ fputs("WAVE", ft->fp); fputs("fmt ", ft->fp); wllong(ft, (long)16); /* fmt chunk size */ wlshort(ft, 1); /* FormatTag: WAVE_FORMAT_PCM */ wlshort(ft, ft->info.channels); wllong(ft, (long)ft->info.rate); /* SamplesPerSec */ /* Average Bytes/sec */ wllong(ft, (long)(ft->info.rate * ft->info.channels * samsize + 7) / 8); /* nBlockAlign */ wlshort(ft, (ft->info.channels * samsize + 7) / 8); wlshort(ft, samsize); /* BitsPerSample */ fputs("data", ft->fp); wllong(ft, datasize); /* data chunk size: FIXUP(40) */ } wavwrite(ft, buf, len) ft_t ft; long *buf, len; { wav_t wav = (wav_t) ft->priv; wav->samples += len * ft->info.size; rawwrite(ft, buf, len); } void wavstopwrite(ft) ft_t ft; { /* All samples are already written out. */ /* If file header needs fixing up, for example it needs the */ /* the number of samples in a field, seek back and write them here. */ wav_t wav = (wav_t) ft->priv; if (!ft->seekable) return; if (fseek(ft->fp, 0L, 0) != 0) fail("Can't rewind output file to rewrite .wav header."); wavwritehdr(ft); }