3.4 Sampling

3.4.1 Theorie

Zunächst muss eine unselige Vermischung besprochen werden: Wir schon gesagt ist ein Sample die kleinste Einheit der Messung und Generierung von Klang im Computer. Es gibt jedoch noch einen anderen Gebrauch des Wortes Sample, der ein kleineres Stück (von ein paar Sekunden Länge) aufgenommenen Klangs meint. Um die Bearbeitung kurzer aufgenommener Klänge geht es in diesem Kapitel. Dafür muss jedoch zuerst der „array“ in Pd erklärt werden, was einigen Platz beansprucht.

3.4.1.1 Speicherung von Klang

3.4.1.1.1 Klangdateien

Im Computer gibt es zwei verschiedene Orte, an denen etwas gespeichert werden kann: der Hauptspeicher und die Festplatte(n). Der Zugriff auf den Hauptspeicher ist sehr schnell im Vergleich zur Festplatte. Dafür ist dort nicht so viel Platz.

In Pd kann man an beiden Orten Klang speichern. Wird auf der Festplatte gespeichert, heißt das, dass man eine fixierte Klangdatei speichert. Übliche Formate sind wav oder aiff. Man speichert mit „writesf~“. Als Argument gibt man die Anzahl der Kanäle, worauf entsprechende Inlets entstehen, an die man den aufzunehmenden Klang anschließt. Zunächst nennt man mit der Message „open [name]“ den Namen der zu erstellenden Datei. Die Aufnahme wird dann mit „start“ gestartet und mit „stop“ gestoppt.

3.4.1.1.2 Buffers

Der erwähnte andere Ort ist der Hauptspeicher. Einen Platz für einen Klang erstellen wir mit dem „array“ (Put Array, dann auf „ok“ klicken). Er ist zugleich eine Visualisierung von Klang.

Zunächst betrachten wir den Array aber ganz allgemein als Speicher von Zahlen. Ein Array hat eine begrenzte Zahl von Speicherplätzen. Die Anzahl kann man einstellen, wenn man mit der rechten Maustaste auf den Array klickt und in die „Properties“ geht. Darauf öffnen sich zwei Fenster, eines mit „array“ überschrieben und eines mit „canvas“. Im „array“-Fenster können wir die „size“, also Größe einstellen. Diese Zahl meint die Anzahl der Speicherplätze. In jedem Speicherplatz kann eine Zahl deponiert werden.

Diese Plätze belegen wir nun mit „tabwrite“. Das rechte Argument bestimmt den Platz, das linke dann (wie immer: von rechts nach links) den zu speichernden Wert. In dem Array wird das auf der x- (Platz) und y- (Wert) Achse angezeigt:

So können wir zum Beispiel Funktionen darstellen:

patches/3-4-1-1-2-funktion1.pd

Oder ohne zeitliche Ausdehnung (falls das Beispiel einen stack overflow erzeugen sollte, hilft ein „del 0“ zwischen „spigot“ und „f“):

patches/3-4-1-1-2-funktion2.pd

Mann kann aber auch quasi von Hand etwas mit der Maus in den Array zeichnen. Bewegt man die Maus auf einen Wert innerhalb des Arrays, ändert sich die Pfeilrichtung des Cursors, so dass man bei gedrückter Maustaste eigene Linien ziehen kann.

In den Properties (Rechtsklick auf den array) lässt sich Folgendes einstellen:

Im „array“-Fenster:

  • Name: Wie bei allen Namen in Pd ohne Leerzeichen und als alphanumerische Zeichenfolge.

  • Größe: Wie schon beschrieben.

  • save contents“: Mit Setzung eines Hakens werden alle Werte des Arrays im Patch gespeichert. Dies kann aber später, bei vielen / großen Arrays, sehr viel Platz auf der Festplatte beanspruchen und verlängert die Ladezeit des Patches enorm.

  • draw as points“ / „polygon“ / „bezier curve“: Verschiedene Arten der Visualisierung – ob bloße Punkte oder zu Linien zusammengefasst.

  • delete me“: Mit Setzung eines Hakens ist der Array daraufhin gelöscht! Allerdings wird der Kasten unnötigerweise noch angezeigt und muss noch eigens gelöscht werden.

  • view list“: Hier werden alle Werte in einer Liste dargestellt.

Im „canvas“-Fenster:

  • graph on parent“: Wird erst unter 3.1.1.2 besprochen.

  • Xrange: Hier können die Anfangs- und Schlusswerte der x-Achse bestimmt werden.

  • YRange: Hier wird der Darstellungsbereich für die y-Achse eingestellt. Werte außerhalb dieses Rahmens werden aber auch gespeichert, nur platzausweitend dargestellt.

  • size“: Visuelle Größe im Patch.

Weiterhin kann ein Array Messages bzw. „sends“ empfangen.

Einen neuen Namen geben:

Alle Werte gleichsetzen:

Die Größe ändern:

Die Größe kann auch ausgedruckt werden:

Den Inhalt in eine Textdatei schreiben:

Eine Textdatei lesen:

Wir können so auch Werte eingeben; die erste Zahl bestimmt, an welchem Speicherplatz begonnen werden soll, alle weiteren sind Werte für die darauf folgenden Plätze:

Zusätzlich können wir noch Raster an die Achsen anlegen und diese beschriften:

Die Argumente benennen 1. den Startplatz auf der Achse, 2. den Abstand zwischen den Strichen und 3. den Abstand zwischen größeren Strichen.

Und Bezifferung:

Beschriftet wird 1. die Position, 2. die anzuzeigenden Ziffern.

Man beachte: Striche und Beschriftung werden nicht im Patch gespeichert, müssen also bei jedem neuen Aufruf des Patches wieder erneut angebracht werden.

Nun können wir aber auch Klang in einem Array speichern. Klang ist ja, wie schon häufig betont, im Computer nichts als eine Folge von Zahlen, genauer gesagt 44100 Zahlen pro Sekunde. Wir können beispielsweise eine Sekunde Klang in einem Array speichern, nur muss dieser dafür auch 44100 Speicherplätze haben. Nun benötigen wir das Objekt „tabwrite~“. Es erhält den Klang-Input und ansonsten nur einen Bang. Anders als bei „tabwrite“ (ohne Tilde), wo wir rechts von Hand den Speicherplatz eingegeben haben und links den zugehörigen Wert, wird hier nun, wenn es einen „bang“ bekommt, automatisch beim ersten Speicherplatz angefangen und dann in Samplegeschwindigkeit weitergeschritten. Gleichzeitig wird jedem Platz ein von links kommender Wert des ablaufenden Klanges zugewiesen; damit werden insgesamt 44100 Zahlen gespeichert. Was danach an Klang kommt, wird nicht mehr gespeichert. Will man vorzeitig abbrechen, schickt man die Message „stop“.

patches/3-4-1-1-2-normalisieren.pd

Erhält „tabwrite~“ eine float message, so wird diese Zahl als Sampleoffset interpretiert d.h. mit diesem Sample beginnend in den Array geschrieben.

Eine nützliche Funktion ist, dass man im Nachhinein die allgemeine Lautstärke auf das maximal Mögliche anheben kann. Ist eine Aufnahme zum Beispiel sehr leise gewesen, d.h. die Membran des Aufnahmemikrofons schwang nicht sonderlich stark, erhalten wir auch nur sehr kleine Werte. Die können wir aber quasi aufblasen bzw. „normalisieren“. Dafür gibt es folgende Message:

Wir können nun auch eine Verbindung zwischen Klangdateien auf der Festplatte und Klang im Hauptspeicher herstellen, also im Array. Dies erfolgt mit dem Objekt „soundfiler“. Damit können wir eine auf der Festplatte gespeicherte Klangdatei in einen Array laden, oder den Inhalt eines Arrays auf der Festplatte als Klangdatei speichern. Das Laden geschieht mit dem Befehl „read“. Die Argumente des Befehls sind der Name der Datei (ggf. mit Verzeichnispfad) und dahinter der Name des Arrays, in den diese geschrieben werden soll.

patches/3-4-1-1-2-soundfile-laden.pd

Nach dem erfolgreichen Laden der Datei wird die Größe der Klangdatei in Samples aus dem Outlet von „soundfiler“ ausgegeben.

Wir können noch zusätzliche Befehle („flags“ genannt) in die Message integrieren:

Durch den resize-Befehl wird die Größe des Arrays auf die genaue Größe der Klangdatei gebracht (wobei da bei 4000000 Samples, das sind ca. 90 Sekunden, die Grenze liegt, was zusätzlich mit „maxsize“ aber geändert werden kann).

Umgekehrt speichert der Befehl „write“ den Inhalt eines Arrays als Klangdatei auf der Festplatte. In diesem Fall muss das Format (wav oder aiff) als Flag angegeben werden, anschließendn der Name (ggf. mit Pfad) der zu schreibenden Datei und dahinter der Name des Arrays.

Weitere „Flags“ hierzu sind:

  • normalize: Bringt die Datei auf optimale Amplitudenaussteuerung, wie vorhin beschrieben.

  • rate: Damit kann die Samplerate für die Datei eingestellt werden.

Alternativ zum Array gibt es auch den „table“. Man erstellt das Objekt „table“ und gibt als erstes Argument den Namen, als zweites die Größe in Samples. Daraufhin wird in einem Subpatch (im Execute Mode auf das Objekt klicken) ein Array erstellt, der wie ein normaler Array behandelt wird. Das hat folgenden Vorteil: Die Grafik eines normalen Arrays ist ab einer gewissen Größe sehr aufwändig; man merkt das, wenn man den Array auf dem Canvas verschiebt – es geht nur sehr langsam. Verbleibt die grafische Repräsentation des Arrays aber in einem Subpatch, lässt sich mit dem Objekt leichter hantieren.

3.4.1.2 Wiedergabe von gespeichertem Klang

Klangdateien, die sich auf einem externen Speichermedium wie beispielsweise einer Festplatte befinden, können in Pd mit „readsf~“ gelesen, das heißt abgespielt werden. Wie bei „writesf~“ verwendet man die Messages „start“ und „stop“ (es geht auch „1“ und „0“). Als Argument gibt man dazu die Anzahl der Kanäle. Der Output ganz rechts macht einen Bang, wenn die Datei zu Ende gelesen ist.

patches/3-4-1-2-datei-spielen.pd

Für den Array betrachten wir zunächst wieder nur die Kontroll-Ebene: Haben wir zum Beispiel einen Array mit 10 Speicherplätzen, können wir mit „tabread“ jeden dieser Plätze einzeln abfragen:

patches/3-4-1-2-array-lesen1.pd

Das Prinzip ist nun für Signale im Grunde dasselbe, nur müssen die gespeicherten Werte nun in der Geschwindigkeit von 44100 Zahlen pro Sekunde erhalten werden. Dafür gibt es „tabread~“. Wollen wir beispielsweise einen in einem Array gespeicherten Klang von 1,5 Sekunden (=66150 Samples) Dauer abspielen, heißt das, wir müssen hintereinander die Arraywerte 0 bis 66149 abfragen, und zwar in der Geschwindigkeit von 44100 Werten pro Sekunde. Dies machen wir mit „line~“:

patches/3-4-1-2-array-lesen2.pd

tabread~“ erhält als Argument den Arraynamen. Wir können den zu lesenden Array aber auch mit einer Message „set [arrayname]“ bestimmen.

Nun können wir aber auch anfangen mit diesen Werten zu spielen. Etwa indem wir die Reihe einfach in der doppelten Zeit ablaufen lassen:

Dadurch wird die Abspielgeschwindigkeit halbiert. Dies führt dazu, dass alles eine Oktave tiefer klingt, denn durch die zeitliche Streckung werden alle Wellen doppelt so lang, das heißt in der Frequenz halbiert und damit eben eine Oktav tiefer.

Hier gibt es nun aber das Problem, dass ein vorhandenes Sample zweimal hintereinander gespielt wird oder es zu Auslassungen kommt. Um diese Lücken zu schließen, gibt es eine modifizierte Form des „tabread~“-Objekts, „tabread4~“, das zwischen diesen Lücken interpoliert, also Zwischenwerte aus den Informationen des davor und danach liegenden Wertes erzeugt. (Mehr zu der Funktionsweise für besonders Interessierte unter 3.4.4.) In den meisten Fällen ist daher zum Auslesen von Arrays „tabread4~“ geeigneter. Dieses braucht ein Auslesespektrum von 1 bis n-2, wobei n die Größe des zu lesenen Arrays ist.

Wir können natürlich auch etwas schneller und damit höher abspielen:

Wir werden später mit Hilfe der Granularsynthese Wege kennenlernen, wie wir Tempo und Tonhöhe unabhängig voneinander verändern können.

Außerdem liegt es natürlich noch nahe, etwas rückwärts abzuspielen:

Man kann sich nun aber auch des „phasor~“-Objekts bedienen:

phasor~“ erzeugt eine Reihe von Zahlen von 0 bis 1 als Signal. Multiplizieren wir diese Werte mit 66148, haben wir eine Reihe von 0 bis 66148. Als Frequenz geben wir 0.75 an, so dass die Reihe in genau 1,5 Sekunden abläuft.

Zudem könnte man auch einen eigenen Array für die Ausleseweise arrangieren, mit dem man den ersten Array abspielt:

patches/3-4-1-2-array-lesen3.pd

Oder wir können für den Amplitudenverlauf einen Array verwenden:

Oder einen Array für einen Frequenzverlauf:

Erneut ist zu sehen: Wir haben es nur mit Zahlen zu tun, die verschiedentlich zur Steuerung eingesetzt werden können.

Man kann mit beliebig vielen „tabread~“-Objekten gleichzeitig aus einem Array lesen. Allerdings sollte man nie zwei Arrays mit dem gleichen Namen verwenden, das führt fast zwangsläufig zu Fehlern.

3.4.1.3 Audiodelay

In Kapitel 2.2.3.1.2 haben wir die Möglichkeit besprochen, Zahlen oder Zahlenfolgen zeitlich zu verzögern („delay“). Das können wir auch mit Signalen machen. Hierfür wird gleichfalls ein Buffer erstellt, in den die Signale zunächst hineingeschrieben werden und aus dem dann zeitverzögert wieder gelesen wird. Diesen Buffer erstellen wir mit „delwrite~“; als erstes Argument geben wir dem Buffer einen beliebigen Namen, als zweites Argument die Größe in Millisekunden. Geben wir dem nun einen Signal-Input, wird dies in den Buffer geschrieben. Ist der Buffer voll, wird vom Anfang an überschrieben. Ist der Buffer also 1000 Millisekunden groß, sind immerzu die letzten 1000 Millisekunden des eingehenden Signals darin gespeichert.

Gelesen wird auf dem Buffer dann mit „delread~“. Als erstes Argument erscheint wieder der Buffername, als zweites die Zeit der Verzögerung (in Millisekunden; kann durch den Input als Kontrolldateneingabe geändert werden):

patches/3-4-1-3-delay.pd

Logischerweise muss die Verzögerungszeit in „delread~“ kleiner als die Buffergröße sein oder zumindest gleich groß. Wenn etwas 2000 Millisekunden später gespielt werden soll, aber in dem Buffer nur für 1000 Millisekunden verbleibt, kann es nicht funktionieren. Ebenso ist eine negative Zahl als Verzögerung natürlich Unsinn, denn in die Zukunft kann Pd nicht schauen. Man kann aus einem Delay-Buffer mit beliebig vielen „delread~“-Objekten gleichzeitig lesen. Man kann nicht in den Wellenverlauf dieses Buffers hineinsehen.

Man kann zwar in „delread~“ die Verzögerungszeit verändern, aber nur als Kontrolldateneingabe und mit der entsprechenden Fehlerwahrscheinlichkeit ab einer bestimmten Geschwindigkeit (das ist wieder der Konflikt zwischen Kontrolldaten und Signalen). Darum gibt es noch ein eigenes Objekt zum variablen Lesen von Delay-Buffern, „vd~“ (Abk. für „variable delay“, also variable Verzögerung). Hier gibt man die Verzögerungszeit (in Millisekunden) als Signal ein, und kann diese permanent verändern (natürlich wiederum nicht unter 0 und nicht oberhalb der Buffergröße):

vd~“ erzeugt wie „readsf4~“ eine Interpolation.

3.4.2 Anwendungen

3.4.2.1 Ein einfacher Sampler

patches/3-4-2-1-einfacher-sampler.pd

3.4.2.2 Mit variabler Geschwindigkeit

patches/3-4-2-2-sampler2.pd

3.4.2.3 Beliebige Positionen

Picken wir uns nun beliebige Positionen aus einem Sample heraus:

patches/3-4-2-3-sampler3.pd

3.4.2.4 Sampler zusammengefasst

Wendet man die oben beschriebenen Funktionen zur optischen Verbesserung (2.2.4) an, dann sieht das Ganze beispielsweise so aus:

patches/3-4-2-4-sampler-gross.pd

Vier Canvas-Objekte bilden den farbigen Hintergrund der Slider und der Arraydarstellung. Man beachte: Es erscheinen immer die Grafiken, die zeitlich zuletzt erstellt wurden, über den anderen. Haben wir also z.B. zuerst den „array1“ und erstellen dann ein farbiges Canvas-Objekt, müssen wir den „array1“ noch einmal neu erstellen (einfach den alten kopieren und dann löschen), so dass er vor dem Canvas-Objekt erscheint.

Zur Erklärung, was jeweils dahinter steckt:

Und im Subpatch:

3.4.2.5 Loop-Generator

patches/3-4-2-5-loop-generator1.pd

Bei diesem Loop-Generator kommt es allerdings immer wieder zu Klicks. Zum einen ist sehr zu empfehlen, den Array in ein Unterfenster auszulagern, denn die grafische Darstellung erfordert relativ viel Rechenaufwand. Zum anderen sollten wir an den Rändern des Loops kurz zu 0 gehen, damit es bei ihrem Anschluss nicht zu einem plötzlichen Wertesprung (und damit zu einem Klick) kommt. Hierzu machen wir eine „Fensterung“. Synchron zum Auslesen des Arrays wird dies in der Amplitude bestimmt durch einen anderen Array (hier „crown“), der die dynamische Hüllkurve vorgibt. Diese Hüllkurve hat zu Beginn und am Ende den Wert Null, so dass es beim Umbruch keine plötzliche Werteänderung gibt. Man könnte statt des „crown“-Fensters aber auch ein anderes wie das „Hanning“-Fenster verwenden, das einen Ausschnitt aus der Sinus-Funktion verwendet (dazu kommen wir später wieder). Eigentlich sollte sich der „crown“-Array natürlich auch in einem Unterfenster befinden, der Anschaulichkeit halber haben wir das hier jedoch unterlassen.

Eine einfachere Version des Loops lässt sich mit einer Rückkopplungsschaltung (engl. „feedback“) erzeugen:

patches/3-4-2-5-loop-generator2.pd

Ein Nachteil ist hierbei, dass die maximale Loop-Dauer vorgegeben ist; hier beträgt sie 10000 Millisekunden.

3.4.2.6 Reverb

So kann man zum Beispiel eine „Hall“-Wirkung (engl. „Reverb“) erzielen, wenn das rückgekoppelte Signal immer leiser wird:

3.4.2.7 Textur

Oder man kann eine Textur erstellen:

patches/3-4-2-7-textur.pd

Hier muss man allerdings sehr aufpassen, dass die Rückkopplung nicht "explodiert", also an Lautstärke (exponentiell) zunimmt.

3.4.2.8 Kammfilter

Mit dem Audiodelay kann man einen Kammfilter bauen. Die Idee ist, dass zum Originalsignal seine Verzögerung addiert wird. Dadurch enstehen Verstärkungen und Auslöschungen in regelmäßigen Abständen, was in der Spektraldarstellung aussieht wie ein Kamm:

patches/3-4-2-8-kammfilter.pd

3.4.2.9 Oktavdoppler

Sofern man die Frequenz des Grundtons eines Signals kennt, kann man nach folgender Idee einen Oktavdoppler konstruieren: Nehmen wir eine Welle ...

... und ihre Verzögerung um die Hälfte ihrer Periodenlänge ...

... ergibt ihre Addition 0. Wenn man also ein Signal um die Hälfte der Periodenlänge seines Grundtons verzögert und dies zum Original addiert, fällt der Grundton (und alle ungeraden Teiltöne) weg. Das könnte also so aussehen:

Das funktioniert jedoch so noch nicht. Wir müssen hierbei wieder in Betracht ziehen (vgl. 3.1.1.3.2), dass Pd alle Audio-Daten in Blöcken von 64 Samples (wenn nicht anders eingestellt) zusammgefasst abarbeitet (das ist effizienter als jedes Sample einzeln). In dem Fall hätten wir eine Verzögerung von 1.136 Millisekunden, das sind 50 Samples. Abhilfe können wir dem schaffen, wenn das Original auch noch einmal aus dem Buffer gelesen wird, mit Verzögerung eines Blocks (64 Samples=1.451ms), ebenso dies als Offset der Verzögerung:

patches/3-4-2-9-oktavdoppler.pd

3.4.2.10 Karplus-Strong-Algorithmus

Eine besondere Anwendung von Rekursion ist der Karplus-Strong-Algorithmus. Er ist eines der ersten Beispiele für das Syntheseverfahren des physical modelling, ein Verfahren, das versucht, virtuell nachzubauen, was physikalisch beim Schwingen von Materie passiert. In unserem Beispiel wird dem physikalischen Modell einer gezupften Saite gefolgt: Durch den Impuls des Zupfens schwingt die Saite zunächst chaotisch und pendelt sich dann auf die Saitenlänge ein. Außerdem nimmt die Energie ab, d.h. die Saite verklingt. Dies lässt sich mathematisch nachbauen: Man nimmt einen Ausschnitt aus weißem Rauschen und spielt diesen periodisch immer wieder ab, indem es immer wieder in einen Buffer geschrieben bzw. daraus gelesen wird:

patches/3-4-2-10-karplus-strong1.pd

Der Saiteneffekt lässt sich aber noch vergrößern, in dem das anfänglich Material immer 'weicher' schwingt. Das funktioniert mit einer Durchschnittsrechnung: Es wird jeweils zwischen zwei aufeinander folgenden Samples der Durchschnittswert gebildet und dieses Ergebnis dann wieder in den Buffer geschrieben. Dadurch verliert die Schwingung immer mehr an 'Ecken'. Den Delay um ein Sample erstellt man mit dem (Pd-extended-)Objekt „z~“, als Argument gilt die Anzahl der Samples:

patches/3-4-2-10-karplus-strong2.pd

Bei jedem Starten klingt der Ton etwas anders. Das liegt daran, dass „noise~“ Zufallszahlen produziert, die natürlich jedesmal verschieden sind. Wir können noch die Rechnung anfügen für die resultierenden Frequenzen:

patches/3-4-2-10-karplus-strong3.pd

3.4.2.11 Weitere Aufgabenstellungen

a) Bauen Sie in den Sample-Player eine Aufnahmefunktion ein.

b) Bilden Sie einen Hall bzw. eine Textur mit verschiedenen Delay-Zeiten des Eingangssignals, zum Beispiel mit Vielfachen der Fibonacci-Reihe (die nächste Zahl bezeichnet immer die Summe der zwei vorangegangenen, also 1 2 3 5 8 13).

c) Schaffen Sie mit verschiedenen Karplus-Strong-Klängen Texturen von variabler Dichte.

d) Wenden Sie den Kammfilter auf andere in den vorigen Kapiteln vorgestellte Klänge an.

3.4.3 Appendix

3.4.3.1 Arrayoszillator

Eine Vereinfachung der Kombination aus „tabread~“ mit einem multiplizierten „phasor~“-Signal ist „tabosc4~“. Dies liest mit gegebener Frequenz einen Array aus. Etwas umständlich ist dabei allerdings, dass der Array hierbei die Größe einer 2er-Potenz (also z.B. 128, 512, 1024) plus drei Punkte haben muss.

patches/3-4-3-1-arrayoszillator.pd

Hier berühren wir schon das in Kapitel 3.5 näher erläuterte „waveshaping“. Wir können mit der Maus eine beliebige Welle in den Array einzeichnen.

3.4.3.2 Array einfach abspielen

Noch eine Vereinfachung ist „tabplay~“. Es spielt einen Array einfach in Originalgeschwindigkeit ab (mit Bang). Komfortabel ist, dass der Start- und Endpunkt auch bestimmt werden kann (Startwert und Länge des Lesens (in Samples)):

patches/3-4-3-2-einfach-array-abspielen.pd

3.4.3.3 Array im Block abspielen

Eine Sonderform von „tabwrite~“ und „tabread~“ sind „tabsend~“ und „tabreceive~“. Sie schreiben / lesen einen Array synchron zu den „Blocks“ (3.1.1.3.2). „tabwrite~“ schreibt jeden Block in einen Array (der darum natürlich die Größe des Blocks haben muss, by default sind das in Pd 64 Samples). „tabreceive~“ liest in jedem Block den Array. Wir werden dies im fft-Kapitel (3.8) wieder antreffen.

3.4.3.4 Glissandi von Samples

Man kann einen Array in normaler Tonhöhe abspielen oder eine Oktav höher etc. Was aber, wenn man ein Glissando von der Oktav zur Originalhöhe erstellen will? Hierzu brauchen wir eine Unterteilung in „Hauptzeiger“ und „Addition“. Der „Hauptzeiger“ verläuft in Normalgeschwindigkeit über den Array. Nehmen wir als Beispiel einen Array mit 132300 Punkten, also 3000 Millisekunden Länge:

Dazu kommt die „Addition“, die das Glissando bewirkt. Nehmen wir als Beispiel, dass ein Glissando bei fünf chromatischen Schritten über der Originaltonhöhe beginnen soll und sich in 500 Millisekunden zur Originaltonhöhe hinbewegt. Wir erstellen eine umgekehrte „line~“ davon, und quadrieren die Werte:

Überdies müssen wir den Faktor der Frequenzen für die fünf chromatischen Schritte ermitteln (vgl. 3.1.1.4.3) ...

... und anschließend folgende Rechnung durchführen:

Dies ist die „Addition“, die zu dem „Hauptzeiger“ hinzukommt:

patches/3-4-3-4-sample-glissando1.pd

Letztlich können wir so beliebige Glissandi zum Zielton erheben; auch negative Werte sind möglich:

patches/3-4-3-4-sample-glissando2.pd

Umgekehrt, vom Originalton weg, lässt sich noch ergänzen:

patches/3-4-3-4-sample-glissando3.pd

3.4.3.5 Additive Synthese mit Array

Als besondere Funktion kann in Pd in einem Array eine Summe von Sinuswellen erstellt werden, also eine additive Synthese wie in Kapitel 3.2 beschrieben. Dies erfolgt mit der Message „sinesum“. Als erstes Argument gibt man die (neue) Arraygröße (sollte eine 2er-Potenz sein; zu der werden dann automatisch noch drei Punkte zum idealen Phasenanschluss hinzugefügt, vom hinteren zum vorderen Ende) und zudem Lautstärkefaktoren für beliebig vieleTeiltöne:

patches/3-4-3-5-sinesum.pd

Statt Sinuswellen kann man auch Cosinuswellen einsetzen, entsprechend mit „cosinesum“.

3.4.3.6 Latenz

Audiodelay erscheint leider auch ungwollt. Bei einer einfachen Schaltung des Mikrofons an die Lautsprecher kann man das schon hören, wenn man einen ganz kurzen Klang ins Mikrofon gibt, zum Beispiel Schnalzen:

Je nach Soundkarte und vor allem Betriebssystem gibt es eine sogenannte „Latenz“. Bestenfalls ist sie so gering (unter 5ms), dass die Verzögerung vom menschlichen Ohr nicht wahrgenommen werden kann. Dies erfordert aber einen schnellen Rechner, eine gute Soundkarte und ein dafür geeignetes Betriebssytem. Man kann in Media Audio settings die Latenzzeit einstellen:

In Microsoft Windows gelangt man derzeit (Juni 2008) noch nicht unter eine Latenz von ca. 50ms, ohne dass Störungen auftreten.

3.4.4 Für besonders Interessierte

3.4.4.1 4-Punkt-Interpolation

An diesem Beispiel kann man die Funktionsweise „tabread4~“ - Interpolation sehen:

patches/3-4-4-1-vier-punkt-interpolation.pd

Der Sprung von 1 zu -1 wird 'weicher' gemacht durch eine Art sinusoide Interpolation. Für ein zu interpolierendes Intervall zwischen zwei Punkten werden, wie es der Name andeutet, zwei vor und zwei hinter dem Intervall verwendet und entsprechend geändert.

3.4.4.2 Sampleweise Delay

Eine Möglichkeit der sampleweisen Verschiebung mit „delread~“ und „vd~“ ist die Auslagerung in Unterpatches (sonst tritt das Problem der Blockgröße, wie vorhin bei der Oktavierung, ein):

patches/3-4-4-2-sampleweise-delay.pd