JavaScriptでサウンドをごにょごにょしてみよう…と思います。HTML5やJavaScript関連の解説ドキュメントでは日頃からMDN(Mozilla Developer Network)あたりを頼りにしているわけですが、ここのサンプルコードをそのまんま走らせてみても、デバイスやブラウザによってはなかなか上手く動きません。
やりたいこと
- とりあえずオシレータで音を出す。
実装は…
- AudioContextを作成。
- Oscillatorを作成。
- OscillatorをAudioContextの出力に接続。
- Oscillatorのパラメータを設定して音声出力スタート。
<script>
var AudioContext = window.AudioContext || window.webkitAudioContext;
var acx = new AudioContext();
var osc = acx.createOscillator();
osc.connect(acx.destination);
osc.type="sine";
osc.frequency.value = 1000;
osc.start();
</script>
var AudioContext = window.AudioContext || window.webkitAudioContext;
var acx = new AudioContext();
var osc = acx.createOscillator();
osc.connect(acx.destination);
osc.type="sine";
osc.frequency.value = 1000;
osc.start();
</script>
音が鳴らない…
- デスクトップ版Safariで音が鳴らない。
- iOS版Safariでも音が鳴らない。
原因・回避方法
- OscillatorNode.startメソッドの引数を省略しないようにする。
- iOSでは音の再生処理をユーザのアクションから呼ぶ必要がある。上の例のように OscillatorNode.startメソッドをページロード時に呼び出しても音は出ない。
- iOSデバイスのサイレントスイッチがオンになっているとスピーカからは音が出ない。イヤホンからは大丈夫。
…というわけで、こんな感じでコードを書くとiOSデバイスやSafariでもちゃんと音が出ます。
<div id="start">Start</div>
<div id="stop">Stop</div>
<script>
var AudioContext = window.AudioContext || window.webkitAudioContext;
var acx = new AudioContext();
var osc = acx.createOscillator();
osc.connect(acx.destination);
osc.type="sine";
osc.frequency.value = 1000;
//osc.start();
document.getElementById('start').addEventListener('click',function(){osc.start(0);},false);
document.getElementById('stop').addEventListener('click',function(){osc.stop(0);},false);
</script>
<div id="stop">Stop</div>
<script>
var AudioContext = window.AudioContext || window.webkitAudioContext;
var acx = new AudioContext();
var osc = acx.createOscillator();
osc.connect(acx.destination);
osc.type="sine";
osc.frequency.value = 1000;
//osc.start();
document.getElementById('start').addEventListener('click',function(){osc.start(0);},false);
document.getElementById('stop').addEventListener('click',function(){osc.stop(0);},false);
</script>
サンプルページはこちら。"Start" を押すと1kHzの純音が再生され、"Stop" で停止します。
で、OscillatorNode.stop で音声再生を止めると、このOscillatorNode は破棄されてしまうのですね。なので音を停止した後にもう一度 "Start" をクリックしても音が出ずにエラーが出ます。
これを回避するためには…
- Startボタンが押される('click'イベントを検知する)たびに「OscillatorNodeを作成して、パラメータを設定して、音を出す」という一連の作業を行う。
- 音の再生中にはStartボタンの機能を無効にして、音が止まっている時にはStopボタンの機能を無効にするような処理を組み込む。
…のように書き換えると、何度でも再生→停止を繰り返すことができます。そんな動作をするサンプルはこちら。
ということで。
コメント