Come posso implementare la correlazione incrociata per dimostrare che due file audio sono simili?


58

Devo fare la correlazione incrociata di due file audio per dimostrare che sono simili. Ho preso la FFT dei due file audio e ho i loro valori di spettro di potenza in array separati.

Come devo procedere ulteriormente per correlarli in modo incrociato e dimostrare che sono simili? C'è un modo migliore per farlo? Qualsiasi idea di base mi sarà utile per apprenderla e applicarla.


Data la correlazione incrociata di due vettori di segnali casuali. Come si implementa il contrario per ottenere i due vettori in MATLAB. John Muhehe

Risposte:


56

La correlazione incrociata e la convoluzione sono strettamente correlate. In breve, per fare la convoluzione con le FFT, tu

  1. azzerare i segnali di input (aggiungere zeri alla fine in modo che almeno metà dell'onda sia "vuota")
  2. prendere la FFT di entrambi i segnali
  3. moltiplicare i risultati insieme (moltiplicazione degli elementi)
  4. fare l'inverso FFT

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

Devi fare lo zero padding perché il metodo FFT è in realtà una correlazione incrociata circolare , il che significa che il segnale si avvolge alle estremità. Quindi aggiungi abbastanza zeri per sbarazzarti della sovrapposizione, per simulare un segnale che è zero fuori all'infinito.

Per ottenere la correlazione incrociata anziché la convoluzione, è necessario invertire il tempo di uno dei segnali prima di eseguire la FFT o prendere il coniugato complesso di uno dei segnali dopo la FFT:

  • 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)))

qualunque sia più facile con il tuo hardware / software. Per l'autocorrelazione (correlazione incrociata di un segnale con se stesso), è meglio eseguire il coniugato complesso, perché è quindi necessario calcolare l'FFT una sola volta.

Se i segnali sono reali, è possibile utilizzare FFT reali (RFFT / IRFFT) e risparmiare metà del tempo di calcolo calcolando solo metà dello spettro.

Inoltre, puoi risparmiare tempo di calcolo riempiendo le dimensioni con una dimensione maggiore per cui l'FFT è ottimizzato (come un numero 5-smooth per FFTPACK, un numero ~ 13-smooth per FFTW o una potenza di 2 per una semplice implementazione hardware).

Ecco un esempio in Python della correlazione FFT rispetto alla correlazione della forza bruta: https://stackoverflow.com/a/1768140/125507

Questo ti darà la funzione di correlazione incrociata, che è una misura di somiglianza vs offset. Per ottenere l'offset in corrispondenza del quale le onde sono "allineate" tra loro, ci sarà un picco nella funzione di correlazione:

picco nella funzione di correlazione

Il valore x del picco è l'offset, che potrebbe essere negativo o positivo.

L'ho visto solo per trovare l'offset tra due onde. È possibile ottenere una stima più precisa dell'offset (migliore della risoluzione dei campioni) utilizzando l'interpolazione parabolica / quadratica sul picco.

Per ottenere un valore di somiglianza tra -1 e 1 (un valore negativo che indica uno dei segnali diminuisce all'aumentare dell'altro) è necessario ridimensionare l'ampiezza in base alla lunghezza degli input, alla lunghezza della FFT, alla specifica implementazione della FFT ridimensionamento, ecc. L'autocorrelazione di un'onda con se stessa ti darà il valore della massima corrispondenza possibile.

Nota che funzionerà solo su onde che hanno la stessa forma. Se sono stati campionati su hardware diverso o hanno aggiunto del rumore, ma per il resto hanno ancora la stessa forma, questo confronto funzionerà, ma se la forma dell'onda è stata cambiata da filtri o sfasamenti, potrebbero suonare allo stesso modo, ma hanno vinto anche correlare.


3
L'imbottitura zero deve essere almeno N = size (a) + size (b) -1, preferibilmente arrotondata per eccesso a una potenza di 2. Per ottenere un valore compreso tra -1 e 1, dividere per norma (a) * norma (b ), che fornisce il coseno dell'angolo tra i due vettori nello spazio N per il ritardo specificato (ovvero spostamento circolare modulo N). Ai ritardi estremi, non ci sono molti campioni sovrapposti (solo uno all'estremo estremo), quindi la divisione per norma (a) * norma (b) distorcerà queste correlazioni verso 0 (cioè mostrando la loro ortogonalità relativa nello spazio N) .
Eryk Sun,

1
Penso che potrebbe esserci un errore nella descrizione. Moltiplicare gli FFT insieme termine per termine darebbe alla FFT la convoluzione dei segnali, non la FFT della correlazione incrociata ? A quanto ho capito, per ottenere la FFT della correlazione incrociata, è necessario utilizzare il coniugato complesso di uno dei vettori FFT nelle moltiplicazioni termine per termine prima di prendere l'IFFT.
Dilip Sarwate,

@DilipSarwate: Sì, hai ragione. Puoi anche invertire un segnale nella direzione del tempo, che ho aggiunto alla risposta.
endolith il

1
x[i]ix[±i]x[i](Ni)x[Ni]iil'aumento dei costi di cablaggio, i ritardi di cablaggio (e quindi riduce la frequenza di clock massima raggiungibile) e inoltre, poiché tutti i fili devono incrociarsi l'uno sull'altro, crea problemi di instradamento. Dovrebbe essere evitato, se possibile, e in questo caso, è evitabile.
Dilip Sarwate,

1
@Leo moltiplicazione degli elementi. array n-by-1 x array n-by-1 = array n-by-1 Nella risposta ho chiamato questo "esempio per campione".
endolito il

17

La correlazione è un modo per esprimere la somiglianza di due timeseries (campioni audio nel tuo caso) in un numero. È un adattamento della covarianza che viene implementato come segue:

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

La correlazione è la versione normalizzata della covarianza, che è la covarianza divisa per il prodotto delle deviazioni standard di entrambe le serie temporali. La correlazione produrrà uno 0 quando non vi è alcuna correlazione (totalmente non simile) e un 1 per la correlazione totale (totalmente simile).

Puoi immaginare che due campioni sonori potrebbero essere simili ma non sincronizzati. Ecco dove entra in gioco la correlazione incrociata . Calcolate la correlazione tra le serie temporali in cui ne avete una spostata di un campione:

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

Quindi cerca il valore massimo nella corrserie e il gioco è fatto. (o fermati se hai trovato una correlazione sufficiente) Ovviamente c'è qualcosa in più. Devi implementare la deviazione standard e devi fare un po 'di gestione della memoria e implementare le cose che cambiano tempo. Se tutti i tuoi campioni audio sono uguali in lunghezza, potresti fare a meno di normalizzare la covarianza e andare avanti e calcolare la covarianza incrociata.

Una bella relazione con la tua domanda precedente : l'analisi di Fourier è solo un adattamento della covarianza incrociata. Invece di spostare una serie temporale e calcolare le covarianze con l'altro segnale, si calcolano le covarianze tra un segnale e un numero di onde (co) sinusoidali con frequenze diverse. È tutto basato sullo stesso principio.


1
Hai detto che 0 non è correlazione e 1 è correlazioni totali. Voglio solo notare che -1 è completo negativamente correlato. Come in, -1 implica che il campione 1 è l'opposto del campione 2. Se ci pensate su un grafico X, Y, è una linea con pendenza positiva rispetto a una linea con pendenza negativa. E man mano che ti avvicini a 0 la linea diventa "più grassa".
Kellenjb,

@kellenjb, Sì, ma probabilmente direi, l'entità della correlazione a cui probabilmente sei interessato. Un 1 o un -1 significano che i segnali si influenzano direttamente a vicenda.
Kortuk,

14

Nell'elaborazione del segnale la correlazione incrociata (xcorr in MATLAB) è un'operazione di convoluzione con una delle due sequenze invertite. Poiché l'inversione del tempo corrisponde a una coniugazione complessa nel dominio della frequenza, è possibile utilizzare il DFT per calcolare la correlazione incrociata come segue:

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

dove N = size (x) + size (y) - 1 (preferibilmente arrotondato per eccesso di potenza a 2) è la lunghezza del DFT.

La moltiplicazione dei DFT equivale alla convoluzione circolare nel tempo. L'imbottitura zero di entrambi i vettori alla lunghezza N impedisce ai componenti spostati in modo circolare di y di sovrapporsi con x, il che rende il risultato identico alla convoluzione lineare di xe al tempo invertito y.

Un ritardo di 1 è uno spostamento circolare destro di y, mentre un ritardo di -1 è uno spostamento circolare sinistro. La correlazione incrociata è semplicemente la sequenza di prodotti punto per tutti i ritardi. In base all'ordinamento fft standard, questi saranno in un array a cui è possibile accedere come segue. Gli indici da 0 a dimensione (x) -1 sono i ritardi positivi. Gli indici di dimensioni N (y) da +1 a N-1 sono i ritardi negativi in ​​ordine inverso. (In Python è possibile accedere comodamente ai ritardi negativi con indici negativi come R_xy [-1].)

Puoi pensare a x e y con spaziatura zero come vettori N-dimensionali. Il prodotto punto di xey per un determinato ritardo è |x|*|y|*cos(theta). Le norme di xey sono costanti per gli spostamenti circolari, quindi la loro divisione lascia solo il coseno variabile dell'angolo theta. Se xey (per un dato ritardo) sono ortogonali nello spazio N, la correlazione è 0 (cioè theta = 90 gradi). Se sono co-lineari, il valore è 1 (correlato positivamente) o -1 (correlato negativamente, cioè theta = 180 gradi). Questo porta alla correlazione incrociata normalizzata all'unità:

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

Questo può essere reso imparziale ricalcolando le norme solo per le parti sovrapposte, ma poi puoi anche fare l'intero calcolo nel dominio del tempo. Inoltre, vedrai diverse versioni di normalizzazione. Invece di essere normalizzato all'unità, a volte la correlazione incrociata è normalizzata da M (di parte), dove M = max (dimensione (x), dimensione (y)) o M- | m | (una stima imparziale del mth lag).

Per la massima significatività statistica, la media (polarizzazione DC) deve essere rimossa prima di calcolare la correlazione. Questo è chiamato cross-covariance (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))

Questo significa che la dimensione finale dell'array dovrebbe essere 2*size (a) + size(b) - 1o 2*size (b) + size (a) - 1? Ma in entrambi i casi i due array imbottiti sono di dimensioni diverse. Qual è la conseguenza del riempimento con troppi zeri?

2

@RobertKJ: Stai scorrevole binsieme a, con un'uscita per turno, una sovrapposizione minima di un campione. Ciò produce size(a)ritardi positivi e size(b) - 1ritardi negativi. Usando la trasformata inversa del prodotto dei DFT del punto N, gli indici 0attraverso size(a)-1sono i ritardi positivi e gli indici N-size(b)+1attraverso N-1sono i ritardi negativi in ​​ordine inverso.
Eryk Sun,

3

se stai usando Matlab prova la funzione di correlazione incrociata:

c= xcorr(x,y)

Ecco la documentazione di Matlab:

xcorrstima la sequenza di correlazione incrociata di un processo casuale. L'autocorrelazione viene gestita come un caso speciale.

...

c = xcorr(x,y)restituisce la sequenza di correlazione incrociata in un vettore lunghezza 2 * N-1, dove xe ysono Nvettori lunghezza ( N > 1). Se xe ynon hanno la stessa lunghezza, il vettore più corto viene arrotondato per zero alla lunghezza del vettore più lungo.

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


Il collegamento sembra essere rotto.
Danijel,

2

Un modo rapido e semplice per confrontare i file audio. Prendi il file audio, creane una copia, in un daw, incollali fianco a fianco, in 2 canali stereo, inverti la fase su una delle tracce stereo, allinea entrambi i file all'inizio in modalità zoom, assicurati che il entrambi i file hanno la stessa ampiezza all'inizio, quindi riproducono, se c'è silenzio totale, quindi entrambi i file sono identici, se c'è una differenza lo sentirai abbastanza chiaramente !.


1

Come molti qui hanno scritto, dovresti usare la correlazione.

Prendi in considerazione solo 2 fattori:

  1. Se il volume viene ridimensionato in modo diverso, è necessario normalizzare la correlazione.
  2. In caso di ridimensionamento del tempo, è possibile utilizzare la funzione Dynamic Time Warping.

1

Per i segnali non periodici (dimensione (y) -1) deve essere sottratto dall'indice di R_xy per ottenere il ritardo effettivo.

N = dimensione (x) + dimensione (y) - 1;

ritardi = [0, N] - (dimensione (y) - 1);


0

Il modo più semplice per trovare la differenza, IMO, è sottrarre i due segnali audio nel dominio del tempo. Se sono uguali, il risultato in ogni momento sarà zero. Se non sono uguali, la differenza tra loro verrà lasciata dopo la sottrazione e potrai ascoltarla direttamente. Una rapida misura di quanto siano simili sarebbe il valore RMS di questa differenza. Questo è spesso fatto nel mixaggio audio e mastering per ascoltare la differenza di un file MP3 vs WAV, ad esempio. (Invertire la fase di un segnale e aggiungerli equivale a sottrarre. Questo è il metodo usato quando questo viene fatto nel software DAW.) Per funzionare, devono essere perfettamente allineati nel tempo. In caso contrario, è possibile sviluppare un algoritmo per allinearli, ad esempio il rilevamento dei dieci picchi principali, il calcolo dell'offset medio dei picchi e lo spostamento di un segnale.

Trasformarsi nel dominio della frequenza e confrontare gli spettri di potenza dei segnali come si propone è ignorare alcune informazioni sul dominio del tempo. Ad esempio, l'audio riprodotto al contrario avrebbe lo stesso spettro se riprodotto in avanti. Pertanto, due segnali audio molto diversi potrebbero avere lo stesso spettro esatto.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.