📄 pc_wav.c
字号:
{ error_msg("get_hd", "couldn't allocate storage for PC WAVE header."); return NULL; } got_ck_hd = get_ck_hd(ckID, &ckSize, end_pref, &num_read, file); while (got_ck_hd && strncmp(ckID, "fmt ", 4) != 0 && strncmp(ckID, "data", 4) != 0) { got_ck_hd = (skip_ck(ckSize, end_pref, &num_read, file) && get_ck_hd(ckID, &ckSize, end_pref, &num_read, file)); } if (!got_ck_hd) { error_msg("get_hd", "end of file within PC WAVE chunk."); return NULL; } if (strncmp(ckID, "fmt ", 4) != 0) { error_msg("get_hd", "no \"fmt\" chunk before data in PC WAVE file."); return NULL; } if (!(get_lsbf_ushort(&wav_hd->FormatTag, end_pref, &num_read, file) && get_lsbf_ushort(&wav_hd->Channels, end_pref, &num_read, file) && get_lsbf_ulong(&wav_hd->SamplesPerSec, end_pref, &num_read, file) && get_lsbf_ulong(&wav_hd->AvgBytesPerSec, end_pref, &num_read, file) && get_lsbf_ushort(&wav_hd->BlockAlign, end_pref, &num_read, file))) { error_msg("get_hd", "failed to read PC WAVE \"fmt\" chunk."); return NULL; } ckSize -= 14; /* 3 ushort & 2 ulong */ switch (wav_hd->FormatTag) { case WAVE_FORMAT_PCM: if (!get_lsbf_ushort(&wav_hd->spec.pcm.BitsPerSample, end_pref, &num_read, file)) { error_msg("get_hd", "failed to read PC WAVE \"fmt\" chunk (PCM part)."); return NULL; } ckSize -= 2; /* 1 ushort */ break; default: error_msg("get_hd", "only WAVE_FORMAT_PCM supported."); return NULL; } if (ckSize < 0) { error_msg("get_hd", "inconsistent chunk size for PC WAVE \"fmt\"."); return NULL; } do { got_ck_hd = (skip_ck(ckSize, end_pref, &num_read, file) && get_ck_hd(ckID, &ckSize, end_pref, &num_read, file)); } while(got_ck_hd && strncmp(ckID, "data", 4) != 0); if (!got_ck_hd) { error_msg("get_hd", "failed to find PC WAVE \"data\" chunk."); return NULL; } if (num_read > 0) { error_msg("get_hd", "read too far ahead."); return NULL; } wav_hd->data_len = ckSize; return wav_hd;}/* * Function used by "get_hd" to "read" a RIFF chunk header, consisting of * a four-character chunk ID and a four-byte unsigned integer chunk size * (in least-significant-first byte order). These are returned via the * pointers "ckID" and "ckSize". The eight bytes are obtained from the * sequence consisting of the catenation of (1) "num_read" bytes just * before the byte indicated by "end_pref" and (2) the unread bytes in * "file". See "get_hd" for the usage of these last three arguments. The * return value is TRUE for success and FALSE for failure. */static intget_ck_hd(char *ckID, unsigned long *ckSize, char *end_pref, int *num_read, FILE *file){ return (get_fourcc(ckID, end_pref, num_read, file) && get_lsbf_ulong(ckSize, end_pref, num_read, file));}/* * Function used by "get_hd" to skip over the body of a RIFF chunk after * its chunk ID and size have been obtained by "get_ck_hd". The number * of bytes to skip is passed as "ckSize"; if this odd, an additional * byte of padding is skipped to make up an even number. The bytes * skipped are in the sequence consisting of the catenation of * (1) "num_read" bytes just before the byte indicated by "end_pref" and * (2) the unread bytes in "file". See "get_hd" for the usage of these * last three arguments. Bytes are skipped by decrementing "num_read", * reading from "file", or both. The return values is TRUE for success * and NO for failure. */static intskip_ck(unsigned long ckSize, char *end_pref, int *num_read, FILE *file){ ckSize += (ckSize & 1); /* round up to multiple of 2 bytes */ if (ckSize <= *num_read) { *num_read -= ckSize; } else { ckSize -= *num_read; *num_read = 0; while (ckSize > 0 && getc(file) != EOF) ckSize--; if (ckSize != 0) { error_msg("skip_ck", "end of file within chunk."); return NO; } } return YES;}/* * Function used by "get_hd" to "read" a two-byte unsigned short integer * in least-significant-first byte order from the sequence consisting of * the catenation of (1) "num_read" bytes just before the byte indicated * by "end_pref" and (2) the unread bytes in "file". See "get_hd" for * the usage of these last three arguments. The value obtained is * returned via the pointer "ptr". The function return value is TRUE * for success and FALSE for failure. */static intget_lsbf_ushort(unsigned short *ptr, char *end_pref, int *num_read, FILE *file){ int ch; unsigned short val; ch = next_char(end_pref, num_read, file); if (ch == EOF) return NO; val = (ch & 0xff); ch = next_char(end_pref, num_read, file); if (ch == EOF) return NO; *ptr = val | (ch & 0xff); return YES;}/* * Function used by "get_hd" and "get_ck_hd" to "read" a two-byte * unsigned short integer in least-significant-first byte order from the * sequence consisting of the catenation of (1) "num_read" bytes just * before the byte indicated by "end_pref" and (2) the unread bytes in * "file". See "get_hd" for the usage of these last three arguments. * The value obtained is returned via the pointer "ptr". The function * return value is TRUE for success and FALSE for failure. */static intget_lsbf_ulong(unsigned long *ptr, char *end_pref, int *num_read, FILE *file){ int i; int ch; unsigned long val; val = 0; for (i = 0; i < 4; i++) { ch = next_char(end_pref, num_read, file); if (ch != EOF) val |= (ch & 0xff) << (8*i); else return NO; } *ptr = val; return YES;}/* * Function used by "get_ck_hd" to "read" a four-character chunk ID from * the sequence consisting of the catenation of (1) "num_read" bytes just * before the byte indicated by "end_pref" and (2) the unread bytes in * "file". See "get_hd" for the usage of these last three arguments. * The value obtained is returned via the pointer "ptr". The function * return value is TRUE for success and FALSE for failure. */static intget_fourcc(char *ptr, char *end_pref, int *num_read, FILE *file){ int i; int ch; for (i= 0; i < 4; i++) { ch = next_char(end_pref, num_read, file); if (ch != EOF) ptr[i] = ch; else return NO; } return YES;}/* * Function used by "get_lsbf_ushort", "get_lsbf_ulong", "get_fourcc", to * "read" the next byte (unsigned char) from the sequence consisting of * the catenation of (1) "num_read" bytes just before the byte indicated * by "end_pref" and (2) the unread bytes in "file". See "get_hd" for * the usage of these last three arguments. The return value is the * value obtained in case of success and EOF in case of failure. */static intnext_char(char *end_pref, int *num_read, FILE *file){ return ((*num_read > 0) ? (unsigned char) *(end_pref - (*num_read)--) : getc(file));}/* * Function used by "pc_wav_get_rec" and "pc_wav_getsd_recs" to read a * given number "len" of two-byte signed short integers in * least-significant-first byte order from a file. The values obtained * are returned via the pointer "ptr". The function return value is the * actual number of values read and is less than "len" in case of * failure. */static longread_lsbf_short(short *ptr, long len, FILE *file){#if defined(DEC_ALPHA) || defined(LINUX) /* Code for Vax-like architectures (including Intel) that * match the least-significant-first byte ordering of the * RIFF standard. */ return fread(ptr, 2, len, file);#elif defined(SUN4) || defined(HP700) || defined(SG) /* Code for Sun-like architectures with most-significant-first * byte ordering, requiring byte-swapping to read RIFF files. */ unsigned char *p = (unsigned char *) ptr; int ch; long n, i; if (len == 1) { if ((ch = getc(file)) == EOF) return 0; p[1] = (unsigned char) ch; if ((ch = getc(file)) == EOF) return 0; p[0] = (unsigned char) ch; return 1; } if (len <= 0) return 0; /* Read the data offset by 1 so that the low-order bytes end up in the * right places and don't have to be moved when we "swap". */ n = fread(p + 1, 1, 2*len - 1, file); /* Now move the high-order bytes into place. */ for (i = 0; i < n - 1; i += 2) p[i] = p[i+2]; if (n != 2*len - 1) return n/2; if ((ch = getc(file)) == EOF) return n/2; p[n - 1] = (unsigned char) ch; return len;#else /* Code for unknown architecture. * This should work regardless of the native byte order of the * maching on which it runs. However, when porting to another * machine, try adding it to one of the #ifdef's above, as it * is likely to be faster. */ long n; unsigned int item; int ch; for (n = 0; n < len; n++) { if ((ch = getc(file)) == EOF) break; item = ch & 0xff; if ((ch = getc(file)) == EOF) break; item |= (ch & 0xff) << 8; ptr[n] = (item & 0x8000) ? (-1 - (int) (item ^ 0xffff)) : item; } return n;#endif}/* * Function used by various functions in this module to output error * messages. */static voiderror_msg(char *func_name, char *msg){ (void) fprintf(stderr, "%s: %s\n", func_name, msg);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -