AudioWorkletの使い方 [Web Audio API]
AudioWorkletとAudioWorkletProcessorの使い方です。
AudioWorkletProcessorでは波形の生データをリアルタイムで編集可能です。Web Workerのようになっていますのでメインスレッドとは別のスレッドで実行されます。メッセージ(変数)の受け渡しも可能です。
デモ
リアルタイムに波形データを編集して音量を変更します。
再生ボタンを押した後に次を操作してださい。
5
ソースコード
ローカル環境でこのコードを実行するとエラーになります。ソースコードはサーバにアップロードして下さい。また、コードを変更した場合は「Ctrl+F5」で完全にキャッシュを削除してからテストしてください。
[demo.html]
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> </head> <body> <audio id="myAudio" src="voice.mp3"></audio> <button onclick="play();">再 生</button> <button onclick="stop();">停 止</button><br> <br>再生ボタンを押した後に次を操作してださい。<br> <input type="range" id="range_myParam" min="1" max="10" value="5" onchange="onChange();"> <span id="msg_myParam">5</span><br> <br> <button onclick="add();">AudioWorkletProcessorで3 +5をしてみる</button> <script> var audioCtx; var audioSourceNode; var workletNode; var tracks; var audioEle; var wm = new WeakMap(); var firstFlag = true; window.onload = function(){ audioEle = document.getElementById('myAudio'); } function play(){ if(firstFlag){ // AudioContextの生成 audioCtx = new AudioContext(); firstFlag = false; if ('audioWorklet' in audioCtx){ }else{ alert('お使いのブラウザはAudioWorkletに対応していません。'); } } modann(); } function stop(){ audioEle.pause(); if(workletNode){ workletNode.port.postMessage({"state":"exit"}); } } async function modann(stream){ // MediaElementAudioSourceNodeの生成 if(audioSourceNode){ audioSourceNode.disconnect(); } if (wm.has(audioEle)) { audioSourceNode = wm.get(audioEle); } else { console.log(1); audioSourceNode = audioCtx.createMediaElementSource(audioEle); wm.set(audioEle, audioSourceNode); } // AudioWorkletの読み込み await audioCtx.audioWorklet.addModule("modan.js"); // AudioWorkletNodeを取得する if(workletNode){ workletNode.disconnect(); } workletNode = new AudioWorkletNode(audioCtx,"MyWorklet"); // メッセージの受け取り workletNode.port.onmessage = function(e){ alert(e.data.result); console.log(e.data); }; workletNode.port.start(); workletNode.port.postMessage({"state":"init","sampleRate":audioCtx.sampleRate, "myParam":document.getElementById('range_myParam').value}); audioSourceNode.connect(workletNode); workletNode.connect(audioCtx.destination); audioEle.play(); } function onChange(){ document.getElementById('msg_myParam').innerHTML = document.getElementById('range_myParam').value; if(workletNode){ workletNode.port.postMessage({"myParam":document.getElementById('range_myParam').value}); } } function add(){ if(workletNode){ workletNode.port.postMessage({"state":"add","a":3,"b":5}); } } </script> </body> </html>
[modan.js]
class MyWorklet extends AudioWorkletProcessor { // コントラスタ constructor (options) { super(options); this.port.onmessage = event => { if (event.data.state){ this.state = event.data.state; } if (event.data.sampleRate){ this.sampleRate = event.data.sampleRate; } if (event.data.a){ this.a = event.data.a; } if (event.data.state){ this.b = event.data.b; } if (event.data.myParam){ this.myParam = event.data.myParam; } } this.port.start(); } // ココに波形の生データが出力される process (inputs, outputs, parameters) { console.log("実行中"); // 波形データの編集 let input = inputs[0]; let output = outputs[0]; for (let channel = 0; channel < output.length; ++channel) { for (let i = 0; i < output[channel].length; ++i) { output[channel][i] = input[channel][i] * this.myParam/10; } } // メソッドのテスト if (this.state == "add"){ this.port.postMessage({'result': this.add(this.a,this.b)}); this.state = ""; } // 終了判定 if (this.state == "exit"){ console.log("終了"); // 終了 return false; }else{ // 次の生データを受け取る return true; } } // オリジナルのメソッド add(a,b) { return a + b; } } // プロセッサーの登録 registerProcessor("MyWorklet", MyWorklet);
注意事項
AudioWorkletは2019年2月現在ではChromeのみ対応しています。
パソコン内の音声を録音する音声録音くんを製作中にAudioWorklet/AudioWorkletProcessorをテストしていたのですが、稀にわかずかな音が途切れるバグがあるようです。現状ではcreateScriptProcessor(scriptProcessorNode)の方が安定しています。
プログラム上ではcreateScriptProcessor()を優先して、廃止された場合は自動的にAudioWorklet/AudioWorkletProcessorを使用するようにした方が良いです。
参考サイト
関連記事
前の記事: | Failed to execute 'createMediaElementSource' on 'AudioContext': HTMLMediaElement already connected previously to a different MediaElementSourceNode |
次の記事: | Waveファイルのボリューム(音量)を変更する [WAVE.js] |