みかづきブログ・カスタム

基本的にはちょちょいのほいです。

PCにオーディオインターフェイス(SERIES 208i)を繋いで、ブラウザから5つのスピーカに対して音源を再生する 📢

blog.kimizuka.org

4チャンネルの音源再生がうまくいったので、1チャンネル増やすのなど簡単なことであろうと思っていたのですが、がっつりハマりました。
今後のためにメモを残しておきます。

結論

こちらで、5つのモノラル音源(440Hzのサイン波)を5つのスピーカーから再生することができます。
ポイントは、6チャンネルのmergerを作成して、3を使用しないことでした。

<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>web-audio-api-5ch</title>
    <meta name="viewport" content="width=device-width">
  </head>
  <body>
    <button data-index="0">0</button>
    <button data-index="1">1</button>
    <button data-index="2">2</button>
    <button disabled data-index="3">3</button>
    <button data-index="4">4</button>
    <button data-index="5">5</button>
    <script>
      const audioCtx = new AudioContext();
      const channelCount = 6;
      const merger = audioCtx.createChannelMerger(channelCount);

      audioCtx.destination.channelCount = channelCount;

      [].slice.call(document.querySelectorAll('[data-index]')).forEach((button) => {
        button.addEventListener('click', (e) => {
          const index = e.target.getAttribute('data-index');
          const oscillator = audioCtx.createOscillator();
          const gain = audioCtx.createGain();

          gain.channelCount = 1;
          gain.connect(merger, 0, Number(index));

          oscillator.type = 'sine';
          oscillator.frequency.setValueAtTime(220, audioCtx.currentTime);
          oscillator.connect(gain);
          oscillator.start();

          setTimeout(() => oscillator.stop(), 1000);
        });
      });

      merger.connect(audioCtx.destination);
    </script>
  </body>
</html>

DEMO

※ 動作確認するためにはPCのオーディオ出力を6チャンネル以上に設定する必要があります

調査メモ

当初は、5チャンネルのmergerを作って、0〜4に音を出せばOKと思い、

const audioCtx = new AudioContext();
const channelCount = 5; // 5ch
const merger = audioCtx.createChannelMerger(channelCount);

audioCtx.destination.channelCount = channelCount;

[].slice.call(document.querySelectorAll('[data-index]')).forEach((button) => {
  button.addEventListener('click', (e) => {
    const index = e.target.getAttribute('data-index');
    const oscillator = audioCtx.createOscillator();
    const gain = audioCtx.createGain();

    gain.channelCount = 1;
    gain.connect(merger, 0, Number(index));

    oscillator.type = 'sine';
    oscillator.frequency.setValueAtTime(220, audioCtx.currentTime);
    oscillator.connect(gain);
    oscillator.start();

    setTimeout(() => oscillator.stop(), 1000);
  });
});

merger.connect(audioCtx.destination);

というコードを書いていたのですが、3・4・5の出力先がひとつずつずれてしまい、なぜだろうと思っていました。

createChannelMerger

createChannelMergerの仕様を調べると、デフォルトでは6チャンネルということがわかりました。

developer.mozilla.org

なので、一旦、

const audioCtx = new AudioContext();
const channelCount = 6; // 6ch
const merger = audioCtx.createChannelMerger(); // 引数削除

audioCtx.destination.channelCount = channelCount;

[].slice.call(document.querySelectorAll('[data-index]')).forEach((button) => {
  button.addEventListener('click', (e) => {
    const index = e.target.getAttribute('data-index');
    const oscillator = audioCtx.createOscillator();
    const gain = audioCtx.createGain();

    gain.channelCount = 1;
    gain.connect(merger, 0, Number(index));

    oscillator.type = 'sine';
    oscillator.frequency.setValueAtTime(220, audioCtx.currentTime);
    oscillator.connect(gain);
    oscillator.start();

    setTimeout(() => oscillator.stop(), 1000);
  });
});

merger.connect(audioCtx.destination);

としてみると、0・1・2・4・5の5つのスピーカーから音源を再生することに成功したため、わかりやすさを優先して、「6チャンネルのmergerを作成して、3を使用しない」という方針で実装しました。

なぜ3から音が再生されないのか

同様の現象に悩んでいる人を数人見つけることはできたのですが、原因はわかりませんでした。
わかったこととしては、5.1chの環境にはスピーカーが6台必要で、その環境においては3はサブウーファーを担当するようです。

0: 左
1: 右
2: センター
3: サブウーファー
4: 左サラウンド
5: 右サラウンド

なんとなく、その辺りが関係しているような気がします。
もしかすると再生されていないのではなく、聴こえていないだけで、スピーカーをサブウーファーに変え、然るべき音源を再生すると聴こえるとか。