AudioWorkletProcessor: process() メソッド
Please take two minutes to fill out our short survey.
AudioWorkletProcessor
の派生クラスの process()
メソッドは、音声処理器ワークレットの音声処理アルゴリズムを実装します。
このメソッドは AudioWorkletProcessor
インターフェイスには含まれていませんが、AudioWorkletProcessor
の実装はすべて process()
メソッドを用意しなければいけません。
このメソッドは、処理器の対応する AudioWorkletNode
に音声ブロック (rendering quantum とも呼ばれる) が送られてくるたびに、音声レンダリングスレッドから同期で呼ばれます。
すなわち、新しい音声ブロックが処理器で処理可能になるたびに、処理をするために process()
関数が呼ばれます。
メモ: 現在、音声データブロックの長さは常に 128 フレームです。すなわち、入力のそれぞれのチャンネルについて 128 個の 32 ビット浮動小数点数のサンプルが格納されています。しかし、この仕様を変更し、状況に応じて (たとえば、音声ハードウェアや CPU の使用の効率がブロックサイズを大きくすると上がる場合) 音声ブロックのサイズを変えることができるようにする計画がすでに進行中です。このため、特定のサイズを仮定するのではなく、常にサンプル配列のサイズをチェックしなければなりません。
このサイズは時間とともに変わることも許される可能性があるので、最初のブロックだけを見てサンプルバッファーのサイズが常に同じだと仮定してはいけません。
構文
process(inputs, outputs, parameters)
引数
inputs
-
ノードに接続されている 入力 の配列です。この配列のそれぞれの要素は チャンネル の配列です。それぞれの チャンネル は 128 個のサンプルが入った
Float32Array
です。たとえば、inputs[n][m][i]
はn
番目の入力のm
番目のチャンネルのi
番目のサンプルにアクセスします。それぞれのサンプルの値は
[-1 .. 1]
の範囲です。入力 の数、そしてそれを反映したこの配列の長さはノードの生成時に固定されます。(
AudioWorkletNode
を参照してください) ノードのn
番目の入力に活動中のノードが接続されていない場合は、inputs[n]
は空の配列になります。(0 個の入力チャンネルが利用可能です)各入力の チャンネル の数は
channelCount
およびchannelCountMode
プロパティによって変化する可能性があります。 outputs
-
出力 の配列で、引数
inputs
と似た構造です。process()
メソッドの実行時に値を入れられることを意図しています。各出力チャンネルはゼロで初期化されます。すなわち、出力の配列を変更しない場合は処理器は無音を出力します。 parameters
-
文字列のキーと
Float32Array
の値を持つオブジェクトです。parameterDescriptors
ゲッターで定義した独自のAudioParam
それぞれについて、name
がこのオブジェクトのキーとなり、値がFloat32Array
となります。配列に格納する値は、スケジュールされた自動化イベントを考慮して計算されます。パラメーターの自動化レートが
"a-rate"
の場合は、配列には 128 個の値が格納され、現在の音声ブロックのそれぞれのフレームに値が 1 個ずつ対応します。現在のブロックが表す時間中に自動化が行われていない場合は、同じ値を 128 個格納するかわりに、ブロック全体で変わらない 1 個の値が格納されることがあります。自動化レートが
"k-rate"
の場合は、配列には 1 個の値が格納され、この値を 128 個のフレームそれぞれで用います。
返値
ユーザーエージェントの内部ロジックがノードをシャットダウンしても安全だと判断しても AudioWorkletNode
の活動を続けるかを表す boolean
値を返します。
この返値により、処理器が AudioWorkletProcessor
とそれを所有するノードの生存期間ポリシーを制御することができます。ブラウザーが返値とノードの状態に基づいてノードを停止すると判断すると、process()
は呼ばれなくなります。
true
を返すことで、ウェブオーディオ API にこのノードの活動を継続させることができます。
false
を返すと、新しい音声データの生成も、処理中の入力からのデータの取得もしていないとき、ブラウザーがノードを終了させることができるようになります。
最もよくみられる音声ノードの種類として、以下の 3 種類があります。
- 出力元。このようなノードを実装している
AudioWorkletProcessor
では、出力を生成している間はずっとprocess
メソッドはtrue
を返すべきです。もう出力を生成しないということがわかったら、このメソッドはできるだけすぐにfalse
を返すべきです。たとえば、AudioBufferSourceNode
を考えてみましょう。この種類のノードのための処理器は、バッファーの再生中はprocess
メソッドはtrue
を返し、バッファーの再生が終わったらfalse
を返し始めるべきです。(同じAudioBufferSourceNode
で再びplay
を呼ぶことはできません) - 入力を変換するノード。このようなノードを実装している処理器は、活動中の入力ノードやノードへの参照があるときガベージコレクトの対象にできるかどうかを判断できるようにするため、
process
メソッドはfalse
を返すべきです。この挙動をするノードの例はGainNode
です。接続されている入力が無くなったらすぐ、参照は残っていても、ゲインを適用する対象が無いので、安全にガベージコレクトの対象にできます。 - 入力を変換するが、テールタイム があるノード。すなわち、入力が切断されたり活動を停止 (0 個のチャンネルを生成する) したりした後もしばらくの間出力を生成するノード。このようなノードを実装している処理器は、(入力に含まれるチャンネルが 0 個になるとすぐに始まる) テールタイム の間は
process
メソッドはtrue
を返すべきです。このようなノードの例はDelayNode
です。このノードにはdelayTime
プロパティに等しい テールタイム があります。
メモ: return
文が無い場合、メソッドは undefined
を返すことになります。これは偽と解釈される値なので、false
を返すのと同じ効果があります。
明示的な return
文を省略すると、ノードが見つけにくい問題を起こす可能性があります。
例外
process()
メソッドはユーザーが実装するので、任意の例外を投げることができます。
補足されないエラーが投げられた場合は、ノードは processorerror
イベントを生成し、その後ずっと無音を出力します。
例
この例では、最初の出力としてホワイトノイズを出力する AudioWorkletProcessor
を作成します。ゲインは customGain
パラメーターで制御できます。
class WhiteNoiseProcessor extends AudioWorkletProcessor {
process(inputs, outputs, parameters) {
// 最初の出力を取得する
const output = outputs[0];
// 各チャンネルにランダム値にゲインを掛けたものを入れる
output.forEach((channel) => {
for (let i = 0; i < channel.length; i++) {
// 各サンプル用のランダム値を生成する
// Math.random の値域は [0; 1) だが、ここでは [-1; 1] が欲しい
// 1 ちょうどにはならないが、簡単のためここではよい
channel[i] =
(Math.random() * 2 - 1) *
// この配列には、自動化が進行中か、
// そして自動化レートが k-rate なのか a-rate なのかにより、
// 1 個または 128 個の値が格納されている
(parameters["customGain"].length > 1
? parameters["customGain"][i]
: parameters["customGain"][0]);
}
});
// これは自身で出力を生成する音源ノードなので、
// メインスレッドから参照されていなくても、
// 間違ってガベージコレクトされないように true を返す
return true;
}
// process メソッドで用いる customGain パラメーターを定義する
static get parameterDescriptors() {
return [
{
name: "customGain",
defaultValue: 1,
minValue: 0,
maxValue: 1,
automationRate: "a-rate",
},
];
}
}
仕様書
Specification |
---|
Web Audio API # process |
ブラウザーの互換性
これはブラウザーが提供するメソッドではなく、クライアントコードで書く必要があるコールバックメソッドです。