3.5 Wave-Shaping

3.5.1 Theorie

3.5.1.1 Wellenformen

Wir haben bereits unter 3.1.1.1.2 verschiedene Wellenformen kennengelernt (Sinus, Sägezahn, Dreieck, Rechteck und Puls). Für zwei dieser Wellenformen gibt es in Pd Objekte, die sie eigens erzeugen, nämlich „osc~“ für den Sinus, „phasor~“ für den Sägezahn. Mit einem Array können wir die Wellenformen nun immer gleich darstellen:

patches/3-5-1-1-wellenformen-darstellen.pd

Man beachte: Der Sägezahn des „phasor~“ geht immer von 0 bis 1, kommt also nie in den negativen Bereich. Man könnte ihn aber dahingehend noch etwas kräftigen, mit einer kleinen Rechnung:

patches/3-5-1-1-starker-phasor.pd

Wir können nun aber auch anderen Wellenformen erzeugen, wenn wir ein paar Rechenoperationen an den „phasor~“ anbringen. Neu ist dafür das Objekt „clip~“, das 'überstehende' Bereiche wegschneidet. Man gibt als Argumente zwei Zahlen für die untere und obere Grenze, an der jeweils 'abgeschnitten' werden soll:

patches/3-5-1-1-andere-wellenformen.pd

Nun zu den Wellenformen Dreieck:

patches/3-5-1-1-dreieck.pd

Rechteck:

patches/3-5-1-1-rechteck.pd

Puls:

patches/3-5-1-1-puls.pd

Dies sind alles noch standardisierte Wellenformen, die alle bestimmte Charakteristika haben:

Sinus: nur Grundton ohne Obertöne

Dreieck: so ähnlich wie Sinus, plus ungerade Teiltöne

Rechteck: nur ungerade Teiltöne

Sägezahn: alle Teiltöne

Puls: alle Teiltöne, fast gleich laut

Wir sehen: Symmetrische Wellenformen haben nur ungerade Teiltöne (in jede Periode passen immer genau zwei Perioden des nächsten ungeraden Teiltons, sie sind darin also symmetrisch), während unsymmetrische immer auch gerade Teiltöne haben.

Diese Wellenformen lassen sich auch mit additiver Synthese (annäherungsweise) erstellen:

patches/3-5-1-1-wellenformen-fourier.pd

Der Experimentierfreude sind hier keine Grenzen gesetzt, und gerade dadurch gelangt man zu neuen Klängen. So kann man einfach eigene Wellenformen in einen Array einzeichnen. Man muss nur im Execute Mode auf die Linie im Array gehen, woraufhin der Cursor ihre Richtung ändert ...

... und dann bei gedrückter Maustaste eine individuelle Welle zeichnen.

Dies ist aber natürlich etwas umständlich und 'unelegant'. Befassen wir uns also mit der Theorie des 'Waveshaping':

3.5.1.2 Transferfunktionen

Eine lineare Funktion geht durch eine sogenannte „Transferfunktion“. Für die lineare Funktion bietet sich freilich der Phasor~ an, der immer von 0 bis 1 geht. Aus ihm können wir zum Beispiel eine Cosinuswelle machen, mit dem „cos~“-Objekt, das eben eine Cosinusfunktion berechnet:

Und so können alle möglichen Transfers gemacht werden, nur als ein Beispiel:

patches/3-5-1-2-transferfunktion.pd

3.5.1.3 (Gelenkte) Zufallswellenformen

Wir können aber auch Rauschen in einen Array aufnehmen und nachher periodisch auslesen; d.h. dasselbe immer wieder hintereinander (vgl. Karplus Strong). Wenn es häufiger als 20 Mal pro Sekunde auftritt, wird daraus eine Tonhöhe:

Das Spektrum dieses Klanges ist natürlich nicht mehr genau absehbar. Jedes Mal, wenn wir den Array mit Zufallszahlen aus dem „noise~“ füllen, erhalten wir eine neue Welle mit neuen Charakteristika.

Aber eine gewisse Systematik lässt sich doch erkennen. Wir können beispielsweise Klicks, also große Sprünge innerhalb der Welle interpolieren, um zu einem weicheren Resultat zu kommen. Generieren wir also Zufallspunkte mit linearer Interpolation dazwischen („Uzi“ aus Pd-extended erzeugt so schnell wie möglich so viele Bangs hintereinander, wie als Argument gegeben sind):

patches/3-5-1-3-wavgorithm.pd

In diesem Beispiel wird immer mit vier Punkten interpoliert.

Noch weicher wird das Ergebnis, wenn wir statt einer linearen eine sinusoide Interpolation erzeugen. Wir verwenden nun zehn Interpolationspunkte:

patches/3-5-1-3-wavgorithm+sin.pd

Nun sollte auch noch der Anschluss von hinten nach vorne interpoliert werden. Dazu empfiehlt sich eine Fensterung; die Berechnung bringen wir in einem Subpatch unter.

patches/3-5-1-3-wavgorithm+sin+fenster.pd

So haben wir am Anfang wie am Schluss immer die Membran auf 0. Noch weicher wäre das Ergebnis, wenn wir es mit dem Hanning-Window „fensterten“ (siehe 3.9.4.1).

Außerdem sind wiederum Transferfunktionen mit den bekannten Wellenformen möglich, etwa mit einem Rechteck, so dass wir wieder weit in den Bereich der ungeraden Teiltöne kommen.

Etc. In den letzten Beispielen mussten wir allerdings auf Kontroll-Ebene die Welle erstellen; im Gegensatz zu den ersten Beispielen nur mit Transferfunktionen können wir diese nicht „live“ verändern.

3.5.1.4 Wave-Stealing

Eine letzte, quasi-Waveshaping-Synthese-Technik ist „wave-stealing“: Dafür können wir einfach aus bekannten Musikstücken einen kleinen Teil herausnehmen...

patches/3-5-1-4-wavestealing.pd

3.5.2 Anwendungen

3.5.2.1 Wellenformen singen

Mit dem folgenden Patch ist es möglich, Wellenformen mit dem Mikrofon aufzunehmen und so beispielsweise Wellenformen zu singen.

Verschiedene Vokale sehen ungefähr so aus:

3.5.2.2 Transfers

Und dieses Eingangssignal können wir natürlich auch durch eine Transferfunktion schicken:

3.5.2.3 Gerade / ungerade Teiltöne

Man kann auch einen Sägezahn in gerade und ungerade Teiltöne zerlegen. Wir bedienen uns hierbei des „wrap~“-Objekts. Es berechnet die Differenz von der Eingangszahl zur nächst darunter liegenden Integerzahl (Ausgabe wird immer in den positiven Bereich gebracht). Kurz ein paar Beispiele hierfür:

Und nun die Sägezahn-Zerteilung. Durch das „wrap~“-Objekt erzielen wir eine Phasenverschiebung des Sägezahns – diese addiert bzw. subtrahiert mit dem Originalsignal ergibt einen doppelt so schnellen Sägezahn und ein Rechteck.

patches/3-5-2-3-gerade-ungerade-teiltoene.pd

3.5.2.4 Weitere Aufgabenstellungen

a) Erzeugen Sie eine sich ständig ändernde Welle.

b) Machen Sie die Anzahl der Interpolationspunkte und der Arraypunkte bei den (gelenkten) Zufallswellenformen variabel.

3.5.3 Appendix

3.5.3.1 Foldover

An dieser Stelle bekommen wir es mit einem sehr heiklen Problem in der digitalen Klangverarbeitung zu tun: dem Foldover. Betrachten wir zunächst diesen Fall:

patches/3-5-3-1-foldover1.pd

Was passiert? Ab 22050Hz kehrt sich die Richtung um, bis wir bei 44100Hz wieder bei einer Tonhöhe von 0 Hz angekommen sind (danach würde es wieder aufwärts gehen). Der Grund dafür ist, dass wir bei einer Samplerate von 44100Hz maximal eine Welle von 22050 erstellen können (siehe 3.1.1.3.1). Darüber hinaus kommt es zu charakteristischen Lesefehlern. Betrachten wir Wellen mit verschiedenen Frequenzen: die obere hat 11025Hz, die mittlere 22050 und die untere etwas mehr als 22050. Die roten Markierungen stehen für die Abtastpunkte, die immer dieselbe Geschwindigkeit von 44100 pro Sekunde haben.

Jede Periode einer Welle von 11025Hz kann mit immerhin vier Punkten erfasst werden (die spezielle Sinuscharakteristik geht dabei natürlich verloren). 22050 ist die höchste Frequenz, die überhaupt noch korrekt erfasst werden kann, da wir ja, laut Nyquist-Theorem, mindestens zwei Punkte pro Periode brauchen. Bei einer Frequenz, die noch höher ist, kommt es folglich zu Fehlern; es wird nicht mehr jede Periode erfasst und statt einer höheren Frequenz ergeben die Ablesepunkte wieder eine tiefere.

Noch schärfer tritt das Problem aber bei solchen Wellen auf, die Obertöne haben, zum Beispiel beim Puls:

patches/3-5-3-1-foldover2.pd

Hier tritt der Effekt schon viel früher ein: Ab ca. 700Hz kehren sich bereits Obertöne wieder um. Das liegt daran, dass die Puls-Welle praktisch nur aus einem einzigen Strich besteht; und dieser wird schon bald 'verfehlt'. Eine Lösung für das Problem ist, bei einer Puls-Welle zu beginnen, sie aber, je höher die Frequenz ist, umso breiter zu machen, bis sie am Ende ein Sinus ist:

patches/3-5-3-1-foldover3.pd

3.5.4 Für besonders Interessierte

3.5.4.1 GENDY

Iannis Xenakis hat ebenfalls in seinen späten Jahren ein Verfahren zur Wellengenerierung entwickelt mit dem Namen GENDY. Er 'komponierte' nichts als Wellenformen und deren Entiwcklungen, zum Beispiel im Tonbandstück „Gendy 3“.