/* * readwave.c --- 無圧縮 WAVE ファイルを読んでテキスト・ファイルにする * version 2 (2003/12/21) * * コンパイル: gcc -o readwave readwave.c * * 使い方: * (1) ./readwave <テキスト・ファイル名> * (2) ./readwave * 標準出力に出力 * (3) ./readwave * 標準入力から入力、標準出力に出力 * * 入手: * http://www.math.meiji.ac.jp/~mk/labo/members/ * * 参考にした情報 * URL: http://member.nifty.ne.jp/Ryuz/programing/wavefmt.html */ #include const int verbose = 0; const int debug = 0; FILE *out; void usage(char *prog) { fprintf(stderr, "usage (1): %s\n", prog); fprintf(stderr, "usage (2): %s \n", prog); fprintf(stderr, "usage (3): %s \n", prog); exit(0); } void setstring(unsigned char *buf, FILE *in, int n) { int i; for (i = 0; i < n; i++) buf[i] = getc(in); buf[n] = 0; } int readint(FILE *in) { int c1, c2, c3, c4; c1 = getc(in); c2 = getc(in); c3 = getc(in); c4 = getc(in); return c1 + 256 * (c2 + 256 * (c3 + 256 * c4)); } int checkstring(unsigned char *buf, unsigned char *key) { int i, n = strlen(key); for (i = 0; i < n; i++) if (buf[i] != key[i]) { fprintf(stderr, "%s は \"%s\" と一致しない\n", buf, key); exit(1); } return 0; } void dump(unsigned char *buf, int n) { int i; printf("# "); for (i = 0; i < n; i++) { printf(" %02x", buf[i]); if ((i + 1) % 16 == 0) printf("\n# "); } printf("\n"); } int read2byte(unsigned char *buf) { return buf[0] + 256 * buf[1]; } int read1(FILE *in) { int c = getc(in); if (debug) { printf("%02x ", c); fprintf(out, "%02x ", c); } return c; } int read2(FILE *in) { int c1, c2, c; c1 = getc(in); c2 = getc(in); if (debug) { printf("%02x %02x ", c1, c2); fprintf(out, "%02x %02x ", c1, c2); } c = c1 + (c2 << 8); if (c >= 32768) c -= 65536; return c; } int read4byte(unsigned char *buf) { return buf[0] + 256 * (buf[1] + 256 * (buf[2] + 256 * buf[3])); } void analyze(unsigned char *buf, int *fmt_tag, int *num_channel, int *sampling_rate, int *bytes_per_seconds, int *block, int *num_bits, int *extended_information_size) { *fmt_tag = read2byte(buf); *num_channel = read2byte(buf + 2); *sampling_rate = read4byte(buf + 4); *bytes_per_seconds = read4byte(buf + 8); *block = read2byte(buf + 12); *num_bits = read2byte(buf + 14); *extended_information_size = read2byte(buf + 16); } void readpcm(FILE *in, int size, int bits, int channel) { int i, c, right; if (bits == 16) { if (channel == 2) { for (i = 0; i < size / 4; i++) { c = read2(in); right = read2(in); if (verbose) printf("%d %d\n", c, right); fprintf(out, "%d %d\n", c, right); } } else { for (i = 0; i < size / 2; i++) { c = read2(in); if (verbose) printf("%d\n", c); fprintf(out, "%d\n", c); } } } else { if (channel == 2) { for (i = 0; i < size / 2; i++) { c = read1(in); right = read1(in); if (verbose) printf("%d %d\n", c, right); fprintf(out, "%d %d\n", c, right); } } else { for (i = 0; i < size; i++) { c = read1(in); if (verbose) printf("%d\n", c); fprintf(out, "%d\n", c); } } } } /* 取り扱うファイルの名前 */ char *input_fname, *output_fname, *prog_name; int main(int argc, char **argv) { int size; FILE *in; unsigned char buf[512]; int fmt_tag, num_channel, sampling_rate, bytes_per_seconds; int block, num_bits, extended_information_size; prog_name = argv[0]; if (argc > 3) usage(prog_name); if (argc == 3) { output_fname = argv[2]; if ((out = fopen(output_fname, "w")) == NULL) { fprintf(stderr, "%s がオープンできません。\n", output_fname); exit(1); } } else { output_fname = "stdout"; out = stdout; } if (argc >= 2) { input_fname = argv[1]; if ((in = fopen(input_fname, "r")) == NULL) { fprintf(stderr, "%s がオープンできません。\n", input_fname); exit(1); } } else { input_fname = "input"; in = stdin; } /* ヘッダーを読む */ setstring(buf, in, 4); checkstring(buf, "RIFF"); size = readint(in); printf("# RIFF データのサイズ=%d\n", size); setstring(buf, in, 4); checkstring(buf, "WAVE"); setstring(buf, in, 4); checkstring(buf, "fmt "); size = readint(in); printf("# fmt データのサイズ=%d\n", size); setstring(buf, in, size); dump(buf, size); analyze(buf, &fmt_tag, &num_channel, &sampling_rate, &bytes_per_seconds, &block, &num_bits, &extended_information_size); printf("# 非圧縮PCM%s。\n", (fmt_tag == 1) ? "です" : "ではありません"); printf("# %sです。\n", (num_channel == 1) ? "モノラル" : "スレレオ"); printf("# サンプリング・レート(標本化周波数)=%d\n", sampling_rate); printf("# 1秒当りのバイト数=%d\n", bytes_per_seconds); printf("# ブロック境界=%d\n", block); printf("# ビット数/サンプル=%d\n", num_bits); printf("# 拡張情報サイズ=%d\n", extended_information_size); setstring(buf, in, 4); if (strcmp(buf, "fact") == 0) { printf("# fact チャンクがあります。"); size = readint(in); printf("# fact データのサイズ=%d\n", size); setstring(buf, in, 4); dump(buf, size); setstring(buf, in, 4); } checkstring(buf, "data"); size = readint(in); printf("# data データのサイズ=%d\n", size); /* 書き出す */ fprintf(out, "#original file: %s\n", input_fname); fprintf(out, "#number of channels: %d\n", num_channel); fprintf(out, "#sampling rate: %d\n", sampling_rate); fprintf(out, "#number of bits (per sample): %d\n", num_bits); fprintf(out, "#number of samples: %d\n", size / num_channel / (num_bits / 8)); readpcm(in, size, num_bits, num_channel); fclose(out); return 0; }