Karplus-Strong Algo中的递归反馈 - 箭头

Lov*_*vaz 5 haskell arrows reactive-programming

我正在尝试使用Euterpea实现最简单的Karplus-Strong算法:

KS算法原理图

我的代码:0.7秒的白噪声爆发

burst :: AudSF () Double
burst = proc () -> do 
   burstEnv <- envLineSeg [1,1,0,0] [0.7, 0, 9.3] -< ()
   noise <- noiseWhite 42 -< ()
   outA -< burstEnv * noise
Run Code Online (Sandbox Code Playgroud)

有问题的部分:

karplus :: AudSF Double Double
karplus = proc input -> do 
  rec  filtered <- filterLowPass -< (delayed, 2000)
       delayed <- delayLine 0.7 -< filtered + input      
  outA -< filtered + input
Run Code Online (Sandbox Code Playgroud)

test1函数应该用几个周期创建一个10秒的文件:

test1 = outFile "test1.wav" 10 $ burst >>> karplus
Run Code Online (Sandbox Code Playgroud)

据我所知,反馈循环应该继续运行.

问题是输入只被延迟并过滤一次.它没有再次进入循环.

我怀疑问题在于我不理解懒惰的评估或价值传递.

Cac*_*tus 2

问题不在于惰性求值或递归箭头;而在于。相反,它的filterLowPass表现不太好burst:它变成了NaN在爆发结束后变得更好。

\n\n

我们可以通过在 GHCi 中运行它来看到:

\n\n
\xce\xbb\xc2\xbb take 15 $ drop 30870 $ Control.SF.SF.run (strip $ burst >>> arr (,2000) >>> filterLowPass) $ repeat ()\n[0.17166330080286152,0.27722776378398983,NaN,NaN,NaN,NaN,NaN,NaN,NaN,NaN,NaN,NaN,NaN,NaN,NaN]\n
Run Code Online (Sandbox Code Playgroud)\n\n

我强烈怀疑这是因为burst它本身在接近尾声时表现得很奇怪:

\n\n
\xce\xbb\xc2\xbb take 15 $ drop 30870 $ Control.SF.SF.run (strip $ burst) $ repeat ()\n[0.5998949495013488,NaN,0.0,-0.0,-0.0,0.0,-0.0,-0.0,0.0,-0.0,-0.0,-0.0,0.0,-0.0,0.0]\n
Run Code Online (Sandbox Code Playgroud)\n\n

我的建议是修复burst它,使其不会生成NaN在末尾生成 a ,然后看看是否可以解决所有问题。0/-0 振荡可能是无害的。

\n\n

尝试修复

\n\n

我对 Euterpea 或声音合成一无所知;然而,通过使用非常短但非 0 从 1 到 0 的过渡时间burstEnv,我能够摆脱NaNs。通过进一步减少突发和延迟线的长度,我认为我得到了接近所需的“弦状”声音的东西:

\n\n
burst :: AudSF () Double\nburst = proc () -> do\n   burstEnv <- envLineSeg [1,1,0,0] [0.01, 0.000001, 9.3] -< ()\n   noise <- noiseWhite 42 -< ()\n   outA -< burstEnv * noise\n\nkarplus :: AudSF Double Double\nkarplus = proc input -> do\n    rec delayed <- delayLine 0.01 -< filtered + input\n        filtered <- filterLowPass -< (delayed, 2000)\n    outA -< filtered + input\n
Run Code Online (Sandbox Code Playgroud)\n