网络音频延迟

时间:2020-10-17 16:03:30

标签: web-audio-api

我正在使用klank.dev构建一个简单的Karplus Strong字符串效果。它可以正常工作直到中间C上方的F左右,但不能再高一些。该示例粘贴在下面,您也可以尝试here(空白仅适用于Firefox atm)。

有问题的行是del: Tuple (g'delay 0.00305) (SProxy :: SProxy "combine")。如果您将延迟时间延长,例如0.009,则延迟会降低。但是,如果您将其缩短,即0.002,则在某一点音调将停止上升。

网络音频对反馈循环中使用的延迟是否有严格的下限限制? MDN报告最小值为0.0,该最小值在未用于反馈中时有效,但在反馈循环中我遇到了这个问题。感谢您提供任何见解!

module A.Felicidade.Pluck where

import Prelude
import Data.Symbol (SProxy(..))
import Data.Tuple (Tuple(..))
import Data.Typelevel.Num (D1)
import FRP.Behavior (Behavior)
import FRP.Behavior.Audio (AudioUnit, audioWorkletGenerator, g'add, g'delay, g'gain, graph, runInBrowser, speaker')
import Foreign.Object as O
import Record.Extra (SLProxy(..), SNil)
import Type.Data.Graph (type (:/))
import Math(pi, sin, cos)
import Type.Klank.Dev (Klank, Worklets, klank)

worklets :: Worklets
worklets _ res rej =
  ( do
      res [ "https://klank-share.s3.eu-west-1.amazonaws.com/K16029410960343210.js" ]
  )

scene :: Number -> Behavior (AudioUnit D1)
scene time =
  pure
    $ speaker'
        ( graph
            { aggregators:
                { out: Tuple g'add (SLProxy :: SLProxy ("combine" :/ SNil))
                , combine: Tuple g'add (SLProxy :: SLProxy ("gain" :/ "mic" :/ SNil))
                , gain: Tuple (g'gain 0.9) (SLProxy :: SLProxy ("del" :/ SNil))
                }
            , processors:
                { del: Tuple (g'delay 0.00305) (SProxy :: SProxy "combine")
                }
            , generators:
                { mic:
                    audioWorkletGenerator
                      "klank-lf-burst"
                      (O.union (O.singleton "nsamples" 15.0) (O.singleton "freq" 1.0))
                }
            }
        ) where rad = time * pi

main :: Klank
main =
  klank
    { run = runInBrowser scene
    , worklets = worklets
    }

1 个答案:

答案 0 :(得分:1)

循环(周期)中的DelayNode的延迟被限制为最少1个渲染量子。参见https://webaudio.github.io/web-audio-api/#DelayNode-attributes。一个渲染量子的时间为128 / sampleRate。对于44.1 kHz的采样率大约需要3毫秒。

无法解决此问题,因为WebAudio(当前)以128帧的块工作,如果有循环,则所有块在产生输出之前都需要128帧。

我知道的唯一解决方案是使用AudioWorklet实现图形中处于循环中的部分。这样可以有效地消除图形的循环,因此您可以执行任何操作。