年末年始は、オーディオ関連の勉強をしようとOpenALプログラムに夢中。 というより、
情報が少な過ぎて試行錯誤だったというのが本音(>_<)
CoreAudioの基礎その1の記事で出てきた、楽器の作り方のサンプルは単体楽器アプリではさほど問題ないかも知れないけど、応用には向かないコーディングかな? と言う事で、OpenALの基礎について少しずつまとめていきます。
OpenALを理解するにはネットも大事ですが、frameworkのソースと睨めっこするのも大切かな?と思いました。 まず、OpenAL.frameworkは以下のファイルで構成されています。
・MacOSX_OALExtensions.h ・alc.h ・al.h
alc.h は主に、ALCdeviceとALCcontext型を扱うクラスで、OpenALの開始、終了を管理する感じです。 al.h はalc.hで作成したdevice、contextを通じてオーディオソース・バッファを管理するクラスです。 MacOSX_OALExtensions.hはそのなの通り、OSX用拡張クラスです。 ただし、OpenAL単体だけでは完結できない事が多いと思うので、最終的にはCoreAudio全体のserviceも色々と知っておくべきかな?と思います。
OpenALで音をならして終了するまでのおおまかな流れは、以下の通りです。 ※実際に動くサンプルではありません
//Deviceを初期化
ALCdevice *device = alcOpenDevice(NULL);
//Deviceを作成、Contextを作る
alcMakeContextCurrent(alcCreateContext(device, NULL));
//オーディオバッファ・ソースのメモリ領域を確保する
alGenBuffers(24, (ALuint *)_buffers);
alGenSources(24, (ALuint *)_sources);
//オーディオファイルを開く
NSString* path = [[NSBundle mainBundle] pathForResource:fileName ofType:@"m4a"];
OSStatus err = ExtAudioFileOpenURL(fileURL, &audioFile);
//データフォーマットを設定する
AudioStreamBasicDescription outputFormat;
err = ExtAudioFileSetProperty(audioFile, kExtAudioFileProperty_ClientDataFormat, sizeof(outputFormat), &outputFormat);
//オーディオファイルフレームを設定する
err = ExtAudioFileGetProperty(audioFile, kExtAudioFileProperty_FileLengthFrames, &size, &fileLengthFrames);
//オーディをバッファを用意する
AudioBufferList dataBuffer;
//オーディオバッファを読み込む
ExtAudioFileRead(audioFile, (UInt32*)&fileLengthFrames, &dataBuffer);
//オーディオバッファを追加する
alBufferData( ALuint bid, ALenum format, const ALvoid* data, ALsizei size, ALsizei freq );
//オーディオソースを追加する
alSourcei( ALuint sid, ALenum param, ALint value );
//音を再生する
alSourcePlay(_sources[0]);
//音を止める
alSourceStopv(24, _sources);
//オーディオソースを削除する
alDeleteSources(24, _sources);
//オーディオバッファを削除する
alDeleteBuffers(24, _buffers);
//Contextを削除する
alcDestroyContext(context)
//Deviceを閉じる
alcCloseDevice(device)
と、音をならすまでには、おおまかでもこれだけの手続きが必要です。 (実際はもっとやらないといけない事がありますが・・・) 単に音をならすだけなら、SystemSoundServices、AVAudioPlayer等を使った方が断然楽です。
オーディオ周りはかなり大変(充実)なので、実際に評価が高い(?)本を買って読んでみました。
が、リッチなアプリを作成しようとした場合、記載されてない内容があったり、汎用クラス化やメモリ管理の手法は実は自分で考えないといけない気がします。 それだけ、ハードルが高い(!?)ってことですかね。
ただ自分もそうですが、実際にはframeworkやserviceの選別って入門者には情報が膨大過ぎて難しいかも知れません。
習うより慣れろ
そんな感じです。