2015-11-03 10 views
5

Ich versuche, die einfachste Version von Karplus-Strong algorithm mit Euterpea zu implementieren:rekursive Feedback in Karplus-Strong Algo - Pfeile

schematic of KS algorithm

Mein Code: 0,7 Sekunden von weißem Rauschen platzen

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

problematischer Teil:

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

test1 Funktion sollte eine Datei von 10 Sekunden mit wenigen Zyklen erstellen:

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

Soweit ich die Rückkopplungsschleife wissen sollte und so weiter laufen.

Das Problem ist der Eingang wird nur verzögert und einmal gefiltert. Es wird nicht wieder in die Schleife gespeist.

Ich vermute, dass das Problem darin liegt, dass ich keine faule Bewertung oder Wertüberschreitung verstehe.

+3

Lazy Evaluation kann beeinflussen, ob ein Programm in einer Endlosschleife steckenbleibt , aber es kann kein Programm ändern, das erfolgreich eine Sache in ein Programm einführt, das erfolgreich ein anderes tut. Ist das Programm blockiert oder einfach falsch? – dfeuer

+0

@dfeuer es ist falsch. Das Ausgangssignal wird nicht in die Schleife eingespeist. – Lovaz

+3

Wenn es falsche Ausgabe produziert, können Sie Faulheit als die Ursache ausschließen. – dfeuer

Antwort

2

Das Problem ist nicht faul Bewertung oder rekursive Pfeile; Es ist eher so, dass filterLowPass sich nicht gut auf burst verhält: es wird NaN, nachdem der Burst beendet ist.

Wir können sehen, dass, indem es z.B. 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] 

ich es vermute stark, weil burst sich seltsam nahe seinem Ende verhält:

λ» 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] 

Mein Vorschlag burst so zu fixieren, dass es nicht ein NaN an seinem Ende generiert, und dann schau, ob das alles behebt. Die 0/0-Oszillation ist wahrscheinlich harmlos.

Versuch Befestigungs

Ich habe keine Ahnung von entweder Euterpea oder Klangsynthese; Durch Verwendung einer sehr kurzen, aber nicht 0-Übergangszeit von 1 zu 0 für burstEnv konnte ich die NaN s loswerden. Indem ich die Länge des Bursts und der Verzögerungsleitung weiter reduziere, denke ich, dass ich etwas habe, das dem gewünschten "stringartigen" Sound nahe kommt:

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