4.3 拙作 writewave.c (テキスト・ファイル→WAVE)

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


   1 /*
   2  * writewave.c --- 無圧縮PCMデータ(テキスト・ファイル)からWAVEファイルを作る
   3  *  version 1 (2003/12/21)
   4  *  version 2 (2013/10/26)
   5  *    ラベルの後に ; を入れた (コンパイル・エラー回避)。
   6  *    文字コードを UTF8 にした。
   7  *
   8  *  コンパイル: gcc -o writewave writewave.c
   9  *
  10  *  使い方:
  11  *   (1): ./writewave <テキスト・ファイル名> <WAVEファイル名>
  12  *   (2): ./writewave <テキスト・ファイル名>
  13  *           標準出力に出力
  14  *   (3): ./writewave
  15  *           標準入力から入力、標準出力に出力
  16  *
  17  *  入手:
  18  *    http://www.math.meiji.ac.jp/~mk/program/
  19  *
  20  *  参考にした情報
  21  *   URL: http://member.nifty.ne.jp/Ryuz/programing/wavefmt.html
  22  *        -> http://homepage3.nifty.com/ryuz/programing/wavefmt.html
  23  *
  24  *  普段置いてある場所
  25  *    ~/Sotsuken/2007/sound/readwave/
  26  */
  27 
  28 #include <stdio.h>
  29 #include <stdlib.h>
  30 #include <strings.h>
  31 
  32 int verbose = 1;
  33 
  34 #define fwrite16(out,n) {fputc((n)&0xff,(out));fputc(((n)>>8)&0xff,(out));}
  35 
  36 #define fwrite32(out,n) {fputc((n)&0xff,(out));fputc(((n)>>8)&0xff,(out));\
  37 fputc(((n)>>16)&0xff,(out));fputc(((n)>>24)&0xff,(out));}
  38 
  39 void usage(char *prog_name)
  40 {
  41   fprintf(stderr, "usage: %s <txt-file> <wave-file>", prog_name);
  42   exit(1);
  43 }
  44 
  45 int main(int argc, char **argv)
  46 {
  47   int num_channels, num_bits, num_samples, sampling_rate;
  48   FILE *in,*out;
  49   char buf[4096], original_fname[1024];
  50   char *prog_name, *input_fname, *output_fname;
  51   int left, right, c;
  52   int ready = 0, len;
  53   int fmt_size, fmt_tag, bytes_per_seconds, block, extended_information_size,
  54     data_size, riff_size;
  55   static char label[5][32] =
  56   {"#original file: ",
  57    "#number of channels: ",
  58    "#number of bits (per sample): ",
  59    "#number of samples: ", "#sampling rate: "};
  60 
  61   prog_name = argv[0];
  62 
  63   if (argc > 3) {
  64     usage(prog_name);
  65   }
  66   if (argc == 3) {
  67     output_fname = argv[2];
  68     if ((out = fopen(output_fname, "w")) == NULL) {
  69       fprintf(stderr, "出力ファイル %s がオープンできません。\n",
  70               output_fname);
  71       exit(1);
  72     }
  73   }
  74   else {
  75     output_fname = "stdout";
  76     out = stdout;
  77   }
  78   if (argc >= 2) {
  79     input_fname = argv[1];
  80     if ((in = fopen(input_fname, "r")) == NULL) {
  81       fprintf(stderr, "入力ファイル %s がオープンできません。",
  82               input_fname);
  83       exit(1);
  84     }
  85   }
  86   else {
  87     input_fname = "stdin";
  88     in = stdin;
  89   }
  90   while (fgets(buf, sizeof(buf), in) != NULL) {
  91     if (buf[0] == '#') {
  92       switch (buf[1]) {
  93       case 'o':
  94         if (strncmp(buf, label[0], len = strlen(label[0])) == 0) {
  95           sscanf(buf + len, "%s", original_fname);
  96           ready |= 0x01;
  97         }
  98         break;
  99       case 'n':
 100         if (strncmp(buf, label[1], len = strlen(label[1])) == 0) {
 101           sscanf(buf + len, "%d", &num_channels);
 102           ready |= 0x02;
 103         }
 104         else if (strncmp(buf, label[2], len = strlen(label[2])) == 0) {
 105           sscanf(buf + len, "%d", &num_bits);
 106           ready |= 0x04;
 107         }
 108         else if (strncmp(buf, label[3], len = strlen(label[3])) == 0) {
 109           sscanf(buf + len, "%d", &num_samples);
 110           ready |= 0x08;
 111         }
 112         else {
 113           fprintf(stderr, "unknown: %s\n", buf);
 114         }
 115         break;
 116       case 's':
 117         if (strncmp(buf, label[4], len = strlen(label[4])) == 0) {
 118           sscanf(buf + len, "%d", &sampling_rate);
 119           ready |= 0x10;
 120         }
 121         break;
 122       default:
 123         ;
 124         /* 何もしない */
 125       }
 126       if (ready == 0x1f) {
 127         if (verbose) {
 128           fprintf(stderr, "original file: %s\n", original_fname);
 129           fprintf(stderr, "number of channels: %d\n", num_channels);
 130           fprintf(stderr, "number of bits: %d\n", num_bits);
 131           fprintf(stderr, "number of samples: %d\n", num_samples);
 132           fprintf(stderr, "sampling rate: %d\n", sampling_rate);
 133         }
 134         break;
 135       }
 136     }
 137     else {
 138       /* パラメーターが揃わない (ready == 0x1f にならない) うちに
 139        * 生データが来たらエラーだ */
 140       printf("ready=%0x\n", ready);
 141       fprintf(stderr, "%s\n", buf);
 142       exit(1);
 143     }
 144   }
 145 
 146   /* fmt チャンク */
 147   fmt_size = 18; /* 2+2+4+4+2+2+2 */
 148   fmt_tag = 1; /* 無圧縮 PCM */
 149   bytes_per_seconds = sampling_rate * (num_bits / 8) * num_channels;
 150   block = 1; /* ブロック境界(何のこと?) */
 151   extended_information_size = 0;
 152   /* fact チャンクつけない */
 153   /* data チャンク */
 154   data_size = num_samples * (num_bits / 8) * num_channels;
 155   /* */
 156   riff_size = fmt_size + data_size;
 157 
 158   /* ヘッダーを書く */
 159   fprintf(out, "RIFF");
 160   fwrite32(out, riff_size);
 161   fprintf(out, "WAVE");
 162   fprintf(out, "fmt ");
 163   fwrite32(out, fmt_size);
 164   fwrite16(out, fmt_tag);           /* 2bytes */
 165   fwrite16(out, num_channels);      /* 2bytes */
 166   fwrite32(out, sampling_rate);     /* 4bytes */
 167   fwrite32(out, bytes_per_seconds); /* 4bytes */
 168   fwrite16(out, block);             /* 2bytes */
 169   fwrite16(out, num_bits);          /* 2bytes */
 170   fwrite16(out, extended_information_size); /* 2bytes */
 171   fprintf(out, "data");
 172   fwrite32(out, data_size);
 173 
 174   if (num_channels == 2 && num_bits == 16)
 175     while (fgets(buf, sizeof(buf), in) != NULL) {
 176       sscanf(buf, "%d%d", &left, &right);
 177       fputc(left & 0xff, out); fputc((left >> 8) & 0xff, out);
 178       fputc(right & 0xff, out); fputc((right >> 8) & 0xff, out);
 179     }
 180   else if (num_channels == 2 && num_bits == 8)
 181     while (fgets(buf, sizeof(buf), in) != NULL) {
 182       sscanf(buf, "%d%d", &left, &right);
 183       fputc(left & 0xff, out);
 184       fputc(right & 0xff, out);
 185     }
 186   else if (num_channels == 1 && num_bits == 16)
 187     while (fgets(buf, sizeof(buf), in) != NULL) {
 188       sscanf(buf, "%d", &c);
 189       fputc(c & 0xff, out); fputc((c >> 8) & 0xff, out);
 190     }
 191   else if (num_channels == 1 && num_bits == 8)
 192     while (fgets(buf, sizeof(buf), in) != NULL) {
 193       sscanf(buf, "%d", &c);
 194       fputc(c & 0xff, out);
 195     }
 196   fclose(out);
 197   return 0;
 198 }

桂田 祐史
2016-11-16