3.8 Fourieranalyse

3.8.1 Theorie

3.8.1.1 Teiltöne analysieren

Erinnern wir uns an die additive Synthese: Ein Klang wird aus Teiltönen zusammengestellt. Wollen wir nun umgekehrt die Bestandteile von einem bestehenden Klang in Erfahrung bringen, können wir für jeden Teilton ein Set von Bandpassfiltern anbringen:

patches/3-8-1-1-teiltoene-analysieren.pd

Dieses Verfahren vollzieht die Fourier Transformation. Sie teilt das gesamte Frequenzspektrum in gleich große Teile und ermittelt in jedem dieser Teile die Amplitude und die Phase. Aus diesen Werten kann danach wieder das Ausgangssignal rekonstruiert werden. Die Ermittlung nennt man Analyse, die Rekonstruktion Resynthese. Wir realisieren dies mit den Objekten „rfft~“ und „irfft~“:

Die Größe der einzelnen Abschnitte, genannt Bins, ist durch die Block Size gegeben. Wie in Kapitel 3.1.1.3.2 besprochen, arbeitet Pd alle Aufgaben immer in Blöcken ab. Normalerweise beträgt die Bock Size in Pd 64 Samples. Mit „print~“ können wir alle Werte eines Blocks sehen:

Ähnlich wie bei „snapshot~“ oder „unsig“ sehen wir die produzierten Amplitudenwerte. Bei „print~“ sehen wir tatsächlich ALLE erzeugten Werte, in der Anzahl eben begrenzt auf einen DSP-Block. Bleiben wir vorerst bei den 64 Samples; das heißt, das gesamte Spektrum bis 44100Hertz wird in Bins zu je 44100/64=689Hertz unterteilt. Als nächstes müssen wir in Betracht ziehen, dass die Daten von Amplitude und Phase bei fft nicht in der uns gewohnten Weise ausgegeben werden; sie erscheinen als Sinus- und Cosinuswerte. Dies wollen wir vorerst nicht weiter verfolgen. Begnügen wir uns damit, dass wir die Amplitude wie folgt in eine uns verständliche Weise umrechnen können:

patches/3-8-1-1-rfft1.pd

Wie wir sehen erhalten wir bei „print~“ für die Amplitude 64 Werte. Die Amplitude wird hier als Magnitude angegeben, als stets positiver Wert (aufgrund der Quadrierung). Schauen wir genau hin: Mit Ausnahme des dritten Bins, das einen Wert von (ca.) 32 hat, haben wir lauter minimal kleine Werte. Oberhalb der Nyquistfrequenz erfolgt gar keine Rechnung.

Üblicherweise führt man am Ende einer fft-Prozedur eine Normalisierung durch, da die Amplitudenwerte relativ hoch werden. Vorerst ist diese die Größe der Block Size:

Wir können die fft-Analyse in einem Array darstellen:

patches/3-8-1-1-rfft-array.pd

So sehen wir nun also das Spektrum eines Signals. Halten wir fest: fft macht aus einer Information in der Zeit eine Information in Frequenzen; diese wird in jedem neuen Block aktualisiert. Man spricht von time domain und frequency domain.

Die Block Size können wir bei Pd nur in einem Subpatch ändern. Dies funktioniert mit dem Objekt „block~“:

Bei der Wahl der Blocksize gilt zu bedenken: Mit einer größeren Blocksize können wir tiefere Frequenzen erfassen; also beispielsweise mit einer Größe von 1024 Samples ist jedes Bin 44100/1024=~43Hz groß, haben wir also eine feinere Auflösung. Dafür dauert die Prozedur länger.

3.8.1.2 Beliebiges analysieren

Bleiben wir bei 64 Samples als Block Size, womit wir Vielfache der Grundfrequenz 689Hz analysieren können. Was aber, wenn Frequenzen dazwischen auftreten?

Dann verteilt sich die Information auf mehrere Bins und die Phase ändert sich bei jedem Analysedurchgang. Dieses Problem kann nicht gänzlich gelöst werden, man muss dazu etwas tricksen. Üblicherweise verwendet man hierzu überlappende Fenster wie in der Granularsynthese. Wir erstellen eine gefensterte Version des Originals. Dazu wir verwenden wir „tabreceive~“, das den angegeben Array immer genau in Block Size mit einem Hanning-Fenster liest, also hier in 64 Samples.

patches/3-8-1-2-rfft3.pd

Dadurch „verbreitern“ sich die Magnitudenwerte immerhin nicht mehr so stark.

Zusätzlich zur Fensterung lassen wir noch die Fenster überlappen; das ist bei fft in Pd ganz leicht: Als zweites Argument von „block~“ geben wir die Anzahl der Fenster an, üblicherweise 4. Erforderlich ist noch, das Resultat am Ende wieder zu fenstern. Die passende Normalisierung bei 4 überlappenden Fenstern ist (3*Blocksize)/2. Das Ganze muss nun, da wir „block~“ anwenden, in einem Unterfenster passieren.

patches/3-8-1-2-fft-unterfenster.pd

Durch Überlappung und Fensterung stehen die Chancen nun gut, ein Signal korrekt zu erfassen.

3.8.2 Anwendungen

3.8.2.1 Filter

Der Nutzen von fft ist natürlich, die aus der Analyse gewonnen Werte zu ändern, ehe man sie wieder in ein klingendes Resultat verwandelt. Beispielsweise können bestimmte Bins leiser oder ganz aus gestellt werden. So kann man sich Filter wie Hipass, Lowpass etc. selbst 'zeichnen'.

patches/3-8-2-1-fft-filter.pd

3.8.2.2 Faltung

Beliebt ist die Convolution – die Faltung eines Signals mit einem anderen; das heißt, nur die Schnittmenge beider Amplituden werden gespielt. Die Hanning-Kalkluation sollte nun bekannt sein. Standard ist eine Block Size von 1024 Samples und vier Überlappungen.

patches/3-8-2-2-faltung.pd

3.8.2.3 Kompressor

Wir können auch einen Kompressor bauen. Das heißt, dass schwächere Lautstärken an die stärkeren mehr angeglichen werden. Wir verwenden die Magnitudenwerte einfach als Faktoren für die Outputs von „rfft“, wobei Werte, die eine gewisse Schwelle („squelch“) übersteigen, einfach an dem Punkt abgeschnitten werden:

patches/3-8-2-3-kompressor.pd

Implementiert man dies bei der Faltung in eine der beiden Analysen, erhalten wir einen reichhaltigeren Convolution-Effekt:

3.8.2.4 Spectral Delay

Wir können auch verschiedene Bins mit verschiedenem Delay abspielen, und erhalten dadurch ein „spectral delay“. Die fft-Analyse wird in zwei Buffer geschrieben. Mit einem Array bestimmen wir dann für jedes Bin, mit welcher Verzögerung es gespielt werden soll. Maximale Delay-Zeit ist ca. 2500 Millisekunden, denn wir haben einen Buffer von 10000 Millisekunden, aber 4fache Überlappung („block~“), darum 10000/4. Genauer gesagt sind es 2496 Millisekunden, das sind 2496*44.1= ca. 110080 Samples, das entspricht 110080/512=215 möglichen Bin-Positionen. Da in den meisten Fällen das Eingangssignal nicht in die Bin-Größe passt, verteilen sich die Analysewerte auf mehrere benachbarte Bins (vgl. 3.8.1.2). Darum kommt es, wenn diese benachbarten Bins zu verschiedenen Zeitpunkten auftreten, zu Lautstärkeminderungen.

patches/3-8-2-4-spectral-delay.pd

Probieren Sie dies einmal mit einer bewegten Musik aus!

3.8.3 Appendix

3.8.3.1 fiddle~

Basierend auf dem fft-Algorithmus gibt es in Pd ein Objekt zur Erkennung von Lautstärke UND Tonhöhe. Es heißt „fiddle~“. Außerdem gibt es die Lautstärken der Teiltöne des Eingangssignals aus.

Als Argumente erhält es: 1. Fenstergröße (in Samples), 2. Anzahl der gleichzeitig zu erkennenden Töne (maximal drei verschiedene), 3. Anzahl der zu erkennenden Teiltöne, 4. Anzahl der auszugebenden Teiltöne. Default sind: 1. 1024, 2. 1, 3. 20, 4. 0. Als Outputs erhalten wir (von links nach rechts): 1. Tonhöhe in MIDI (nur bei Änderung), 2. Lautstärke in dB (nur bei starker Änderung („attack“)), 3. Tonhöhe und Lautstärke des Grundtones als Liste, 4. die Lautstärke insgesamt, 5. die einzelnen Teiltöne mit Lautstärke (in Hertz / rms!) als Liste.

patches/3-8-3-1-fiddle.pd

Messages für „fiddle~“: Damit nicht andauernd Werte ermittelt werden, kann der „Auto-Mode“ augeschaltet und statt dessen der „Poll-Mode“ aktiviert werden, bei dem nur Zahlen ausgegeben werden, wenn man mit dem Objekt eine "bang"-Message sendet:

Wir können die Fenstergröße bestimmen (Vielfache von zwei):

Höhere Teiltöne werden zur Ermittlung der Grundfrequenz weniger stark untersucht. Das kann aber geändert werden, in dem wir das Objekt anweisen, einen bestimmten Teilton zumindest mit der Hälfte der Stärke der Grundtonuntersuchung zu behandeln:

Dies ist hilfreich, wenn wir wissen, dass einige Teiltöne des Eingangssignals besonders stark sind (z.B. bei einer Klarinette der dritte Teilton).

Es gilt zu beachten: Eine Analyse des Eingangssignals wird alle halbe Fenstergröße durchgeführt, d.h. bei einer Fenstergröße von 1024 Samples alle 512 Samples, also alle 11.6 Millisekunden. Die minimale Frequenz, die „fiddle~“ erkennen kann ist, ist (44100/Fenstergröße)*2.5, also bei 1024 Samples ca. 108Hertz.

3.8.3.2 Stimmgerät

So können wir uns beispielsweise ein Stimmgerät erstellen:

patches/3-8-3-2-stimmgeraet.pd

Zur Visualierung wird hier ein Array mit nur einem Speicherplatz verwendet.

3.8.3.3 Oktavdoppler #2

Für den unter 3.4.2.9 beschriebenen Oktavdoppler kann man nun auch einen Mikrofoninput verwenden, sofern sich von diesem der Grundton grundsätzlich ermitteln lässt (am Eingang also ein periodisches Signal anliegt, das „fiddle~“ erfassen kann):

patches/3-8-3-3-oktavdoppler-fiddle.pd

3.8.3.4 Pitch Follower

Für das fiddle~ Objekt sind auf diese Weise viele interessante Anwendungen vorstellbar. Prototypisch ist, dass wir einen Mikrofoninput, etwa eine Singstimme haben und mit einem Sinuston die Melodie der Stimme wie mit einem Laserpointer quasi 'nachzeichnen':

Folgendes Dilemma wird hier ersichtlich: Bei „fiddle~“ ergibt sich immer eine Verzögerung. Diese ist umso kürzer, je kleiner die Fenstergröße ist. Doch je kleiner die Fenstergröße, desto weniger tief nach unten reicht die Erkennung der Tonhöhen. Außerdem ist das Resultat von „fiddle~“ immer auch etwas chaotisch. Wie man dies minimieren kann, erfahren wir unter 4.3.1.3

3.8.3.5 Weitere Aufgabenstellungen

Erstellen Sie statt dem einfachen 'Nachzeichnen' nun eine parallele Stimme im Quintabstand oder einen Akkord parallel.