Web Audio API スタートガイド

HTML5 の <audio> 要素が表示される前は、Flash または別のプラグインが必要でした ウェブの沈黙を打ち破ろうとしています。ウェブの音声は利用できなくなりましたが 必要な場合、audio タグを使用すると、 高度なゲームやインタラクティブ アプリの実装。

Web Audio API は、音声処理と音声処理のための高レベルの JavaScript API です。 ウェブ アプリケーションで音声を合成しています。この API の目標は、 最新のゲーム オーディオ エンジンに搭載されている機能や 混合、処理、フィルタリングといったタスクはよく使用されます。 さまざまな用途に活用できます。ここからは、データ アナリストが 使用できます。

AudioContext のスタートガイド

AudioContext は、すべてのサウンドの管理と再生に使用します。生成 Web Audio API を使用したサウンドの作成、1 つ以上の音源の作成 AudioContext で指定されたサウンド デスティネーションに接続します。 構成されますこの接続は直接ではなく、 処理として機能する任意の数の中間 AudioNodes オーディオ信号用のモジュールを使用します。このルーティングについては、 ウェブ オーディオの仕様をご覧ください。

AudioContext の 1 つのインスタンスで複数の音声入力をサポートできます 複雑な音声グラフであるため、各グラフに 1 つだけで十分です。 オーディオ アプリケーションを作成します。

次のスニペットは AudioContext を作成します。

var context;
window.addEventListener('load', init, false);
function init() {
    try {
    context = new AudioContext();
    }
    catch(e) {
    alert('Web Audio API is not supported in this browser');
    }
}

古い WebKit ベースのブラウザの場合は、webkit webkitAudioContext

Web Audio API の興味深い機能の多くには、 AudioNode と音声ファイル データのデコードは AudioContext のメソッドです。

サウンドを読み込んでいます

Web Audio API は、短~中程度の長さのオーディオに AudioBuffer を使用 できます。基本的なアプローチは、HTTP リクエストごとに XMLHttpRequest を 取得しています。

この API では、 WAV、MP3、AAC、OGG、その他ブラウザによるさまざまな 音声形式は異なります

次のスニペットは、音声のサンプルを読み込む方法を示しています。

var dogBarkingBuffer = null;
var context = new AudioContext();

function loadDogSound(url) {
    var request = new XMLHttpRequest();
    request.open('GET', url, true);
    request.responseType = 'arraybuffer';

    // Decode asynchronously
    request.onload = function() {
    context.decodeAudioData(request.response, function(buffer) {
        dogBarkingBuffer = buffer;
    }, onError);
    }
    request.send();
}

音声ファイルのデータはテキストではなくバイナリであるため、responseType を設定します。 'arraybuffer' へのリクエストのレスポンスです。詳細については、このモジュールの ArrayBuffers については、XHR2 に関する記事をご覧ください。

受け取った音声ファイルの(デコードされていない)データは、保持しておくことができます。 後でデコードできるようにしたり、 AudioContext decodeAudioData() メソッド。このメソッドは、 音声ファイル データの ArrayBufferrequest.response に保存されました。 非同期にデコードする(メインの JavaScript の実行をブロックしない) あります)。

decodeAudioData() が終了すると、次のコールバック関数が呼び出されます。 は、デコードされた PCM 音声データを AudioBuffer として提供します。

音を鳴らす

<ph type="x-smartling-placeholder">
</ph> シンプルな音声グラフ
シンプルな音声グラフ

1 つ以上の AudioBuffers が読み込まれたら、プレイの準備が整います できます。サウンドを含む AudioBuffer を読み込んだとしましょう。 読み込みが完了しました。その後、 このバッファを次のコードで置き換えます。

var context = new AudioContext();

function playSound(buffer) {
    var source = context.createBufferSource(); // creates a sound source
    source.buffer = buffer;                    // tell the source which sound to play
    source.connect(context.destination);       // connect the source to the context's destination (the speakers)
    source.noteOn(0);                          // play the source now
}

この playSound() 関数は、誰かがキーを押すたびに呼び出すか、 マウスで何かをクリックしたりします

noteOn(time) 関数を使用すると、正確なサウンドのスケジュールを簡単に調整できます ゲームなど時間制限のあるアプリでの 再生に最適ですただし、 このスケジュールが正しく機能するため、サウンド バッファが できます。

Web Audio API の抽象化

もちろん、より一般的な読み込みシステムを作成する方がよいでしょう。 ハードコードされていませんGoogle の さまざまな短編から中程度の長さの音を扱うための たとえば、(ウェブ標準には含まれていない)BufferLoader を使用する 1 つの方法を紹介します。

BufferLoader クラスの使用例を次に示します。 2 つの AudioBuffers を作成しましょう。読み込みが完了するとすぐに それらを同時に再生します

window.onload = init;
var context;
var bufferLoader;

function init() {
    context = new AudioContext();

    bufferLoader = new BufferLoader(
    context,
    [
        '../sounds/hyper-reality/br-jam-loop.wav',
        '../sounds/hyper-reality/laughter.wav',
    ],
    finishedLoading
    );

    bufferLoader.load();
}

function finishedLoading(bufferList) {
    // Create two sources and play them both together.
    var source1 = context.createBufferSource();
    var source2 = context.createBufferSource();
    source1.buffer = bufferList[0];
    source2.buffer = bufferList[1];

    source1.connect(context.destination);
    source2.connect(context.destination);
    source1.noteOn(0);
    source2.noteOn(0);
}

時間との闘い: リズムに合わせてサウンドを再生する

Web Audio API を使用すると、デベロッパーは再生のスケジュールを正確に設定できます。宛先 簡単なリズムトラックを設定しましょうおそらく 最も広く知られているドラムキットのパターンは、次のとおりです。

<ph type="x-smartling-placeholder">
</ph> シンプルなロックドラムのパターン
シンプルなロックドラムのパターン

ハイハットは 8 分音符で キックとスネアは 四半期ごとに交互に 4 分の 4 の動画で配信していました。

kicksnarehihat の各バッファを読み込んだと仮定すると、 そのためのコードは簡単です。

for (var bar = 0; bar < 2; bar++) {
    var time = startTime + bar * 8 * eighthNoteTime;
    // Play the bass (kick) drum on beats 1, 5
    playSound(kick, time);
    playSound(kick, time + 4 * eighthNoteTime);

    // Play the snare drum on beats 3, 7
    playSound(snare, time + 2 * eighthNoteTime);
    playSound(snare, time + 6 * eighthNoteTime);

    // Play the hi-hat every eighth note.
    for (var i = 0; i < 8; ++i) {
    playSound(hihat, time + i * eighthNoteTime);
    }
}

ここでは、先ほど見た無制限のループではなく、1 回だけ繰り返します。 あります。関数 playSound は、特定の処理を実行するメソッドです。 次のように指定して実行します。

function playSound(buffer, time) {
    var source = context.createBufferSource();
    source.buffer = buffer;
    source.connect(context.destination);
    source.noteOn(time);
}

音の音量の変更

サウンドに対して行う最も基本的な操作の 1 つは、 音量を変更します。Web Audio API を使うと、ソースを AudioGainNodeを介してそのデスティネーションを ボリューム:

<ph type="x-smartling-placeholder">
</ph> ゲインノードを含む音声グラフ
ゲインノードを含む音声グラフ

この接続の設定手順は次のとおりです。

// Create a gain node.
var gainNode = context.createGainNode();
// Connect the source to the gain node.
source.connect(gainNode);
// Connect the gain node to the destination.
gainNode.connect(context.destination);

グラフを設定したら、プログラムで ボリュームを増やすには、gainNode.gain.value を次のように操作します。

// Reduce the volume.
gainNode.gain.value = 0.5;

2 つの音間のクロスフェード

ここで、もう少し複雑なシナリオを考えてみましょう。 複数のサウンドを再生しながら、それらの間でクロスフェードを行いたい場合に適しています。これは たとえば DJ のようなアプリで 2 つのターンテーブルと ある音源から別の音源にパンできるようにします

そのためには、次の音声グラフを使用します。

<ph type="x-smartling-placeholder">
</ph> ゲインノードで接続された 2 つのソースのオーディオ グラフ
ゲインノードで接続された 2 つのソースを含む音声グラフ

この設定を行うには、2 つの AudioGainNodes を作成し、 各ソースをノードから渡します。この関数は次のような関数を使用します。

function createSource(buffer) {
    var source = context.createBufferSource();
    // Create a gain node.
    var gainNode = context.createGainNode();
    source.buffer = buffer;
    // Turn on looping.
    source.loop = true;
    // Connect source to gain.
    source.connect(gainNode);
    // Connect gain to destination.
    gainNode.connect(context.destination);

    return {
    source: source,
    gainNode: gainNode
    };
}

イコール パワー クロスフェード

単純な線形クロスフェード アプローチでは、パンしたときに音量が下がる 予測します。

<ph type="x-smartling-placeholder">
</ph> 線形クロスフェード
線形クロスフェード

この問題に対処するために、等電力曲線を使用します。 対応するゲイン曲線は非線形で、 あります。これにより、オーディオ領域間の音量低下が最小限に抑えられ、 リージョン間でより均等にクロスフェードします。 異なります

<ph type="x-smartling-placeholder">
</ph> 等電力クロスフェード。
イコール パワーのクロスフェード

プレイリストのクロスフェード

もう 1 つの一般的なクロスフェーダー アプリケーションとして、音楽プレーヤー アプリケーションがあります。 曲が変わったら、現在のトラックをフェードアウトし、 スムーズに移行する必要があります。そのためには、 未来へのクロスフェードですsetTimeout を使用してこれを行うこともできますが、 これは正確ではありません。Web Audio API では AudioParam インターフェースを使用して、将来の値をスケジュール設定できます。 パラメータ(AudioGainNode のゲイン値など)です。

したがって、プレイリストが与えられたときに、特定のトラックのトラックへの移動をスケジュール設定して、 現在再生中のトラックのゲインは下がり、トラックのゲインは 現在のトラックの再生が終わる少し前に再生します。

function playHelper(bufferNow, bufferLater) {
    var playNow = createSource(bufferNow);
    var source = playNow.source;
    var gainNode = playNow.gainNode;
    var duration = bufferNow.duration;
    var currTime = context.currentTime;
    // Fade the playNow track in.
    gainNode.gain.linearRampToValueAtTime(0, currTime);
    gainNode.gain.linearRampToValueAtTime(1, currTime + ctx.FADE_TIME);
    // Play the playNow track.
    source.noteOn(0);
    // At the end of the track, fade it out.
    gainNode.gain.linearRampToValueAtTime(1, currTime + duration-ctx.FADE_TIME);
    gainNode.gain.linearRampToValueAtTime(0, currTime + duration);
    // Schedule a recursive track change with the tracks swapped.
    var recurse = arguments.callee;
    ctx.timer = setTimeout(function() {
    recurse(bufferLater, bufferNow);
    }, (duration - ctx.FADE_TIME) - 1000);
}

Web Audio API には、便利な RampToValue メソッドのセットが用意されており、 パラメータの値を徐々に変更していく linearRampToValueAtTimeexponentialRampToValueAtTime

遷移タイミング関数は、組み込みの線形関数から (上記のように指数関数的)の場合は、独自の値も setValueCurveAtTime 関数を使って値の配列を曲線で表します。

サウンドにシンプルなフィルタ効果を適用する

<ph type="x-smartling-placeholder">
</ph> BiquadFilterNode を含む音声グラフ
BiquadFilterNode を含む音声グラフ

Web Audio API を使用すると、あるオーディオ ノードから別のオーディオ ノードに音声をパイプで転送できます。 処理が複雑になりがちで、処理が複雑になりがち 効果音を追加できます

そのためには、音声と音声の間に BiquadFilterNode を配置する方法があります。 定義できます。このタイプのオーディオ ノードでは、さまざまな処理を実行できます。 低次フィルタを使用でき、グラフィック イコライザーや より複雑な効果を表現できます。主に、画像のどの部分を どの周波数スペクトルで抑えるかを指定できます

サポートされているフィルタのタイプは次のとおりです。

  • ローパス フィルタ
  • ハイパス フィルタ
  • バンドパス フィルタ
  • ローシェルフ フィルタ
  • ハイシェルフ フィルタ
  • ピーキング フィルタ
  • ノッチフィルタ
  • オールパス フィルタ

どのフィルタにもパラメータが含まれており、 ゲイン、フィルタを適用する頻度、品質係数です。 ローパス フィルタは、低い周波数帯を維持し、高い周波数帯を破棄 あります。ブレークオフ ポイントは、周波数の値、 Q 係数は単位なしであり、モデルの形状を決定します。 表示されます。ゲインは、ローシェルフ / ゲインなどの特定のフィルタにのみ影響し、 重要な役割を果たします

単純なローパス フィルタを設定して、 音声のサンプル:

// Create the filter
var filter = context.createBiquadFilter();
// Create the audio graph.
source.connect(filter);
filter.connect(context.destination);
// Create and specify parameters for the low-pass filter.
filter.type = 0; // Low-pass filter. See BiquadFilterNode docs
filter.frequency.value = 440; // Set cutoff to 440 HZ
// Playback the sound.
source.noteOn(0);

一般的に、高い頻度で機能させるには、頻度のコントロールを微調整する必要があります。 人間の聴覚自体も同じ原理で機能するため、対数スケール (つまり、A4 は 440 Hz、A5 は 880 Hz です)。詳しくは、 FilterSample.changeFrequency 関数(上記のソースコード リンク内)

最後に、サンプルコードを使用すると、 AudioContext グラフを動的に変更します。接続を解除できます node.disconnect(outputNumber) を呼び出してグラフから AudioNode。 たとえば、グラフをフィルタを通過し、 直接接続する場合、次のことができます。

// Disconnect the source and filter.
source.disconnect(0);
filter.disconnect(0);
// Connect the source directly.
source.connect(context.destination);

もっと聞く

音声の読み込みや再生など、API の基本についてはすでに説明しました。 提供しますゲインノードとフィルタを含む音声グラフを作成しました。 スケジュール設定されたサウンドとオーディオ パラメータを微調整して、一般的なサウンドを有効にする できます。これで、優れたウェブを構築する準備が整いました。 あります。

インスピレーションを得ようとしているデベロッパーの多くは、 お疲れさまでした。私のお気に入り 含める:

  • AudioJedit: ブラウザ内音声スプライス ツールで、 SoundCloud のパーマリンク。
  • ToneCraft: 音声を作成するサウンド シーケンサー ブロックを積み重ねていきます。
  • Plink: ウェブ オーディオとウェブを使用したコラボレーション指向の音楽制作ゲーム ソケット。