2012/06/08

C言語 音声ファイル加工 音量

オーディオファイルの音量調整プログラム。gainの設定値で全体の音量を変えられる。以下のソースはサンプルなので、ヘッダレスのrawデータで32bit-float専用。gainの設定はプロンプトから入力する。実用的なプログラムにするには、ヘッダ情報の読込みと、それに基づいた処理が必要。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main (int argc, char *argv[]){ 
  FILE *fpr, *fpw;
  int i, fileSize=1024;
  unsigned char str1[256], *str2;
  /* gainの初期値 */
  float *buff, *buffout, gain=1.0;
  char strgain[10];

  for(i=0; i<argc; i++){
    printf("%d = %s\n", i, argv[i]);
  }
  fpr = fopen(argv[1], "rb");
  if (fpr == NULL){
     printf("error rb");
     getchar();
     exit(EXIT_FAILURE);
  }
  strcpy(str1,argv[1]);
  str2 = strtok(str1,".");
  strcat(str2,"_new.wav");
  fpw = fopen(str2, "wb");
  if (fpw == NULL){
     printf("error wb");
     getchar();
     exit(EXIT_FAILURE);
  }
  /* プロンプトからgain値を入力 */
  printf("gain = ");
  fgets(strgain,10,stdin);
  /* atof 浮動少数点文字列を浮動少数点値に変換 */
  gain = atof(strgain); 

  /* ファイルサイズの取得 */
  fseek(fpr, 0L, SEEK_END);
  fileSize = ftell(fpr)/4;
  fseek(fpr, 0L, SEEK_SET);

  /* 動的メモリ入力用 float(4byte) x fileSize */
  buff = (float*)malloc(sizeof(float) * fileSize);
    if (buff == NULL){
      getchar(); 
      exit(1);
    }
  /* 動的メモリ出力用 */
  buffout = (float*)malloc(sizeof(float) * fileSize);
    if (buffout == NULL){
      getchar();
      exit(1);
    }
  printf("filesize: %s = %d byte\n",argv[1], fileSize*4);
  /* 読込み */
  fread(buff, sizeof(float), fileSize, fpr);

  /* 音処理 gain 音量を変化させる */
  for(i=0; i<fileSize; i++){
     *(buffout+i) = *(buff+i) * gain;
  } 
  /* 書込み */
  fwrite(buffout, sizeof(float), fileSize, fpw);
  printf("newfile = %s\n",str2);
  fclose(fpr);
  fclose(fpw);
  /*メモリを解放*/
  free(buff);
  free(buffout);
  printf("success");
  getchar();
  return 0;
}
上記をコンパイルして出来たexeファイルに、wav(ヘッダのないrawデータ)ファイルをドラッグ&ドロップすると、コマンドプロンプトが起動する。gain値を入力してEnterを押すと新規でwavファイルをオリジナルと同じディレクトリに保存する。さらにEnterキーを押すとプログラムは終了する。

試しに作ってみただけのソースだが、処理スピードは高速で期待できる。ただ、ちゃんとC言語を理解しないで作っているので、間違いや、無駄な部分があるかもしれない。バッファは、この場合ひとつあれば間に合うのだが、今後いろいろいじることを考えて加工前と加工後のバッファに分けた。またソースがダラダラと長くなってきたので、関数にして分けるべきだなぁ。そもそもmain関数に具体的な処理を書くのはマナーがよろしくない。
0 = C:\a.exe
1 = C:\sample.wav
gain = 0.5
filesize: C:\sample.wav = 105840000 byte
newfile = C:\sample_new.wav
success
Audacityで波形を表示。gainを0.5で入力した例。ちゃんと0.5倍の音量になっている。

C言語 ANSI C89 Meadow & MinGW GCC 目次はこちら