2019/06/09
ADX2が強いです。wararyoです。
Unityでゲームを製作していたら、必ず一回はやりたいと思うのが、イントロ付きBGMのループ再生です。
イントロ付きBGMと言いましたが、先日紹介したように、音楽としてのイントロが無くてもイントロ部分を設けないといけないケースが多いです。
ところが、Unityでは、イントロ付きBGMを再生する機能が標準ではついていません。(例外あり後述)
そこで、巷でよく用いられている方法の中から、
- ループデータ入りWAVファイルを再生
- ファイルを分けて遅延再生
- Update()で監視
- CRIWARE ADX2を用いる
この4つの精度を測定し、それぞれのメリット・デメリットを議論していきます。
sponsored link
測定方法
- Unityエディター上で4つの方法でそれぞれBGMを再生します。
- それをUR22mkIIのループバック機能を使って録画します。
- Audacityを使って、リファレンスと録音した音、2つの波形の最初の方をサンプル単位で合わせます。
- ループが起こった直後の波形のズレを測定します。
4つのループ方式でそれぞれ3回試行します。
Unityでは、毎秒4096個のパーティクルを発生し、かつUIを描画しつづけます。PCに負荷をかける試みです。
ただし、1回目はこの負荷をかけず、2,3回目のみ負荷をかけます。
無視できないズレが生じた場合は、ズレたサンプル数を秒数およびフレーム数に換算して示しています。
音源および録音のサンプリングレートは44100Hzです。フレームレートは60fpsとしています。
実験用に作成したUnityプロジェクトはこちらから見れます。
https://github.com/wararyo/LoopMusicComparison
ループデータ入りWAVファイルを再生
先ほど「Unityでは、イントロ付きBGMを再生する機能が標準ではついていません」と言いましたが、例外があります。
それは、WAVファイルの中にループ情報が埋め込まれている場合です。
この場合に限り、Unity側で特に何もしなくても、AudioSourceから再生すればいい感じにループしてくれます。
WAVファイルにループ情報を埋め込む過程は省略します。Wavosaurというソフトウェアを使いました。
精度測定
- 1回目: 1サンプル以内
- 2回目:約1サンプル
- 3回目: 約2サンプル
特徴
- 特別なアセットやスクリプトが不要
- Wavosaurとかいう胡散臭いソフトが必要
- ファイルサイズが膨大になる
手軽に高精度なループが実現できるんですが、ファイルサイズがやばくなります。そりゃ非圧縮ですから…
ビルドする際にUnityが圧縮してくれるでしょうからビルドしちゃえば大丈夫なんですが、主にバージョン管理で死にます。
簡単に言うと、プログラマが2人以上居る制作チームではプログラマが死ぬのでこの方法はやめてください、ということです。
Gitとか使わない完全個人開発のゲームだったらアリなのかもしれません。
ファイルを分けて遅延再生
これは、AudioSourceコンポーネントの、音声を遅れて再生させる機能を用いた方法です。
BGM_intro.ogg, BGM_loop.oggといった2つのファイルを用意し、2つのファイルを同時再生します。
ただし、この時BGM_loop.oggの方をイントロの長さだけ遅延させます。するとBGM_intro.ogg再生終了直後にBGM_loop.oggが始まるという寸法です。
精度測定
- 1回目: 1サンプル以内
- 2回目: -937サンプル(0.0212秒 1.272フレーム)
- 3回目: 1サンプル以内
特徴
- ファイルを2つに分けるのがめんどくさい
- たまに超ズレる
DTMerはファイルを2つに分けないといけないのが面倒ですね。外部ツールを使わなくて良いと言う点ではお手軽です。
問題は精度です。3回中1回、盛大なズレが起こりました。
実は僕はこの手法で1つゲームを作ったことがあります。普段は大丈夫なんですが、たまーに耳で聴いてはっきり分かるほどのズレが生じます。1フレーム以上ずれるのはダメだと思う。
Update()で監視
これは、BGMを再生し終わったかを毎フレーム監視し続け、ループ部分の再生が終わったらまた、あらかじめ指定したループ開始ポイントから再生を始めるという方法です。ファイルは1個で済みます。
精度測定
- 1回目: 295サンプル(0.00669秒 0.401フレーム)
- 2回目: 295サンプル(0.00669秒 0.401フレーム)
- 3回目: 295サンプル(0.00669秒 0.401フレーム)
特徴
- 楽
- 最大で 1/フレームレート (秒)のズレが生じる
かなり手軽な方法です。一個スクリプト作成してしまえば、DTMerもプログラマも幸せになれます。なれるはずでした。
だいたい仕組みからして、ぴったりループする確率は0に近いことがわかりますよね。0から1フレームの間で必ず遅くなることは容易に想像できます。実際、0.4フレームほど遅くなりました。
ただ、3回とも全く同じサンプル数の遅延が起こったのは予想外でした。ボタンを押すタイミングもバラバラだったんですが、これはよくわかりません…
楽なんですが、聴いてわかるレベルの遅延が常に起こるのはさすがにマズいので、実用には耐えないですね。
CRIWARE ADX2を用いる
きました真打。ADX2とは、Unityなどの制作環境において、音声周りを強化するソフトウェアです。
専用のオーサリングソフトで音データを変換してからUnity用ADX2プラグインに読み込み、再生します。
詳しい使い方は他のサイトをどうぞ。
ADX2は有料なので、非商用に限り無料で使えるADX2 LEを用いました。
精度測定
- 1回目: 1サンプル以内
- 2回目: 1サンプル以内
- 3回目: 1サンプル以内
特徴
- 精度は高い
- Windowsが必要
- ADX2形式に変換するのがめんどくさい
- WebGLビルドで使用不可
さすがの高精度!!
使える精度を確保しつつ現実的なファイルサイズで管理できる方法としては、今回試した4つの中で唯一の方法です。
「Windowsが必要」というのは、ADX2形式に変換するソフトウェア、「CRI Atom Craft」がWindowsでしか動作しないからです。
(2017/05/26現在、Macへの対応がアナウンスされています。)
また、ネイティブプラグインを用いるため、WebGLビルドで動作しません。つまりブラウザゲーでは使えません。
(2017/05/26現在、WebGL用の「ADX2 for ブラウザ」がアナウンスされています。)
ADX2はBGMのループ再生以外にも多くの便利機能を搭載しているようです。この方法を採用するなら、せっかくだしUnity標準サウンドは無効化して完全にADX2を使うようにしてみると幸せになれるかもしれません。というか今僕がそれを試してる最中です。
いかがでしたか。
DAWとUnity以外のツールを使わずに綺麗なループを実現する方法が現状存在しないということが判明してしまいました。残念です。
安心して使える方法はADX2しかないのではないかと思います。
この実験を踏まえて、僕はこれからADX2を使う方法で一個ゲームを作ってみたいと思っています。
他にもUnityでイントロ付きループBGMを再生する方法があればぜひコメントください。
この比較をもとに、あなたのプロジェクトに一番合った方法が見つかれば幸いです。