📄 headers.c
字号:
#define DPOW2TO31 ((double)2147483648.0) /* 2^31 */static double myUlongToDouble(unsigned int ul){ double val; if(ul & ULPOW2TO31) val = DPOW2TO31 + (ul & (~ULPOW2TO31)); else val = ul; return val;}static unsigned int myDoubleToUlong(double val){ unsigned int ul; if(val < DPOW2TO31) ul = (unsigned int)val; else ul = ULPOW2TO31 | (unsigned int)(val-DPOW2TO31); return ul;}static double ieee_80_to_double(unsigned char *p){ unsigned char sign; short lexp = 0; unsigned int mant1 = 0; unsigned int mant0 = 0; lexp = *p++; lexp <<= 8; lexp |= *p++; sign = (lexp & 0x8000) ? 1 : 0; lexp &= 0x7FFF; mant1 = *p++; mant1 <<= 8; mant1 |= *p++; mant1 <<= 8; mant1 |= *p++; mant1 <<= 8; mant1 |= *p++; mant0 = *p++; mant0 <<= 8; mant0 |= *p++; mant0 <<= 8; mant0 |= *p++; mant0 <<= 8; mant0 |= *p++; if(mant1 == 0 && mant0 == 0 && lexp == 0 && sign == 0) return 0.0; else { double val; val = myUlongToDouble(mant0) * pow(2.0, -63.0); val += myUlongToDouble(mant1) * pow(2.0, -31.0); val *= pow(2.0, ((double) lexp) - 16383.0); return sign ? -val : val; }}static void double_to_ieee_80(double val, unsigned char *p){ short lexp = 0; unsigned char sign = 0; unsigned int mant1 = 0; unsigned int mant0 = 0; if(val < 0.0) { sign = 1; val = -val; } if(val != 0.0) /* val identically zero -> all elements zero */ { lexp = (short)(log(val) / log(2.0) + 16383.0); val *= pow(2.0, 31.0 + 16383.0 - (double)lexp); mant1 = myDoubleToUlong(val); val -= myUlongToDouble(mant1); val *= pow(2.0, 32.0); mant0 = myDoubleToUlong(val); } *p++ = ((sign << 7) | (lexp >> 8)); *p++ = 0xFF & lexp; *p++ = 0xFF & (mant1 >> 24); *p++ = 0xFF & (mant1 >> 16); *p++ = 0xFF & (mant1 >> 8); *p++ = 0xFF & (mant1); *p++ = 0xFF & (mant0 >> 24); *p++ = 0xFF & (mant0 >> 16); *p++ = 0xFF & (mant0 >> 8); *p++ = 0xFF & (mant0);}static off_t update_form_size, update_frames_location, update_ssnd_location;static int seek_and_read(int chan, unsigned char *buf, off_t offset, int nbytes){ if (offset < 0) return(-1); lseek(chan, offset, SEEK_SET); return(read(chan, buf, nbytes));}static int read_aiff_marker(int m, unsigned char *buf){ int psize; marker_ids[m] = mus_char_to_bshort((unsigned char *)buf); marker_positions[m] = mus_char_to_bint((unsigned char *)(buf + 2)); psize = (int)buf[6] + 1; if (psize & 1) psize++; return(psize+6);}static int read_aiff_header(const char *filename, int chan, int overall_offset){ /* we know we have checked for FORM xxxx AIFF|AIFC when we arrive here */ /* as far as I can tell, the COMM block has the header data we seek, and the SSND block has the sound data */ int chunksize, chunkloc, i, j, ssnd_bytes = 0; bool happy, got_comm = false; off_t offset; type_specifier = mus_char_to_uninterpreted_int((unsigned char *)(hdrbuf + 8 + overall_offset)); update_ssnd_location = 0; chunkloc = 12 + overall_offset; offset = 0; for (i = 0; i < AUX_COMMENTS; i++) aux_comment_start[i] = 0; data_format = MUS_BSHORT; srate = 0; chans = 0; happy = true; true_file_length = SEEK_FILE_LENGTH(chan); update_form_size = mus_char_to_bint((unsigned char *)(hdrbuf + 4 + overall_offset)); /* should be file-size-8 unless there are multiple forms */ while (happy) { offset += chunkloc; if (seek_and_read(chan, (unsigned char *)hdrbuf, offset, 32) <= 0) { if ((got_comm) && (data_location > 0)) { mus_print("%s, aiff header: chunks confused at " OFF_TD "; will try to continue", filename, offset); break; } return(mus_error(MUS_HEADER_READ_FAILED, "%s, aiff header: chunks confused at " OFF_TD , filename, offset)); } chunksize = mus_char_to_bint((unsigned char *)(hdrbuf + 4)); if ((chunksize == 0) && /* can be empty data chunk */ (hdrbuf[0] == 0) && (hdrbuf[1] == 0) && (hdrbuf[2] == 0) && (hdrbuf[3] == 0)) break; /* fprintf(stderr,"chunk: %c%c%c%c for %d\n", hdrbuf[0], hdrbuf[1], hdrbuf[2], hdrbuf[3], chunksize); */ if (match_four_chars((unsigned char *)hdrbuf, I_COMM)) { int frames; got_comm = true; chans = mus_char_to_bshort((unsigned char *)(hdrbuf + 8)); frames = mus_char_to_ubint((unsigned char *)(hdrbuf + 10)); /* was bint 27-Jul-01 */ update_frames_location = 10 + offset; original_data_format = mus_char_to_bshort((unsigned char *)(hdrbuf + 14)); if ((original_data_format % 8) != 0) { /* weird sizes are legal -- * these samples are left-justified (and zero padded on the right), so * we can handle any bit size by rounding up to the nearest byte. */ original_data_format = 8 * (1 + (original_data_format >> 3)); } if (original_data_format == 8) data_format = MUS_BYTE; else if (original_data_format == 16) data_format = MUS_BSHORT; else if (original_data_format == 24) data_format = MUS_B24INT; else if (original_data_format == 32) data_format = MUS_BINT; else if (original_data_format == 64) data_format = MUS_BDOUBLE; else return(mus_error(MUS_HEADER_READ_FAILED, "%s: bits per sample: %d?", filename, mus_char_to_bshort((unsigned char *)(hdrbuf + 14)))); srate = (int)ieee_80_to_double((unsigned char *)(hdrbuf + 16)); /* if AIFC, compression type over-rides (possibly bogus) original_data_format */ if (type_specifier == mus_char_to_uninterpreted_int((unsigned const char *)I_AIFC)) { /* some aifc files assume the compression field is a new and very weird chunk!! -- surely a bug? */ /* AIFF spec says COMM size is always 18, but this is amended in the newer AIFC spec */ if (chunksize == 18) chunksize += (5 + ((int)hdrbuf[30])); /* 5 = chunk header length in this case */ if ((!(match_four_chars((unsigned char *)(hdrbuf + 26), I_NONE))) && (!(match_four_chars((unsigned char *)(hdrbuf + 26), I_twos)))) { original_data_format = mus_char_to_uninterpreted_int((unsigned char *)(hdrbuf + 26)); if ((match_four_chars((unsigned char *)(hdrbuf + 26), I_ALAW)) || (match_four_chars((unsigned char *)(hdrbuf + 26), I_alaw))) data_format = MUS_ALAW; else { if ((match_four_chars((unsigned char *)(hdrbuf + 26), I_ULAW)) || (match_four_chars((unsigned char *)(hdrbuf + 26), I_ulaw))) data_format = MUS_MULAW; else { if ((match_four_chars((unsigned char *)(hdrbuf + 26), I_sowt)) || (match_four_chars((unsigned char *)(hdrbuf + 26), I_ni23))) { /* Sound.h sez sowt is just 16-bit format */ if (data_format == MUS_BSHORT) data_format = MUS_LSHORT; else if (data_format == MUS_B24INT) data_format = MUS_L24INT; else if (data_format == MUS_BINT) data_format = MUS_LINT; } else { if (match_four_chars((unsigned char *)(hdrbuf + 26), I_raw_)) { if (data_format == MUS_BYTE) data_format = MUS_UBYTE; else if (data_format == MUS_BSHORT) data_format = MUS_UBSHORT; } else { if ((match_four_chars((unsigned char *)(hdrbuf + 26), I_fl32)) || (match_four_chars((unsigned char *)(hdrbuf + 26), I_FL32))) data_format = MUS_BFLOAT; else { if (match_four_chars((unsigned char *)(hdrbuf + 26), I_fl64)) data_format = MUS_BDOUBLE; else { if (match_four_chars((unsigned char *)(hdrbuf + 26), I_ima4)) { block_align = 34; original_data_format = MUS_AIFF_IMA_ADPCM; } else { if (match_four_chars((unsigned char *)(hdrbuf + 26), I_in32)) data_format = MUS_BINT; else { if (match_four_chars((unsigned char *)(hdrbuf + 26), I_in24)) data_format = MUS_B24INT; else { /* others from Sound.h: 0x6D730002, -- Microsoft ADPCM - ACM code 2 0x6D730011, -- DVI/Intel IMA ADPCM - ACM code 17 'MAC3' -- MACE 3:1 'MAC6' -- MACE 6:1 'cdx4' -- CD/XA 4:1 'cdx2' -- CD/XA 2:1 'dvca' -- DV Audio 'QDMC' -- QDesign music 'QDM2' -- QDesign2 music 'Qclp' -- QUALCOMM PureVoice 0x6D730055 -- MPEG Layer 3, CBR only (pre QT4.1) '.mp3' -- MPEG Layer 3, CBR & VBR (QT4.1 and later) */ data_format = MUS_UNKNOWN; } } } } } } } } } } } data_size = (frames * mus_bytes_per_sample(data_format) * chans); } else { if (match_four_chars((unsigned char *)hdrbuf, I_SSND)) { if (data_location != 0) return(mus_error(MUS_HEADER_READ_FAILED, "%s: two SSND chunks found", filename)); update_ssnd_location = offset + 4; data_location = mus_char_to_bint((unsigned char *)(hdrbuf + 8)) + offset + 16; /* Baroque! */ /* offset is where the hdrbuf is positioned in the file, the sound data offset itself is at loc+8 and the */ /* 0-based location of the sound data is at the end of the chunk = 16 (8 = header+4 = offset+4 = blocksize) */ /* the next int can be the block size if the data is block-aligned */ /* only one SSND per AIFF is allowed */ if (chunksize == 0) break; /* this may happen while pre-reading an in-progress output file for updating */ ssnd_bytes = offset + chunksize - data_location + 8; } else { if ((match_four_chars((unsigned char *)hdrbuf, I_ANNO)) || (match_four_chars((unsigned char *)hdrbuf, I_COMT)) || (match_four_chars((unsigned char *)hdrbuf, I_NAME)) || (match_four_chars((unsigned char *)hdrbuf, I_AUTH))) { j = 0; for (i = 0; i < AUX_COMMENTS; i++) if (aux_comment_start[i] == 0) { j = i; break; } if (j >= AUX_COMMENTS) { mus_print("read_aiff_header: ran out of auxiliary comment space"); j = 0; } aux_comment_start[j] = offset + 8; if (match_four_chars((unsigned char *)hdrbuf, I_COMT)) aux_comment_start[j] += 8; /* skip time stamp and markerId (not ID, I assume!) */ aux_comment_end[j] = offset + 7 + chunksize; } else { if (match_four_chars((unsigned char *)hdrbuf, I_APPL)) { if (match_four_chars((unsigned char *)(hdrbuf + 8), I_MUS_)) { /* my own chunk has the arbitrary length comment I use (actually the ASCII */ /* representation of a lisp program evaluated in the CLM package) to handle mix et al. */ /* It is nothing more than the actual string -- remember to pad to even length here. */ comment_start = offset + 12;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -