それは AudioBufferSourceNode, OscillatorNode, ConstantSourceNode を使う方法です。 これらは音声データや正弦波、定数値を再生するためのノードですが、 これらには s秒後に再生を開始し、t秒後に再生を止める機能が備わっています。
上記を用いてタイマー機能を作成すると、方法によって様々な精度の違いが生まれます。 精度を検証するためのアプリ js-timer-benchmark はこちら。 Audio 関連のコードは Node/Deno では動かないのでブラウザ上で確認するしかありません。 まずはフォアグラウンドで初回起動時の結果がこちら。
method | 1sec error | 2sec error |
---|---|---|
setTimeout | 0.9ms | 0.6ms |
setInterval (10) | 0.8ms | 0.4ms |
setInterval (100) | 0.6ms | 0.4ms |
AudioBufferSourceNode | 106.1ms | 2.2ms |
OscillatorNode | 6.2ms | 14.3ms |
ConstantSourceNode | 6.6ms | 20.2ms |
requestAnimationFrame | 9.7ms | 8.8ms |
フォアグラウンドで2回目以降時の結果がこちら。
method | 1sec error | 2sec error |
---|---|---|
setTimeout | 0.7ms | 0.4ms |
setInterval (10) | 0.6ms | 0.4ms |
setInterval (100) | 0.4ms | 0.5ms |
AudioBufferSourceNode | 8.6ms | 5.8ms |
OscillatorNode | 9.3ms | 19.1ms |
ConstantSourceNode | 10.1ms | 20.4ms |
requestAnimationFrame | 1.0ms | 0.1ms |
バッググラウンドで初回起動時の結果がこちら。
method | 1sec error | 2sec error |
---|---|---|
setTimeout | 998.9ms | 900.6ms |
setInterval (10) | 0.5ms | 999.7ms |
setInterval (100) | 998.8ms | 999.5ms |
AudioBufferSourceNode | 89.9ms | 5.8ms |
OscillatorNode | 10.7ms | 19.9ms |
ConstantSourceNode | 3.9ms | 20.2ms |
requestAnimationFrame | 34985.8ms | 30565.4ms |
バックグラウンドで2回目以降時の結果がこちら。
method | 1sec error | 2sec error |
---|---|---|
setTimeout | 998.4ms | 390.6ms |
setInterval (10) | 1000.2ms | 0.4ms |
setInterval (100) | 999.5ms | 999.1ms |
AudioBufferSourceNode | 8.0ms | 1.3ms |
OscillatorNode | 9.7ms | 19.6ms |
ConstantSourceNode | 10.1ms | 19.5ms |
requestAnimationFrame | 14580.2ms | 2245.5ms |
まとめると、requestAnimationFrame はバックグラウンドでは停止しているようなもので使いものになりません。 setTimeout, setInterval はバックグラウンドでは非常に遅くなります。 AudioBufferSourceNode, OscillatorNode, ConstantSourceNode は同じ速度で実行できます。 音楽などはバックグラウンドで再生速度が変わったら困るので、それを考慮しているのだと思います。 AudioBufferSourceNode は初回起動時になぜか遅いですが、それ以降は高速です。 つまり、音声処理のタイマーや、バックグラウンドでミリ秒単位の高精度タイマーが必要なら、 AudioBufferSourceNode を使いましょうという結論になりそうです。 とはいえ setInterval より精度が低いのは意外でした。
ちなみにウィンドウが非アクティブのときにどのように動作するかは、Window: setTimeout() メソッド - Web API | MDN にまとまっています。 setTimeout/setInterval はベンチマークの結果通り、1秒単位で処理するようです。 記述を読む限り AudioContext を使った手法はおそらく処理速度が落ちたりはしないですが、特にそれが定まっている訳でもないみたいです。
0 件のコメント:
コメントを投稿