通常Macにイヤホンを繋いだ場合、音源はイヤホンから再生されます。
しかし、Macにはデフォルトアプリとして「Audio MIDI 設定」が入っており、オーディオのインアウトを好きなようにカスタマイズできます。
そして、Audio MIDI 設定とWebAudioAPIを組み合わせると、
- Macのスピーカー(左)
- Macのスピーカー(右)
- イヤホン(左)
- イヤホン(右)
の全てから異なる音源を再生することができます。
Macの設定
- アプリケーション > その他 > Audio MIDI 設定を開く
- 左下の+ボタンを押して危機セットを作成
- MacBookのスピーカーとイヤホンの使用にチェックを入れる
- 右下のスピーカーを構成...をクリック
- 構成を4チャンネルに設定
これでOKです。
index.htmlの作成
<html> <head> <meta charset="UTF-8"> <title>web-audio-api-4ch</title> <meta name="viewport" content="width=device-width"> </head> <body> <button id="load">load</button> <span style="display: none;"> <button id="a">a</button> <button id="b">b</button> <button id="c">c</button> <button id="d">d</button> </span> <script> document.getElementById('load').addEventListener('click', async () => { const channelCount = 4; const audioCtx = new AudioContext(); if (audioCtx.destination.maxChannelCount < channelCount) { return alert(`${channelCount}チャンネル欲しいけど、${audioCtx.destination.maxChannelCount}チャンネルしかありません`); } const merger = audioCtx.createChannelMerger(channelCount); audioCtx.destination.channelCount = channelCount; const [ controllerA, controllerB, controllerC, controllerD ] = await Promise.all([ loadAudio('a.mp3', 0), loadAudio('b.mp3', 1), loadAudio('c.mp3', 2), loadAudio('d.mp3', 3) ]); document.getElementById('load').style.display = 'none'; document.querySelector('span').style.display = 'inline'; document.getElementById('a').addEventListener('click', () => { controllerA.start(); }); document.getElementById('b').addEventListener('click', () => { controllerB.start(); }); document.getElementById('c').addEventListener('click', () => { controllerC.start(); }); document.getElementById('d').addEventListener('click', () => { controllerD.start(); }); merger.connect(audioCtx.destination); async function loadAudio(src, channel) { return new Promise((resolve) => { const request = new XMLHttpRequest(); request.open('GET', src, true); request.responseType = 'arraybuffer'; request.onload = () => { const gain = audioCtx.createGain(); gain.channelCount = 1; gain.connect(merger, 0, channel); audioCtx.decodeAudioData(request.response, (buffer) => { const source = audioCtx.createBufferSource(); source.buffer = buffer; source.loop = true; source.connect(gain); resolve({ start: () => source.start() }); }); }; request.send(); }) } }); </script> </body> </html>
こんな感じです。
index.htmlと同階層にa.mp3〜d.mp3を置く必要があります。
僕はこういう時に使うテスト用のmp3ファイルは、sayコマンドで作ったaiffファイルをffmpegでmp3化して作ってます。
DEMO
loadボタンを押した後にa〜dボタンを押すことで、対応したmp3が対応したチャンネルから再生されます。
loadボタンを押した時に「4チャンネル欲しいけど、2チャンネルしかありません」と表示された場合はAudio MIDI 設定がうまく設定できていないので見返してみてください。