/* * writewave.c --- 無圧縮PCMデータ(テキスト・ファイル)からWAVEファイルを作る * version 1 (2003/12/21) * * コンパイル: gcc -o writewave writewave.c * * 使い方: * (1): ./writewave <テキスト・ファイル名> * (2): ./writewave <テキスト・ファイル名> * 標準出力に出力 * (3): ./writewave * 標準入力から入力、標準出力に出力 */ #include #include int verbose = 1; #define fwrite16(out,n) {fputc((n)&0xff,(out));fputc(((n)>>8)&0xff,(out));} #define fwrite32(out,n) {fputc((n)&0xff,(out));fputc(((n)>>8)&0xff,(out));\ fputc(((n)>>16)&0xff,(out));fputc(((n)>>24)&0xff,(out));} void usage(char *prog_name) { fprintf(stderr, "usage: %s ", prog_name); exit(1); } int main(int argc, char **argv) { int num_channels, num_bits, num_samples, sampling_rate; FILE *in,*out; char buf[4096], original_fname[1024]; char *prog_name, *input_fname, *output_fname; int left, right, c; int ready = 0, len; int fmt_size, fmt_tag, bytes_per_seconds, block, extended_information_size, data_size, riff_size; static char label[5][32] = {"#original file: ", "#number of channels: ", "#number of bits (per sample): ", "#number of samples: ", "#sampling rate: "}; 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 がオープンできません。", input_fname); exit(1); } } else { input_fname = "stdin"; in = stdin; } while (fgets(buf, sizeof(buf), in) != NULL) { if (buf[0] == '#') { switch (buf[1]) { case 'o': if (strncmp(buf, label[0], len = strlen(label[0])) == 0) { sscanf(buf + len, "%s", original_fname); ready |= 0x01; } break; case 'n': if (strncmp(buf, label[1], len = strlen(label[1])) == 0) { sscanf(buf + len, "%d", &num_channels); ready |= 0x02; } else if (strncmp(buf, label[2], len = strlen(label[2])) == 0) { sscanf(buf + len, "%d", &num_bits); ready |= 0x04; } else if (strncmp(buf, label[3], len = strlen(label[3])) == 0) { sscanf(buf + len, "%d", &num_samples); ready |= 0x08; } else { fprintf(stderr, "unknown: %s\n", buf); } break; case 's': if (strncmp(buf, label[4], len = strlen(label[4])) == 0) { sscanf(buf + len, "%d", &sampling_rate); ready |= 0x10; } break; default: /* 何もしない */ } if (ready == 0x1f) { if (verbose) { fprintf(stderr, "original file: %s\n", original_fname); fprintf(stderr, "number of channels: %d\n", num_channels); fprintf(stderr, "number of bits: %d\n", num_bits); fprintf(stderr, "number of samples: %d\n", num_samples); fprintf(stderr, "sampling rate: %d\n", sampling_rate); } break; } } else { /* パラメーターが揃わない (ready == 0x1f にならない) うちに * 生データが来たらエラーだ */ printf("ready=%0x\n", ready); fprintf(stderr, "%s\n", buf); exit(1); } } /* fmt チャンク */ fmt_size = 18; /* 2+2+4+4+2+2+2 */ fmt_tag = 1; /* 無圧縮 PCM */ bytes_per_seconds = sampling_rate * (num_bits / 8) * num_channels; block = 1; /* ブロック境界(何のこと?) */ extended_information_size = 0; /* fact チャンクつけない */ /* data チャンク */ data_size = num_samples * (num_bits / 8) * num_channels; /* */ riff_size = fmt_size + data_size; /* ヘッダーを書く */ fprintf(out, "RIFF"); fwrite32(out, riff_size); fprintf(out, "WAVE"); fprintf(out, "fmt "); fwrite32(out, fmt_size); fwrite16(out, fmt_tag); /* 2bytes */ fwrite16(out, num_channels); /* 2bytes */ fwrite32(out, sampling_rate); /* 4bytes */ fwrite32(out, bytes_per_seconds); /* 4bytes */ fwrite16(out, block); /* 2bytes */ fwrite16(out, num_bits); /* 2bytes */ fwrite16(out, extended_information_size); /* 2bytes */ fprintf(out, "data"); fwrite32(out, data_size); if (num_channels == 2 && num_bits == 16) while (fgets(buf, sizeof(buf), in) != NULL) { sscanf(buf, "%d%d", &left, &right); fputc(left & 0xff, out); fputc((left >> 8) & 0xff, out); fputc(right & 0xff, out); fputc((right >> 8) & 0xff, out); } else if (num_channels == 2 && num_bits == 8) while (fgets(buf, sizeof(buf), in) != NULL) { sscanf(buf, "%d%d", &left, &right); fputc(left & 0xff, out); fputc(right & 0xff, out); } else if (num_channels == 1 && num_bits == 16) while (fgets(buf, sizeof(buf), in) != NULL) { sscanf(buf, "%d", &c); fputc(c & 0xff, out); fputc((c >> 8) & 0xff, out); } else if (num_channels == 1 && num_bits == 8) while (fgets(buf, sizeof(buf), in) != NULL) { sscanf(buf, "%d", &c); fputc(c & 0xff, out); } fclose(out); return 0; }