OpenALとC 補足
二日に一回更新しようとしてさっそく途切れましたが私は元気です。
さて、今回はこちらでやったコードの解説でも。
注意ですが、コメントで十分なものやプログラム的なところは割愛していきます・・・
ソースコードは上を参照してください。
まずはincludeなどの下準備。こちらは大丈夫ですね。みたままリンクするだけです。
メイン関数に入りましょう。
//OpenALの下準備 おまじない的な
ALCdevice *device = alcOpenDevice(NULL);
ALCcontext *context = alcCreateContext(device, NULL);
alcMakeContextCurrent(context);
deviceは出力デバイスを表します。ここではスピーカですね。
引数NULLでデフォルトのスピーカを選びます。ヘッドフォンを挿したら自動的に切り替わるアレです。
context関係はたくさんのソースから発せられた音を一つにまとめて出力する宣言みたいなものです。いずれたくさんの効果音とかを同時に出力するときに生きてくるんじゃないかな・・・?
つぎはソースとバッファです。変数を宣言した後Genで生成していきます。
ALuintっていうのはOpenAL内で使われるunsigned intの略です。ぶっちゃけintで事足りたりするのですが、せっかくなのでもりもり使っていきましょう。
波形の生成です。今回で一番重要な部分かも
//ここで440Hzのsin波を1秒間分生成
for (int i = 0; i < SAMPLINGRATE; i++) {
wav_data[i] = 32767 * sin(2 * M_PI*i * 440 / SAMPLINGRATE);
}
wav_data[i]にsin波を入れていくだけなのですが、sinの中を注意してください。関数電卓ならsin(…に角度を入れれば値が出ますが、プログラムではしっかりとラジアンに直します。
32767は16bit wavの最大振幅を表しています。なんで?って方は前回の記事を!
二番目に重要なのがこちら。(途切れちゃってすみません・・・)
//バッファに音源データを入れる
alBufferData(buffer, AL_FORMAT_MONO16, &wav_data[0], SAMPLINGRATE * sizeof(signed short), SAMPLINGRATE);
バッファにデータを格納するという作用があります。
第一引数に入れたいバッファ
第二引数にそのデータのフォーマット(モノ、ステレオ、8、16bit)
第三引数に入れるデータのアドレス
第四引数にデータサイズ
第五引数にサンプリングレート
といった感じです。
データサイズのところですが、サンプル数に量子化ビット数に応じた値をかけます。1サンプルに対し8bitなら1byte、16bitなら2byte使いますので、sizeof()でいつでも変更できるようにしておきましょう。
alSourcei()でsourceにいろいろな情報を入れます。
//ソースにバッファを適用
alSourcei(source, AL_BUFFER, buffer);
//ループ再生をON
alSourcei(source, AL_LOOPING, AL_TRUE);
第一引数にソース
第二引数にどの機能を使うか
第三引数はそれらに応じた値を入れます。
今回はこの二行でバッファの指定とループ再生をONにしました。
いよいよ音を鳴らします。
//ソースを再生!
alSourcePlay(source);
ソースを指定してPlayするだけです簡単ですハイ。
あとは使ったメモリとかを破棄して安全に終了する手続きだけなのでこれにて終了です。
注意なのが動的メモリ確保に使用したnew演算子。実はちょーっと曲者でして。
本来使ったメモリは自動的に破棄されるのが理想ですが、new演算子は確保してしまうとずっと確保しっぱなしになってしまう点に注意です。
今回は音を鳴らしたらすぐにアプリが終わるので大丈夫ですが、サーバー管理とかで破棄し忘れるとメモリを爆食いする恐ろしい魔物に変身します。
使い終わったメモリはdelete[]で破棄する癖をつけておくと◎です。
なんでそんなの使わせたんだ!っていう意見もあると思いますが、これ速いんですよ。
ほかにはvectorとかmallocとかあるんですが、なんか処理の速さが一番だったような・・・という裏話でした。
以上で補足は終わりです。OpenALは便利ですが詳しい解説をしているサイトが多いとは言えないのも事実。そんな中で参考にしてもらえれば幸いです。
それではまた次回の置手紙でお会いしましょう・・・