📄 aiff.c
字号:
/* just read what's left of SSND chunk */ if (len > p->nsamples) len = p->nsamples; rawread(ft, buf, len); p->nsamples -= len; return len;}void aiffstopread(ft) ft_t ft;{ char buf[5]; ULONG chunksize; if (!ft->seekable) while (! feof(ft->fp)) { if (fread(buf, 1, 4, ft->fp) != 4) return; chunksize = rblong(ft); if (feof(ft->fp)) return; buf[4] = '\0'; warn("Ignoring AIFF tail chunk: '%s', %d bytes long\n", buf, chunksize); if (! strcmp(buf, "MARK") || ! strcmp(buf, "INST")) warn(" You're stripping MIDI/loop info!\n"); while ((LONG) (--chunksize) >= 0) if (getc(ft->fp) == EOF) return; } return;}/* When writing, the header is supposed to contain the number of samples and data bytes written. Since we don't know how many samples there are until we're done, we first write the header with an very large number, and at the end we rewind the file and write the header again with the right number. This only works if the file is seekable; if it is not, the very large size remains in the header. Strictly spoken this is not legal, but the playaiff utility will still be able to play the resulting file. */void aiffstartwrite(ft)ft_t ft;{ struct aiffpriv *p = (struct aiffpriv *) ft->priv; int littlendian = 0; char *endptr; p->nsamples = 0; if (ft->info.style == ULAW && ft->info.size == BYTE) { report("expanding 8-bit u-law to 16 bits"); ft->info.size = WORD; } ft->info.style = SIGN2; /* We have a fixed style */ /* Compute the "very large number" so that a maximum number of samples can be transmitted through a pipe without the risk of causing overflow when calculating the number of bytes. At 48 kHz, 16 bits stereo, this gives ~3 hours of music. Sorry, the AIFF format does not provide for an "infinite" number of samples. */ aiffwriteheader(ft, 0x7f000000L / (ft->info.size*ft->info.channels)); endptr = (char *) &littlendian; *endptr = 1; if (littlendian == 1) ft->swap = 1;}void aiffwrite(ft, buf, len)ft_t ft;LONG *buf, len;{ struct aiffpriv *p = (struct aiffpriv *) ft->priv; p->nsamples += len; rawwrite(ft, buf, len);}voidaiffstopwrite(ft)ft_t ft;{ struct aiffpriv *p = (struct aiffpriv *) ft->priv; if (!ft->seekable) return; if (fseek(ft->fp, 0L, SEEK_SET) != 0) fail("can't rewind output file to rewrite AIFF header"); aiffwriteheader(ft, p->nsamples / ft->info.channels);}void aiffwriteheader(ft, nframes)ft_t ft;LONG nframes;{ int hsize = 8 /*COMM hdr*/ + 18 /*COMM chunk*/ + 8 /*SSND hdr*/ + 12 /*SSND chunk*/; int bits = 0; int i; hsize += 8 + 2 + 16*ft->instr.nloops; /* MARK chunk */ hsize += 20; /* INST chunk */ if (ft->info.style == SIGN2 && ft->info.size == BYTE) bits = 8; else if (ft->info.style == SIGN2 && ft->info.size == WORD) bits = 16; else fail("unsupported output style/size for AIFF header"); fputs("FORM", ft->fp); /* IFF header */ wblong(ft, hsize + nframes * ft->info.size * ft->info.channels); /* file size */ fputs("AIFF", ft->fp); /* File type */ /* ANNO chunk -- holds comments text, however this is */ /* discouraged by Apple in preference to a COMT comments */ /* chunk, which holds a timestamp and marker id */ fputs("ANNO", ft->fp); wblong(ft, (LONG) strlen(ft->comment)); /* ANNO chunk size, the No of chars */ fputs(ft->comment, ft->fp); /* COMM chunk -- describes encoding (and #frames) */ fputs("COMM", ft->fp); wblong(ft, (LONG) 18); /* COMM chunk size */ wbshort(ft, ft->info.channels); /* nchannels */ wblong(ft, nframes); /* number of frames */ wbshort(ft, bits); /* sample width, in bits */ write_ieee_extended(ft, (double)ft->info.rate); /* MARK chunk -- set markers */ if (ft->instr.nloops) { fputs("MARK", ft->fp); if (ft->instr.nloops > 2) ft->instr.nloops = 2; wblong(ft, 2 + 16*ft->instr.nloops); wbshort(ft, ft->instr.nloops); for(i = 0; i < ft->instr.nloops; i++) { wbshort(ft, i + 1); wblong(ft, ft->loops[i].start); fputc(0, ft->fp); fputc(0, ft->fp); wbshort(ft, i*2 + 1); wblong(ft, ft->loops[i].start + ft->loops[i].length); fputc(0, ft->fp); fputc(0, ft->fp); } fputs("INST", ft->fp); wblong(ft, 20); /* random MIDI shit that we default on */ fputc(ft->instr.MIDInote, ft->fp); fputc(0, ft->fp); /* detune */ fputc(ft->instr.MIDIlow, ft->fp); fputc(ft->instr.MIDIhi, ft->fp); fputc(1, ft->fp); /* low velocity */ fputc(127, ft->fp); /* hi velocity */ wbshort(ft, 0); /* gain */ /* sustain loop */ wbshort(ft, ft->loops[0].type); wbshort(ft, 1); /* marker 1 */ wbshort(ft, 3); /* marker 3 */ /* release loop, if there */ if (ft->instr.nloops == 2) { wbshort(ft, ft->loops[1].type); wbshort(ft, 2); /* marker 2 */ wbshort(ft, 4); /* marker 4 */ } else { wbshort(ft, 0); /* no release loop */ wbshort(ft, 0); wbshort(ft, 0); } } /* SSND chunk -- describes data */ fputs("SSND", ft->fp); /* chunk size */ wblong(ft, 8 + nframes * ft->info.channels * ft->info.size); wblong(ft, (LONG) 0); /* offset */ wblong(ft, (LONG) 0); /* block size */}double read_ieee_extended(ft)ft_t ft;{ char buf[10]; if (fread(buf, 1, 10, ft->fp) != 10) fail("EOF while reading IEEE extended number"); return ConvertFromIeeeExtended(buf);}void write_ieee_extended(ft, x)ft_t ft;double x;{ char buf[10]; ConvertToIeeeExtended(x, buf); /* report("converted %g to %o %o %o %o %o %o %o %o %o %o", x, buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7], buf[8], buf[9]); */ (void) fwrite(buf, 1, 10, ft->fp);}/* * C O N V E R T T O I E E E E X T E N D E D *//* Copyright (C) 1988-1991 Apple Computer, Inc. * All rights reserved. * * Machine-independent I/O routines for IEEE floating-point numbers. * * NaN's and infinities are converted to HUGE_VAL or HUGE, which * happens to be infinity on IEEE machines. Unfortunately, it is * impossible to preserve NaN's in a machine-independent way. * Infinities are, however, preserved on IEEE machines. * * These routines have been tested on the following machines: * Apple Macintosh, MPW 3.1 C compiler * Apple Macintosh, THINK C compiler * Silicon Graphics IRIS, MIPS compiler * Cray X/MP and Y/MP * Digital Equipment VAX * * * Implemented by Malcolm Slaney and Ken Turkowski. * * Malcolm Slaney contributions during 1988-1990 include big- and little- * endian file I/O, conversion to and from Motorola's extended 80-bit * floating-point format, and conversions to and from IEEE single- * precision floating-point format. * * In 1991, Ken Turkowski implemented the conversions to and from * IEEE double-precision format, added more precision to the extended * conversions, and accommodated conversions involving +/- infinity, * NaN's, and denormalized numbers. */#ifndef HUGE_VAL# define HUGE_VAL HUGE#endif /*HUGE_VAL*/# define FloatToUnsigned(f) ((ULONG)(((LONG)(f - 2147483648.0)) + 2147483647L) + 1)void ConvertToIeeeExtended(num, bytes)double num;char *bytes;{ int sign; int expon; double fMant, fsMant; ULONG hiMant, loMant; if (num < 0) { sign = 0x8000; num *= -1; } else { sign = 0; } if (num == 0) { expon = 0; hiMant = 0; loMant = 0; } else { fMant = frexp(num, &expon); if ((expon > 16384) || !(fMant < 1)) { /* Infinity or NaN */ expon = sign|0x7FFF; hiMant = 0; loMant = 0; /* infinity */ } else { /* Finite */ expon += 16382; if (expon < 0) { /* denormalized */ fMant = ldexp(fMant, expon); expon = 0; } expon |= sign; fMant = ldexp(fMant, 32); fsMant = floor(fMant); hiMant = FloatToUnsigned(fsMant); fMant = ldexp(fMant - fsMant, 32); fsMant = floor(fMant); loMant = FloatToUnsigned(fsMant); } } bytes[0] = expon >> 8; bytes[1] = expon; bytes[2] = hiMant >> 24; bytes[3] = hiMant >> 16; bytes[4] = hiMant >> 8; bytes[5] = hiMant; bytes[6] = loMant >> 24; bytes[7] = loMant >> 16; bytes[8] = loMant >> 8; bytes[9] = loMant;}/* * C O N V E R T F R O M I E E E E X T E N D E D *//* * Copyright (C) 1988-1991 Apple Computer, Inc. * All rights reserved. * * Machine-independent I/O routines for IEEE floating-point numbers. * * NaN's and infinities are converted to HUGE_VAL or HUGE, which * happens to be infinity on IEEE machines. Unfortunately, it is * impossible to preserve NaN's in a machine-independent way. * Infinities are, however, preserved on IEEE machines. * * These routines have been tested on the following machines: * Apple Macintosh, MPW 3.1 C compiler * Apple Macintosh, THINK C compiler * Silicon Graphics IRIS, MIPS compiler * Cray X/MP and Y/MP * Digital Equipment VAX * * * Implemented by Malcolm Slaney and Ken Turkowski. * * Malcolm Slaney contributions during 1988-1990 include big- and little- * endian file I/O, conversion to and from Motorola's extended 80-bit * floating-point format, and conversions to and from IEEE single- * precision floating-point format. * * In 1991, Ken Turkowski implemented the conversions to and from * IEEE double-precision format, added more precision to the extended * conversions, and accommodated conversions involving +/- infinity, * NaN's, and denormalized numbers. */#ifndef HUGE_VAL# define HUGE_VAL HUGE#endif /*HUGE_VAL*/# define UnsignedToFloat(u) (((double)((LONG)(u - 2147483647L - 1))) + 2147483648.0)/**************************************************************** * Extended precision IEEE floating-point conversion routine. ****************************************************************/double ConvertFromIeeeExtended(bytes)unsigned char *bytes; /* LCN */{ double f; int expon; ULONG hiMant, loMant; expon = ((bytes[0] & 0x7F) << 8) | (bytes[1] & 0xFF); hiMant = ((ULONG)(bytes[2] & 0xFF) << 24) | ((ULONG)(bytes[3] & 0xFF) << 16) | ((ULONG)(bytes[4] & 0xFF) << 8) | ((ULONG)(bytes[5] & 0xFF)); loMant = ((ULONG)(bytes[6] & 0xFF) << 24) | ((ULONG)(bytes[7] & 0xFF) << 16) | ((ULONG)(bytes[8] & 0xFF) << 8) | ((ULONG)(bytes[9] & 0xFF)); if (expon == 0 && hiMant == 0 && loMant == 0) { f = 0; } else { if (expon == 0x7FFF) { /* Infinity or NaN */ f = HUGE_VAL; } else { expon -= 16383; f = ldexp(UnsignedToFloat(hiMant), expon-=31); f += ldexp(UnsignedToFloat(loMant), expon-=32); } } if (bytes[0] & 0x80) return -f; else return f;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -