WebAudio计时如何工作?使用setInterval是一个糟糕的解决方案吗?

时间:2017-02-08 21:59:11

标签: javascript html5 timer web-audio synthesizer

我正在尝试使用WebAudio API制作合成器/音序器。大多数人试图制作可以播放由MIDI等音符和事件组成的歌曲来控制合成器的多个声道。但我仍然需要解决时间问题。

我已经阅读了WebAudio API的教程,但我不太明白时序/调度/时钟是如何工作的。起初我做了一个polyphonic synthesizer,为按键演奏音符,这不需要考虑时间。然后,我使用setInterval以特定的时间间隔使振荡器播放成一组音符。但是,当我在谷歌浏览器中切换标签时,我注意到 过去 ,播放速度明显变慢,我认为资源消耗较少 - 但其他合成库没有这个问题。另外,我只能假设使用setInterval对于平滑(缓冲正确的字?)回放来说并不是很好,特别是在考虑ADSR包络振荡器时。

从我正在阅读的内容来看,WebAudio API有一个不断增加的currentTime计时器变量。但是如果音符存储在数组中并且我想以设定的速率循环它,那么WebAudio计时器如何被操纵以在设定的速率上迭代数组?我的setInterval solution (volume warning)根本没有考虑WebAudio计时器,只需用voice()拨打setInterval即可播放音符,覆盖最后播放的语音。

是否有更好或更有效的方法来播放/循环除setInterval以外的一系列音符?

只是更新澄清:当我写这个问题时,我正在使用setInterval以固定的时间间隔播放一系列音符(例如,未安排的 - 不断启动/停止振荡器)并且想知道更可靠的方式来演奏音符。我发现更好的解决方案是在setValueAtTime上使用osc.frequency以及GainNode。对于简单的原型合成器,这很有效,但更高级的合成器可以使用osc.startosc.stop上的计时器。问题是循环播放歌曲。为了循环,我需要不断安排更多音符,以便在歌曲结束时重新开始。我可以使用setInterval安排整个歌曲循环,但仍需要留出时间播放歌曲setInterval(甚至是Web Workers'{{1}例如,当选项卡处于非活动状态时,可以减慢调用速度。 setInterval的时钟甚至不可靠,所以我只需检查onmessage每5ms,并安排条件是否满足。这种方法可能效率不高。 What I have so far

1 个答案:

答案 0 :(得分:3)

几年前我写了这篇文章:https://www.html5rocks.com/en/tutorials/audio/scheduling/。它涉及Web音频计时器和setInterval之间的差异;简而言之,你不能操纵时间"在网络音频时钟中,它由声卡中的硬件时钟驱动。但是,您可以使用setInterval作为非常抖动/较慢的周期提醒来安排事件在其时间范围内发生,以安排新事件。

至于你的切换标签问题,这是一个1Hz的速率限制器,大多数现代浏览器必须避免使用setInterval作为渲染定时器的人的电力成本(例如setInterval,间隔为16ms,以尝试安排每一帧视频)。您可以通过两种方式避免它 - 使用Web Workers进行黑客攻击,我在节拍器演示中使用它(https://github.com/cwilso/metronome),或者当窗口失去焦点(在窗口对象上触发onb​​lur事件)时可以挂钩一次开始安排超过1个事件。唯一的问题是当窗口再次获得焦点时(onfocus事件在窗口对象上触发),您将在Web Audio中安排最多一秒钟的事件 - 您无法切换回到窗口,立即点击"停止",例如

setInterval本身并不是重复节奏的音乐定时的一个很好的解决方案,因为当主线程中有大量其他内容(包括垃圾收集)时它会抖动(即被延迟)。您将开始听到抖动,尤其是在能力较弱的CPU上。