Recursive feedback in Karplus-Strong Algo - arrows

I am trying to implement the simplest version of the Karplus-Strong algorithm using Euterpea :

KS algorithm diagram

My code: 0.7 seconds white noise burst

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

problematic part:

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

The test1 function should create a file in 10 seconds with several cycles:

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

As far as I know, the feedback loop should go on and on.

The problem is that the input is only delayed and filtered once. It does not cycle again.

I suspect that the problem is that I do not understand lazy appreciation or transfer of value.

+5
source share
1 answer

The problem is not lazy pricing or recursive arrows; rather, it is that filterLowPass does not behave well on burst : after the package finishes, NaN ends.

We see that, executing it, for example, in 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] 

I strongly suspect that this is because burst itself behaves strangely near its end:

 ฮปยป 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] 

My suggestion is to fix burst so that it does not generate NaN at the end, and then see if that fixes everything. The 0 / -0 oscillation is probably harmless.

Attempt to fix

I know neither of Euterpea, nor of sound synthesis; however, using a very short, but non-0 transition time from 1 to 0 for burstEnv , I was able to get rid of NaN s. To further reduce the packet length and delay line, I think I have something that is close to the desired "string" sound:

 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 
+2
source

Source: https://habr.com/ru/post/1235073/


All Articles