📄 sndheader.c
字号:
loop->end = markers[i].position; } }}static double StepToHz(double step) { return exp(step * 0.0577622650466621 + 2.1011784386926213);}#define AIFF_SND_MAGIC (*((long *) "FORM"))#define WAVE_SND_MAGIC (*((long *) "RIFF"))long snd_read_header(snd_type snd, long *flags){ long read_in = 0; long magic, bytemode, len; short type=IRCAM_SND_COMMENT, size=0, encoding; unsigned char buf[SIZEOF_IRCAM_HEADER]; snd->u.file.loop_info = FALSE; len = snd_file_len(snd->u.file.file); /* get length of file */ magic = readlong(snd->u.file.file, &read_in); magic = htonl(magic); /* undo what readlong did */ if (magic == IRCAM_SND_MAGIC) { snd->u.file.header = SND_HEAD_IRCAM; snd->format.srate = (double) readfloat(snd->u.file.file, &read_in); snd->format.channels = readlong(snd->u.file.file, &read_in); bytemode = readlong(snd->u.file.file, &read_in); (*flags) |= SND_HEAD_SRATE | SND_HEAD_CHANNELS; /* now SF_ULAW, SF_SHORT, SF_FLOAT,AE_CHAR, AE_ALAW, AE_ULAW, AE_SHORT, AE_LONG, AE_FLOAT or other */ while (type != IRCAM_SND_END && type != IRCAM_SND_AUDIOENCODE) { type = readshort(snd->u.file.file, &read_in); size = readshort(snd->u.file.file, &read_in); if (size > 2 * sizeof(short)) { int rc; /* make sure we don't overflow buffer */ if (size < SIZEOF_IRCAM_HEADER) { rc = snd_file_read(snd->u.file.file, (char *) buf, (size - 2 * sizeof(short))); } else { rc = 0; /* force error */ } if (rc != (size - 2 * (int) sizeof(short))) { return fail(snd, "bad IRCAM header"); } read_in += size - 2 * sizeof(short); } } if (type == IRCAM_SND_AUDIOENCODE) { /* printf("Got IRCAM sound format\n"); */ encoding = *((short *)(buf)); (*flags) |= SND_HEAD_MODE | SND_HEAD_BITS; switch (encoding) { case IRCAM_SND_CHAR: snd->format.mode = SND_MODE_PCM; snd->format.bits = 8; break; case IRCAM_SND_ALAW: snd->format.mode = SND_MODE_ALAW; snd->format.bits = 8; break; case IRCAM_SND_ULAW: snd->format.mode = SND_MODE_ULAW; snd->format.bits = 8; break; case IRCAM_SND_SHORT: snd->format.mode = SND_MODE_PCM; snd->format.bits = 16; break; case IRCAM_SND_LONG: snd->format.mode = SND_MODE_PCM; snd->format.bits = 32; break; case IRCAM_SND_FLOAT: snd->format.mode = SND_MODE_FLOAT; snd->format.bits = 32; break; default: (*flags) &= ~(SND_HEAD_MODE | SND_HEAD_BITS); break; } } else { snd->format.bits = bytemode << 3; (*flags) |= SND_HEAD_BITS; switch (bytemode) { case sizeof(char): (*flags) |= SND_HEAD_MODE; snd->format.mode = SND_MODE_ULAW; break; case sizeof(short): snd->format.mode = SND_MODE_PCM; break; case sizeof(float): snd->format.mode = SND_MODE_FLOAT; break; default: snd->format.mode = SND_MODE_PCM; break; } } /* seek to end of header */ snd_file_lseek(snd->u.file.file, SIZEOF_IRCAM_HEADER, SND_SEEK_SET); snd->u.file.byte_offset = SIZEOF_IRCAM_HEADER; snd->u.file.current_offset = snd->u.file.byte_offset; } else if (magic == NEXT_SND_MAGIC) { long hdr_size, trash, rate; snd->u.file.header = SND_HEAD_NEXT; hdr_size = readlong(snd->u.file.file, &read_in); /* dataLocation */ trash = readlong(snd->u.file.file, &read_in); /* dataSize */ bytemode = readlong(snd->u.file.file, &read_in); /* dataFormat */ rate = readlong(snd->u.file.file, &read_in); /* samplingRate */ snd->format.channels = readlong(snd->u.file.file, &read_in); /* channelCount */ snd->format.srate = (double) rate; (*flags) = SND_HEAD_SRATE | SND_HEAD_CHANNELS; switch (bytemode) { case NEXT_SND_FORMAT_ULAW_8: snd->format.bits = 8; snd->format.mode = SND_MODE_ULAW; (*flags) |= SND_HEAD_BITS | SND_HEAD_MODE; break; case NEXT_SND_FORMAT_LINEAR_8: snd->format.bits = 8; snd->format.mode = SND_MODE_PCM; (*flags) |= SND_HEAD_BITS | SND_HEAD_MODE; break; case NEXT_SND_FORMAT_LINEAR_16: snd->format.bits = 16; snd->format.mode = SND_MODE_PCM; (*flags) |= SND_HEAD_BITS | SND_HEAD_MODE; break; case NEXT_SND_FORMAT_LINEAR_24: snd->format.bits = 24; snd->format.mode = SND_MODE_PCM; (*flags) |= SND_HEAD_BITS | SND_HEAD_MODE; break; case NEXT_SND_FORMAT_LINEAR_32: snd->format.bits = 32; snd->format.mode = SND_MODE_PCM; (*flags) |= SND_HEAD_BITS |SND_HEAD_MODE; break; case NEXT_SND_FORMAT_FLOAT: snd->format.bits = sizeof(float) * 8; snd->format.mode = SND_MODE_FLOAT; (*flags) |= SND_HEAD_BITS | SND_HEAD_MODE; break; case NEXT_SND_FORMAT_DOUBLE: snd->format.bits = sizeof(double) * 8; snd->format.mode = SND_MODE_FLOAT; (*flags) |= SND_HEAD_BITS | SND_HEAD_MODE; break; case NEXT_SND_FORMAT_INDIRECT: break; case NEXT_SND_FORMAT_DSP_DATA_8: snd->format.bits = 8; (*flags) |= SND_HEAD_BITS; break; case NEXT_SND_FORMAT_DSP_DATA_16: snd->format.bits = 16; (*flags) |= SND_HEAD_BITS; break; case NEXT_SND_FORMAT_DSP_DATA_24: snd->format.bits = 24; (*flags) |= SND_HEAD_BITS; break; case NEXT_SND_FORMAT_DSP_DATA_32: snd->format.bits = 32; (*flags) |= SND_HEAD_BITS; break; case NEXT_SND_FORMAT_MULAW_SQUELCH: snd->format.mode = SND_MODE_ULAW; (*flags) |= SND_HEAD_MODE; break; default: break; } /* position file past header */ if (read_in < hdr_size) { snd_file_lseek(snd->u.file.file, hdr_size, SND_SEEK_SET); read_in = hdr_size; } snd->u.file.byte_offset = read_in; } else if (magic == AIFF_SND_MAGIC) { unsigned long totalsize; unsigned long ssnd_start = 0; char buf[4]; long blocksize; long offset; long chunksize; long ssnd_chunksize; inst_node inst; short nmarkers; marker_type markers = NULL; int inst_read = FALSE; snd->u.file.header = SND_HEAD_AIFF; totalsize = (unsigned long) readlong(snd->u.file.file, &read_in); if (snd_file_read(snd->u.file.file, buf, 4) != 4 || strncmp(buf, "AIFF", 4) != 0) { snd->u.file.header = SND_HEAD_NONE; (*flags) = 0; resetfile(snd->u.file.file); read_in = 0; } else {#ifdef TRACE printf("snd_read: 'AIFF', totalsize %d, at %d\n", totalsize, snd_file_lseek(snd->u.file.file, (off_t) 0, SND_SEEK_CUR) - 8);#endif /* Skip everything but the COMM, MARK, INST, and SSND chunks, */ while (1) { if (snd_file_read(snd->u.file.file, buf, 4) != 4) { if (ssnd_start != 0) break; /* found SSND chunk */ return fail(snd, "Missing SSND chunk in AIFF file\n"); }#ifdef TRACE printf("snd_read: '%c%c%c%c' at %d (0%o)\n", buf[0], buf[1], buf[2], buf[3], snd_file_lseek(snd->u.file.file, (off_t) 0, SND_SEEK_CUR) - 8, snd_file_lseek(snd->u.file.file, (off_t) 0, SND_SEEK_CUR) - 8);#endif if (strncmp(buf, "COMM", 4) == 0) { /* COMM chunk */ long chunksize; long frames; chunksize = readlong(snd->u.file.file, &read_in); if (chunksize != 18) { return fail(snd, "AIFF COMM chunk has bad size\n"); } snd->format.channels = (long) readshort(snd->u.file.file, &read_in); frames = readlong(snd->u.file.file, &read_in); snd->format.bits = readshort(snd->u.file.file, &read_in); snd->format.mode = SND_MODE_PCM; snd->format.srate = read_ieee_extended(snd); snd->u.file.end_offset = frames * snd_bytes_per_frame(snd) + read_in; (*flags) = SND_HEAD_MODE | SND_HEAD_BITS | SND_HEAD_SRATE | SND_HEAD_CHANNELS | SND_HEAD_LEN; } else if (strncmp(buf, "SSND", 4) == 0) { /* SSND chunk */ ssnd_chunksize = readlong(snd->u.file.file, &read_in); offset = readlong(snd->u.file.file, &read_in); blocksize = readlong(snd->u.file.file, &read_in); /* remember the file offset, there may be more chunks */ ssnd_start = snd_file_lseek(snd->u.file.file, 0, SND_SEEK_CUR); chunksize = ssnd_chunksize; if (chunksize & 1) chunksize++; /* round up to even number */ /* subtract 8, size of offset and blocksize: */ snd_file_lseek(snd->u.file.file, chunksize - 8, SND_SEEK_CUR); read_in += chunksize - 8; } else if (strncmp(buf, "MARK", 4) == 0) { long chunksize = readlong(snd->u.file.file, &read_in); int i; nmarkers = readshort(snd->u.file.file, &read_in); markers = (marker_type) snd_alloc(nmarkers * sizeof(marker_node)); for (i = 0; i < nmarkers; i++) { unsigned char label[256]; int len; markers[i].id = readshort(snd->u.file.file, &read_in); markers[i].position = readlong(snd->u.file.file, &read_in); if (snd_file_read(snd->u.file.file, (char *) label, 1L) != 1) return fail(snd, "problem reading AIFF file\n"); len = label[0] | 1; if (snd_file_read(snd->u.file.file, (char *) label, (long) len) != len) return fail(snd, "problam reading AIFF file\n"); } } else if (strncmp(buf, "INST", 4) == 0) { chunksize = readlong(snd->u.file.file, &read_in); inst.base_note = readchar(snd->u.file.file, &read_in); inst.detune = readchar(snd->u.file.file, &read_in); inst.low_note = readchar(snd->u.file.file, &read_in); inst.high_note = readchar(snd->u.file.file, &read_in); inst.low_velocity = readchar(snd->u.file.file, &read_in); inst.high_velocity = readchar(snd->u.file.file, &read_in); inst.gain = readshort(snd->u.file.file, &read_in); readloop(&inst.sustain_loop, snd->u.file.file, &read_in); readloop(&inst.release_loop, snd->u.file.file, &read_in); /* compute some properties from inst structure: * (marker chunk may not be read in yet, so do that later */ /* snd should have a StepToHz function, but it doesn't */ snd->u.file.native_hz = StepToHz(inst.base_note + inst.detune/100.0); /* the constant is to convert from db */ snd->u.file.gain = (float) exp(((double) inst.gain) * 0.11512925); snd->u.file.low_hz = StepToHz(inst.low_note); snd->u.file.high_hz = StepToHz(inst.high_note); snd->u.file.low_velocity = inst.low_velocity; snd->u.file.high_velocity = inst.high_velocity; inst_read = TRUE; } else { long chunksize = readlong(snd->u.file.file, &read_in); if (chunksize & 1) chunksize ++; /* round up to even number */ read_in += chunksize; /* skip the chunk */ snd_file_lseek(snd->u.file.file, chunksize, SND_SEEK_CUR); } } snd_file_lseek(snd->u.file.file, ssnd_start, SND_SEEK_SET); /* now we're positioned back at SSND chunk samples */ if (blocksize != 0) { return fail(snd, "AIFF header specifies nonzero blocksize."); } if (markers && inst_read) { convert_loop_data(&snd->u.file.sustain_loop, &inst.sustain_loop, markers, nmarkers); convert_loop_data(&snd->u.file.release_loop, &inst.release_loop, markers, nmarkers); if (snd->u.file.native_hz <= 0.0) { return fail(snd, "Bad base pitch + detune in AIFF file"); } if (snd->u.file.sustain_loop.mode < 0 || snd->u.file.sustain_loop.mode > 3) { return fail(snd, "Bad sustain loop mode in AIFF file"); } if (snd->u.file.sustain_loop.mode && (snd->u.file.sustain_loop.begin < 0 || snd->u.file.sustain_loop.end <= snd->u.file.sustain_loop.begin)) { return fail(snd, "Bad sustain loop in AIFF file"); } if (snd->u.file.release_loop.mode < 0 || snd->u.file.release_loop.mode > 3) { return fail(snd, "Bad release loop mode in AIFF file"); } if (snd->u.file.release_loop.mode && (snd->u.file.release_loop.begin < 0 || snd->u.file.release_loop.end <= snd->u.file.release_loop.begin)) { return fail(snd, "Bad release loop in AIFF file"); } snd->u.file.loop_info = TRUE; } if (markers) snd_free(markers); /* byte_offset is where the file pointer ends up after SND_SEEK_CUR */ snd->u.file.byte_offset = snd_file_lseek(snd->u.file.file, offset, SND_SEEK_CUR); snd->u.file.current_offset = snd->u.file.byte_offset; snd->u.file.end_offset = snd->u.file.byte_offset + ssnd_chunksize - 8; } } else if (magic == WAVE_SND_MAGIC) { long size; char buf[4]; short format; snd->u.file.header = SND_HEAD_WAVE; /* RIFF WAVE uses little-endian format -- be careful! */ size = readrevlong(snd->u.file.file, &read_in); if (snd_file_read(snd->u.file.file, buf, 4) != 4 || strncmp(buf, "WAVE", 4) != 0) { return fail(snd, "RIFF file does not specify 'WAVE' as type\n"); } /* Skip to the next "fmt " or end of file */ while (1) { long siz; if (snd_file_read(snd->u.file.file, buf, 4) != 4) { return fail(snd, "WAVE file missing fmt spec"); } if (strncmp("fmt ", buf, 4) == 0) break; siz = readrevlong(snd->u.file.file, &read_in);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -