openFrameworksでテルミンもどき

今更ではありますが、楽しそうなので手をつけてみる。AndroidC++のちいさな音楽ライブラリを作ったので、それ流用しながら少しずつ進めていく感じで。

開発環境はCode:Blocksです。いくつかのサイトを参考にインストールしたのですが、ビルドターゲットをリリースにした状態でビルドできていません。しかしデバッグでビルドして動作確認はできるのでこのまま続けて、そのうち何とかしたいと考えています。

それではexamplesフォルダにあるemptyExampleを土台にはじめます

まずmain.cpp。main.cppで自作クラスコンストラクタする。

#include "ofMain.h"
#include "testApp.h"
#include "ofAppGlutWindow.h"
int main( ){
  ofAppGlutWindow window;
  ofSetupOpenGL(&window, 1024,768, OF_WINDOW);
  ofRunApp( new testApp()); //testAppが自作クラス。
}

自作クラス(testApp)はofBaseAppを継承する。変数の初期化でsetup()、定期的な更新にupdata()、描画にdraw()という流れ。動的なオーディオ生成はaudioRequested()です。引数の説明はソースファイルの方で。それではヘッダーファイル(testApp.h)を書いてみる。

#pragma once //インクルードガード。環境によって書き方ある。

#include "ofMain.h"

class testApp : public ofBaseApp{
  public:
    void setup();
    void update();
    void draw();

    void keyPressed  (int key);
    void keyReleased(int key);
    void mouseMoved(int x, int y );
    void mouseDragged(int x, int y, int button);
    void mousePressed(int x, int y, int button);
    void mouseReleased(int x, int y, int button);
    void windowResized(int w, int h);
    void dragEvent(ofDragInfo dragInfo);
    void gotMessage(ofMessage msg);

    void audioRequested(float* input, int bufferSize, int nChannels);

    int sampleRate;
    float freq;
    float amp;
    float phase;
};

さてaudioRequestedの第1引数は出力する配列でしょうね。この配列のサイン波のデータを渡してやれば良いんですね。後、ofSoundStreamSetupはオーディオの初期化でしょうか。第1引数は出力数(今回モノラルなので)、次が入力数、ofSimpleAppのポインタで自分自身なのでthis、サンプルレート、バッファーサイズ、リングバッファの分割数かな?。最後にTWO_PIは組み込みの定数です。ソースファイル(testApp.cpp)を書きます

#include "testApp.h"
#include "math.h"
void testApp::setup(){
  ofBackground(255,255,255);

  sampleRate = 44100;
  phase = 0.0f;
  freq = 440.0f;
  amp = 0.0f;
  ofSoundStreamSetup(1,0,this,sampleRate,256,4);

  ofSetFrameRate(60);
}
void testApp::update(){}
void testApp::draw(){}
void testApp::keyPressed(int key){}
void testApp::keyReleased(int key){}
void testApp::mouseMoved(int x, int y ){}
void testApp::mouseDragged(int x, int y, int button){
  int width = ofGetWidth();
  freq = 3000.0f * (x/(float)width) + 20;
}
void testApp::mousePressed(int x, int y, int button){
  amp = 1.0f;
}
void testApp::mouseReleased(int x, int y, int button){
  amp = 0.0f;
}
void testApp::windowResized(int w, int h){}
void testApp::gotMessage(ofMessage msg){}
void testApp::dragEvent(ofDragInfo dragInfo){}
//-----------Audio Output---------------------------------------
void testApp::audioRequested(float* output, int bufferSize, int nChannels){
  for(int i=0; i<bufferSize; i++){
    phase += freq/(float)sampleRate;
    if(phase > 1.0){
      phase = 0.0;
    }
    output[i] = sin(TWO_PI*phase)*amp;
  }
}