1

I am using klank.dev to build a simple Karplus Strong string effect. It works ok up until around F above middle-C but can't get any higher. The example is pasted below, and you can try it here as well (klank only works on Firefox atm).

The line in question is del: Tuple (g'delay 0.00305) (SProxy :: SProxy "combine"). If you make the delay longer, ie 0.009, it gets lower as expected. But if you make it shorter, ie 0.002, at a certain point the pitch stops going up.

Does web audio have a hard lower limit for delays used in feedback loops? MDN reports that the minimum value is 0.0, which works when not used in feedback, but in a feedback loop I'm hitting this problem. Thanks for any insights!

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 Answer 1

2

A DelayNode in a loop (cycle) has its delay clamped to a minimum of 1 render quantum. See https://webaudio.github.io/web-audio-api/#DelayNode-attributes. The time for one render quantum is 128 / sampleRate. That's about 3 ms for a sample rate of 44.1 kHz.

There's no way to work around this because WebAudio (currently) works in blocks of 128 frames and if you have a cycle, all blocks need 128 frames before producing an output.

The only solution I know of is to implement the part of your graph that's in a cycle using an AudioWorklet. This, effectively, removes the cycle fro m the graph so you can whatever you need to do.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.