Die Frequenzerkennung (engl. Pitch detection, frequency detection) ist ein Prozess, mit dem man die dominantesten Frequenzen eines Audio-Abschnitts berechnet. Hierbei muss betont werden, dass ein Audio-Abschnitt nicht eine einzige Schwingung mit einer Frequenz besitzt. Er ist vielmehr eine Zusammensetzung von vielen Grundschwingungen, die sich zu jedem Zeitpunkt ändert. Wir nehmen z.B. die Gitarre: Wenn wir eine Saite zupfen, entstehen mehrere harmonische Grundschwingungen und ein paar nicht-harmonische Störschwingungen, die der Natur des Instruments geschuldet sind. Wir hören quasi ein „Bouqet“ aus Grundschwingungen. Wir als Menschen, nehmen deuten (zumindest oft) die dominanteste Schwingung als Grundfrequenz wahr. Die Aufgabe ist nun also diese Grundfrequenzen herauszufinden. Das ist eine sehr heikle Aufgabe, weil

  • die Amplituden der dominantesten Schwingungen sich kontinuierlich ändern
  • die dominanteste Schwingung sich im Laufe des Sample-Abschnitts ändern kann, (obwohl der ganze Sample auf eine Note deuten kann)

Die Anforderungen an einen Tuner können folgendermaßen zusammengefasst werden:

  • Aktualisierungsrate > f_s=10Hz
  • Minimale Frequenz: f_{min}=27,5Hz (A0)
  • Maximale Frequenz= f_{max}=440Hz (A4)
  • Messgenauigkeit:= \Delta_{max}=1cent
  • Effiziente Berechnung (abhängig vom eingesetzten DSP)

Mathematische Ansätze

Es gibt verschiedene mathematische Ansätze für die Umsetzung der Frequenzbestimmung:

  • Fourier-Transformation
  • Hartley-Transformation
  • Auto-Correlation

Die Fourier und Hartley-Transformationen basieren auf den Ansatz, dass man das Signal erst in Frequenzbereich transformiert und das Frequenzspektrum ermittelt. Für niedrige Frequenzen kann das eine geeignete Methode sein, um 1 Cent Genauigkeit zu erreichen. Allerdings wird die Transformation sehr langsam, wenn wir das Spektrum über mehrere 100Hz mit Hundertstel-Hertz-Genauigkeit ermitteln wollen. Denn die Genauigkeit der Fourier-Transformation müssen wir über das ganze Spektrum festlegen. Anders bei der Auto-Korrelation:

Auto Korrelation

Das Prinzip der Auto-Korrelation (Selbst-Übereinstimmung) ist relativ einfach. Wir multiplizieren unser Signal mit sich selbst mit einem zeitlichen Offset. Danach erhalten wir einen skalaren Wert. Dieser Wert gibt uns eine quantitative Aussage darüber, wie das Signal bei diesem Offset mit sich selbst übereinstimmt. Wenn wir dann die Offsets finden, bei denen die Korrelation am Höchsten ist, können wir daraus die Frequenzen ermitteln. Die Frequenz wäre dann einfach der Kehrwert vom Offset.

Der Algorithmus sieht folgendermaßen aus:

(1)   \begin{equation*} AC(\delta)=\sum_{i=1}^{n} y(i) \cdot y(i-\delta) \end{equation*}

oder wenn das Signal im Puffer vorliegt, auch vorwärts berechnend:

(2)   \begin{equation*} AC(\delta)=\sum_{i=1}^{n} y(i) \cdot y(i+\delta) \end{equation*}

Dann erhalten wir einen Auto-Korrelationswert AC für das Offset \delta. Die Anzahl der Samples n, über die wir diesen Wert berechnen muss

  • so groß wie möglich sein, um niedrige Frequenzen abbilden zu können und
  • so klein wie möglich sein, um die Anzahl der Multiplikationen zu reduzieren.

Wenn wir bei der Messung von f_{max}=440Hz eine Genauigkeit von 1 cent haben wollen, bedeutet das eine Frequenzgenauigkeit F_{\Delta}

(3)   \begin{equation*} F_{\Delta}=440 \cdot 2^{\frac{1}{1200}}-440=0.254Hz \end{equation*}

Auf der anderen Seite, wenn wir tiefe Frequenzen gut auflösen wollen, brauchen wir einen Sampleabschnitt, der ein paar volle Schwingungen beinhaltet. Bei 4 mal 20Hz Schwingungen ergibt sich eine Sample-Anzahl von

(4)   \begin{equation*} n_{27,5Hz}=48000/27,5 \cdot 4= 6981 \end{equation*}

Also wenn wir den ganzen Frequenzbereich mit 0,3Hz Genauigkeit scannen und daraus die Autokorrelation von allen Frequenzen mit 9600 Samples berechnen, beträgt der Rechenaufwand

(5)   \begin{equation*} O_{MAC}=[(440-27,5)/0.28] 6981=10284508 \end{equation*}

Multiplikation und Additionen. Das bedeutet rund 10,2Mio. Operationen pro Scan. Bei einer Aktualisierungsrate von f_S=10Hz brauchen wir 200Mio. Rechenoperationen pro Scan – nur um Autokorrelationswerte zu berechnen. Also dieser primitiver Ansatz ist nicht geeignet, um die Frequenz auf eine effiziente Weise zu berechnen.

Ein effizienter Ansatz zur Frequenzbestimmung

Wenn wir nur an ein paar dominanten Frequenzen interessiert sind, müssen wir nicht die Auto-Korrelationswerte für das ganze Spektrum mit feiner Auflösung berechnen. Daraus entstehen einige Optimierungsansätze: Man kann erst den groben Bereich der dominanten Frequenzen berechnen und dann diese in dem Bereich suchen. Dieser Ansatz ist im unteren Diagramm dargestellt.

Die einzelnen Schritte dieses Ansatzes ist im Folgenden erklärt.

Das Spektrum RASTERN

Zuerst wollen wir das Spektrum zwischen A0 und A4, also 27,5Hz und 440Hz in so wenig wie möglich Raster teilen, bei denen wir uns sicher sind, dass nicht mehrere dominante Frequenzen drin vorkommen können. Im vorliegenden Fall möchten wir die dominante Frequenz eines Musikinstruments, konkreter Gitarre und Bassgitarre ermitteln. Für den Zweck bietet es sich an, die chromatischen Notenfrequenzen als Raster zu nehmen. Unten sind die Noten von 27,5Hz bis 440 Hz dargestellt.

Notenfrequenzen

Notenfrequenzen

Das heißt, wir können das Spektrum, dass uns interessiert, erstmal in 49 Blöcke teilen. Dann berechnen wir nur den AC-Wert, der uns interessiert. Wir ermitteln hier die Information: „Um welche Note geht’s denn überhaupt?

Zudem: Die Wahl der Noten nach chromatischen Frequenzen bei 440Hz-Stimmung, ist auch eine strategische Wahl. Denn: Die gefundenen Noten aus diesem Array werden genommen, um in ihrer Nähe nach der exakten Frequenz zu suchen. Diese Noten sind auch die erste Schätzung für die Suche. Mit der Annahme, dass dieser Algorithmus als chromatischer Tuner bei einem 440Hz-gestimmten Instrument benutzt werden soll, erwarten wir oft eine Übereinstimmung in unmittelbarer Nähe.

Zunächst werden diese Frequenzen als Offsets \delta in einem Array gespeichert:

(6)   \begin{equation*} \delta(f)=f_s/f \end{equation*}

Wir denken ab nun nicht mehr in Frequenzen f sondern in Offsets \delta.

Erforderliche Sample-Anzahl n für die Raster berechnen

Wie bereits erwähnt, brauchen wir bei tieferen Frequenzen mehr Samples für die Auto-Korrelation-Berechnung als bei höheren Frequenzen. Dafür muss man sich eine Art Güte ausdenken. Wenn man sich z.B. für eine Güte von 4 vornimmt, bedeutet das, dass man 4 volle Schwingungen einer Frequenz für die Auto-Korrelationsberechnung braucht. Das ergibt

(7)   \begin{equation*} n(\delta)=[f_s/f] \psi \end{equation*}

bei der Güte \psi.

Die Implementierung würde folgendermaßen aussehen:

Auto-Korrelationswert berechnen

Die Berechnung vom Auto-Korrelationswert ist oben beschrieben. Je nach Hardwareressourcen kann dies z.B. folgendermaßen implementiert werden.

Auto-Korrelationswert normieren

Wir haben variable Anzahl an Samples für jede Frequenz, da wir erstens tiefe Frequenzen erfassen können, andererseits bei höheren Frequenzen Ressourcen sparen wollen. Daraus ergeben sich Auto-Korrelationswerte, die nicht untereinander vergleichbar sind. Wir normieren diese deshalb nach der Länge der Samples, mit denen sie berechnet wurden. Damit kann man die Amplituden einzelner Raster miteinander vergleichen.

Extrema des Spektrums (PEAKS) ermitteln

Jetzt haben wir das Spektrum, d.h. die AC-Werte für jeden Rasterpunkt, ermittelt. Wir müssen nun dort herausfiltern, welche Offsets wir brauchen. Dieser Teil ist etwas „tricky“ und beruht auf folgenden Erfahrungswerten für Gitarren und Bass-Stimmung:

  1. Bei einer Einzelsaite entstehen u. a. zwei deutlich dominante Peaks.
  2. Die Peaks sind die ersten Harmonischen voneinander (f_1/f_2=2)
  3. Die Amplituden der beiden Peaks sind sehr ähnlich und wechseln sich oft beim Ausklingen.
  4. Der tiefere Peak ist aussagekräftiger, da man dadurch die Frequenz (ohne Oversampling) präziser messen kann (n_2>n_1)

Deshalb versuchen wir im folgenden Schritt

  1. Zwei dominanteste Offsets (Peaks) aussuchen
  2. Diese sortieren

Das wird folgendermaßen implementiert.

Nach den exakten Frequenzen (Offsets) suchen

Wir haben nun zwei Frequenzen ermittelt, bei denen wir wissen, unsere gesuchte Frequenz liegt in deren unmittelbare Nähe. Man kann sich das ungefähr folgendermaßen vorstellen:

Rendered by QuickLaTeX.com

Es existieren zahlreiche Suchalgorithmen. Je nach Anwendung können diese Vor- und Nachteile haben. Eine Übersicht ist hier verfügbar. In dem Fall bieten sich hauptsächlich zwei Suchalgorithmen

Die Wahl zwischen diesen Algorithmen sind im vorliegenden Fall schwierig. Wenn die gesuchte Frequenz in der Ferne liegt, ist binäre Suche vorteilhafter. Wenn diese aber in der Nähe liegt, ist lineare Suche vorteilhafter.

Die Implementierung dieser Suche ist folgendermaßen zu realisieren:

Stochastische Abschätzung der GESUCHTEN Frequenz

Nachdem die exakten zwei Frequenzen ermittelt wurden, merkt man, dass dieser Wert in einem kleinen Intervall schwankt, was der Natur der Instrumente geschuldet ist. Nun muss

  • die Plausibilität der berechneten Frequenzen bewertet und
  • der Frequenzverlauf gemittelt werden,

damit der Benutzer eine vernünftige Frequenz- bzw. Notenanzeige hat. Dafür wird eine Toleranz \sigma eingeführt, innerhalb dessen die Frequenz schwanken darf. Wenn eine Messung diese Toleranz überschreitet, vermutet man ein Notenwechsel. Also entweder wird eine andere Saite gezupft oder so stark korrigiert, dass man diese Messung nicht mehr in die Mittelung einfließen darf. Danach wird die Mittelung zurückgesetzt und weiterhin auf eine Messungfolge gewartet, wo alle Messungswerte innerhalb der Toleranz liegen. Danach wird die Note wieder gezeigt.

Die Implementierung kann folgendermaßen aussehen:

Ressourcen

Hiermit wurde der Ablauf einer Frequenzermittlung für eine Tuner-Applikation gezeigt. Der vollständige Target-Code für DSP und der Simulationscode für Windows kann vom GitHub heruntergeladen werden.