ソースを見る
まずはコードをmaxiDelaylineクラスの部分だけ抜き出して見てみる
class maxiDelayline { double frequency; int phase; double startphase; double endphase; double output; double memory[88200]; public: maxiDelayline(); double dl(double input, int size, double feedback); double dl(double input, int size, double feedback, int position); };
//Delay with feedback maxiDelayline::maxiDelayline() { memset( memory, 0, 88200*sizeof (double) ); phase=0; } double maxiDelayline::dl(double input, int size, double feedback) { if ( phase >=size ) { phase = 0; } output=memory[phase]; memory[phase]=(memory[phase]*feedback)+(input*feedback)*0.5; phase+=1; return(output); } double maxiDelayline::dl(double input, int size, double feedback, int position) { if ( phase >=size ) phase = 0; if ( position >=size ) position = 0; output=memory[position]; memory[phase]=(memory[phase]*feedback)+(input*feedback)*chandiv; phase+=1; return(output); }
たったこれだけ。
バッファで用意されているのが、一秒間44100Hzとすると2秒分用意されている。
関数を読み解く
dl関数が二つ用意されていいるが、基本的に中身は一緒なので、より簡単な方で見ていこう。
double maxiDelayline::dl(double input, int size, double feedback) { if ( phase >=size ) { phase = 0; } output=memory[phase]; memory[phase]=(memory[phase]*feedback)+(input*feedback)*0.5; phase+=1; return(output); }
上記は簡易的なリングバッファを使ったディレイと考えられる。
88200個のバッファに順に書き込まれ、終わりが来たらまた頭に戻る。
ただそれだけだ。
そして、書き込むと同時にアウトプットの値も返ってくる。
引数で注意したいのはsizeで、この値は88200を超えないことが暗黙の了解のようだ。
dlを呼ぶたびにphaseの値はインクリメントされinputの値とバッファがfeedbackの割合で加算される。その時inputの値は0.5倍される。
決めうちの値が多いが、初心者にとってはこのぐらいの方が使いやすい。
配列を渡すのではなく、ループでそれぞれの値を渡す形になっている
ここら辺気持ち悪ければ、関数をオーバーロードして配列を渡すようにしてもいいかもしれない。
使ってみる
下記は、ループ音源を使ったサンプル。
マウスのx座標でバッファのサイズを0~88200まで変化するようにした。
0だと、ディレイのない音で10,000を超えたぐらいからおかしくなる感じだ。
大体、4000~8000ぐらいが良さそうな感じ。
#pragma once #include "ofMain.h" #include "ofxMaxim.h" class testApp : public ofBaseApp{ public: ~testApp();/* destructor is very useful */ 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); /* output method */ void audioReceived (float * input, int bufferSize, int nChannels); /* input method */ int initialBufferSize; /* buffer size */ int sampleRate; /* stick you maximilian stuff below */ double sample,size,outputs[2]; ofxMaxiMix mymix; ofxMaxiSample beat; ofxMaxiDelayline delay; };
/* This is an example of how to integrate maximilain into openFrameworks, including using audio received for input and audio requested for output. You can copy and paste this and use it as a starting example. */ #include "testApp.h" //------------------------------------------------------------- testApp::~testApp() { /*delete beat.myData;*/ /*you should probably delete myData for any sample object that you've created in testApp.h*/ } //-------------------------------------------------------------- void testApp::setup(){ ofEnableAlphaBlending(); ofSetupScreen(); ofBackground(0, 0, 0); ofSetVerticalSync(true); sampleRate = 44100; /* Sampling Rate */ initialBufferSize = 512; /* Buffer Size. you have to fill this buffer with sound*/ beat.load(ofToDataPath("beat2.wav")); beat.getLength(); ofSoundStreamSetup(2,0,this, sampleRate, initialBufferSize, 4);/* Call this last ! */ } //-------------------------------------------------------------- void testApp::update(){ } //-------------------------------------------------------------- void testApp::draw(){ ofSetColor(255, 255, 255,255); ofCircle(ofGetWidth()/2, ofGetHeight()/2, sample*150); } //-------------------------------------------------------------- void testApp::audioRequested (float * output, int bufferSize, int nChannels){ for (int i = 0; i < bufferSize; i++){ sample=delay.dl(beat.play(0.25, 0, beat.length),size,0.5); mymix.stereo(sample, outputs, 0.5); output[i*nChannels ] = outputs[0]; /* You may end up with lots of outputs. add them here */ output[i*nChannels + 1] = outputs[1]; } } //-------------------------------------------------------------- void testApp::audioReceived (float * input, int bufferSize, int nChannels){ /* You can just grab this input and stick it in a double, then use it above to create output*/ for (int i = 0; i < bufferSize; i++){ /* you can also grab the data out of the arrays*/ } } //-------------------------------------------------------------- void testApp::keyPressed(int key){ } //-------------------------------------------------------------- void testApp::keyReleased(int key){ } //-------------------------------------------------------------- void testApp::mouseMoved(int x, int y ){ size = ((double)ofGetMouseX()/(double)ofGetWidth()) * 88200.f; if(size < 0) size=0; if(size > 88200) size = 88200; printf("size:%f\n",size); } //-------------------------------------------------------------- void testApp::mouseDragged(int x, int y, int button){ } //-------------------------------------------------------------- void testApp::mousePressed(int x, int y, int button){ } //-------------------------------------------------------------- void testApp::mouseReleased(int x, int y, int button){ } //-------------------------------------------------------------- void testApp::windowResized(int w, int h){ } //-------------------------------------------------------------- void testApp::gotMessage(ofMessage msg){ } //-------------------------------------------------------------- void testApp::dragEvent(ofDragInfo dragInfo){ }