Wie implementiere ich Kreuzkorrelation, um zu beweisen, dass zwei Audiodateien ähnlich sind?


58

Ich muss eine Kreuzkorrelation zwischen zwei Audiodateien herstellen, um zu beweisen, dass sie ähnlich sind. Ich habe die FFT der beiden Audiodateien genommen und deren Leistungsspektrumswerte in separaten Arrays gespeichert.

Wie soll ich weiter vorgehen, um eine Kreuzkorrelation herzustellen und zu beweisen, dass sie ähnlich sind? Gibt es einen besseren Weg, es zu tun? Grundlegende Ideen helfen mir, sie zu lernen und anzuwenden.


Angesichts der Kreuzkorrelation zweier zufälliger Signalvektoren. Wie implementiert man das Gegenteil, um die beiden Vektoren in MATLAB zu erhalten? John Muhehe

Antworten:


56

Kreuzkorrelation und Faltung sind eng miteinander verbunden. Kurz gesagt, um mit FFTs Faltung zu machen, Sie

  1. Null-Pad für die Eingangssignale (fügen Sie am Ende Nullen hinzu, so dass mindestens die Hälfte der Welle "leer" ist)
  2. nimm die FFT beider Signale
  3. Multiplizieren Sie die Ergebnisse (elementweise Multiplikation)
  4. mache die inverse FFT

conv(a, b) = ifft(fft(a_and_zeros) * fft(b_and_zeros))

Sie müssen das Auffüllen mit Nullen durchführen, da es sich bei der FFT-Methode um eine zirkuläre Kreuzkorrelation handelt, dh, das Signal wird an den Enden herumgewickelt. Sie addieren also genügend Nullen, um die Überlappung zu beseitigen und ein Signal zu simulieren, das null bis unendlich ist.

Um Kreuzkorrelation statt Faltung zu erhalten, müssen Sie entweder eines der Signale vor der FFT zeitlich umkehren oder das komplexe Konjugat eines der Signale nach der FFT nehmen:

  • corr(a, b) = ifft(fft(a_and_zeros) * fft(b_and_zeros[reversed]))
  • corr(a, b) = ifft(fft(a_and_zeros) * conj(fft(b_and_zeros)))

je nachdem, was mit Ihrer Hardware / Software einfacher ist. Für die Autokorrelation (Kreuzkorrelation eines Signals mit sich selbst) ist es besser, das komplexe Konjugat durchzuführen, da Sie dann die FFT nur einmal berechnen müssen.

Wenn die Signale echt sind, können Sie echte FFTs (RFFT / IRFFT) verwenden und die Hälfte Ihrer Rechenzeit sparen, indem Sie nur die Hälfte des Spektrums berechnen.

Sie können auch Rechenzeit sparen, indem Sie eine größere Größe auffüllen, für die die FFT optimiert ist (z. B. eine 5-glatte Zahl für FFTPACK, eine ~ 13-glatte Zahl für FFTW oder eine Potenz von 2 für eine einfache Hardwareimplementierung).

Hier ist ein Beispiel der Python-FFT-Korrelation im Vergleich zur Brute-Force-Korrelation: https://stackoverflow.com/a/1768140/125507

Dadurch erhalten Sie die Kreuzkorrelationsfunktion, die ein Maß für die Ähnlichkeit gegenüber dem Offset ist. Um den Versatz zu erhalten, bei dem die Wellen "aneinandergereiht" sind, gibt es eine Spitze in der Korrelationsfunktion:

Peak in der Korrelationsfunktion

Der x-Wert des Peaks ist der Offset, der negativ oder positiv sein kann.

Ich habe nur gesehen, dass dies verwendet wurde, um den Versatz zwischen zwei Wellen zu finden. Sie können eine genauere Schätzung des Offsets (besser als die Auflösung Ihrer Proben) erhalten, indem Sie eine parabolische / quadratische Interpolation für den Peak verwenden.

Um einen Ähnlichkeitswert zwischen -1 und 1 zu erhalten (ein negativer Wert, der anzeigt, dass eines der Signale abnimmt, wenn das andere zunimmt), müssen Sie die Amplitude entsprechend der Länge der Eingänge, der Länge der FFT und Ihrer speziellen FFT-Implementierung skalieren Skalierung usw. Die Autokorrelation einer Welle mit sich selbst gibt Ihnen den Wert der maximal möglichen Übereinstimmung.

Beachten Sie, dass dies nur bei Wellen funktioniert, die dieselbe Form haben. Wenn sie auf einer anderen Hardware abgetastet wurden oder Rauschen hinzugefügt wurden, aber ansonsten immer noch dieselbe Form haben, funktioniert dieser Vergleich. Wenn die Wellenform jedoch durch Filterung oder Phasenverschiebung geändert wurde, klingen sie möglicherweise gleich, haben aber gewonnen auch nicht korrelieren.


3
Der Nullabstand sollte mindestens N = Größe (a) + Größe (b) -1 sein, vorzugsweise auf eine Potenz von 2 aufgerundet. Um einen Wert zwischen -1 und 1 zu erhalten, dividieren Sie durch Norm (a) * Norm (b) ), der den Cosinus des Winkels zwischen den beiden Vektoren im N-Raum für die gegebene Verzögerung angibt (zirkulares Shift-Modulo N). Bei den extremen Verzögerungen gibt es nicht viele überlappende Samples (nur eines im äußersten Extrem). Wenn Sie also durch Norm (a) * Norm (b) dividieren, werden diese Korrelationen in Richtung 0 verschoben (dh, sie zeigen ihre relative Orthogonalität im N-Raum). .
Eryk Sun

1
Ich denke, es könnte ein Fehler in der Beschreibung sein. Sollte das Multiplizieren der FFTs mit jedem Term nicht die FFT der Faltung der Signale ergeben, nicht die FFT der Kreuzkorrelation ? Um die FFT der Kreuzkorrelation zu erhalten, ist es meines Wissens erforderlich, das komplexe Konjugat eines der FFT-Vektoren in den termweisen Multiplikationen zu verwenden, bevor die iFFT genommen wird.
Dilip Sarwate

@ DilipSarwate: Ja, du hast recht. Sie können auch ein Signal in Zeitrichtung umkehren, was ich der Antwort hinzugefügt habe.
Endolith

1
x[i]ix[±i]x[i](Ni)x[Ni]iiErhöhen der Verdrahtungskosten, Verzögerungen bei der Verdrahtung (und damit die maximal erreichbare Taktrate) und das Überkreuzen aller Drähte verursachen Routingprobleme. Es sollte möglichst vermieden werden, und in diesem Fall ist es ist vermeidbar.
Dilip Sarwate

1
@Leo elementweise Multiplikation. n-mal-1-Array x n-mal-1-Array = n-mal-1-Array Ich habe dies in der Antwort "Stichprobenweise" genannt.
Endolith

17

Korrelation ist eine Möglichkeit, die Ähnlichkeit von zwei Zeitreihen (in Ihrem Fall Audio-Samples) in einer Zahl auszudrücken. Es ist eine Anpassung der Kovarianz, die wie folgt implementiert wird:

period = 1/sampleFrequency;
covariance=0;

for (iSample = 0; iSample<nSamples; iSample++)
    covariance += (timeSeries_1(iSample)*timeSeries_2(iSample))/period;
    //Dividing by `period` might not even be necessary

Die Korrelation ist die normalisierte Version der Kovarianz, bei der es sich um die Kovarianz handelt, die durch das Produkt der Standardabweichungen beider Zeitreihen dividiert wird. Die Korrelation ergibt eine 0, wenn keine Korrelation vorliegt (absolut nicht ähnlich), und eine 1 für die totale Korrelation (absolut ähnlich).

Sie können sich vorstellen, dass zwei Klangbeispiele ähnlich, aber nicht synchronisiert sind. Das ist , wo Kreuzkorrelation kommen Sie die Korrelation zwischen der Zeitreihe zu berechnen , wo Sie haben eine von ihnen durch eine Probe verschoben.:

for (iShift=0; iShift<nSamples; iShift++)
    xcorr(iShift) = corr(timeSeries_1, timeSeries_2_shifted_one_sample);

Suchen Sie dann den Maximalwert in der corrReihe und Sie sind fertig. (oder hören Sie auf, wenn Sie eine ausreichende Korrelation gefunden haben) Natürlich steckt etwas mehr dahinter. Sie müssen die Standardabweichung implementieren und Sie müssen etwas Speicherverwaltung durchführen und das zeitversetzte Zeug implementieren. Wenn alle Audio-Samples gleich lang sind, müssen Sie möglicherweise die Kovarianz nicht normalisieren und die Cross-Kovarianz berechnen.

Eine coole Beziehung zu Ihrer früheren Frage : Die Fourier-Analyse ist nur eine Anpassung der Kreuz-Kovarianz. Anstatt eine Zeitreihe zu verschieben und die Kovarianzen mit dem anderen Signal zu berechnen, berechnen Sie die Kovarianzen zwischen einem Signal und einer Anzahl von (Co) Sinuswellen mit unterschiedlichen Frequenzen. Es basiert alles auf dem gleichen Prinzip.


1
Sie haben erwähnt, dass 0 keine Korrelation und 1 Gesamtkorrelationen sind. Ich möchte nur feststellen, dass -1 vollständig negativ korreliert ist. Wie in impliziert -1, dass Beispiel 1 das Gegenteil von Beispiel 2 ist. Wenn Sie in einem X-, Y-Diagramm darüber nachdenken, ist es eine Linie mit positiver Steigung gegenüber einer Linie mit negativer Steigung. Und wenn Sie sich 0 nähern, wird die Linie "dicker".
Kellenjb

@kellenjb, ja, aber ich würde wahrscheinlich sagen, die Größe der Korrelation, an der Sie wahrscheinlich interessiert sind. Eine 1 oder eine -1 bedeuten, dass die Signale sich direkt gegenseitig beeinflussen.
Kortuk

13

Bei der Signalverarbeitung ist die Kreuzkorrelation (xcorr in MATLAB) eine Faltungsoperation, bei der eine der beiden Sequenzen umgekehrt ist. Da die Zeitumkehrung einer komplexen Konjugation im Frequenzbereich entspricht, können Sie die DFT verwenden, um die Kreuzkorrelation wie folgt zu berechnen:

R_xy = ifft(fft(x,N) * conj(fft(y,N)))

Dabei ist N = Größe (x) + Größe (y) - 1 (vorzugsweise auf eine Potenz von 2 aufgerundet) die Länge der DFT.

Die Multiplikation von DFTs entspricht einer zirkulären Faltung in der Zeit. Das Null-Auffüllen beider Vektoren auf die Länge N verhindert, dass sich die zirkular verschobenen Komponenten von y mit x überlappen, wodurch das Ergebnis mit der linearen Faltung von x und der Zeitumkehrung von y identisch wird.

Eine Verzögerung von 1 ist eine Verschiebung des rechten Kreises um y, während eine Verzögerung von -1 eine Verschiebung des linken Kreises ist. Die Kreuzkorrelation ist einfach die Folge von Punktprodukten für alle Verzögerungen. Basierend auf der Standard-FFT-Bestellung befinden sich diese in einem Array, auf das wie folgt zugegriffen werden kann. Die Indizes 0 bis Größe (x) -1 sind die positiven Verzögerungen. Die Indizes N-Größe (y) +1 bis N-1 sind die negativen Verzögerungen in umgekehrter Reihenfolge. (In Python kann auf die negativen Verzögerungen bequem mit negativen Indizes wie R_xy [-1] zugegriffen werden.)

Sie können sich die mit Nullen aufgefüllten x und y als n-dimensionale Vektoren vorstellen. Das Skalarprodukt von x und y für eine gegebene Verzögerung ist |x|*|y|*cos(theta). Die x- und y-Normen sind für kreisförmige Verschiebungen konstant. Wenn Sie sie also aufteilen, bleibt nur der variierende Cosinus des Winkels Theta übrig. Wenn x und y (für eine gegebene Verzögerung) im N-Raum orthogonal sind, ist die Korrelation 0 (dh Theta = 90 Grad). Wenn sie kolinear sind, ist der Wert entweder 1 (positiv korreliert) oder -1 (negativ korreliert, dh Theta = 180 Grad). Dies führt zu der Kreuzkorrelation, die auf Eins normiert ist:

R_xy = ifft(fft(x,N) * conj(fft(y,N))) / (norm(x) * norm(y))

Dies kann vorurteilsfrei gemacht werden, indem die Normen nur für die überlappenden Teile neu berechnet werden. Sie können jedoch auch die gesamte Berechnung im Zeitbereich durchführen. Außerdem sehen Sie verschiedene Versionen der Normalisierung. Manchmal wird die Kreuzkorrelation nicht auf 1 normiert, sondern auf M (voreingenommen), wobei M = max (Größe (x), Größe (y)) oder M- | m | (eine unvoreingenommene Schätzung der m. Verzögerung).

Für maximale statistische Signifikanz sollte der Mittelwert (DC Bias) vor der Berechnung der Korrelation entfernt werden. Dies nennt man die Cross-Kovarianz (xcov in MATLAB):

x2 = x - mean(x)
y2 = y - mean(y)
phi_xy = ifft(fft(x2,N) * conj(fft(y2,N))) / (norm(x2) * norm(y2))

Bedeutet dies, dass die endgültige Größe des Arrays sein sollte 2*size (a) + size(b) - 1oder 2*size (b) + size (a) - 1? In beiden Fällen sind die beiden gepolsterten Arrays jedoch unterschiedlich groß. Was ist die Folge des Auffüllens mit zu vielen Nullen?

2

@RobertKJ: Sie Gleiten bentlang amit einem Ausgang pro Schicht, eine minimale Überlappung von einer Probe. Das ergibt size(a)positive und size(b) - 1negative Verzögerungen. Unter Verwendung der inversen Transformation des Produkts von N-Punkt-DFTs sind die Indizes 0durch size(a)-1die positiven Verzögerungen und die Indizes N-size(b)+1durch N-1die negativen Verzögerungen in umgekehrter Reihenfolge.
Eryk So

3

Wenn Sie Matlab verwenden, probieren Sie die Kreuzkorrelationsfunktion aus:

c= xcorr(x,y)

Hier ist die Matlab-Dokumentation:

xcorrschätzt die Kreuzkorrelationssequenz eines zufälligen Prozesses. Autokorrelation wird als Sonderfall behandelt.

...

c = xcorr(x,y)gibt die Kreuzkorrelationssequenz in einem Vektor der Länge 2 * N-1 zurück, wobei xund yLängenvektoren N( N > 1) sind. Wenn xund ynicht gleich lang sind, wird der kürzere Vektor auf die Länge des längeren Vektors aufgefüllt.

Korrelation http://www.mathworks.com/help/toolbox/signal/ref/eqn1263487323.gif


Die Verbindung scheint unterbrochen zu sein.
Danijel

2

Eine schnelle und einfache Möglichkeit, Audiodateien zu vergleichen. Nehmen Sie die Audiodatei, kopieren Sie sie, fügen Sie sie in einer Morgendämmerung nebeneinander in 2 Stereokanäle ein, vertauschen Sie die Phase auf einer der Stereospuren, richten Sie beide Dateien am Anfang im Zoommodus aus, und achten Sie darauf, dass die beide dateien haben am anfang die gleiche amplitude, dann spielen sie ab, wenn es absolute stille gibt, dann sind beide dateien identisch, wenn es einen unterschied gibt, hören sie das ziemlich deutlich !.


1

Wie die meisten hier geschrieben haben, sollten Sie Korrelation verwenden.

Nehmen Sie einfach 2 Faktoren in Betracht:

  1. Wenn das Volumen unterschiedlich skaliert ist, sollten Sie die Korrelation normalisieren.
  2. Wenn die Zeit skaliert ist, können Sie Dynamic Time Warping verwenden.

0

Der einfachste Weg, den Unterschied zu finden, besteht darin, die beiden Audiosignale im Zeitbereich zu subtrahieren. Wenn sie gleich sind, ist das Ergebnis zu jedem Zeitpunkt Null. Wenn sie nicht gleich sind, bleibt der Unterschied zwischen ihnen nach der Subtraktion bestehen und Sie können ihn direkt anhören. Ein schnelles Maß dafür, wie ähnlich sie sind, wäre der Effektivwert dieser Differenz. Dies geschieht häufig beim Mischen und Mastern von Audiodaten, um beispielsweise den Unterschied zwischen MP3- und WAV-Dateien zu erkennen. (Das Invertieren und Addieren der Phase eines Signals entspricht dem Subtrahieren. Dies ist die Methode, die in der DAW-Software verwendet wird.) Sie müssen zeitlich perfekt aufeinander abgestimmt sein, damit dies funktioniert. Wenn dies nicht der Fall ist, können Sie einen Algorithmus entwickeln, um sie auszurichten, z. B. die Top-Ten-Peaks zu ermitteln, den durchschnittlichen Offset der Peaks zu berechnen und ein Signal zu verschieben.

Beim Transformieren in den Frequenzbereich und Vergleichen der Leistungsspektren der von Ihnen vorgeschlagenen Signale werden einige Zeitbereichsinformationen ignoriert. Beispielsweise würde umgekehrt wiedergegebenes Audio bei Vorwärtswiedergabe dasselbe Spektrum aufweisen. Somit könnten zwei sehr unterschiedliche Audiosignale genau dasselbe Spektrum haben.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.