読者です 読者をやめる 読者になる 読者になる

Shut the fuck up and write some code

グダグダ言わずにコードを書きたいブログ

openFrameworks iOS版でFFT

openFrameworks

最近「インスタレーションっぽいものを作りませんか」というお話を打診レベルですが頂いたこともあり、メディアアート系の勉強も兼ねてopenFrameworksを本格的にいじり始めてる。諸々ライブラリが充実しているもの、かつクロスプラットフォームで出来るものという面で選択してみたのだけど、C++を今からやるのは辛い・・・と思いきや、さすが過去の遺産が充実しているのもあり、勉強しやすい。そんな中でハマったことをメモっておきます。

音周りの実験をしていたのですが、openFrameworksはFFT処理もライブラリ本体だけで処理が出来る。前後の処理は省略しますが

fft = ofSoundGetSpectrum(nBandsToGet);

こんな感じでFFT処理したバッファの配列が取得出来る。「すげー楽チン!」と思ってこれをiOS版で試してみると

ofSoundGetSpectrum returning NULL - no implementation!

というエラーを返して動かない。no implementation?実装してない?

元のソースを見ると

float * ofSoundGetSpectrum(int nBands){
    
	#ifdef OF_SOUND_PLAYER_FMOD
		return ofFmodSoundGetSpectrum(nBands);
	#elif defined(OF_SOUND_PLAYER_OPENAL)
		return ofOpenALSoundPlayer::getSystemSpectrum(nBands);
	#else
		ofLog(OF_LOG_ERROR, "ofSoundGetSpectrum returning NULL - no implementation!");
		return NULL;
	#endif
}

どうもまだ実装されてないっぽい・・・やはりまだまだスマートフォン向けって分けにはいかないのか。残念。

仕方なく他の方法を探すべくググってみると
http://forum.openframeworks.cc/index.php?topic=11518.0
同じ事で悩んでる人を発見。読んでみると「ofxMaxim使えばいいんじゃね?これは動くよー」とのこと。

https://github.com/micknoise/Maximilian
githubから落としてaddonを入れます。このとき注意するのが、注意書きに

You can install the ofxMaxim addon by copying the ofxMaxim/ofxMaxim folder into your openframeworks addons directory.
Important: when using Maximilian on OSX, link against the Accelerate framework.

とあるようにosxの人はAccelerate frameworkフレームワークをプロジェクトに追加してやります。

追加方法は至って簡単なので
http://memo.yoshimax.net/2012/02/vdsp-vdsp.html
あたりを参考にサクッとやります。

実際の実装はサンプルも付いているので、そちらを見てもらった方がいいですが、簡単に書くとサウンド再生時にaudioRequestedメソッドが呼ばれるのでこのときにFFT処理を実行します。
サンプルよりコードを一部抽出。

void testApp::audioRequested 	(float * output, int bufferSize, int nChannels){
	for (int i = 0; i < bufferSize; i++){
		if (mfft.process(wave)) {
                 mfft.magsToDB();
			oct.calculate(mfft.magnitudesDB)
		}
	}
}

mfftはofxMaxiFFTクラスのインスタンスで、ここで諸々計算してくれる模様(まだ細かいところは理解してない!)。

結果取得はofxMaxiFFTクラスのインスタンスから取得できる。同じくサンプルよりコードを一部抽出。

    //draw fft output
    ofSetColor(255, 0, 0,100);
    for(int i=0; i < fftSize / 2; i++) {
		float height = mfft.magnitudesDB[i] / 50.0 * 400;
		ofRect(0 + (i*xinc),320 - height,2, height);
	}

	//draw phases
	ofSetColor(0, 255, 0,100);
	for(int i=0; i < fftSize / 2; i++) {
		float height = mfft.phases[i] / 50.0 * 400;
		ofRect(0 + (i*xinc),320 - height,2, height);
	}
	
	//octave analyser
	ofSetColor(0, 0, 2550,100);
	xinc = 900.0 / oct.nAverages;
	for(int i=0; i < oct.nAverages; i++) {
		float height = oct.averages[i] / 50.0 * 100;
		ofRect(0 + (i*xinc),320 - height,2, height);
	}

FFTの結果の他に位相なども取得出来る。ここまで出来ればあとはヴィジュアル周りに繋ぎ込めば大体使えそうかな。

以上です、お疲れさまでした。

openFrameworksのFFTのaddonは色々あるようだけど、これが一番手っ取り早く出来たのと、maximillianは元々は音響合成用のライブラリなのでシンセっぽい使い方も出来そうで、それも面白そうだな
〜という理由で使ってみてます。PdやSuperColliderとの連携も出来るみたいなので、しばらくいじり倒してみようかと思います。