3

我正在使用 Web Audio API 来显示正在播放的音频的可视化。我有一个控制播放的元素,然后我通过从该元素创建一个节点将<audio>它连接到 Web 音频 API 。然后将其连接到 a和 an 。设置然后将 连接到。MediaElementSource<audio>GainNodeAnalyserNodeAnalyserNodesmoothingTimeConstant0.6GainNodeAudioContext.destination

然后我调用我的音频处理函数:onAudioProcess(). 该函数将使用以下方法不断调用自身:

audioAnimation = requestAnimationFrame(onAudioProcess);

该函数使用音频中的AnalyserNodeto getByteFrequencyData,然后循环遍历(现在已填充)并在元素的 2d 上下文中Uint8Array绘制每个频率幅度。<canvas>这一切都很好。

我的问题是,当您暂停<audio>元素时,我的onAudioProcess函数会继续循环(通过请求自身的动画帧),这会不必要地占用 CPU 周期。我可以cancelAnimationFrame(audioAnimation),但这会在画布上留下最后绘制的频率。我也可以通过调用画布的 2d 上下文来解决这个问题,但与仅让音频处理循环继续(由于.clearRectsmoothingTimeConstant

所以我最终做的<audio>是在取消动画帧之前在暂停时设置超时。这样做我能够在没有音频播放时节省 CPU 周期,并且我仍然能够保持平滑降低<canvas>.

我的问题:如何根据AnalyserNode's 的smoothingTimeConstant值准确计算频率幅度为 255 达到 0(范围为 0-255)所需的毫秒数,以便我可以正确设置超时以取消动画帧?

4

1 回答 1

2

根据我对规范的阅读,我认为您会这样理解:

var val = 255 
  , smooth = 0.6
  , sampl = 48000
  , i = 0
  , ms;
for ( ; val > 0.001; i++ ){
  val = ( val + val * smooth ) / 2;
}
ms = ( i / sampl * 1000 );

问题是,通过这种平均,你永远不会真正降到零——所以循环条件有点随意。您可以使该数字更小,并且如您所料,值ms会变大。

无论如何,我可以在这里完全脱离基地。但是快速浏览一下实际的 Chromium 源代码似乎可以确认这就是它的工作原理。虽然我会第一个承认我的 C++ 很糟糕。

于 2013-03-21T19:53:23.793 回答