Pure Data (PD)

Pure Data (PD): grafische Programmieroberfläche, Freeware-Version von Max MSP = virtuelle Objekte (objects) zur Klangerzeugung / Klangveränderung / Klangsteuerung können innerhalb von programmen (patches) mit virtuellen beliebig Kabeln verbunden werden zur Echtzeitsteuerung von Musik und Videos.

Kern des Programms wurde Mitte der 1980er Jahre am IRCAM von Miller S. Puckette entwickelt


Pure Data Features

  • beliebige Anzahl von Programmen sind möglich
  • Umgebung für Mac, PC, Linux, iOs, Android
  • beliebige Anzahl von MIDI-inputs und -outputs

Grundlagen

Nach dem Öffnen von Pure Data gelangt man erstmal an den Kern des Programms = GEM (Graphics Environment for Multimedia), über den sich die Programmumgebungen (Patcher) starten lassen:


GEM-Oberfläche nach dem Starten

Davor jedoch sollten noch einige Grundeinstellungen vorgenommen werden. Hier kann man im Menü via "Medien -> DSP an" die Fähigkeit des Digital Sound Processing starten (damit auch Klangsynthese etc. möglich ist) und über "Medien -> Teste Audio und MIDI" eine Oberfläche aufrufen, um die Soundeinstellungen zu testen.


Fenster (Patcher) zum Testen der Audio-Einstellungen

Nachdem alle Audio-Einstellungen funktionieren kann man über das Menü via "Datei -> Neu" einen neuen Patcher aufrufen und darin virtuelle Module mit virtuellen Kabeln zu eigenen Patches zusammenfügen. Module findet man im Patcher unter dem Menüpunkt "Einfügen":


Patcher-Fenster mit Modul-Auswahl

Grundlegende Prinzipien

  • Module werden meist über einen Auslöser ("Bang") angesteuert werden, wie z.B. über einen Button, eine Zahl, ein Keyboard o.ä.
  • Module werden über Kabel miteinander verbunden.
  • auf der oberen Seite der Module sind die Eingänge, auf der unteren die Ausgänge.
  • ausgewählte Objekte sind blau, nicht-ausgewählt grau.

Über den Menüpunkt "Bearbeiten -> Editiermodus" kann man zwischen dem Editier- und dem Playmodus wechseln (auch via STRG + E). Im Editiermodus wird das Patch zusammengestellt und im Playmodus können damit Töne, Kompositionen, Instrumente und Effektgeräte hergestellt werden.

  • Objekt = beliebige Objekte können hierüber erstellt werden, je nachdem, wie man diese Box benennt hat sie dann eine andere Funktion.
  • Nachricht (Message) = Objekte, deren Inhalte (die eigentliche Nachricht Z.B. eine Zahl) als Auslöser weiter gegeben wird. Innerhalb einer Nachricht können auch Variablen eingesetzt werden. Variablen werden mit $ gekennzeichnet.
  • Zahl (Number) = Zahlen oder Fließkommazahlen (Integers oder Double)
  • Symbol (Symbol) = Modul um Inhalte, die von anderen Modulen kommen, zu speichern und/oder anzuzeigen
  • Kommentar (Comment) = Kommentar zur Verschaltung (hat nur beschreibende Funktion)

Neben den einfachen Modulen gibt es GUI-Module (Graphic User Interface), die im Menü unter "Einfügen" unter den normalen Modulen gelistet sind:


GUI-Module (Graphic User Interface)

  • Bang (Bang) = sendet bei jedem Klick eine spezielle Nachricht ("Bang") = setzt eine Aktion in Gang (kann auch Nachrichten empfangen, die dann wiederum einen "Bang auslösen")
  • Schalter (Toggle) = sendet ein "Aus" (0) oder "An"-Signal (1, der Wert des "An"-Signals kann unter den Eigenschaften (Porperties) verändert werden)
  • Zahl2 (Number2) = wie die normale Zahl (Nummer), nur dass der Inhalt mitgespeichert wird, wenn das Patch gespeichert wird
  • Vertikaler und horizontaler Schieberegler (VSlider, HSlider) = Schieberegler, die nach Maus-Ziehen die entsprechenden Werte senden (defaultmäßig von 0-127, kann unter Eigenschaften (Properties) geändert werden)
  • Vertikaler und horizontaler Radioknopf (VRadio, HRadio) = Auswahlknöpfe (Radiobuttons), die ihren jeweiligen Wert senden, wenn sie gedrückt werden. Defaultmäßig sind 8 Knöpfe waagerecht oder senkrecht nebeneinander angeordnet (die Anzahl kann in den Properties verändert werden)
  • Aussteuerungsanzeige (VU) = zeigt den Pegel einer Audioquelle in dB an
  • Arbeitsfläche (Canvas) = rechteckige Fläche, deren Größe und Farbe über Properties einstellbar ist (gut als Hintergrund für eine übersichtlichere Darstellung oder auch als bewegliche Fläche, deren x- und y-Position als Steuersignal weiter an andere Module übertragen wird).
  • Feld (Array) = editierbare Kurvenanzeige mit einer Reihe von X- und Y-Werten, für Hüllkurven, Darstellungen von Wellenformen, Steuerungen aller Art. Das Feld hat gleich zwei Eigenschaftsfenster, eines für die Arbeitsfläche, in der die Kurve erscheint, und eines für die Art und Form der Kurve an sich.


Feld (Array) für Hüllkurvendarstellungen/steuerungen

 

Pure Data Einführung (MIDI-Steuerung)

via random lassen sich zufällige Zahlen von 0 bis zu einer beliebigen Zahl-1 (und damit via MIDI zufällige Tonhöhen) erzeugen:


Zahlencodierung für Tonhöhen via MIDI
(Manzo 2011, S. 19)


Frequenz vs. Notennamen / MIDI-Nummer
(http://newt.phys.unsw.edu.au/jw/notes.html)

Mit Zahlen zwischen 0 und 127 lassen sich alle musikalisch erreichbaren Tonhöhen via MIDI wiedergeben.

Mit dem Objekt makenote lassen sich MIDI-Tonhöhen mit drei Parametern erzeugen: Velocity (Anschlagsstärke: 0-127) / Dauer (in ms) / Kanal (0-15)

Mit dem Objekt noteout wird die in makenote erzeugte Note als MIDI-Befehl ausgegeben. Hierbei ist es wichtig, dass der erste Eingang die Zahl für die Tonhöhe erhält und der zweite Eingang die Zahl für die Velocity (diese beiden Eingänge müssen mit den entsprechenden Ausgängen von makenote verbunden sein)

Der Auslöser für den Zufallsgenerator (random) kann ein Button sein, aber auch ein Taktgeber (metro), der den Button ansteuert.

Der Taktgeber wiederum wird über einen Schalter (toggle) aus- und eingeschaltet.

Über einen zweiten Zufallsgenerator kann auch die Velocity gesteuert werden

Man kann auch via HSlider einen Schieberegler einsetzen (mit Werten zwischen 0 und 1000), z.B. für die Temposteuerung (Ausgang des Sliders am rechten Eingang des Taktgebers anschließen; Wertebereich kann über den Inspektor verändert werden)


Script für zufällige Tonhöhen und Lautstärken mit Millisekunden gesteuertem Tempo (via metro)

zufall.pd

Das Pitchbend-Rad kann via bendout (pitch bend) und einen Slider verändert werden. Via bendlin können auch Pitchbend-Daten von außen empfangen werden. Über die Properties sollte ein Rahmen von 14 Bit (16384, also -8192 bis +8192) eingestellt werden

Das Modulationsrad kann via ctlout (Control Change) und einen Slider verändert werden. Via ctlin können auch Modulationsrad-Daten (und auch andere Controller Change-Daten) von außen empfangen werden. Über die Zahl nach ctlin/ctlout wird der Controller addressiert; gängige Controllerwerte sind (1 = Modulation Wheel, 2 = Breath controller, 7 = Volumen etc.).

Die Klangfarbe (bzw. welches MIDI-Instrument gespielt werden soll = Program Change) kann via pgmout und einen daran angeschlossenen Slider verändert werden. Via pgmin können auch Program Change-Daten von außen empfangen werden.


Script für MIDI-Steuerung, Modulation, Pitchbend, Klangfarbenauswahl (Program Change)
midi_steuerung.pd

 

Mit Hilfe von Selectboxen und Radiobuttons lassen sich auch Intervalle und Akkord in Abhängigkeit vom Eingangssignal erzeugen:

Über + und einer Nummernausgabe (number) lassen sich parallel zur eingehenden Tonhöhe weitere Tonhöhen erzeugen.

Die Änderungen lassen sich als Zahlen direkt über Buttons (button) und eine Message-Box (Message) hinzuaddieren.

Wenn man zwei Intervalle hinzuaddiert kann man diese auch als Akkorde zusammenfassen. Über message kann man mit einzelnen Zahlen die geeigneten Intervalle auswählen (3 = kleine Terz, 4 = große Terz, 6 = Tritonus, 7 = Quinte, 8 = kl. Sexte).

Über Radiobuttons und ein Sammelauswahlfeld (select) lassen sich diese Auswahlen zusammenfassen. Bei den Radiobutons hilft wieder der Inspector, in dem man die "Number of Items" einstellen kann(bei 4 geht die Zählung von 0-3). Beim Sammelauswahlfeld wird über die Zahlenfolge 0 1 2 3 bestimmt, zu welchem Ausgang das Signal geschickt wird = welche Message-Buttons aktiviert werden = welche Intervalle in den beiden Intervall-Dropdown-Menüs ausgewählt werden.


Script für die Erzeugung von Intervallen und Akkorden
midi_steuerung_akkorde.pd

Möchte man keine zufälligen Melodien oder Akkorde erzeugen, so kann man dies über ein Array (oder Tab bzw. Feld) erreichen: Über einen Taktgeber (metro) wird eine Zahl (float) immer weiter hochgezählt (+ 1 zu sich selbst).
Von dieser wird (wenn es ein 16stufiger Sequenzer sein soll) via modulo 16 (% 16) der jeweilige Rest einer Teilung von 16 gebildet, so dass immer die Zahlen 0-15 gezählt werden. Über ein 16stufiges Auswahlfeld (horizontaler Radioknopf) lässt sich die Zählgrenze zwischen 0 und 15 einstellen, so dass auch kleinere Durchläufe möglich sind.
Via einfügen -> Kurve kann man eine Kurve einfügen, der man einen Namen gibt (hier: melodie), und die als Speicher für ein Array dient.
Dieser Kurve weist man via "Arbeitsflächen-Eigenschaften" 16 Einheiten auf der X-Achse zu und 24 (= 2 Oktaven) auf der Y-Achse. Mit Hilfe von einfügen -> Nachricht kann man dem Feld melodie nun verschiedene Strukturen aufprägen. Das Feld selbst wird via tabread melodie gelesen, so dass nacheinander die Zahlen aus dem Feld in den Signalfluss gespielt werden und dann mit 60 addiert (um die Noten in die eingestrichene Oktave zu bekommen) und zur MIDI-Ausgabe geschickt wird:


Script für die Erzeugung einer Sequenzer-Melodie
midi_sequenzer.pd

 

Komplexes Script für den Umgang mit MIDI-Daten mit Zufallsgenerator,
Harmonien erzeugen und Step-Sequenzer
midi_komplex.pd

 


(seit Version 0.48 nicht mehr aktuell)

Mit Hilfe von borax lassen sich jede Menge Informationen aus eingehenden MIDI-Signalen bzw. Notes herausholen, wie z.B. die Reihenfolge der Noten, wie viele Noten gleichzeitig gedrückt sind, die Tonhöhe, Anschlagsgeschwindigkeit, Dauer, Abstand zwischen zwei Noten etc.
All diese Informationen können dazu verwendet werden, um neue Noten-Events auszulösen. Über select können hier if/else-Schleifen gelegt werden, mit denen bestimmt wird, dass z.B. ab einer bestimmten Note, Dauer, Tonhöhe, Reihenfolge, Notenanzahl etc. ein neues Ereignis ("Bang") ausgelöst wird.


Script für die Ermittlung von MIDI-Daten
via Borax
midi_borax.pd

 

 

 

Digitale Audiosignalverarbeitung (DSP) mit Pure Data

Audiomodule haben in Pure Data dickere Kabelverbindungen sowie eine Tilde (~) als Erkennungsmerkmal. Um sie mit einer MIDI-Steuerung zu verbinden müssen die MIDI-pitch- und -verlocity-Werte in Frequenzen und Amplituden umgerechnet werden. Dies geschieht über das Modul mtof (MIDI to Frequency).

Oszillatoren für Sinus- (osc~) oder Sägezahnschwingungen (phasor~) sowie ein Rauschgenerator (noise~) bilden die Grundlage zur Erzeugung anderer Grundschwingungsarten (Rechteck und Dreieck) von Synthesizern.

Die Dreieckschwingung wird erzeugt, indem die Sägezahnschwingung mit *-1 phasengedreht wird und zum aktuellen Amplitudenwert 1 addiert wird und diese Summe mit der Original-Sägezahnschwingung verglichen wird: über das Vergleichsmodul (min~) wird jeweils der geringere Wert der beiden Schwingungsarten rausgegeben, so dass man immer erst eine auf- und dann eine absteigende Rampe hat, die sich zu einer Dreieckschwingung ergänzt.

Die Rechteckschwingung wird erzeugt, indem immer nur dann ein Spannungswert weitergegeben wird, wenn die am Eingang v1 anliegende Spannung der Sägezahnschwingung (liegt in der festen Variablen $v1 vor) größer als die Hälfte ist, sonst wird als Spannungswert 0 weitergegeben. Durch diese Rechenoperationen bewegen sich die Werte der Dreieck- und Rechteckschwingung zwischen 0 und 1 und nicht - so wie beim Rauschen oder bei der Sinusschwingung zwischen -1 und +1. Um diesen Spannungsversatz zu korrigieren (DC Offset) müsste man noch das Ergebnis mit dem Modul *~ mit 2 multiplizieren und dann via -~ 1 davon abziehen.

Das Modul *~ dient zur Amplitudenänderung (1 ist dabei die Maximalamplitude). Das Modul line~ erzeugt ebenfalls eine Amplitudenänderung, jedoch innerhalb einer bestimmten Rampenfunktion, wobei die erste Zahl den Zielwert beschreibt (zwischen 0 und 1) und die zweite Zahl die Dauer in ms, die zum Erreichen des Zielwerts benötigt wird. Ohne Zahlen wirkt sie wie eine Sprungfunktion auf den Maximalwert (1).

Über einen Radiobutton mit angeschlossenem Select-Modul kann man zwischen den einzelnen Oszillatoren wechseln; man kann sie auch mit Hilfe der Toggle-Schalter einzeln aus- und anschalten.

Über das Modul tabwrite~ (und dem Namen des Arrays bzw. Feldes, hier "Oszilloskop") lässt sich die aktuelle Spannungsschwankung in einem Sichtfelt ausgeben, d.h. man kann sich die Wellenform anzeigen lassen. Über das Metronom (metro) kann man die Ausgabe des Arrays bzw. des Oszilloskops alle 100 ms aktualisieren.

Die Audioausgabe kann über dac~ mit einem Toggle-Schalter ein- und ausgeschaltet werden.


Script für Tonhöhensteuerung und Wellenformauswahl von verschiedenen Oszillatoren
synth_grundschwingungen.pd

Wenn die Kabelverbindungen unübersichtlicher werden können die Module in Subpatches geordnet werden: Mit Hilfe von pd kann ein Subpatch erstellt werden, in das eine Gruppe von Modulen eingebaut werden kann. Die Eingänge werden via inlet (bzw. inlet~ bei Audiosignalen) mit der Außenwelt verbunden und die Ausgänge via outlet (bzw. outlet~ bei Audiosignalen). über Rechtsklick und "Öffnen" lässt sich das Subpatch öffnen und weiter bearbeiten.


Das gleiche Script wie oben, nur mit Subpatch für die Oszillatoren


Subpatches mit Auswahl und Oszillatoren
synth_subpatch.pd

Über svf~ kann man ein Multifunktionsfilter einsetzen (Hoch-/Tief-/Bandpass-/Bandsperre-Filter), dessen Ausgänge ähnlich wie bei den Oszillatoren via *~ und einem Auswahlmenü mit select und Radiobuttons ausgewählt werden können. Über Schieberegler (vslider) lassen sich die Cut-off-Frequenz (zwischen 0 und 11025 Hz) und die Resonanzüberhöhung = Filtergüte (zwischen 0 und 1) einstellen.

Das ganze Filter lässt sich in ein Subpatch (pd Filter) zusammenfassen, ebenso wie die Auswahl der Filter-Arten in ein Subpatch (pd Auswahl).

Ein einzelner Tiefpass ließe sich auch über das Modul lop~ realisieren, ebenso wie ein einzelner Hochpass über das Modul hip~ und der Bandpass über das Modul bp~.
Ein Voltage Controlled Filter mit veränderbarer Resonanzfrequenz lässt sich wie beim Synthesizer über das Modul vcf~ erzeugen. Dies wäre jedoch nur ein Tiefpassfilter und kein Multifunktionsfilter wie über svf~.


Hoch-/Tief-/Bandpass-/Bandsperre-Filter
synth_filter.pd

Eine Hüllkurve lässt sich entweder über das Modul vline~ erzeugen oder komfortabler über ein Feld (Array):

Bei vline~ wird die Hüllkurve über eine durch Kommata getrennte Zahlenreihe gebildet, die als Nachricht (Message) übermittelt wird: Das erste Zahlenpaar gibt den Zielwert und die Zeit (in ms) an, die zum Erreichen des Zielwerts gebraucht wird, das zweite Zahlentrio gibt den zweiten Zielwert, die Dauer des aktuellen Werts (in ms) und die Zeit bis zum Erreichen des gewünschten Zielwerts an, das dritte Zahlentrio gibt den dritten Zielwert, die Dauer des aktuellen Werts (in ms) und die Zeit bis zum Erreichen des gewünschten Zielwerts an usw. Bei der Zahlenreihe "1 300, 0.5 500 200, 0 1000 200" bedeutet das:

  • Der Maximalwert 1 wird nach 300 ms Einschwingzeit erreicht
  • Auf diesem Maximalwert wird für 500 ms verblieben und dann in einem Zeitraum von 200 ms auf den Wert 0,5 gewechselt
  • dort wird für 200 ms geblieben und in einer Dauer von 1000 ms wird im Ausschwingvorgang das Minimum 0 erreicht.

Durch die Nachricht "stop" wird die Hüllkurve auf dem aktuellen Wert "eingefroren", durch die Nachricht "0" wird sie resettet.

Bei einem Feld (Array) kann man die Hüllkurve (hier: ADSR) direkt zeichnen und über das Modul tabread (und Feldnamen) ablesen. Damit die Datenübergabe richtig erfolgt, muss die X-Achse von 0-99 und die Y-Achse von 1-0 in den Properties eingestellt werden. Über das Module line wird das Array in eine Zahlenfolge umgewandelt, die nacheinander ausgelesen wird. Mit der Nachricht eines Zahlenpaars startet man den Auslesevorgang (1. Zahl: gewünschter Zielwert auf der X-Achse, 2. Zahl: Zeitraum, in dem dieser erreicht werden soll), z.B. beim Zahlenpaar "99 10000": Das Array soll in einer Zeit von 10000 ms von 0-99 nacheinander ausgegeben werden. Mit der Nachricht 0 kann den Zeiger des Arrays wieder auf die Ausgangsposition setzen. Will man mit dem Feld (Array) die Tonhöhe (hier: pitch) steuern, so müssen die ausgelesenen Werte (zwischen 0 und 1) mit 127 multipliziert werden, damit die MIDI-Noten 0-127 angesprochen werden können. Danach können die MIDI-Werte via mtof in Frequenzwerte umgewandelt werden.


Hüllkurvengeneratoren (ADSR und pitch)
synth_adsr.pd

Über das Modul notein lassen sich MIDI-Eingaben von aussen einspeisen, an den Ausgängen liegen die MIDI-Tonhöhe (ganz links), die MIDI-Velocity (in der Mitte) und der MIDI-Kanal (ganz rechts) vor. Mit "notein 1" gibt man die MIDI-Tonhöhe (links) und die MIDI-Velocity (rechts) auf dem 1. MIDI-Kanal aus. Die MIDI-Velocity muss dann noch durch 127 geteilt werden, damit sie einen Wert zwischen 0 und 1 annehmen kann.

Über die Module key, keyup und keyname können auch Eingaben von der Tastatur als MIDI-Befehle umgewandelt werden.

  • key: sendet den Tastaturcode der gedrückten Taste
  • keyup: sendet den Tastaturcode der losgelassenen Taste
  • keyname: gibt bei Tastendruck neben einer 1 (für gedrückt) den Namen der gedrückten Taste wieder (gut für Tasten, die unter Pure Data keinen Tastatur-Code wiedergeben wie Space, Escape, Pfeil aufwärts etc.)

So lässt sich Pure Data z.B. auch mit MakeyMakey verbinden, wo man folgende Tastatur-Codes braucht:

left arrow = Left
right arrow = Right
up arrow = Up
down arrow = Down
a = 97
d = 100
s = 115
w = 119
(vorsicht: die Zahlen sind keine ASCII Char Codes, sie lassen sich ermitteln, indem man die Key-Eingabe mit einer Nummern-Ausgabe verbindet)

Über das Modul select kann man beliebigen Tastaturcodes beliebige Werte zuweisen, die dann für die Erzeugung der jeweiligen MIDI-Note verwendet werden (oder auch für die Steuerung anderer Events).

Über das Modul cursor und das nachgeschaltete Modul route mit der Einstellung motion lässt sich auch die Mausbewegung als zwei Koordinaten ("route x y") ausgeben und zur Steuerung von Audio-Events verwenden:


Patch: MIDI, Maus- und Tastatureingaben als Steuersignale: synth_steuerung.pd

Über das Modul *~ lässt sich auch die Amplitude eines Tongenerators in der Frequenz eines zweiten Tongenerators modulieren.


Beispiel für eine Amplitudenmodulation (AM, Tremolo und Ringmodulation)
synth_am.pd

Wenn man das Oszillator-Modul (osc~) durch den Eingang der Soundkarte tauscht (mit dem Modul adc~) kann man beliebige Klänge ringmodulieren.


Beispiel für eine Ringmodulation mit Klängen von aussen (AM, Tremolo (unter 20 Hz) und Ringmodulation)
synth_ringmod.pd

Über das Additionsmodul +~ lässt sich auch die Frequenz eines Tongenerators in der Frequenz eines zweiten Tongenerators modulieren


Beispiel für eine Frequenzmodulation (Vibrato und FM)
synth_fm.pd