ToneJS播放8分音符听感不均的WebAudio时序性能问题咨询
问题原因
- 核心错误是未使用调度回调传入的高精度时间参数:
Tone.Transport.scheduleRepeat给回调函数传入的time参数是WebAudio上下文的高精度绝对时间,不受主线程阻塞影响,但调用synth.triggerAttackRelease时没有传入第三个参数指定发声时间,Tone会默认使用回调执行时刻的当前时间触发声音。而JS回调本身在主线程执行,会受到页面渲染、其他JS任务、IO操作(比如示例中的console.log)的影响,执行时机存在抖动,导致实际发声时间不均。 - 回调内的
console.log本身是高开销的IO操作,会进一步加剧主线程阻塞,放大时间抖动的问题。 - 这个问题完全不属于WebAudio或者JavaScript的性能限制,是API的使用方式错误导致的,WebAudio的音频线程独立于主线程,只要提前把音频事件调度到正确的时间点,就可以实现微秒级的精准时序。
解决方案
- 把回调拿到的
time参数传入triggerAttackRelease,指定精准的发声时间,同时移除回调内不必要的高开销操作:
Tone.Transport.scheduleRepeat(function(time){ // 生产环境移除console.log,仅调试时可临时开启 synth.triggerAttackRelease('C4', '8n', time) }, "8n");
- 如果页面本身负载较高,可以适当调大Tone.Transport的提前调度窗口,给主线程留更多缓冲空间:
// 默认值是0.1(单位:秒,即提前100ms调度事件),可根据情况调整到0.2~0.3 Tone.Transport.lookAhead = 0.2;
- 如果是长序列的音符播放,建议提前把所有音符事件预调度到Transport中,不要依赖
scheduleRepeat的实时回调生成事件,进一步降低主线程压力。
修改完成后即可获得完全均匀的播放效果,三类浏览器均能达到非常精准的时序表现。
内容的提问来源于stack exchange,提问作者drenl
相关产品推荐
相关产品推荐

