この大先生の記事を読んで、自分の知ってるWebAudio知識のアップデートをしときたいなーと思って調べたことのメモです。
なので重複する部分もあるけど、+ αな部分もあります。
20191129: あらためて読み直したけど、特に更新すべき部分はない
そもそもAudioWorklet
- `ScriptProcessorNode`の後継
- 重い音声処理をメインスレッドでやりたくないよね
- いちおうAudioスレッドでやってたけど、完全ではなかった
- 今度こそAudioスレッドだけでできるよ
2017年12月の記事なんかこれ・・時代を感じる・・。
コード
まずは使う側。
// app.js // いつものGlobalScope (async function() { // お決まり const ctx = new AudioContext(); // Workerみたく読み込んで使う // このパスはESModules的なパスではなく、ドキュメントルートからのルート await ctx.audioWorklet.addModule('./my-worklet.js') // 使うのに必要なのはノード名だけ const workletNode = new AudioWorkletNode(ctx, 'my-worklet'); // あとは今まで通りのAudioNodeとして使えば良し workletNode.connect(ctx.destination); // どんなAudioParamsにするかも自分で決める workletNode.dummy.value = 1; // MessagePortが生えてるので、直接なんかすることもできる workletNode.port.onmessage = ev => {}; workletNode.port.start(); workletNode.port.postMessage('xxx'); }());
メインのWorklet側。
// my-worklet.js // AudioWorkletGlobalScopeになってる class MyWorkletProcessor extends AudioWorkletProcessor { // AudioParamsの指定 static get parameterDescriptors () { return [{ name: 'dummy', defaultValue: 0.5, minValue: 0, maxValue: 1, automationRate: "k-rate" }]; } // これが本丸 process(inputs, outputs, parameters) { // outputsを、inputsとparameters.dummyでいじる // 生えてるのでよしなに使えばよい this.port.postMessage('x'); return true; } } // WebComponentsみたいに登録する registerProcessor('my-worklet', MyWorkletProcessor);
このへんのAPIの詳しく・サンプルは、冒頭の記事 or 仕様を見るべし。
WASM
`AudioWorklet`ではWASMが使えるぜ的な触れ込みだったと思うので、そこも調べた。
デフォルトでなんかそういう機能があるのではなく、組み合わせて使えるというだけの話。
どうやら2パターンの使い方がある。
- メインスレッドでWASMを`fetch()`してで読み込んで、`port`経由で渡す
- WASMをインスタンスにするのは`AudioWorkletProcessor`側でもできる
- `AudioWorkletProcessor`側で、JSにしたWASMを直接`import`する
どっちを選ぶかは要件次第。
でもほとんど後者なのでは・・?
ということが書いてある記事がこれ。
記事内デモのサンプルコードのリポジトリ。
2018年6月・・。
その他
TypeScript
- 型はまだない
- `AudioWorkletGlobalScope`側がないっぽい
- 中の人の返事待ちだが果たして・・
放置されてる感あるのでPRをいきなり送るのもナァって感じ。