writewave は、 readwave の出力を読んで WAVE ファイルを作成する。 (完全な逆変換と言うわけではなく、ヘッダーが軽くなります。)
http://nalab.mind.meiji.ac.jp/~mk/program/sound/writewave.c
| コンパイルと色々な使い方 |
oyabun% gcc -o writewave writewave.c oyabun% ./readwave piano.wav piano.txt oyabun% ./readwave piano.wav > piano2.txt oyabun% ./writewave piano.txt piano1.wav oyabun% ./writewave piano2.txt > piano2.wav oyabun% ./readwave piano.wav | ./writewave > piano3.wav |
/*
* writewave.c --- 無圧縮PCMデータ(テキスト・ファイル)からWAVEファイルを作る
* version 1 (2003/12/21)
* version 2 (2013/10/26)
* ラベルの後に ; を入れた (コンパイル・エラー回避)。
* 文字コードを UTF8 にした。
*
* コンパイル: gcc -o writewave writewave.c
*
* 使い方:
* (1): ./writewave <テキスト・ファイル名> <WAVEファイル名>
* (2): ./writewave <テキスト・ファイル名>
* 標準出力に出力
* (3): ./writewave
* 標準入力から入力、標準出力に出力
*
* 入手:
* http://www.math.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 <stdio.h>
#include <stdlib.h>
#include <strings.h>
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 <txt-file> <wave-file>", 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;
}