BMSプレイヤー開発 for macOS: サウンドシステム編

2017-05-06 17:24  -  1 min read

前回の記事でBMSパーサー実装時の動作テストとして,パース結果をもとに譜面(の音声)をオートプレイできるところまでいけたと書きましたが,どうにも音声が遅延する問題が気がかりでした。 今回はその問題が解決できたことを報告いたします。

AVAudioPlayerはゲーム向きでない

結論です。聞いていてわかるほどの遅延が発生してもはやゲームになりません。音ゲーじゃなかったらギリギリ許せるレベルですが,できるならゲームへの採用は避けた方が良いということがわかりました。SpriteKitにもSKAction を使った音声の再生手段を提供しているようですが,自由度がないためキー音を大量に扱う音ゲーに於いてはAVAudioPlayer同様不安要素があります。

CoreAudioの概要という公式の資料を読んでみた

CoreAudioの概要 知りたい情報はわりかし序盤の方に出てくるのですが,内容が興味深くて最後まで読んでしまいました。特にDTMをやっている人には AudioUnit の概念が割と突っ込まれて書かれいるので興味を引く内容になっているのではないのでしょうか!読み物としてオススメです。

公式の見解では,ゲーム開発においては OpenAL のAPIを利用が適している,のだそうです。 OpenGLライクなAPIで音声を扱えるAPI群だそうで,広く利用されているらしいです。これがCoreAudioの上位レイヤー部分に実装されており,このAPIを利用すると遅延の少ない音声再生を実現できるとのことでした。

OpenALについての資料をあさる

参考にしたページは以下

OpenALExample

コードを読むことが一番の近道です。

公式が提供しているObjective-Cの実装は音声を再生する手順だけではなく,パンを変えたりリバーブ等のエフェクトを掛けるところまで解説しています。IIDXっぽくいくなら音声に対するエフェクトの適用は必須なのでありがたい限りです。

またgithubに公開されていたswift-openal-example はswiftの特徴を生かし,日本語のメソッドでわかりやすくAPIの利用フローが書かれており,素早い理解への一助となりました。

どちらもmacOS及びiOSにおけるOpenALの理解への近道なのでオススメです。音声を単に再生するだけが目的なので上に紹介した実装を見れば十分であり,今回は公式のドキュメントにはあまり目を通しておりません…。おかげでメモリリークなどの問題に若干悩まされたりしまいたが…—;

ALUREでoggが再生できるとのこと

OpenALを便利に利用できるライブラリとして ALURE というものがあることを知りました。OpenALをより便利に使える OpenGLにおける GLUT 的なライブラリです。

公式サイトには

Currently ALURE includes a basic .wav and .aif file reader, and can leverage external libraries such as libSndFile (for extended wave formats and several others), VorbisFile (for Ogg Vorbis), FLAC (for FLAC and Ogg FLAC), and others

と書かれており,.ogg の読み込みをサポートしてしまうとのこと。

ALURE(OpenALユーティリティ)をiOSで使う をもとに,プロジェクトに取り込んでみると,簡単に .ogg を再生することができました。拍子抜けです。

他の方法としては oggのデコーダと Audio Queue Servicesを利用することで実現する方法があるそうです。 IDZAQAudioPlayer このリポジトリをビルドするとiOSで .ogg を再生できることを確認できました。 今回はOpenALを利用しているので,こちらは不採用となりましたが,参考までに。

かくして遅延はなくなった

厳密には遅延しているのでしょうが,聞いていてい不自然になるような出力結果にはなっていません。ひとまず安心できるレベルです。新しい課題として,キー音でないバックで流れる音声は処理落ちすると簡単にずれてしまうので,譜面の進度に合わせて音声の再生位置を無理やり同期させる処理が必要そうということがわりました。それは追々やっていきます。

詳しい実装に関して

あまりなさそうな情報なので,Qiitaに書いておきました。

OpenAL + ALURE + Swift3でゲーム用の低遅延なサウンド再生システムを作る