diff --git a/aucat/afile.c b/aucat/afile.c index 3bc9505..69680e7 100644 --- a/aucat/afile.c +++ b/aucat/afile.c @@ -22,28 +22,6 @@ #include "afile.h" #include "utils.h" -/* - * Max size of a .wav file, format design limitation. - */ -#define WAV_MAXPOS (0x7fffffff) - -/* - * Encoding IDs used in .wav headers. - */ -#define WAV_FMT_PCM 1 -#define WAV_FMT_FLOAT 3 -#define WAV_FMT_ALAW 6 -#define WAV_FMT_ULAW 7 -#define WAV_FMT_EXT 0xfffe - -#define AU_FMT_PCM8 2 -#define AU_FMT_PCM16 3 -#define AU_FMT_PCM24 4 -#define AU_FMT_PCM32 5 -#define AU_FMT_FLOAT 6 -#define AU_FMT_ALAW 0x1b -#define AU_FMT_ULAW 1 - typedef struct { unsigned char ld[4]; } le32_t; @@ -61,7 +39,7 @@ typedef struct { } be16_t; struct wav_riff { - char magic[4]; + char id[4]; le32_t size; char type[4]; }; @@ -72,6 +50,11 @@ struct wav_chunk { }; struct wav_fmt { +#define WAV_FMT_PCM 1 +#define WAV_FMT_FLOAT 3 +#define WAV_FMT_ALAW 6 +#define WAV_FMT_ULAW 7 +#define WAV_FMT_EXT 0xfffe le16_t fmt; le16_t nch; le32_t rate; @@ -79,7 +62,6 @@ struct wav_fmt { le16_t blkalign; le16_t bits; #define WAV_FMT_SIZE 16 -#define WAV_FMT_SIZE2 (16 + 2) #define WAV_FMT_EXT_SIZE (16 + 24) le16_t extsize; le16_t valbits; @@ -96,7 +78,7 @@ struct wav_hdr { }; struct aiff_form { - char magic[4]; + char id[4]; be32_t size; char type[4]; }; @@ -137,6 +119,13 @@ struct au_hdr { char id[4]; be32_t offs; be32_t size; +#define AU_FMT_PCM8 2 +#define AU_FMT_PCM16 3 +#define AU_FMT_PCM24 4 +#define AU_FMT_PCM32 5 +#define AU_FMT_FLOAT 6 +#define AU_FMT_ALAW 0x1b +#define AU_FMT_ULAW 1 be32_t fmt; be32_t rate; be32_t nch; @@ -229,6 +218,76 @@ be32_set(be32_t *p, unsigned int v) p->bd[0] = v >> 24; } +static int +afile_readhdr(struct afile *f, void *addr, size_t size) +{ + if (lseek(f->fd, 0, SEEK_SET) < 0) { + log_puts(f->path); + log_puts(": failed to seek to beginning of file\n"); + return 0; + } + if (read(f->fd, addr, size) != size) { + log_puts(f->path); + log_puts(": failed to read header\n"); + return 0; + } + return 1; +} + +static int +afile_writehdr(struct afile *f, void *addr, size_t size) +{ + if (lseek(f->fd, 0, SEEK_SET) < 0) { + log_puts(f->path); + log_puts(": failed to seek back to header\n"); + return 0; + } + if (write(f->fd, addr, size) != size) { + log_puts(f->path); + log_puts(": failed to write header\n"); + return 0; + } + f->curpos = f->startpos; + return 1; +} + +static int +afile_checkpar(struct afile *f) +{ + if (f->nch == 0 || f->nch > NCHAN_MAX) { + log_puts(f->path); + log_puts(": "); + log_putu(f->nch); + log_puts(": unsupported number of channels\n"); + return 0; + } + if (f->rate < RATE_MIN || f->rate > RATE_MAX) { + log_puts(f->path); + log_puts(": "); + log_putu(f->rate); + log_puts(": unsupported rate\n"); + return 0; + } + if (f->par.bits < BITS_MIN || f->par.bits > BITS_MAX) { + log_puts(f->path); + log_puts(": "); + log_putu(f->par.bits); + log_puts(": unsupported bits per sample\n"); + return 0; + } + if (f->par.bits > f->par.bps * 8) { + log_puts(f->path); + log_puts(": bits larger than bytes-per-sample\n"); + return 0; + } + if (f->fmt == AFILE_FMT_FLOAT && f->par.bits != 32) { + log_puts(f->path); + log_puts(": only 32-bit floating points are supported\n"); + return 0; + } + return 1; +} + static int afile_wav_readfmt(struct afile *f, unsigned int csize) { @@ -246,7 +305,7 @@ afile_wav_readfmt(struct afile *f, unsigned int csize) csize = WAV_FMT_EXT_SIZE; if (read(f->fd, &fmt, csize) != csize) { log_puts(f->path); - log_puts(": failed to read .wav format chun\n"); + log_puts(": failed to read format chunk\n"); return 0; } wenc = le16_get(&fmt.fmt); @@ -268,34 +327,7 @@ afile_wav_readfmt(struct afile *f, unsigned int csize) } else f->par.bps = (f->par.bits + 7) / 8; f->nch = le16_get(&fmt.nch); - if (f->nch == 0 || f->nch > NCHAN_MAX) { - log_puts(f->path); - log_puts(": "); - log_putu(f->nch); - log_puts(": unsupported number of channels\n"); - return 0; - } f->rate = le32_get(&fmt.rate); - if (f->rate < RATE_MIN || f->rate > RATE_MAX) { - log_puts(f->path); - log_puts(": "); - log_putu(f->rate); - log_puts(": unsupported rate\n"); - return 0; - } - if (f->par.bits < BITS_MIN || f->par.bits > BITS_MAX) { - log_puts(f->path); - log_puts(": "); - log_putu(f->par.bits); - log_puts(": unsupported bits per sample\n"); - return 0; - } - if (f->par.bits > f->par.bps * 8) { - log_puts(f->path); - log_puts(": "); - log_puts("bits larger than bytes-per-sample\n"); - return 0; - } f->par.le = 1; f->par.msb = 1; switch (wenc) { @@ -315,18 +347,13 @@ afile_wav_readfmt(struct afile *f, unsigned int csize) break; case WAV_FMT_FLOAT: f->fmt = AFILE_FMT_FLOAT; - if (f->par.bits != 32) { - log_puts(f->path); - log_puts(": only 32-bit float supported\n"); - return 0; - } break; default: log_putu(wenc); - log_puts(": unsupported encoding in .wav file\n"); + log_puts(": unsupported encoding\n"); return 0; } - return 1; + return afile_checkpar(f); } static int @@ -337,17 +364,9 @@ afile_wav_readhdr(struct afile *f) unsigned int csize, rsize, pos = 0; int fmt_done = 0; - if (lseek(f->fd, 0, SEEK_SET) < 0) { - log_puts(f->path); - log_puts(": failed to seek to beginning of file\n"); + if (!afile_readhdr(f, &riff, sizeof(struct wav_riff))) return 0; - } - if (read(f->fd, &riff, sizeof(riff)) != sizeof(riff)) { - log_puts(f->path); - log_puts(": failed to read riff header\n"); - return 0; - } - if (memcmp(&riff.magic, &wav_id_riff, 4) != 0 || + if (memcmp(&riff.id, &wav_id_riff, 4) != 0 || memcmp(&riff.type, &wav_id_wave, 4)) { log_puts(f->path); log_puts(": not a .wav file\n"); @@ -395,7 +414,7 @@ afile_wav_readhdr(struct afile *f) } if (!fmt_done) { log_puts(f->path); - log_puts(": missing format chunk in .wav file\n"); + log_puts(": missing format chunk\n"); return 0; } return 1; @@ -410,7 +429,7 @@ afile_wav_writehdr(struct afile *f) struct wav_hdr hdr; memset(&hdr, 0, sizeof(struct wav_hdr)); - memcpy(hdr.riff.magic, wav_id_riff, 4); + memcpy(hdr.riff.id, wav_id_riff, 4); memcpy(hdr.riff.type, wav_id_wave, 4); le32_set(&hdr.riff.size, f->endpos - sizeof(hdr.riff)); memcpy(hdr.fmt_hdr.id, wav_id_fmt, 4); @@ -423,19 +442,7 @@ afile_wav_writehdr(struct afile *f) le16_set(&hdr.fmt.bits, f->par.bits); memcpy(hdr.data_hdr.id, wav_id_data, 4); le32_set(&hdr.data_hdr.size, f->endpos - f->startpos); - - if (lseek(f->fd, 0, SEEK_SET) < 0) { - log_puts(f->path); - log_puts(": failed to seek back to header\n"); - return 0; - } - if (write(f->fd, &hdr, sizeof(hdr)) != sizeof(hdr)) { - log_puts(f->path); - log_puts(": failed to write header\n"); - return 0; - } - f->curpos = f->startpos; - return 1; + return afile_writehdr(f, &hdr, sizeof(struct wav_hdr)); } static int @@ -461,13 +468,6 @@ afile_aiff_readcomm(struct afile *f, unsigned int csize, return 0; } f->nch = be16_get(&comm.base.nch); - if (f->nch == 0 || f->nch > NCHAN_MAX) { - log_puts(f->path); - log_puts(": "); - log_putu(f->nch); - log_puts(": unsupported number of channels\n"); - return 0; - } e = be16_get(&comm.base.rate_ex); m = be32_get(&comm.base.rate_hi); if (e < 0x3fff || e > 0x3fff + 31) { @@ -476,13 +476,6 @@ afile_aiff_readcomm(struct afile *f, unsigned int csize, return 0; } f->rate = m >> (0x3fff + 31 - e); - if (f->rate < RATE_MIN || f->rate > RATE_MAX) { - log_puts(f->path); - log_puts(": "); - log_putu(f->rate); - log_puts(": unsupported sample rate\n"); - return 0; - } if (comp) { if (memcmp(comm.comp_id, aiff_id_none, 4) == 0) { f->fmt = AFILE_FMT_PCM; @@ -505,19 +498,12 @@ afile_aiff_readcomm(struct afile *f, unsigned int csize, f->fmt = AFILE_FMT_PCM; f->par.bits = be16_get(&comm.base.bits); } - if (f->par.bits < BITS_MIN || f->par.bits > BITS_MAX) { - log_puts(f->path); - log_puts(": "); - log_putu(f->par.bits); - log_puts(": unsupported number of bits per sample\n"); - return 0; - } f->par.le = 0; f->par.sig = 1; f->par.msb = 1; f->par.bps = (f->par.bits + 7) / 8; *nfr = be32_get(&comm.base.nfr); - return 1; + return afile_checkpar(f); } static int @@ -550,17 +536,9 @@ afile_aiff_readhdr(struct afile *f) unsigned int csize, rsize, nfr = 0, pos = 0, offs; int comm_done = 0, comp; - if (lseek(f->fd, 0, SEEK_SET) < 0) { - log_puts(f->path); - log_puts(": failed to seek to beginning of file\n"); + if (!afile_readhdr(f, &form, sizeof(struct wav_riff))) return 0; - } - if (read(f->fd, &form, sizeof(form)) != sizeof(form)) { - log_puts(f->path); - log_puts(": failed to read file form header\n"); - return 0; - } - if (memcmp(&form.magic, &aiff_id_form, 4) != 0) { + if (memcmp(&form.id, &aiff_id_form, 4) != 0) { log_puts(f->path); log_puts(": not an aiff file\n"); return 0; @@ -571,7 +549,7 @@ afile_aiff_readhdr(struct afile *f) comp = 1; else { log_puts(f->path); - log_puts(": unknown aiff file type\n"); + log_puts(": unsupported aiff file sub-type\n"); return 0; } rsize = be32_get(&form.size); @@ -600,7 +578,7 @@ afile_aiff_readhdr(struct afile *f) #ifdef DEBUG if (log_level >= 2) { log_puts(f->path); - log_puts(": skipped unknown .aiff file chunk\n"); + log_puts(": skipped unknown chunk\n"); } #endif } @@ -653,7 +631,7 @@ afile_aiff_writehdr(struct afile *f) bpf = f->nch * f->par.bps; memset(&hdr, 0, sizeof(struct aiff_hdr)); - memcpy(hdr.form.magic, aiff_id_form, 4); + memcpy(hdr.form.id, aiff_id_form, 4); memcpy(hdr.form.type, aiff_id_aiff, 4); be32_set(&hdr.form.size, f->endpos - sizeof(hdr.form)); @@ -670,18 +648,7 @@ afile_aiff_writehdr(struct afile *f) be32_set(&hdr.data_hdr.size, f->endpos - f->startpos); be32_set(&hdr.data.offs, 0); be32_set(&hdr.data.blksz, 0); - if (lseek(f->fd, 0, SEEK_SET) < 0) { - log_puts(f->path); - log_puts(": failed to seek back to header\n"); - return 0; - } - if (write(f->fd, &hdr, sizeof(hdr)) != sizeof(hdr)) { - log_puts(f->path); - log_puts(": failed to write header\n"); - return 0; - } - f->curpos = f->startpos; - return 1; + return afile_writehdr(f, &hdr, sizeof(struct aiff_hdr)); } static int @@ -690,16 +657,8 @@ afile_au_readhdr(struct afile *f) struct au_hdr hdr; unsigned int fmt; - if (lseek(f->fd, 0, SEEK_SET) < 0) { - log_puts(f->path); - log_puts(": failed to seek to beginning of file\n"); + if (!afile_readhdr(f, &hdr, sizeof(struct wav_riff))) return 0; - } - if (read(f->fd, &hdr, sizeof(hdr)) != sizeof(hdr)) { - log_puts(f->path); - log_puts(": failed to read file header\n"); - return 0; - } if (memcmp(&hdr.id, &au_id, 4) != 0) { log_puts(f->path); log_puts(": not a .au file\n"); @@ -752,28 +711,14 @@ afile_au_readhdr(struct afile *f) f->par.bps = f->par.bits / 8; f->par.msb = 0; f->rate = be32_get(&hdr.rate); - if (f->rate < RATE_MIN || f->rate > RATE_MAX) { - log_puts(f->path); - log_puts(": "); - log_putu(f->rate); - log_puts(": unsupported sample rate\n"); - return 0; - } f->nch = be32_get(&hdr.nch); - if (f->nch == 0 || f->nch > NCHAN_MAX) { - log_puts(f->path); - log_puts(": "); - log_putu(f->nch); - log_puts(": unsupported number of channels\n"); - return 0; - } if (lseek(f->fd, f->startpos, SEEK_SET) < 0) { log_puts(f->path); log_puts(": "); log_puts("failed to seek to data chunk\n"); return 0; } - return 1; + return afile_checkpar(f); } /* @@ -813,18 +758,7 @@ afile_au_writehdr(struct afile *f) be32_set(&hdr.fmt, fmt); be32_set(&hdr.rate, f->rate); be32_set(&hdr.nch, f->nch); - if (lseek(f->fd, 0, SEEK_SET) < 0) { - log_puts(f->path); - log_puts(": failed to seek back file header\n"); - return 0; - } - if (write(f->fd, &hdr, sizeof(hdr)) != sizeof(hdr)) { - log_puts(f->path); - log_puts(": failed to write .au file header\n"); - return 0; - } - f->curpos = f->startpos; - return 1; + return afile_writehdr(f, &hdr, sizeof(struct au_hdr)); } size_t @@ -895,7 +829,7 @@ afile_seek(struct afile *f, off_t pos) pos += f->startpos; if (f->endpos >= 0 && pos > f->endpos) { log_puts(f->path); - log_puts(": attempt to seek ouside file boundaries\n"); + log_puts(": attempt to seek outside file boundaries\n"); return 0; } @@ -932,7 +866,7 @@ afile_open(struct afile *f, char *path, int hdr, int flags, struct aparams *par, int rate, int nch) { char *ext; - union { + static union { struct wav_hdr wav; struct aiff_hdr aiff; struct au_hdr au; @@ -1010,13 +944,9 @@ afile_open(struct afile *f, char *path, int hdr, int flags, if (f->par.bits & 7) f->par.msb = 1; f->endpos = f->startpos = sizeof(struct wav_hdr); - f->maxpos = WAV_MAXPOS; - memset(&dummy, 0xd0, sizeof(struct wav_hdr)); - if (write(f->fd, &dummy, sizeof(struct wav_hdr)) < 0) { - log_puts(f->path); - log_puts(": couldn't write .wav header\n"); + f->maxpos = 0x7fffffff; + if (!afile_writehdr(f, &dummy, sizeof(struct wav_hdr))) goto bad_close; - } } else if (f->hdr == AFILE_HDR_AIFF) { f->par.bps = (f->par.bits + 7) >> 3; if (f->par.bps > 1) @@ -1025,13 +955,9 @@ afile_open(struct afile *f, char *path, int hdr, int flags, if (f->par.bits & 7) f->par.msb = 1; f->endpos = f->startpos = sizeof(struct aiff_hdr); - f->maxpos = WAV_MAXPOS; - memset(&dummy, 0xd0, sizeof(struct aiff_hdr)); - if (write(f->fd, &dummy, sizeof(struct aiff_hdr)) < 0) { - log_puts(f->path); - log_puts(": couldn't write .aiff header\n"); + f->maxpos = 0x7fffffff; + if (!afile_writehdr(f, &dummy, sizeof(struct aiff_hdr))) goto bad_close; - } } else if (f->hdr == AFILE_HDR_AU) { f->par.bits = (f->par.bits + 7) & ~7; f->par.bps = f->par.bits / 8; @@ -1039,13 +965,9 @@ afile_open(struct afile *f, char *path, int hdr, int flags, f->par.sig = 1; f->par.msb = 1; f->endpos = f->startpos = sizeof(struct au_hdr); - f->maxpos = WAV_MAXPOS; - memset(&dummy, 0xd0, sizeof(struct au_hdr)); - if (write(f->fd, &dummy, sizeof(struct au_hdr)) < 0) { - log_puts(f->path); - log_puts(": couldn't write .au header\n"); + f->maxpos = 0x7fffffff; + if (!afile_writehdr(f, &dummy, sizeof(struct au_hdr))) goto bad_close; - } } else { f->endpos = f->startpos = 0; f->maxpos = -1;