取消预定的网络音频

Cancelling scheduled Web audio

我已经了解了 A Tale of Two Clocks 的全部内容,它描述了一种通过实时编辑为 Web 音频应用程序(如鼓机)安排时间的方法,但我对一个关键方面感到困惑。

该技术的一个主要动机是一旦 AudioBufferSourceNode 被安排与 start() 一起玩,就不能取消。

但是如果我在 AudioBufferSourceNodes 预定播放之前调用 stop(),它就不会播放,因此可以取消。那么为什么需要这种技术呢?我错过了什么?

主要优点是 audioBufferSourceNode.start(someTimeInTheFuture) 样本准确。这就是为什么它优于根本不准确的 setTimeout(() => audioBufferSourceNode.start(), someTimeInTheFuture) 的原因。

由于网络音频的内部运作方式API,如果可能的话,提前安排一些事情总是一个好主意。每当在 AudioBufferSourceNode 上调用 start() 时,该命令必须从主线程传输到音频线程,然后在音频线程中执行。这需要一些时间,这意味着如果您想立即开始某些事情,它可能会在音频线程上到达得太晚。

我认为 OP 在问 "why don't I just schedule all the notes in advance, and then cancel all the remaining ones (via .stop()) if I want to stop?"

实际上你可以做到这一点。对于小序列,这可能是一种不错的方法。然而:

如果你想要取消它们的能力,你需要分别挂起对每个 AudioBufferSourceNode 的引用 - 单独的 16 音符踩镲模式,在 140bpm 下,是 2800 个音符(=AudioBufferSourceNodes)5 -分钟歌曲。这也是(对于整首歌曲)可能要同时分配和取消分配的大量内存。对于较长的序列,它可能不那么吸引人。

如果您正在对序列播放进行任何实时更改,则尤其如此 - 例如,如果您想要更改速度,则需要取消所有剩余的音符,然后重新安排它们。

我在 ATOTC 中详述的技术的主要动机是在第二部分的末尾:"In short, because you will need the flexibility to change tempo or parameters like frequency or gain (or stop scheduling altogether), you don’t want to push too many audio events into the queue - or, more accurately, you don’t want to look ahead too far in time, because you may want to change that scheduling entirely."虽然我确实提到了取消,但那是事后才想到的,真的。

如果您正在处理相对较短的序列,并且您不关心是否使用了一点额外的内存,那么最简单的做法就是创建一个 GainNode,将其连接到目的地,然后设置所有您的 AudioBufferSourceNodes 连接到该 GainNode。明确不要保留对您的 ABSN 的引用,但要保留对 GainNode 的引用——如果您想取消,只需断开 GainNode 的连接并释放它。没有进一步的发挥到目的地,一切最终都会得到释放。 (我在第二部分也提到了这一点,尽管它可能读起来有点贬义。对于较小的应用程序来说没关系。)