ウェブ オーディオに関するよくある質問

WebKit Web Audio API は、ここ数か月で、ウェブ上のゲームやオーディオ アプリケーションにとって魅力的なプラットフォームとして台頭してきました。開発者が慣れ親しんでいると、同じような質問が何度も繰り返し出てくるのを聞きます。この簡単なアップデートは、Web Audio API をより快適にご利用いただくために、よくある質問に対処するためのものです。

Q: 音を鳴らせません。

A: Web Audio API を初めて使用する場合は、スタートガイド チュートリアルや、ユーザーの操作に基づいて音声を再生するための Eric のレシピをご覧ください。

Q: オーディオ コンテキストは何個必要か?

A: 通常は、1 ページに 1 つの AudioContext を含める必要があり、1 つのオーディオ コンテキストがそれに接続される多数のノードをサポートできます。1 つのページに複数の AudioContexts を含めても、パフォーマンスが低下する可能性があります。

Q: noteOn() で再生したばかりの AudioBufferSourceNode をもう一度再生したいのですが、noteOn() では何も起こりません。どうすればよいですか?

A: ソースノードの再生が完了すると、これ以上再生することはできません。基になるバッファをもう一度再生するには、新しい AudioBufferSourceNode を作成して noteOn() を呼び出す必要があります。

ソースノードの再作成は効率が悪いように感じるかもしれませんが、ソースノードはこのパターンに合わせて大幅に最適化されています。さらに、AudioBuffer へのハンドルを保持している場合は、同じサウンドを再度再生するためにアセットに別のリクエストを行う必要はありません。このパターンを繰り返す必要がある場合は、playSound(buffer) などのシンプルなヘルパー関数で再生をカプセル化します。

Q: サウンドを再生する際に、毎回新しいソースノードを作成する必要があるのはなぜですか?

A: このアーキテクチャは、音声アセットを再生状態から分離するためのものです。レコード プレーヤーに例えるなら、バッファはレコードやプレイヘッドのソースに似ています。多くのアプリケーションでは、同じバッファの複数のバージョンが同時に再生されるため、このパターンは不可欠です。

Q: audio タグと video タグの音声を処理するにはどうすればよいですか?

A: MediaElementAudioSourceNode は現在開発中です。使用可能な場合、その動作はおおむね次のようになります(audio タグを介して再生するサンプルにフィルタ エフェクトを追加する場合)。

<audio src="sounds/sample.wav" controls>
var audioElement = document.querySelector('audio');
var mediaSourceNode = context.createMediaElementSource(audioElement);
mediaSourceNode.connect(filter);
filter.connect(context.destination);

この機能はこちらの crbug で追跡されています。この設定では、mediaSourceNode.noteOn() を呼び出す必要はありません。オーディオタグによって再生が制御されます。

Q: マイクから音声が届くのはいつですか?

A: オーディオ入力部分は、getUserMedia を使用して WebRTC の一部として実装され、Web Audio API の特別なソースノードとして利用できます。createMediaElementSource と連携して動作します。

Q: AudioSourceNode の再生が終了したことを確認するにはどうすればよいですか?

A: Web Audio API はこの機能をサポートしていないため、現時点では JavaScript タイマーを使用する必要があります。Web Audio API のスタートガイド チュートリアルの次のスニペットは、この実例です。

// Assume source and buffer are previously defined.
source.noteOn(0);
var timer = setTimeout(function() {
    console.log('playback finished');
}, buffer.duration * 1000);

Web Audio API により正確なコールバックを実装するための未解決のバグがあります。

Q: サウンドを読み込むと UI スレッド全体がロックされ、UI が反応しなくなります。**

A: 非同期読み込みに decodeAudioData API を使用して、メインスレッドをブロックしないようにします。こちらの例をご覧ください。

Q: Web Audio API を使用して、リアルタイムよりも速く音声を処理できますか?

A: はい。現在対応中です。もうしばらくお待ちください。

Q: 優れた Web Audio API アプリケーションを作成しましたが、実行中のタブがバックグラウンドになると、音声が不自然になります。

A: これは、setTimeouts を使用していることが原因と考えられます。ページがバックグラウンドで実行されている場合は動作が異なります。将来的には、ウェブ音声の内部タイマー(context.currentTime 属性)を使用して、特定の時間にコールバックできるようになる予定です。詳しくは、こちらの機能リクエストをご覧ください。

一般的に、アプリがバックグラウンドに移動したら再生を停止することをおすすめします。Page Visibility API を使用すると、ページがバックグラウンドに移動されたことを検出できます。

Q: Web Audio API を使用して音のピッチを変更するにはどうすればよいですか?

A: ソースノードで playbackRate を変更します。

Q: 速度を変更せずにピッチを変更できますか?

A: Web Audio API では音声コンテキストに PitchNode を含めることはできますが、実装が困難です。これは、オーディオ コミュニティには簡単なピッチシフト アルゴリズムが存在しないためです。既知の手法では、特にピッチのずれが大きい場合にアーティファクトが生じます。この問題に対処するには次の 2 種類のアプローチがあります。

  • 時間領域アルゴリズム。これにより、繰り返されるセグメントでのアーティファクトのエコーが発生します。
  • 残響アーティファクトを引き起こす周波数ドメイン技術。

これらの手法を行うためのネイティブ ノードはありませんが、JavaScriptAudioNode で実行できます。以下のコード スニペットを出発点としてご利用いただけます。

Q: 選択したサンプルレートで AudioContext を作成するにはどうすればよいですか?

A: 現時点ではサポートされていませんが、現在調査中です。こちらの機能リクエストをご覧ください。

他にもご不明な点がありましたら、StackOverflow で web-audio タグを使用してお気軽にご質問ください。