在网络音频中,使用 .value(x) 和 setValueAtTime(x, context.currentTime) 有什么区别?

In web audio, what's the difference between using .value(x) and setValueAtTime(x, context.currentTime)?

我正在修改一个delayNode的delayTime音频参数。我试过直接使用值 属性,如:

delayNode.delayTime.value = x

还有 - 我认为是等效的 - setValueAtTime 方法与上下文的当前时间:

delayNode.delayTime.setValueAtTime(x, context.currentTime)

查看网络音频规范 here,我在音频参数的 value 部分读到:

The effect of setting this (.value) attribute is equivalent to calling setValueAtTime() with the current AudioContext's currentTime and the requested value.

尽管如此,我注意到直接使用 .value 会导致很大的音频故障,而 .setValueAtTime 的噪音要小得多。您可以通过单击按钮在这两个 jsFiddles 中听到这个声音(顺便说一句,它很吵):

我的问题是:使用value属性和使用.setValueAtTime与当前时间有什么区别?他们为什么不同?是什么导致毛刺出现在一个而不是另一个?

您听到的差异是因为 Chrome 团队没有删除 Chris Rogers 最初放入实施中的解压缩。 Dezippering是平滑参数变化的一般过程;例如您可以使用小 t 调用 setTargetAtTime,而不是实际直接更改值;然后值变化平滑。

对于 delayTime,这尤其成问题,因为任何更改都可能导致极端的故障。 (例如,增益参数的更改可能会导致故障,但它们可能不那么引人注目。)

Chris 的原始实现为所有参数内置了解压缩功能,因此参数更改在默认情况下是平滑的 - 简而言之,当您更改 .value 时,它​​并不是真的立即更改值。然而,这会导致某些参数出现问题(例如,平滑振荡器上的频率参数会产生类似滑音的效果,这通常是不希望出现的)。最终,经过多次讨论 (https://github.com/WebAudio/web-audio-api/issues/76),Web 音频工作组决定解压缩不应该是自动的(毕竟,您始终可以使用 setTargetAtTime 平滑参数); Chromium 团队只需要将其从代码中删除即可。 (显然 Firefox 也没有删除他们的解压缩。)

在您的特定示例中,您对 delayTime 进行了极端更改 - 四秒的更改 - 并且它在非常短的时间内得到 "smoothed"。这类似于使用模拟延迟线,并非常快速地改变 delayTime。 (查看 Korg Monotron Delay 单元的演示,您会听到听起来很熟悉的声音。:)相比之下,瞬时变化(使用 setValueAtTime)只是 "jumping" - 它可能会引起咔哒声,但您不会甚至通过比较听到它。

所以,简而言之:在这种情况下不要使用 .value 来设置 delayTime,如果您希望它平滑,请使用 setTargetAtTime(),如果您希望它是瞬时的,请使用 setValueAtTime()。但是,对 delayTime 参数的巨大更改总是会导致某种问题;你可能真的想在两条延迟线之间交叉淡入淡出或类似的东西。