VANNAN GAMES.

← 制作ノート一覧

音が鳴るようになったら、今度は遅れた——効果音の遅延と重なりを直した話

サイト全体

前回、音が鳴らない問題の地図を書きました。結論は「効果音も全部WAVファイルにして、BGMと同じAudio要素で再生する」でした。これで鳴らない問題は消えました。

そして今度は、遅れました。

「若干遅れる」から始まる犯人探し

報告は「SEが若干遅れる」というものでした。厄介な種類の報告です。鳴らないなら原因は切り分けられますが、遅れるは「気のせいかもしれない」の隣にあります。まず、遅れているのが本当かを数字にするところから始めました。

最初に疑ったのは音源です。書き出しに無音が入っていれば、コードがどれだけ速くても遅れて聞こえます。ありがちな話なので、共通効果音のWAV22本を全部デコードして、先頭から「ピークの2%を超える最初のサンプル」までの時間を測りました。

結果は0.1〜0.3ms。全ファイル、ほぼ完璧に切り詰められていました。音源は無実です。ここで疑いが再生方法に移りました。

遠回りに見えますが、この順番は大事でした。もし音源が原因なら、コードをいくら書き換えても直りません。「安い方から潰す」より「原因の上流から潰す」ほうが、結局は速いことが多いです。

犯人は「巻き戻して鳴らす」だった

当時の実装は素直なものでした。音1種類につきAudio要素を1個持っておき、鳴らすときは再生位置を先頭に戻してplay()する。よく見る書き方です。

ところがこの「先頭に戻す」がシーク扱いになり、実際に音が進み始めるまで待たされます。同じ端末・同じブラウザで測った数字がこれです。

再生方法音が出始めるまで
Audio要素を巻き戻して再生(当時)初回 102.6ms、以降 8.7〜14.2ms
Web Audio(デコード済みを再生)0.1〜0.3ms

ハードウェア由来の出力遅延はどちらにも等しく乗るので、差分がまるごと上乗せぶんです。しかもこれはPCのChromeでの数字で、モバイルSafariのAudio要素はさらに悪化します。「若干遅れる」の正体でした。

もうひとつ、報告されていなかった不具合

調べている途中で、誰も報告していない問題が見つかりました。音1種類につき要素が1個しかないということは、同じ音が連続すると前の音が途中で切れるということです。

実際に測ると、320msある撃破音が68msまで進んだところで2発目に巻き戻され、1発目が消えていました。敵が同時に倒れる場面で、鳴るべき音が鳴っていなかったわけです。遅延より、こちらのほうが体験としては損をしていたかもしれません。

合成に戻ったわけではない

直し方は、WAVを起動時に一度デコードしてメモリに持ち、鳴らすたびに使い捨ての発音体を作って再生する方式です。これで遅延は0.1〜0.3msになり、発音体が毎回別なので音は自然に重なります。

ここで自分に念を押したのは、これは前回やめた「WebAudio合成」への逆戻りではないということです。音源は同じWAVのままで、音色は1ミリも変わりません。変えたのは再生経路だけです。前回WebAudioで鳴らなかった原因は合成そのものではなく、オーディオの文脈が停止したまま復帰していなかったことでした。初回タップで復帰させ、それでも駄目な環境ではAudio要素に自動で退避する作りにしてあります。

「一度失敗した技術」に戻るときは、失敗の原因を名指しできるかどうかが分かれ目だと思います。名指しできないうちに戻ると、同じ穴に落ちます。

おまけ: 効果音だと思っていたものが曲だった

同じ流れで「結果画面でBGMと効果音が重なって濁る」という報告も来ました。原因を探す前に、まず結果音の長さを測りました。

ファイル長さ
クリア時のジングル6.0秒
勝利時のジングル9.7秒
失敗時のジングル22.8秒

22.8秒は効果音ではありません。曲です。これがループBGMと同時に鳴っていれば、濁って当然でした。あるゲームではBGM開始とジングル開始を同じ行で並べて呼んでいて、別のゲームでは「2.2秒後にBGMを重ねる」という固定待ちを入れていました。9.7秒のジングルに対して2.2秒なので、7.5秒ぶん重なっていた計算になります。

直し方は単純で、ジングルが鳴り終わってからBGMを始めるようにしただけです。ただし固定の待ち時間は使いませんでした。音源を差し替えた瞬間にまたズレるからです。「終わったら次を鳴らす」を仕組みとして持たせておけば、長さが変わっても勝手に正しくなります。

教訓

今回いちばん効いたのは、体感の報告を最初に数字に変換したことでした。「遅れる」は主観ですが、9〜100msは主観ではありません。数字にした瞬間に、直すべき場所とそうでない場所(音源)がはっきり分かれました。

そして「効果音」という名前を疑わなかったせいで、22.8秒の曲を効果音として扱い続けていました。ファイル名やフォルダ名は、作った本人の思い込みをそのまま固定します。ときどき中身を測ってみるといいです。うちは測って驚きました。