代码之家  ›  专栏  ›  技术社区  ›  idbehold

计算AnalyserNode的平滑时间常数

  •  3
  • idbehold  · 技术社区  · 13 年前

    我正在使用Web音频API来显示正在播放的音频的可视化。我有一个 <audio> 元素控制播放,然后通过创建一个 MediaElementSource 的节点 <音频> 要素然后连接到 GainNode 和一个 AnalyserNode . The AnalyserNode 's smoothingTimeConstant is set to 0.6 这个 增益节点 然后连接到 AudioContext.destination .

    然后我调用我的音频处理功能: onAudioProcess() 。该函数将不断调用自己,使用:

    audioAnimation = requestAnimationFrame(onAudioProcess);
    

    该函数使用 分析器节点 getByteFrequencyData 从音频,然后循环通过(现在已填充) Uint8Array 并在 <canvas> 元素的2d上下文。这一切都很好。

    我的问题是,当你暂停 <音频> 元素,我的 onAudioProcess 函数继续循环(通过在自身上请求动画帧),这不必要地占用了CPU周期。我可以 cancelAnimationFrame(audioAnimation) 但这就把最后绘制的频率留在了画布上。我能解决 那个 同时拨打 clearRect 在画布的2d上下文中,但与让音频处理循环继续相比,这看起来非常奇怪(因为 平滑时间常数 ).

    所以我最终做的是设置一个超时,当 <音频> 在取消动画帧之前暂停。这样做可以在没有音频播放的情况下节省CPU周期 以及 我仍然能够保持绘制在 <画布> .

    我的问题: 如何根据 分析器节点 平滑时间常数 值,以便我可以正确设置超时以取消动画帧?

    1 回复  |  直到 13 年前
        1
  •  2
  •   Kevin Ennis    13 年前

    根据我对规范的解读,我想你会这样想的:

    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++相当糟糕。