Como implemento a correlação cruzada para provar que dois arquivos de áudio são semelhantes?


58

Eu tenho que fazer a correlação cruzada de dois arquivos de áudio para provar que são semelhantes. Peguei a FFT dos dois arquivos de áudio e tenho seus valores de espectro de potência em matrizes separadas.

Como devo proceder para correlacioná-los e provar que eles são semelhantes? Há uma melhor forma de fazê-lo? Quaisquer idéias básicas serão úteis para eu aprender e aplicá-las.


Dada a correlação cruzada de dois vetores de sinal aleatórios. Como você implementa o inverso para obter os dois vetores no MATLAB. John Muhehe

Respostas:


56

A correlação cruzada e a convolução estão intimamente relacionadas. Em resumo, para fazer convolução com FFTs, você

  1. zere os sinais de entrada (adicione zeros no final para que pelo menos metade da onda fique "em branco")
  2. pegue a FFT de ambos os sinais
  3. multiplique os resultados juntos (multiplicação por elementos)
  4. faça a FFT inversa

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

Você precisa fazer o preenchimento zero, porque o método FFT é na verdade correlação cruzada circular , o que significa que o sinal passa pelas extremidades. Então, você adiciona zeros suficientes para se livrar da sobreposição, para simular um sinal que é zerado até o infinito.

Para obter correlação cruzada em vez de convolução, você precisa reverter o tempo de um dos sinais antes de executar a FFT ou usar o complexo conjugado de um dos sinais após a 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)))

o que for mais fácil com o seu hardware / software. Para autocorrelação (correlação cruzada de um sinal consigo mesmo), é melhor fazer o conjugado complexo, porque então você só precisa calcular a FFT uma vez.

Se os sinais são reais, você pode usar FFTs reais (RFFT / IRFFT) e economizar metade do seu tempo de computação calculando apenas metade do espectro.

Além disso, você pode economizar tempo de computação preenchendo um tamanho maior para o qual a FFT é otimizada (como um número suave de 5 para FFTPACK, um número suave de 13 para FFTW ou uma potência de 2 para uma implementação simples de hardware).

Aqui está um exemplo no Python da correlação FFT em comparação com a correlação de força bruta: https://stackoverflow.com/a/1768140/125507

Isso fornecerá a função de correlação cruzada, que é uma medida de similaridade versus deslocamento. Para obter o deslocamento no qual as ondas estão "alinhadas" umas com as outras, haverá um pico na função de correlação:

pico na função de correlação

O valor x do pico é o deslocamento, que pode ser negativo ou positivo.

Eu só vi isso usado para encontrar o deslocamento entre duas ondas. Você pode obter uma estimativa mais precisa do deslocamento (melhor que a resolução de suas amostras) usando interpolação parabólica / quadrática no pico.

Para obter um valor de semelhança entre -1 e 1 (um valor negativo indicando que um dos sinais diminui à medida que o outro aumenta), é necessário dimensionar a amplitude de acordo com o comprimento das entradas, o comprimento da FFT, a sua implementação específica da FFT escala, etc. A autocorrelação de uma onda consigo fornecerá o valor da correspondência máxima possível.

Observe que isso funcionará apenas em ondas que tenham a mesma forma. Se eles tiverem sido amostrados em hardware diferente ou tiverem acrescentado algum ruído, mas ainda assim tiverem a mesma forma, essa comparação funcionará, mas se a forma da onda tiver sido alterada por filtragem ou mudanças de fase, elas poderão soar iguais, mas ganharão correlacionar também.


3
O preenchimento zero deve ser pelo menos N = tamanho (a) + tamanho (b) -1, de preferência arredondado para uma potência de 2. Para obter um valor entre -1 e 1, divida pela norma (a) * norma (b ), que fornece o cosseno do ângulo entre os dois vetores no espaço N para o atraso especificado (ou seja, módulo de deslocamento circular N). Nos atrasos extremos, não há muitas amostras sobrepostas (apenas uma no extremo extremo), portanto, a divisão pela norma (a) * norma (b) irá influenciar essas correlações para 0 (ou seja, mostrando sua ortogonalidade relativa no espaço N) .
Eryk Sun

11
Eu acho que pode haver um erro na descrição. A multiplicação das FFTs juntas, termo a termo, não deve fornecer a FFT da convolução dos sinais, não a FFT da correlação cruzada ? Pelo que entendi, para obter a FFT da correlação cruzada, é necessário usar o conjugado complexo de um dos vetores da FFT nas multiplicações termo a termo antes de tomar o iFFT.
precisa

@DilipSarwate: Sim, você está certo. Você também pode reverter um sinal na direção do tempo, que adicionei à resposta.
Endolith

11
"Por que a reversão do tempo é difícil de fazer no hardware?" Em muitos casos, os dados são armazenados em matrizes sistólicas na expectativa de que os cálculos sejam locais , ou seja, , armazenado na ésima célula, interage apenas com os vizinhos mais próximos . Enviando para a célula # e enviando para a célula # , e fazendo isso para todos os aumentando os custos de fiação, atrasos na fiação (e, portanto, reduz a taxa de clock máxima possível) e também, porque todos os os fios devem se cruzar, cria problemas de roteamento. Deve ser evitado se possível e, neste caso, é evitável.i x [ ± i ] x [ i ] ( N - i ) x [ N - i ] i ix[i]ix[±i]x[i](Ni)x[Ni]ii
Dilip Sarwate

11
@Leo multiplicação por elementos. matriz n por 1 x matriz n por 1 = matriz n por 1 Eu chamei isso de "amostra por amostra" na resposta.
Endolith

17

A correlação é uma maneira de expressar a semelhança de duas séries temporais (amostras de áudio no seu caso) em um número. É uma adaptação da covariância que é implementada da seguinte maneira:

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

A correlação é a versão normalizada da covariância, que é a covariância dividida pelo produto dos desvios padrão de ambas as séries temporais. A correlação produzirá um 0 quando não houver correlação (totalmente não semelhante) e um 1 para correlação total (totalmente semelhante).

Você pode imaginar que duas amostras de som podem ser semelhantes, mas não são sincronizadas. É aí que entra a correlação cruzada . Você calcula a correlação entre as séries temporais em que uma delas foi deslocada por uma amostra:

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

Em seguida, procure o valor máximo da corrsérie e pronto. (ou pare se você encontrou uma correlação suficiente) Claro que há um pouco mais. Você deve implementar o desvio padrão e gerenciar a memória e implementar as mudanças de horário. Se todas as suas amostras de áudio tiverem o mesmo comprimento, você poderá ficar sem normalizar a covariância e prosseguir e calcular a covariância cruzada.

Uma relação interessante com sua pergunta anterior : a análise de Fourier é apenas uma adaptação da covariância cruzada. Em vez de alterar uma série temporal e calcular as covariâncias com o outro sinal, você calcula as covariâncias entre um sinal e um número de (co) ondas senoidais com frequências diferentes. É tudo baseado no mesmo princípio.


11
Você mencionou que 0 não tem correlação e 1 é total. Eu só quero observar que -1 está completo correlacionado negativamente. Como em -1, implica que a amostra 1 é o oposto da amostra 2. Se você pensar sobre isso em um gráfico X, Y, é uma linha com inclinação positiva versus uma linha com inclinação negativa. E à medida que você se aproxima de 0, a linha fica "mais gorda".
Kellenjb

@kellenjb, Sim, mas eu provavelmente diria, a magnitude da correlação em que você provavelmente está interessado. Um 1 ou um -1 significa que os sinais afetam diretamente um ao outro.
Kortuk

14

No processamento de sinal, a correlação cruzada (xcorr no MATLAB) é uma operação de convolução com uma das duas seqüências invertidas. Como a reversão do tempo corresponde à conjugação complexa no domínio da frequência, você pode usar o DFT para calcular a correlação cruzada da seguinte maneira:

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

onde N = tamanho (x) + tamanho (y) - 1 (de preferência arredondado para uma potência de 2) é o comprimento da DFT.

A multiplicação de DFTs é equivalente a convolução circular no tempo. O preenchimento zero de ambos os vetores no comprimento N evita que os componentes deslocados circularmente de y se sobreponham a x, o que torna o resultado idêntico à convolução linear de x e o tempo invertido y.

Um atraso de 1 é um deslocamento circular direito de y, enquanto um atraso de -1 é um deslocamento circular esquerdo. A correlação cruzada é simplesmente a sequência de produtos de ponto para todos os atrasos. Com base na ordem fft padrão, eles estarão em uma matriz que pode ser acessada da seguinte maneira. Os índices de 0 a tamanho (x) -1 são os lags positivos. Os índices N-size (y) +1 a N-1 são os lags negativos na ordem inversa. (No Python, os lags negativos podem ser acessados ​​convenientemente com índices negativos, como R_xy [-1].)

Você pode pensar nos x e y com preenchimento zero como vetores N-dimensionais. O produto escalar de xey para um determinado atraso é |x|*|y|*cos(theta). As normas de xey são constantes para mudanças circulares, portanto, dividi-las deixa apenas o cosseno variável do ângulo teta. Se x e y (para um determinado atraso) são ortogonais no espaço N, a correlação é 0 (ou seja, teta = 90 graus). Se forem co-lineares, o valor é 1 (correlacionado positivamente) ou -1 (correlacionado negativamente, ou seja, teta = 180 graus). Isso leva à correlação cruzada normalizada para a unidade:

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

Isso pode ser tornado imparcial, recalculando as normas apenas para as partes sobrepostas, mas você também pode fazer todo o cálculo no domínio do tempo. Além disso, você verá diferentes versões da normalização. Em vez de ser normalizada para a unidade, algumas vezes a correlação cruzada é normalizada por M (enviesado), onde M = max (tamanho (x), tamanho (y)) ou M- | m | (uma estimativa imparcial do mésimo atraso).

Para máxima significância estatística, a média (viés de DC) deve ser removida antes do cálculo da correlação. Isso é chamado de covariância cruzada (xcov no MATLAB):

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

Isso significa que o tamanho final da matriz deve ser 2*size (a) + size(b) - 1ou 2*size (b) + size (a) - 1? Mas, em ambos os casos, as duas matrizes acolchoadas são de tamanhos diferentes. Qual é a conseqüência do preenchimento com muitos zeros?

@RobertK A matriz de correlação cruzada precisa ter pelo menos a soma dos comprimentos de aeb (menos um), como diz eryksun em sua resposta. Por uma questão de simplicidade, geralmente o comprimento é o dobro do comprimento do vetor mais longo (às vezes arredondado para a próxima potência maior de para usar uma FFT eficiente). A escolha ajuda quando o cliente decide tardiamente que também deseja a autocorrelação do vetor mais longo. Uma consequência do preenchimento com muitos zeros é o cálculo adicional, mas isso pode ser amenizado por implementações de FFT mais eficientes. 2
usar o seguinte

@RobertKJ: Está deslizar bao longo a, com uma saída por turno, uma sobreposição mínima de uma amostra. Isso produz size(a)atrasos positivos e size(b) - 1negativos. Usando a transformação inversa do produto de DFTs de ponto N, os índices 0through size(a)-1são os lags positivos e os índices N-size(b)+1through N-1são os lags negativos na ordem inversa.
Eryk Sun

3

se você estiver usando o Matlab, tente a função de correlação cruzada:

c= xcorr(x,y)

Aqui está a documentação do Matlab:

xcorrestima a sequência de correlação cruzada de um processo aleatório. A autocorrelação é tratada como um caso especial.

...

c = xcorr(x,y)retorna a sequência de correlação cruzada em um vetor de comprimento 2 * N-1, onde xe ysão Nvetores de comprimento ( N > 1). Se xe ynão tiverem o mesmo comprimento, o vetor mais curto será preenchido com zero no comprimento do vetor mais longo.

correlação http://www.mathworks.com/help/toolbox/signal/ref/eqn1263487323.gif


O link parece estar quebrado.
Danijel

2

Uma maneira rápida e simples de comparar arquivos de áudio. Pegue o arquivo de áudio, faça uma cópia, daw, cole-os lado a lado, em 2 canais estéreo, inverta a fase em uma das faixas estéreo, alinhe os dois arquivos no início no modo zoom, verifique se o os dois arquivos têm a mesma amplitude no início e, em seguida, são reproduzidos; se houver um silêncio total, os dois arquivos são idênticos; se houver uma diferença, você ouvirá isso com muita clareza!


1

Como a maioria aqui escreveu, você deve usar a correlação.

Basta considerar dois fatores:

  1. Se o volume tiver uma escala diferente, você deve normalizar a correlação.
  2. Se houver uma escala do tempo, você poderá usar o Dynamic Time Warping.

1

Para sinais não periódicos (tamanho (y) -1) deve ser subtraído do índice de R_xy para obter o atraso real.

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

defasagens = [0, N] - (tamanho (y) - 1);


0

A maneira mais fácil de encontrar a diferença, IMO, é subtrair os dois sinais de áudio no domínio do tempo. Se forem iguais, o resultado em cada momento será zero. Se eles não forem iguais, a diferença entre eles será deixada após a subtração e você poderá ouvi-la diretamente. Uma medida rápida de quão semelhantes elas são seria o valor RMS dessa diferença. Isso geralmente é feito na mixagem e masterização de áudio para ouvir a diferença de um arquivo MP3 vs WAV, por exemplo. (Inverter a fase de um sinal e adicioná-lo é o mesmo que subtrair. Esse é o método usado quando isso é feito no software DAW.) Eles devem estar perfeitamente alinhados no tempo para que isso funcione. Se não estiverem, você poderá desenvolver um algoritmo para alinhá-los, como detectar os dez picos principais, calcular o deslocamento médio dos picos e mudar um sinal.

Transformar no domínio da frequência e comparar os espectros de potência dos sinais como você propõe está ignorando algumas informações do domínio do tempo. Por exemplo, o áudio reproduzido no sentido inverso teria o mesmo espectro quando reproduzido para a frente. Assim, dois sinais de áudio muito diferentes podem ter exatamente o mesmo espectro.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.