2013/02/16

C言語 OpenAL でメトロノームを作ってみる

OpenALで音が出せたので、メトロノームを試しに作ってみる。出来たアプリケーションは 9KB と小さく起動は高速。ダブルクリックすると、コマンドプロンプトが開いて初期値 120 のテンポで鳴り続ける。他のテンポにしたいときは、テンポを入力して Enter する。小数でも入れられるようにした。テンポの範囲は 20 から 300 まで。終了したいときは q を入力して Enter。メトロノームの音はプログラムの中でサイン波を作ってみた。音にパワーがあまり感じられないので、今後メトロノームに合った波形を作ってみたいと思う。

翌日ボリューム調整可能なバージョンも作ってみた。

OpenAL metronome ソースコード


/* metronome.c 
 * February 16th, 2013
 * Namagi Products メトロノーム
 * gcc metronome.c -lOpenAL32 -lalut -s -o metronome
 * BPM(Beats Per Minute)
 */
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <AL/alut.h>

double input(void){
  char str[32];
  int i;
  double bpm = 0;
  for(i=0; i<3; i++){
     /* tempoの入力 */
     printf("input\tBPM:\t");
     /* 整数入力 */
     fgets(str, 32, stdin);
     /* 数値判定 数字でなければ再入力 3回まで */
     if(str[0]=='q'){
         return -1;
     }else if(isdigit(str[0]) != 0){
     bpm = atof(str);
     break;
     }
  }
  /* Tempoの範囲調整 */
  if(bpm < 20){
     bpm = 20;
  }else if(bpm > 300){
     bpm = 300;
  }
  return bpm;
}

int main(int argc, char *argv[]){
  alutInit(&argc,argv);
  ALuint buffer, source;
  int i, j, bpmi;
  double bpm = 120;
  /* サンプリング周波数 */
  double samplingfreq = 44100;
  /* 点間のステップ */
  double step = 2 * M_PI / samplingfreq;
  /* 角速度 1Hz */
  double w = 0;
  /* 出力最大 1.0 */
  double amp = 0.95;
  printf("Namagi Metronome (q to exit)\n");

  for(;;){
     alGenBuffers(1, &buffer);
     alGenSources(1, &source);
     /* 波形を入れる配列を用意 */
     printf("play\tBPM:\t%f\n",bpm);
     bpmi = (int)(samplingfreq / (bpm / 60));
     ALshort data[bpmi];
     /* サイン波1周期作成  16bitなので32767をmaxとする */
     for(i=0; i<bpmi; i++){
     /* 2205Hz sine wave */
        if(i < 800){ 
           data[i] = (int)(32767 * amp * sin(w * 2205));
           w += step;
        }else{
           data[i] = 0;
        }
     }
     /* データ用バッファに入れる 16bit-mono 注意size:バイト単位*/
     alBufferData(buffer, AL_FORMAT_MONO16, data,
                    bpmi * 2, samplingfreq);
     alSourcei(source, AL_BUFFER, buffer);
     alSourcei(source, AL_LOOPING, AL_TRUE);
     /* 再生 */
     alSourcePlay(source);
     alutSleep(1);
     bpm = input();
     if(bpm == -1) break;
     alSourceStop(source);
     alDeleteSources(1, &source);
     alDeleteBuffers(1, &buffer);
   }
   alutExit();
   return 0;
}


C言語 ANSI C89 Meadow & MinGW GCC 目次
sound programming 目次