English
Johannes Kreidler Komponist

wavgorithm

 

Bei diesem Programm, erstellt mit pd, handelt es sich um einen Synthesizer, der Wellenformen algorithmisch generiert.

Mir kam bei der Programmierung von gesticulator die Überlegung, Signale nicht mit Oszillatoren zu erzeugen, sondern durch Algorithmen in der nonsignal-domain. Dafür war zunächst eine gründliche empirische Untersuchung der Darstellungen verschiedenster Klänge auf dem Oszilloskop nötig. Vorerst beschränkte ich mich auf die Nachbildung der bekannten einfachen Wellenformen wie Sinus, Sägezahn etc., komplexere wie Akkorde oder dynamischere wurden nicht untersucht, können aber sehr wohl mit dem Programm erzeugt werden. Insofern ist die Arbeit in solcher alternativen Klangsynthese vor allem empirisch, wie es allgemein bei Waveshaping bekanntlich der Fall ist.

Als Ziel galt mir, nicht gänzlich neue Klänge, jedoch Varianten bekannter Formen zu erzeugen, die sich nicht mit den gängigen Modulationsverfahren von verschiedenen Oszillatoren erstellen lassen. Der erste Schritt war: Ein Zufallsgenerator erzeugt eine Reihe l von 100 Punkten zwischen -1 und 1. Diese werden in einem Array gespeichert und dann als Samples fortweg von einem Phasor ausgelesen. Dadurch bekommen wir ein periodisches Signal mit der Frequenz Samplerate/l, also in dem Beispiel von 441 Herz. Da die Kurve sehr zackig ist, ist der Obertongehalt dieses Tones ziemlich hoch (So ergibt zum Beispiel eine riesige Periode von 100000 Samples, allesamt zufällig gewählt und nicht interpoliert, annähernd ein weisses Rauschen, das ja ebenfalls (in DSP) nichts anderes als kontinuierliche Zufallszahlen zwischen -1 und 1 darstellt. Da dies einer Frequenz von 0.441 Hz entspricht, befinden wir uns weit unterhalb der Schwelle von Rhythmus- zur Tonhöhenwahrnehmung. Indes wird dieser Rhythmus ebenfalls nicht mehr erkannt aufgrund des chaotischen Klangresultats.). Nun kann diese Kurve weicher gemacht werden, in dem die 100 Punkte auseinandergezogen und zwischen ihnen mit j Punkten interpoliert wird. Je höher j, desto weicher und sinusförmiger die Welle. Es sei darauf hingewiesen, dass zwischen Periodenlänge und Abspielfrequenz fortan unterschieden werden kann. So kann der abtastende Phasor in der Frequenz von 1 erhöht oder reduziert werden; Samplerate/l markiert dann den Wechsel zu extrapolierendem Abspielen.

Als nächstes kann auch die Dichte der Interpolation algorithmisch verändert werden. Sie läßt sich aus einer gegebenen Grenze jedesmal neu bestimmen. Dann kann unterschieden werden zwischen steigend und fallend. Hier ist nun die Einführung von Eckbestimmungen der Welle sinnfällig. Dem Nyquist-Theorem zufolge sind für die Darstellung einer Welle mindestens 2 Punkte erforderlich. Entsprechend kann in Wavgorithm für die 2 Punkte Rahmendaten bestimmt werden, zwischen denen der Zufallsgenerator Werte bestimmt. Zusätzlich ist ein in der Länge bestimmbares oberes und unteres Plateau einfügbar.

Bsp. algorithmisch variierte Rechteck-Schwingung.

Doch zurück zur unterschiedlichen Interpolation, je nach positiver oder negativer Steigung: Wird beispielsweise für steigende Interpolation j=5 und für fallend j=1 gewählt, nähern wir uns der Form einer Sägezahnkurve an. Außerdem kann zwischen 2 verschiedenen Interpolationsmethoden gewählt werden: linear oder sinusoid.

Bsp. Unterschied lineare und sinusoide Interpolation.

So habe ich verschiedene Algorithmen mit Variablen bestimmt, die verschiedenen bekannten Wellenformen entlehnt sind: Sinus, Sägezahn, Rechteck, Dreieck, Impuls. Zuletzt kann über das generierte Sample noch ein Window gelegt werden, um Klicks am Anfang und Ende zu vermeiden. Hierfür habe ich, neben der ungefensterten Version (none) eine Rampe angeboten (übrigens mit gesticulator schnell erstellt), die ich "crown" nenne, da sie ledlich am Anfang und Ende kurz von 0 bzw. zu 0 führt; dies ist für sinusähnliche Klänge nötig, da koninuierliche Anschlüsse an die Phasenlage ansonsten nicht hundertprozentig gewährleistet sind. Als drittes noch das bekannte Hanning-Fenster, das ein noch sehr viel weicheres Ergebnis zeitigt.

Bsp. verschiedene Fenster.

Dieses Resultat kann mit Sample-Techniken zu vielfacher musikalischer Anwendung geführt, ausserdem natürlich dann immer noch einer bekannten Additions- oder Multiplikations-Modulationsoperation unterzogen werden.

Mit der erzeugten Kurve läßt sich wiederum ein Sample auslesen, so kann sie z.B. als Algorithmus zur Granularsynthese verwendet werden. Dieser Algorithmus ist ungleich komplexer als es mit herkömmlicher Granularsynthese möglich ist, da viel mehr Varianz bestimmt werden kann.

Klangbeispiel: Periodisches Signal, erzeugt mit wavgorithm. wavgorithm-bsp1

Klangbeispiel: Algorithmus mit einem Sample (Helmut Qualtinger Lesung) auf Basis einer wavgorithm-Welle. wavgorithm-bsp2

Johannes Kreidler, Januar 2005

Mit folgendem Lisp-Code kann als Liste mit Argumenten durch Lisp an pd ein Textfile mit Arraydaten geschickt werden:

(progn (defun wavgorithm (laenge randoffs randrange inpolr platu inpolh plato style)
(setq out1 (open "wg1.txt" :direction :output :if-exists :supersede))
(format out1 "~&0 arrayw resize ~D;" laenge)
(format out1 "~&0 arrays ~D;" laenge)
(wago laenge randoffs randrange inpolr platu inpolh plato style 0 0 0))

 

(defun wago (laenge randoffs randrange inpolr platu inpolh plato style start startc cc)
(setq d (+ startc 1))
(cond ((<= d plato) (setq b (+ (random randrange) randoffs)))
(t (setq b (random randrange))))
(cond ((>= d (+ platu plato)) (setq d 0))
(t ()))
(let ((x start) (y b) (z1 inpolh) (z2 inpolr) (f style) (ccx cc))
(cond ((< (- y x) 0) (setq e z2))
(t (setq e z1)))
(do ((schrit1 1 (+ schrit1 1))
(c ccx (+ c 1))
(wert x (cond
((= f 0) (+ x (* (/ (- y x) e) schrit1)))
(t (+ (* (/ (+ (sin (* (/ pi 2) (- (* (/ 2 e) schrit1) 1))) 1) 2) (- y x)) x)))))
((= schrit1 e) (setq cc c) 'done)
(format out1 "~&0 x ~D;~%0 y ~,6f;" c (- (/ wert 1000) 1))))
(cond ((> cc laenge) (close out1))
(t (wago laenge randoffs randrange inpolr platu inpolh plato style b d cc)))))

Nun genügt folgende Lisp-Eingabe mit der Syntax: (wavgorithm Arraygröße, hoch-tief-Abstand, Randomrange, Interpolationspunkte runter, Plateaupunkte unten, Interpolationspunkte hoch, Plateaupunkte oben, lin/sin {0/1}):

(wavgorithm 6500 1 1950 7 1 6 1 0)

 

was in pd dann folgendermaßen aussieht:

Johannes Kreidler, Juni 2006