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

时间:2015-11-03 01:49:42

标签: haskell reactive-programming arrows

我正在尝试使用Karplus-Strong algorithm实现最简单的Euterpea版本:

schematic of KS algorithm

我的代码: 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

有问题的部分:

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

test1函数应创建一个10秒的文件,只需几个周期:

test1 = outFile "test1.wav" 10 $ burst >>> karplus

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

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

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

1 个答案:

答案 0 :(得分:2)

问题不是懒惰评估或递归箭头;相反,filterLowPassburst上的行为并不好:在爆发结束后它变为NaN

我们可以看到通过运行它,例如在GHCi:

λ» take 15 $ drop 30870 $ Control.SF.SF.run (strip $ burst >>> arr (,2000) >>> filterLowPass) $ repeat ()
[0.17166330080286152,0.27722776378398983,NaN,NaN,NaN,NaN,NaN,NaN,NaN,NaN,NaN,NaN,NaN,NaN,NaN]

我强烈怀疑这是因为burst本身在其结尾附近表现得很奇怪:

λ» take 15 $ drop 30870 $ Control.SF.SF.run (strip $ burst) $ repeat ()
[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]

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

尝试修复

我不知道Euterpea或声音合成;但是,通过使用burstEnv的从1到0的非常短但非0的转换时间,我能够摆脱NaN s。通过进一步减少突发和延迟线的长度,我想我得到的东西接近所需的&#34;字符串式&#34;音:

burst :: AudSF () Double
burst = proc () -> do
   burstEnv <- envLineSeg [1,1,0,0] [0.01, 0.000001, 9.3] -< ()
   noise <- noiseWhite 42 -< ()
   outA -< burstEnv * noise

karplus :: AudSF Double Double
karplus = proc input -> do
    rec delayed <- delayLine 0.01 -< filtered + input
        filtered <- filterLowPass -< (delayed, 2000)
    outA -< filtered + input