/* * readwave.c --- 無圧縮 WAVE ファイルを読んでテキスト・ファイルにする * 動作することはまったく保証しません * * version 2 (2003/12/21) * version 3 (2005/7/4) "PAD " チャンクの存在を知りそれに対応 * version 4 (2013/10/26) #include 増やした。文字コードをUTF8にした。 * version 5 (2014/8/12) FLLR チャンクの存在を知りそれに対応 * version 5.1 (2017/10/9) www.math.meiji.ac.jp を変える * version 6 (2020/12/22) LIST チャンクの存在を知りそれに対応 * version 7 (2020/12/24) fread() を使うようにした * * コンパイル: gcc -o readwave readwave.c * * 使い方: * (1) ./readwave <テキスト・ファイル名> * (2) ./readwave * 標準出力に出力 * (3) ./readwave * 標準入力から入力、標準出力に出力 * * 入手: * http://nalab.mind.meiji.ac.jp/~mk/program/ * * 参考にした情報 * URL: http://member.nifty.ne.jp/Ryuz/programing/wavefmt.html * -> http://homepage3.nifty.com/ryuz/programing/wavefmt.html * * 普段置いてある場所 * ~/Sotsuken/2007/sound/readwave/ */ #include #include #include const int verbose = 1; 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); } 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, 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[5120]; unsigned char *buf2; 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) は fread(buf, 1, 4, in) で良いかな。 /* ヘッダーを読む */ fread(buf, 1, 4, in); checkstring(buf, "RIFF"); size = readint(in); printf("# RIFF データのサイズ=%d\n", size); fread(buf, 1, 4, in); checkstring(buf, "WAVE"); fread(buf, 1, 4, in); checkstring(buf, "fmt "); size = readint(in); printf("# fmt データのサイズ=%d\n", size); fread(buf, 1, size, in); 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); while (1) { fread(buf, 1, 4, in); if (strncmp("data", (char *)buf, 4) == 0) { if (verbose) printf("# dataチャンク見つかった\n"); break; } else { // dataチャンク以外。"PAD "とか "FLLR" とか "fact" とか "LIST" とか if (verbose) { buf[4] = 0; printf("# %s チャンクがある。サイズは%d\n", buf, size = readint(in)); fread(buf, 1, size, in); dump(buf, size); } else { size = readint(in); fseek(in, size, SEEK_CUR); } } } size = readint(in); if (verbose) 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; }