📄 sndheader.c
字号:
while (siz > 0) { snd_file_read(snd->u.file.file, buf, 1); siz--; } } size = readrevlong(snd->u.file.file, &read_in); format = readrevshort(snd->u.file.file, &read_in); switch (format) { case WAVE_FORMAT_UNKNOWN: return fail(snd, "file in Microsoft Official Unknown format"); case WAVE_FORMAT_PCM: break; case WAVE_FORMAT_ADPCM: return fail(snd, "file in ADPCM format"); case WAVE_FORMAT_ALAW: return fail(snd, "file in ALAW format"); case WAVE_FORMAT_MULAW: return fail(snd, "file in ULAW format"); case WAVE_FORMAT_OKI_ADPCM: return fail(snd, "file in OKI ADPCM format"); case WAVE_FORMAT_DIGISTD: return fail(snd, "file in Digistd format"); case WAVE_FORMAT_DIGIFIX: return fail(snd, "file in Digifix format"); case IBM_FORMAT_MULAW: return fail(snd, "file in IBM U-law format"); case IBM_FORMAT_ALAW: return fail(snd, "file in IBM A-law format"); case IBM_FORMAT_ADPCM: return fail(snd, "file in IBM ADPCM format"); default: return fail(snd, "file in unknown format"); } snd->format.channels = readrevshort(snd->u.file.file, &read_in); snd->format.srate = (double) readrevlong(snd->u.file.file, &read_in); readrevlong(snd->u.file.file, &read_in); /* Average bytes/second */ readrevshort(snd->u.file.file, &read_in); /* Block align */ snd->format.bits = readrevshort(snd->u.file.file, &read_in); snd->format.mode = SND_MODE_PCM; if (snd->format.bits == 8) snd->format.mode = SND_MODE_UPCM; /* unsigned */ *flags = SND_HEAD_MODE | SND_HEAD_BITS | SND_HEAD_SRATE | SND_HEAD_CHANNELS | SND_HEAD_LEN; /* size is size of "fmt " section; we've read 16 bytes, so * advance file pointer over any remaining bytes */ snd->u.file.byte_offset = snd_file_lseek(snd->u.file.file, size - 16, SND_SEEK_CUR); /* skip over any other forms until you find "data" */ while (1) { long n = snd_file_read(snd->u.file.file, buf, 4); if (n != 4) { return fail(snd, "missing data portion"); } if (strncmp("data", buf, 4) == 0) break; n = readrevlong(snd->u.file.file, &read_in); /* length of form */ snd->u.file.byte_offset = snd_file_lseek(snd->u.file.file, n, SND_SEEK_CUR); } snd->u.file.byte_offset += 8; /* "data" and length use 8 bytes */ snd->u.file.current_offset = snd->u.file.byte_offset; snd->u.file.end_offset = snd->u.file.byte_offset + readrevlong(snd->u.file.file, &read_in); } else { snd->u.file.header = SND_HEAD_NONE; (*flags) = 0; resetfile(snd->u.file.file); read_in = 0; } /* If not already determined from file header, assume remainder of file is sound data */ if (!(*flags & SND_HEAD_LEN)) { snd->u.file.end_offset = snd->u.file.byte_offset = read_in; snd->u.file.current_offset = snd->u.file.byte_offset; snd->u.file.end_offset = len; *flags |= SND_HEAD_LEN; } return SND_SUCCESS;}/* write_zeros -- add zeros to end of file *//**/void write_zeros(int fout, long n){ long zero = 0; while (n > 0) { /* don't put min() in the arg list of write on an RS6K */ /* there seems to be a compiler bug */ long len = min(n, sizeof(long)); snd_file_write(fout, (char *) &zero, len); n -= sizeof(long); }}/* write_ircam_start -- write an IRCAM header at current file position *//* * length is the total length of the header to be written; this is normally * SIZEOF_IRCAM_HEADER, but in the case of the hybrid CMIX headers, length * will be shorter to accommodate the NeXT header prefix */void write_ircam_start(snd_type snd, long length){ short encoding; writelong(snd->u.file.file, IRCAM_SND_MAGIC); writefloat(snd->u.file.file, (float) snd->format.srate); writelong(snd->u.file.file, snd->format.channels); writelong(snd->u.file.file, snd->format.bits >> 3); /* now write the "CODE" section */ writeshort(snd->u.file.file, IRCAM_SND_AUDIOENCODE); writeshort(snd->u.file.file, 3 * sizeof(short)); /* size of this record */ if (snd->format.bits == 8) { encoding = IRCAM_SND_CHAR; if (snd->format.mode == SND_MODE_ULAW) encoding = IRCAM_SND_ULAW; if (snd->format.mode == SND_MODE_ALAW) { snd_warn("ALAW not implemented, writing 8-bit PCM\n"); } } else if (snd->format.bits == 16) { encoding = IRCAM_SND_SHORT; } else if (snd->format.bits == 32) { encoding = IRCAM_SND_FLOAT; if (snd->format.mode == SND_MODE_PCM) encoding = IRCAM_SND_LONG; } writeshort(snd->u.file.file, encoding); /* end the "CODE" section */ writeshort(snd->u.file.file, IRCAM_SND_END); writeshort(snd->u.file.file, 2 * sizeof(short)); /* write filler */ length -= ( 16 /* head */ + 6 /* AudioEncode */ + 4 /* End */ ); write_zeros(snd->u.file.file, length);}/* write_next_start -- write a NeXT header *//* * Note: uses length for Length field, but does not fill with zeros. * Instead, this routine writes only the NeXT 24 byte header. */void write_next_start(snd_type snd, long length){ short encoding; writelong(snd->u.file.file, NEXT_SND_MAGIC); /* header size matches cmix's bsd format */ writelong(snd->u.file.file, length); writelong(snd->u.file.file, 0); /* data size, 0 -> unspecified */ if (snd->format.bits == 8) { encoding = NEXT_SND_FORMAT_LINEAR_8; if (snd->format.mode == SND_MODE_ULAW) encoding = NEXT_SND_FORMAT_ULAW_8; if (snd->format.mode == SND_MODE_ALAW) { snd_warn("ALAW not implemented, writing 8-bit PCM\n"); } } else if (snd->format.bits == 16) { encoding = NEXT_SND_FORMAT_LINEAR_16; } else if (snd->format.bits == 32) { encoding = NEXT_SND_FORMAT_FLOAT; if (snd->format.mode == SND_MODE_PCM) encoding = NEXT_SND_FORMAT_LINEAR_32; } writelong(snd->u.file.file, encoding); writelong(snd->u.file.file, (long) (snd->format.srate + 0.5)); writelong(snd->u.file.file, snd->format.channels);}/* snd_write_header -- write header, position file for sample data *//**/void snd_write_header(snd_type snd, long *flags){ long nframes = 0x7f000000; long bytes_per_frame = snd_bytes_per_frame(snd); /* end_offset will keep track of how much data written so far */ snd->u.file.end_offset = 0; switch (snd->u.file.header) { case SND_HEAD_NONE: break; case SND_HEAD_AIFF: { int hsize = 12 /* bytes at beginning */ + 8 /*COMM hdr*/ + 18 /*COMM chunk*/ + 8 /*SSND hdr*/ + 8 /*SSND chunk*/; if (snd->format.bits != 8 && snd->format.bits != 16) { char msg[64]; sprintf(msg, "Warning: using 16 bits per sample instead of %d\n", snd->format.bits); snd_warn(msg); snd->format.bits = 16; bytes_per_frame = snd_bytes_per_frame(snd); } snd_file_write(snd->u.file.file, "FORM", 4); /* IFF header */ /* (bogus) file size: */ writelong(snd->u.file.file, hsize + nframes * bytes_per_frame); snd_file_write(snd->u.file.file, "AIFF", 4); /* File type */ /* COMM chunk -- describes encoding (and #frames) */ snd_file_write(snd->u.file.file, "COMM", 4); writelong(snd->u.file.file, 18); /* COMM chunk size */ writeshort(snd->u.file.file, (short) snd->format.channels); /* nchannels */ writelong(snd->u.file.file, nframes); /* number of frames */ writeshort(snd->u.file.file, (short) snd->format.bits); /* sample width, in bits */ write_ieee_extended(snd->u.file.file, snd->format.srate); /* SSND chunk -- describes data */ snd_file_write(snd->u.file.file, "SSND", 4); writelong(snd->u.file.file, 8 + nframes * bytes_per_frame); /* chunk size */ writelong(snd->u.file.file, 0); /* offset */ writelong(snd->u.file.file, 0); /* block size */ snd->u.file.byte_offset = hsize; /* printf("snd_write_header AIFF, byte_offset = %ld\n", snd_lseek(snd->u.file.file, (off_t) 0, SND_SEEK_CUR)); */ break; } case SND_HEAD_IRCAM: write_ircam_start(snd, SIZEOF_IRCAM_HEADER); snd->u.file.byte_offset = SIZEOF_IRCAM_HEADER; break; case SND_HEAD_NEXT: /* for compatibility with CMIX, we will always write an IRCAM * header after the NeXT header, and use 1024 bytes of header. */ write_next_start(snd, SIZEOF_IRCAM_HEADER); write_ircam_start(snd, SIZEOF_IRCAM_HEADER - 24); snd->u.file.byte_offset = SIZEOF_IRCAM_HEADER; break; case SND_HEAD_WAVE: snd_file_write(snd->u.file.file, "RIFF", 4); writerevlong(snd->u.file.file, 12+18+8 + nframes * bytes_per_frame); snd_file_write(snd->u.file.file, "WAVE", 4); snd_file_write(snd->u.file.file, "fmt ", 4); writerevlong(snd->u.file.file, 18L); switch (snd->format.mode) /* Format type */ { case SND_MODE_ADPCM: writerevshort(snd->u.file.file, 2); break; case SND_MODE_PCM: case SND_MODE_UPCM: writerevshort(snd->u.file.file, 1); break; case SND_MODE_ULAW: writerevshort(snd->u.file.file, 7); break; case SND_MODE_ALAW: writerevshort(snd->u.file.file, 6); break; case SND_MODE_UNKNOWN: case SND_MODE_FLOAT: default: writerevshort(snd->u.file.file, 0); break; } writerevshort(snd->u.file.file, (short) snd->format.channels); /* Number of channels */ writerevlong(snd->u.file.file, (long) (snd->format.srate + 0.5)); /* Samples per second */ writerevlong(snd->u.file.file, (((long) snd->format.srate) * bytes_per_frame)); /* Bytes per second*/ writerevshort(snd->u.file.file, (short) bytes_per_frame); /* Block alignment */ writerevshort(snd->u.file.file, (short) snd->format.bits); /* Bits per sample */ writerevshort(snd->u.file.file, (short) 0); /* Size of needed extra data */ snd_file_write(snd->u.file.file, "data", 4); writerevlong(snd->u.file.file, (long) (nframes * bytes_per_frame)); snd->u.file.byte_offset = 46; break; default: break; } snd->u.file.end_offset = snd->u.file.byte_offset;}void write_sndheader_finish(snd_type snd){ long n; switch (snd->u.file.header) { case SND_HEAD_NONE: break; case SND_HEAD_AIFF: { int hsize = 8 /*COMM hdr*/ + 18 /*COMM chunk*/ + 8 /*SSND hdr*/ + 12 /*SSND chunk*/; int datasize = snd->u.file.end_offset - hsize - 8; /* get the current position = file size */ n = snd_file_lseek(snd->u.file.file, 0, SND_SEEK_CUR); if (n != snd->u.file.end_offset) { char str[80]; sprintf(str, "Actual file size %ld does not match predicted size %ld\n", n, snd->u.file.end_offset); fail(snd, str); } /* write filesize in the header */ snd_file_lseek(snd->u.file.file, 4, SND_SEEK_SET); writelong(snd->u.file.file, n - 8 /* 'FORM'+size do not count */); /* write number of frames in COMM chunk */ snd_file_lseek(snd->u.file.file, (4 /* 'AIFF' */ + 4 /* 'COMM' */ + 4 /* size */ + 2 /* channels */), SND_SEEK_CUR); writelong(snd->u.file.file, (n - (hsize + 8)) / snd_bytes_per_frame(snd)); /* write size in SSND chunk */ snd_file_lseek(snd->u.file.file, (2 /* snd->format.bits */ + 10 /* sr */ + 4 /* 'SSND' */), SND_SEEK_CUR); writelong(snd->u.file.file, 8 + datasize); /* chunk size */ break; } case SND_HEAD_IRCAM: break; case SND_HEAD_NEXT: break; case SND_HEAD_WAVE: /* get the current position = file size */ n = snd_file_lseek(snd->u.file.file, 0, SND_SEEK_CUR); /* back to the top */ snd_file_lseek(snd->u.file.file, 4, SND_SEEK_SET); writerevlong(snd->u.file.file, n - 8); /* file size - ['RIFF', len] */ snd_file_lseek(snd->u.file.file, 42, SND_SEEK_SET); writerevlong(snd->u.file.file, n - 46); /* data size */ break; default: break; }}double read_ieee_extended(snd_type snd){ unsigned char buf[10]; if (snd_file_read(snd->u.file.file, (char *) buf, 10L) != 10) fail(snd, "EOF while reading IEEE extended number"); return ConvertFromIeeeExtended(buf);}void write_ieee_extended(int file, 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]); */ snd_file_write(file, buf, 10);}char *mode_string[] = { "ADPCM", "PCM", "ULAW", "ALAW", "Float", "UPCM", "Unknown" };char *mode_to_string(long mode){ if (mode < 0 || mode >= SND_NUM_MODES) return "InvalidData"; else return mode_string[mode];}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -