FirefoxでAudio Data APIを使ってリアルタイムにインタラクティブなオーディオ処理をするとき、信号データを書き込むタイミングは自分で制御しないといけません。
制御しないと未来に再生する音がガンガン作られてしまって、UIで操作したのものがなかなか反映されないように聞こえるからです。
audioprocess.js
var audio = new Audio();
audio.mozSetup(channels, samplerate);
var written = 0; // 書き込んだサンプル数
var onaudioprocess = function() {
// ここでタイミング制御を行う (*1)
var offset = audio.mozCurrentSampleOffset(); // 今再生しているサンプル数
if (offset > 0 && written > offset + 16384) {
return;
}
var samples = MAKE_WAVE(); // 信号をつくる
audio.mozWriteAudio(samples); // 書き込む
written += samples.length; // 書き込んだサンプル数を更新
};
// 20msec間隔でオーディオ処理を行う
setInterval(onaudioprocess, 20);
*1 の箇所でタイミングの制御を行います。
上の例では今再生しているサンプル数よりも書き込んだサンプル数が大きすぎる場合は書き込み処理を行わない。などして先に進み過ぎないように調整しています。
注意が必要なのは、ある程度データを書き込まないと再生が始まらず mozCurrentSampleOffset()
が更新されず 0 のまま返ってくる点。しかも環境によって更新されない量が異なっていて、Linux版のFirefoxはかなり遅いです。
なので offset > 0
のように mozCurrentSampleOffset()
の更新が始まったら、タイミング制御を始めるようにしたほうが良さそうです。
でないと書き込んだ量が大きい状態のまま再生が始まらず、いつまでたっても差が埋まらず音が出ないという状態になってしまいます。