This is wav.c in view mode; [Download] [Up]
/* * 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 */ /* * Fixed by various contributors: * 1) Little-endian handling * 2) Skip other kinds of file data * 3) Handle 16-bit formats correctly * 4) Not go into infinite loop */ #include "st.h" #include "wav.h" /* Private data for .wav file */ typedef struct wavstuff { long samples; } *wav_t; IMPORT float volume, amplitude; IMPORT 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; int littlendian = 1; char *endptr; char c; endptr = (char *) &littlendian; if (!*endptr) ft->swap = 1; /* If you need to seek around the input file. */ if (0 && ! ft->seekable) fail("Sorry, .wav input file must be a file, not a pipe"); fread(magic, 4, 1, ft->fp); if (strncmp("RIFF", magic, 4)) fail("Sorry, not a RIFF file"); len = rllong(ft); fread(magic, 4, 1, ft->fp); if (strncmp("WAVE", magic, 4)) fail("Sorry, not a WAVE file"); /* Skip to the next "fmt " or end of file */ while(1) { if (feof(ft->fp)) fail("Sorry, missing fmt spec"); fread(magic, 4, 1, ft->fp); if (! strncmp("fmt ", magic, 4)) break; for (len = rllong(ft); len>0; len--) fread(&c,1,1,ft->fp); } len = rllong(ft); switch (rlshort(ft)) { case WAVE_FORMAT_UNKNOWN: fail("Sorry, this WAV file is in Microsoft Official Unknown format."); case WAVE_FORMAT_PCM: /* this one, at least, I can handle */ break; case WAVE_FORMAT_ADPCM: fail("Sorry, this WAV file is in Microsoft ADPCM format."); case WAVE_FORMAT_ALAW: fail("Sorry, this WAV file is in Microsoft A-law format."); case WAVE_FORMAT_MULAW: fail("Sorry, this WAV file is in Microsoft U-law format."); case WAVE_FORMAT_OKI_ADPCM: fail("Sorry, this WAV file is in OKI ADPCM format."); case WAVE_FORMAT_DIGISTD: fail("Sorry, this WAV file is in Digistd format."); case WAVE_FORMAT_DIGIFIX: fail("Sorry, this WAV file is in Digifix format."); case IBM_FORMAT_MULAW: fail("Sorry, this WAV file is in IBM U-law format."); case IBM_FORMAT_ALAW: fail("Sorry, this WAV file is in IBM A-law format."); case IBM_FORMAT_ADPCM: fail("Sorry, this WAV file is in IBM ADPCM format."); default: fail("Sorry, 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; ft->info.style = UNSIGNED; break; case 16: ft->info.size = WORD; ft->info.style = SIGN2; break; case 32: ft->info.size = LONG; ft->info.style = SIGN2; break; default: fail("Sorry, don't understand size"); } len -= 16; while (--len >= 0) getc(ft->fp); fread(magic, 4, 1, ft->fp); if (strncmp("data", magic, 4)) fail("Sorry, missing data portion"); wav->samples = rllong(ft) / ft->info.size; } /* * 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); if (done == 0) report("Premature EOF on .wav input file"); wav->samples -= done; 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 = 1; char *endptr; if (! ft->seekable) fail("Sorry, output .wav file must be a file, not a pipe"); endptr = (char *) &littlendian; if (!*endptr) 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; ft->info.style = UNSIGNED; break; case WORD: samsize = 16; ft->info.style = SIGN2; break; default: case LONG: ft->info.size = LONG; ft->info.style = SIGN2; samsize = 32; break; } datasize = ft->info.size * 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; 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. */ if (!ft->seekable) return; if (fseek(ft->fp, 0L, 0) != 0) fail("Sorry, can't rewind output file to rewrite .wav header."); wavwritehdr(ft); }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.