2013/02/17

C言語 OpenAL でメトロノーム 2 機能追加

先日のメトロノームにボリュームを加えてみた。コードも少しシンプルに変更。自分で使う分には、これで十分だわ。exe のサイズが 9KB というところと、省メモリ、起動の速さがポイント。それにしても GUI がないアプリはソースコードが短くなって楽。GUI のダラダラしたソースコードは公開するのも気が引けるけど、これぐらいなら見通しもよいと思う。
コンパイルされた exe ファイルをダブルクリックで起動。初期値 120 のテンポで 0.9 のボリュームで自動再生。テンポを変更するときは数値を入力して Enter する。ボリュームを変えるときは v0.5 のように打って Enter する。終了するときは q Enter とする。

OpenAL metronome2 volume ソースコード

/* metronome2.c
 * February 17th, 2013
 * Namagi Products メトロノーム ボリューム付
 * compile win
 * gcc metronome2.c -lOpenAL32 -lalut -s -o metronome2
 * compile linux
 * gcc metronome2.c  -lalut -s -o metronome2
 * BPM(Beats Per Minute)60bpm 
 */
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <AL/alut.h>

void input(double *amp, double *bpm){
  char str[32];
  int i;
  /* 入力 */
  for(i=0; i<3; i++){
    printf("input:\t");
    fgets(str, 32, stdin);
    if(str[0]=='q'){
      *bpm = -1;
      break;
    /* ボリュームの調整 */
    }else if(str[0]=='v'){
      str[0] = '0';
      *amp = atof(str);
      if(*amp > 1.0) *amp = 1.0;
      if(*amp < 0.0) *amp = 0.0;
      break;
    /* テンポの範囲調整 */
    }else if(isdigit(str[0]) != 0){
      *bpm = atof(str);
      if(*bpm < 20) *bpm = 20;
      if(*bpm > 300) *bpm = 300;
      break;
    }
  }
}

int main(int argc, char *argv[]){
  alutInit(&argc,argv);
  ALuint buffer = 0, source = 0;
  int i, j, bpmi;
  /* テンポ初期値 20-300 */
  double bpm = 120;
  /* サンプリング周波数 */
  double samplingfreq = 44100;
  /* 点間のステップ */
  double step = 2 * M_PI / samplingfreq;
  /* 角速度 1Hz */
  double w = 0;
  /* ボリューム初期値 0.0 - 1.0 */
  double amp = 0.9;
  printf("Namagi Metronome\n" 
         "BPM:20-300, volume:v0-1, q to exit\n");
  for(;;){
     alGenBuffers(1, &buffer);
     alGenSources(1, &source);
     /* 波形を入れる配列を用意 */
     printf("play\tBPM: %6.3f\tvolume: %3.2f\n",bpm, amp);
     bpmi = (int)(samplingfreq / (bpm / 60));
     ALshort data[bpmi];
     /* サイン波1周期作成  16bitなので32767をmaxとする */
     for(i=0; i<bpmi; i++){
       /* (samplingfreq / 2205)*2  sine2205Hz */
       if(i < 40*20){
          data[i] = (int)(32767 * amp * sin(w * 2205));
          w += step;
       }else{
          data[i] = 0;
       }
     }
     /* データ用バッファに入れる 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);
     input(&amp, &bpm);
     if(bpm == -1) break;
     alSourceStop(source);
     alDeleteSources(1, &source);
     source = 0;
     alDeleteBuffers(1, &buffer);
     buffer = 0;
  }
  alutExit();
  return 0;
}


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