効果音を後回しにした試作に音を足すと、どこがずれるのか:遅れを切り分ける実験の設計書
遊びをつくる執筆にClaudeを使用しています。

見た目と動きだけで組んだ試作を、いったん遊べる形にしたとします。ボタンを押すと的が光る、キャラクターが跳ねる、といった反応があり、遊んでいて引っかかりはありません。そこへ効果音を足したとたん、「なんとなく反応が重い」と感じる場面を考えてみます。画面は何も変わっていないのに、音が加わっただけで手応えが変わって感じられます。 この記事の問いは、その「ずれ」がどこから来るのかを、自分の環境で切り分けられるかどうかです。音を足す前は、画面の反応だけが唯一の手がかりでした。音が入ると、画面と音という二つの手がかりを耳と目で比べることになります。そのため、無音のときには気づけなかった遅れが目立つ可能性があります。ただし、これは仮説です。実際にどう聞こえるかは、端末、ブラウザ、出力機器の組み合わせで変わるので、この記事は結果を示さず、自分で確かめる設計書として書きます。 用意するのは、HTMLファイル1つ、スマートフォンなど動画が撮れる機器、イヤホンかスピーカーです。外部の音声ファイルもライブラリも使いません。
遅れを三つに分けてから始める
「音が遅い」という感覚は、原因の違う遅れが重なったものです。先に分けておくと、記録を読むときに迷いません。
- 処理の遅れ:入力を受けてから、再生の命令を出すまでの時間です。コードの書き方で変わります。
- 準備の遅れ:音データの読み込みや変換、音を出す仕組みの起動待ちです。初回だけ起こる場合があります。
- 出力の遅れ:再生を命令してから、実際に耳に届くまでの時間です。端末の音声処理やスピーカー、無線イヤホンの影響を受けます。無線接続の機器は、有線より遅れが出やすいことが一般に知られています。
このうち1と2はコードで直せます。3は多くの場合、直せません。直せないものは、設計で目立たなくする方向で考えます。たとえば反応の演出を音に合わせて少し遅らせる、音に頼らない視覚の手がかりを残す、といった方法です。実験の目的は、手元のずれがどの遅れに当たるかを見分けることです。
準備:わざと遅らせる試作を作る
次のコードは、無音の試作に音を足す最小の構成です。ボタンを押すと四角が黄色く光り、短い音が鳴ります。音はコードで生成するので、外部ファイルは要りません。再生のタイミングを3通りに切り替えられます。
<!doctype html>
<meta charset="utf-8">
<button id="hit" style="width:200px;height:200px">押す</button>
<select id="mode">
<option value="sync">同じ処理で</option>
<option value="raf">次のフレームで</option>
<option value="delay">わざと遅らせる</option>
</select>
<input id="ms" type="number" value="50">ms
<pre id="log"></pre>
<script>
const ctx = new AudioContext(), sr = ctx.sampleRate;
const buf = ctx.createBuffer(1, sr * 0.08, sr);
const d = buf.getChannelData(0);
for (let i = 0; i < d.length; i++)
d[i] = Math.sin(2 * Math.PI * 880 * i / sr) * Math.exp(-40 * i / sr);
function play(t0) {
const s = ctx.createBufferSource();
s.buffer = buf;
s.connect(ctx.destination);
s.start();
log.textContent += (performance.now() - t0).toFixed(1) + " ms\n";
}
function flash() {
hit.style.background = "#ff0";
setTimeout(() => hit.style.background = "", 100);
}
hit.addEventListener("pointerdown", () => {
ctx.resume();
const t0 = performance.now();
flash();
if (mode.value === "sync") play(t0);
else if (mode.value === "raf") requestAnimationFrame(() => play(t0));
else setTimeout(() => play(t0), Number(ms.value));
});
</script>三つの条件の意味は次のとおりです。
- 同じ処理で:押した直後の同じ処理の中で、光らせる命令と再生の命令を続けて出します。
- 次のフレームで:再生の命令を、次の描画のタイミングまで待ってから出します。
- わざと遅らせる:入力した数値(初期値は50)のミリ秒だけ待ってから再生します。
3つ目は、自分の感覚の物差しにするための条件です。遅れを人工的に足した音を何度か聞いておけば、「これくらい遅らせると自分には遅れて聞こえる」という基準が手元にできます。数値を10、30、50、100と変えて、どこから違和感が出るかを先に確かめます。この基準は個人差も環境差もあるため、他人の数値を借りずに自分の値を使います。
画面に出る「ms」の数値には注意が必要です。これは押した瞬間から再生の命令を出すまでの時間で、音が耳に届くまでの時間ではありません。出力の遅れはコードの中からは測れません。
手順:条件を変えて、同じ操作を繰り返す
測定の単位は「1条件につき10回押す」とします。10回あれば、1回だけ外れた値と、毎回出る傾向とを見分けやすくなります。
- 使う環境を決めて、表の1行目に記録します。端末の種類、ブラウザ名、出力機器(内蔵スピーカー、有線イヤホン、無線イヤホンなど)です。
- ページを開き直し、最初の1回目の押下から記録します。初回だけ違う可能性があるので、練習で鳴らしてしまわないようにします。
- 「同じ処理で」を10回押し、画面の数値を記録します。耳の感想も、「揃って聞こえた」「音が遅れた」「判断できない」の3段階で書き留めます。
- 「次のフレームで」「わざと遅らせる」(10ms、50ms、100msなど)も同様に10回ずつ行います。
- 出力機器を変えて、2〜4を繰り返します。可能であれば、ブラウザも変えます。
耳の評価に加えて、動画でも記録します。スマートフォンで、画面とスピーカーの音が一緒に映るように録画します。動画編集ソフトやコマ送りができるプレーヤーで、「四角が黄色くなった最初のコマ」と「音の波形が立ち上がった位置」の差を数えます。60fpsの動画なら1コマは約16.7ミリ秒なので、差が何コマかを数えれば、おおよその大きさがつかめます。
録画自体にも音と映像のずれがあり得ます。そのため、絶対値は信用せず、条件どうしの差を見ます。たとえば「わざと遅らせる50ms」の録画と、「同じ処理で」の録画を並べて、差が何コマ違うかを比べます。同じ録画方法で撮った動画どうしなら、録画のずれは両方に同じように乗るはずです。
結果の読み方:どの遅れかを見分ける
記録がそろったら、パターンで原因を絞ります。以下は判断の目安で、数値の良し悪しを決めるものではありません。
- 1回目だけ他と違う、疑う原因:準備の遅れ(音の起動、データの準備)、次に試すこと:最初の操作の前に音を準備しておく。操作のたびに音データを作り直していないか確認する
- 毎回同じ程度ずれる。条件を変えても変わらない、疑う原因:出力の遅れ(端末や機器)、次に試すこと:出力機器を変えて同じ記録を取る。差が出るなら機器側が原因
- 「次のフレームで」だけ他と違う、疑う原因:描画との同期の仕方、次に試すこと:画面の反応と音を同じタイミングで出す方式を採るか決める
- 画面の数値は小さいのに、耳では遅れて聞こえる、疑う原因:出力の遅れ、または音の先頭の無音、次に試すこと:音データの先頭に無音が入っていないか確認する
- 回ごとの値がばらつく、疑う原因:処理の混雑、タブの状態、次に試すこと:他のタブを閉じて取り直す。ばらつきが残るか見る
- 「わざと遅らせる」で違和感が出る境目が人によって違う、疑う原因:個人差、次に試すこと:一人の基準で決めず、複数人で比べる
読み方の要点は、変えた条件と一緒に動いた数値だけを原因とみなすことです。出力機器を替えて変化したなら出力側、機器を替えても変化しないなら自分のコード側です。一つずつ条件を動かして記録を見れば、原因を絞り込めます。
誤りやすい点
- 無線イヤホンのまま測る:出力の遅れが大きくなる可能性があります。コードの比較をするときは、有線か内蔵スピーカーに固定します。
- 音量が小さいと遅れて聞こえる:立ち上がりが聞き取りにくいと、始まりが遅く感じます。条件間で音量を揃えます。
- 初回を捨てる:初回に差が出るかどうかは、この実験の見どころの一つです。練習で先に鳴らして初回をなくすと、見逃します。
- 連打で音が重なる:速く押すと前の音と重なり、タイミングの判断がしにくくなります。1回ごとに間隔をあけます。
- 画面の数値だけで結論を出す:先ほどの数値は処理の遅れだけです。耳と動画の記録と必ず突き合わせます。
- 一度の記録で決める:端末の混み具合で値は変わります。10回のばらつきも含めて読みます。
- 試作の環境と公開後の環境を同じとみなす:ブラウザ、端末、再生の開始条件が違えば結果も変わり得ます。
アソバースに作品として投稿する場合、ゲームはsandbox付きのiframeで実行されます。投稿して表示を確認する段階で、音が実際に鳴るか、鳴り始めのタイミングが手元の試作と同じ感触かを、公開後の画面で改めて確認してください。この環境での音の扱いについて細かな挙動は、現在の案内で確認します。
次に、ずれを設計に戻す
測れたずれは、次の三つのどれかに振り分けて対応を決めます。
- コードで直せるもの:準備の遅れ、再生の命令を出す位置、音データの先頭の無音。まず直します。
- 直せないが目立たなくできるもの:出力の遅れ。画面の反応にも見える手がかりを残す、音に頼らない設計にする、といった方法で影響を減らします。
- 許容するもの:自分の「わざと遅らせる」の基準より小さく、複数人に聞いてもらっても気にならないずれです。
音が大事なゲームかどうかでも判断は変わります。たとえばアソバースの公式作品には、音の聞こえ方が遊びの中心に近い「雨音のピアノ」や「WAVE / WAVE」、音を聞いて覚える「こだまの森」があります。「こだまの森」には音なしでも遊べる設定があるので、音がなくても成立する設計がどういう形かを見る材料になります。ただし、各作品がどのようにタイミングを扱っているかは確認済みの情報にありません。作品を開いて、自分の環境で押してみてください。
次の行動
まず上のコードを保存し、「わざと遅らせる」の数値を10、30、50、100と変えて、自分が違和感を覚える境目を書き留めます。そのうえで、手元の試作に効果音を足し、1回目の操作と、2回目以降の操作の聞こえ方を比べてください。どこかで条件を一つだけ変える、という進め方で、遅れの原因を一つずつ絞り込めます。
参考資料
- MDN Web Docs「Web Audio API」

