ウェブ音声の更新(Chrome 49)

Chris Wilson 氏
Chris Wilson

Chrome では、Web Audio API のサポートを継続的かつ密に改善してきました。Chrome 49(2016 年 2 月時点でベータ版で提供され、2016 年 3 月に Stable 版になる予定です)では、仕様を追跡するためにいくつかの機能が更新され、新しいノードが 1 つ追加されました。

decodeAudioData() が Promise を返すようになりました

AudioContextdecodeAudioData() メソッドが Promise を返すようになり、Promise ベースの非同期パターン処理が可能になりました。decodeAudioData() メソッドは常に成功とエラー コールバック関数をパラメータとして受け取ります。

context.decodeAudioData( arraybufferData, onSuccess, onError);

代わりに標準の Promise メソッドを使用して、音声データをデコードする非同期の性質を処理できるようになりました。

context.decodeAudioData( arraybufferData ).then(
        (buffer) => { /* store the buffer */ },
        (reason) => { console.log("decode failed! " + reason) });

1 つの例では冗長に見えますが、Promise を使用すると、非同期プログラミングがより簡単で一貫性の高いものになります。互換性を確保するため、仕様に従って、成功およびエラーのコールバック関数は引き続きサポートされます。

OfflineAudioContext が suspend() と restore() をサポートするようになりました

一見すると、OfflineAudioContext に suspend() があると不思議に思えるかもしれません。結局のところ、オーディオ ハードウェアをスタンバイ モードにするため、suspend()AudioContext に追加されました。これは、バッファにレンダリングするシナリオでは無意味に思えます(もちろん OfflineAudioContext の場合です)。ただし、この機能のポイントは、メモリ使用量を最小限に抑えるために、一度に「スコア」の一部のみを構築できるようにすることです。レンダリングの途中で一時停止している間、追加のノードを作成できます。

たとえば、ベートーヴェンの「月光ソナタ」には 6,500 音ほどの音符が含まれています。 各「音」は、おそらく少なくともいくつかのオーディオ グラフノード(AudioBuffer ノードと ゲイン ノードなど)に分解されます。OfflineAudioContext で 7 分半全体をバッファにレンダリングする場合、これらのノードを一度にすべて作成することはおすすめしません。代わりに、複数の時間セットで作成できます。

var context = new OfflineAudioContext(2, length, sampleRate);
scheduleNextBlock();
context.startRendering().then( (buffer) => { /* store the buffer */ } );

function scheduleNextBlock() {
    // create any notes for the next blockSize number of seconds here
    // ...

    // make sure to tell the context to suspend again after this block;
    context.suspend(context.currentTime + blockSize).then( scheduleNextBlock );

    context.resume();
}

これにより、レンダリングの開始時に事前作成する必要があるノードの数を最小限に抑え、メモリの需要を削減できます。

IIRFilterNode

この仕様では、正確に指定された独自の infinite-impulse-response を作成したいオーディオ マニア向けのノード IIRFilterNode が追加されています。このフィルタは BiquadFilterNode を補完するものですが、フィルタのレスポンス パラメータを完全に指定できます(タイプ、周波数、Q などについて BiquadFilterNode の使いやすい AudioParams を指定することはできません)。IIRFilterNode を使用すると、単一順序フィルタなど、これまで作成できなかったフィルタを正確に指定できます。ただし、IIRFilterNode を使用するには、IIR フィルタの仕組みに関する深い知識が必要です。また、BiquadFilterNodes のようにスケジュールすることもできません。

以前の変更

また、以前実施された改善点もいくつかあります。Chrome 48 では、BiquadFilter ノードの自動化が音声レートで実行され始めました。このために API はまったく変更されていませんが、これはフィルタ スイープがより滑らかに聞こえることを意味します。また Chrome 48 では、接続先のノードを返すことで AudioNode.connect() メソッドにチェーンを追加しました。これにより、次ののように、ノードのチェーンを簡単に作成できます。

sourceNode.connect(gainNode).connect(filterNode).connect(context.destination);

これで終わりです。続けてください!