Як здійснити перехресну кореляцію, щоб довести, що два звукові файли схожі?


58

Я повинен зробити перехресну кореляцію двох аудіофайлів, щоб довести, що вони схожі. Я взяв FFT двох аудіофайлів і маю їхні значення спектру потужності в окремих масивах.

Як я повинен продовжувати перехресно співвідносити їх і доводити, що вони схожі? Чи є кращий спосіб це зробити? Будь-які основні ідеї будуть корисними для мене, щоб вивчити та застосувати її.


Дано поперечну кореляцію двох випадкових векторів сигналу. Як ви реалізуєте зворотній зв'язок, щоб отримати два вектори в MATLAB. John Muhehe

Відповіді:


56

Перехресна кореляція та згортання тісно пов'язані. Коротше кажучи, робити згортку з FFTs, вам

  1. нульові колодки вхідних сигналів (додайте нулі до кінця, щоб принаймні половина хвилі була "порожньою")
  2. прийняти FFT обох сигналів
  3. помножувати результати разом (множення елементів)
  4. зробити зворотний FFT

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

Вам потрібно зробити нульову підкладку, оскільки метод FFT - це насправді кругова перехресна кореляція, тобто сигнал накручується на кінцях. Таким чином, ви додаєте достатньо нулів, щоб позбутися перекриття, щоб імітувати сигнал, який дорівнює нулю до нескінченності.

Щоб отримати перехресну кореляцію замість згортки, вам потрібно або повернути один з сигналів за часом перед тим, як зробити FFT, або взяти складний кон'югат одного з сигналів після 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)))

залежно від вашого обладнання та програмного забезпечення. Для автокореляції (перехресна кореляція сигналу з самим собою) краще робити складний кон'югат, тому що тоді потрібно обчислити FFT лише один раз.

Якщо сигнали справжні, ви можете використовувати реальні FFT (RFFT / IRFFT) і економити половину часу на обчислення, лише обчисливши половину спектру.

Крім того, ви можете заощадити час на обчислення, доповнивши більший розмір, під який оптимізовано FFT (наприклад, 5-гладке число для FFTPACK, ~ 13-гладке число для FFTW або потужність 2 для простої апаратної реалізації).

Ось приклад кореляції FFT у Python порівняно з кореляцією грубої сили: https://stackoverflow.com/a/1768140/125507

Це дасть вам функцію перехресної кореляції, яка є показником подібності та зміщення. Для отримання зрушення, при якому хвилі «вишикуються» між собою, буде досягнутий пік функції кореляції:

пік кореляційної функції

Значення x піку - це зміщення, яке може бути негативним чи позитивним.

Я бачив, як це використовується для знаходження зміщення між двома хвилями. Ви можете отримати більш точну оцінку зміщення (краще, ніж роздільна здатність ваших зразків), використовуючи параболічну / квадратичну інтерполяцію на піку.

Щоб отримати значення подібності між -1 і 1 (від'ємне значення, що вказує на один із сигналів, зменшується, оскільки інший збільшується), вам потрібно буде масштабувати амплітуду відповідно до довжини входів, довжини FFT, відповідної вашої реалізації FFT масштабування тощо. Автокореляція хвилі із собою дасть вам значення максимально можливого збігу.

Зауважте, що це буде працювати лише на хвилях, що мають однакову форму. Якщо вони взяли пробу на іншому обладнанні або додали шум, але в іншому випадку все-таки мають однакову форму, це порівняння спрацює, але якщо форма хвилі була змінена фільтруванням або зсувом фаз, вони можуть звучати однаково, але виграють Не корелюю також.


3
Нульова прокладка повинна бути принаймні N = розмір (a) + розмір (b) -1, бажано округлений до потужності 2. Щоб отримати значення між -1 і 1, розділіть на норму (a) * норму (b ), який дає косинус кута між двома векторами в N-просторі за задане відставання (тобто модуль кругового зсуву N). У крайніх відставаннях не так багато зразків, що перекриваються (лише один у крайній крайній частині), тому ділення на норму (a) * норма (b) буде зміщувати ці кореляції на 0 (тобто показувати їх відносну ортогональність у N-просторі) .
Ерік Нд

1
Я думаю, що може бути помилка в описі. Чи не слід, помножуючи FFT разом на термін, давати FFT згортки сигналів, а не FFT перехресної кореляції ? Як я розумію, щоб отримати FFT перехресної кореляції, перед тим, як приймати iFFT, необхідно використовувати складний кон'югат одного з векторів FFT у терміновому розмноженні.
Діліп Сарват

@DilipSarwate: Так, ти маєш рацію. Ви також можете повернути один сигнал у часовому напрямку, який я додав у відповідь.
ендоліт

1
"Чому обертання часу важко зробити апаратним способом?" У більшості випадків дані зберігаються в систолічних масивах, очікуючи, що обчислення локальні , тобто , що зберігаються в -й клітині, взаємодіють лише з найближчими сусідами . Відправка на мобільний # і відправки в клітинку # , і робити це для всіх збільшення витрат на проводку, затримки проводки (і , отже , зменшує максимальну досяжну частоту), а також, тому що все провід повинен перетинати один одного, створює проблеми з маршрутизацією. Слід уникати, якщо це можливо, і в цьому випадку цього можна уникнути.i x [ ± i ] x [ i ] ( N - i ) x [ N - i ] i ix[i]ix[±i]x[i](Ni)x[Ni]ii
Діліп Сарват

1
@Leo стиле множення. n-by-1 масив x n-by-1 масив = n-by-1 масив Я назвав це у відповіді "зразок за зразком".
ендоліт

17

Кореляція - це спосіб виразити подібність двох часових серій (аудіозображень у вашому випадку) в одному числі. Це адаптація коваріації, яка реалізується наступним чином:

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

Кореляція - це нормалізований варіант коваріації, який є коваріацією, поділеною на добуток стандартних відхилень обох часових рядів. Кореляція дасть 0, коли немає кореляції (абсолютно не схоже), а 1 для повної кореляції (повністю подібної).

Ви можете уявити, що два зразки звуку можуть бути схожими, але не синхронізовані. Тут випливає перехресне співвідношення . Ви обчислюєте співвідношення між тимчасовими рядами, у яких один із них зміщений на один зразок:

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

Потім знайдіть максимальне значення в corrсерії, і ви закінчите. (або зупиніться, якщо ви знайшли достатню кореляцію) Звичайно, це трохи більше. Ви повинні реалізувати стандартне відхилення, і ви повинні виконати деяке управління пам’яттю та реалізувати інформацію про зміну часу. Якщо всі ваші зразки звуку однакові за довжиною, ви можете обійтися без нормалізації коваріації та йти вперед та обчислювати перехресну коваріацію.

Класне відношення до вашого попереднього запитання : аналіз Фур’є - це лише адаптація перехресної коваріації. Замість того, щоб зміщувати один часовий ряд і обчислювати коваріанси на інший сигнал, ви обчислюєте коваріації між одним сигналом і кількома (ко) синусоїдами з різною частотою. Все це базується на одному принципі.


1
Ви згадали, що 0 не є кореляцією, а 1 - загальною кореляцією. Я просто хочу зазначити, що -1 повністю негативно корелює. Як і в -1, випливає, що зразок 1 протилежний зразку 2. Якщо ви думаєте про це на графіку X, Y, це лінія з позитивним нахилом проти лінії з негативним нахилом. І коли ви наближаєтесь до 0, рядок стає "товстішим".
Kellenjb

@kellenjb, Так, але я, мабуть, скажу це, величина кореляції того, що вас, мабуть, цікавить. 1 або -1 означають, що сигнали безпосередньо впливають один на одного.
Кортук

14

При обробці сигналу перехресна кореляція (xcorr в MATLAB) - це операція згортання з однією з двох послідовностей, обернених назад. Оскільки обертання часу відповідає складній кон'югації в частотній області, ви можете використовувати DFT для обчислення перехресної кореляції наступним чином:

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

де N = розмір (x) + розмір (y) - 1 (бажано округлений до потужності 2) - довжина DFT.

Множення DFT еквівалентно круговій згортці в часі. Нульова накладка обох векторів на довжину N утримує кругові зрушені компоненти y від перекриття з x, що робить результат ідентичним лінійній згортці x та часу, перевернутому y.

Відстань 1 - це правильний круговий зсув y, тоді як відставання -1 - лівий круговий зсув. Перехресна кореляція - це просто послідовність точкових продуктів для всіх відставань. На основі стандартного замовлення у Fft вони будуть знаходитись у масиві, доступ до якого можна отримати наступним чином. Індекси від 0 до розміру (х) -1 - це позитивні відставання. Індекси N-розміру (y) +1 до N-1 - це негативні відставання у зворотному порядку. (У Python до негативних лагів можна легко отримати доступ із негативними індексами, такими як R_xy [-1].)

Ви можете подумати про нульовані x і y як N-мірні вектори. Точковий добуток x і y для даного відставання дорівнює |x|*|y|*cos(theta). Нормативи x і y є постійними для кругових зрушень, тому їх поділ залишає просто різний косинус кути тети. Якщо x і y (для заданого відставання) є ортогональними в N-просторі, кореляція дорівнює 0 (тобто тета = 90 градусів). Якщо вони є лінійними, значення або 1 (позитивно корелює), або -1 (негативно корелює, тобто тета = 180 градусів). Це призводить до перехресної кореляції, нормалізованої до єдності:

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

Це можна зробити неупередженим, перерахувавши норми лише деталей, що перекриваються, але тоді ви також можете зробити все обчислення у часовій області. Також ви побачите різні версії нормалізації. Замість того, щоб нормалізуватись на єдність, іноді перехресне співвідношення нормалізується через M (упереджене), де M = max (розмір (x), розмір (y)), або M- | m | (неупереджена оцінка м-го відставання).

Для досягнення максимальної статистичної значущості середнє значення (зміщення постійного струму) слід видалити перед обчисленням кореляції. Це називається перехресною коваріацією (xcov в MATLAB):

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

Чи означає це, що кінцевий розмір масиву повинен бути 2*size (a) + size(b) - 1або 2*size (b) + size (a) - 1? Але в будь-якому випадку два прокладених масиви мають різну величину. Що є наслідком прокладки із занадто великою кількістю нулів?

@RobertK Масив перехресної кореляції повинен бути довжиною щонайменше сумою довжин a і b (мінус один), як говорить у своїй відповіді Ериксун. Для простоти довжина часто приймається вдвічі довшою довшого вектора (іноді округляється до наступної більшої потужності в , щоб використовувати ефективний FFT). Вибір допомагає, коли клієнт із запізненням вирішує, що він також хоче автокореляції більш тривалого вектора. Одним із наслідків прокладки із занадто великою кількістю нулів є додаткові обчислення, але це може бути покращено більш ефективними реалізаціями FFT. 2
Діліп Сарват

@RobertKJ: Ви ковзаєте bразом a, з одним виходом за зміну, мінімальним перекриттям одного зразка. Це дає size(a)позитивні та size(b) - 1негативні відставання. Використовуючи зворотне перетворення продукту N-точкового ДПФ, індекси 0через size(a)-1позитивні лаг, і індекси N-size(b)+1через N-1є негативними лаг в зворотному порядку.
Ерик Вс

3

якщо ви використовуєте Matlab, спробуйте перехресну кореляцію:

c= xcorr(x,y)

Ось документація Matlab:

xcorrоцінює перехресну кореляційну послідовність випадкового процесу. Автокореляція розглядається як окремий випадок.

...

c = xcorr(x,y)повертає перехресну кореляційну послідовність у довжині 2 * N-1 вектор, де xі yє Nвектори довжини ( N > 1). Якщо xі yне однакової довжини, коротший вектор занулений нулем до довжини більш тривалого вектора.

кореляція http://www.mathworks.com/help/toolbox/signal/ref/eqn1263487323.gif


Здається, посилання розірвана.
Даніель

2

Швидкий і простий спосіб порівняння аудіофайлів. Візьміть аудіофайл, зробіть копію на світанку, вставте їх поруч, у 2 стереоканали, переверніть фазу на одному із стереодоріжок, вирівняйте обидва файли на початку в режимі збільшення, переконайтеся, що обидва файли мають однакову амплітуду на початку, потім відтворити, якщо є цілковита тиша, то обидва файли однакові, якщо є різниця, ви почуєте це досить чітко !.


1

Як писало більшість тут, ви повинні використовувати кореляцію.

Просто врахуйте 2 фактори:

  1. Якщо гучність масштабується по-різному, слід нормалізувати співвідношення.
  2. Якщо є масштабування часу, то ви можете використовувати динамічний викривлення часу.

1

Для неперіодичних сигналів (розмір (y) -1) необхідно відняти від індексу R_xy, щоб отримати фактичне відставання.

N = розмір (x) + розмір (y) - 1;

лаги = [0, N] - (розмір (у) - 1);


0

Найпростіший спосіб знайти різницю, IMO - це відняти два аудіосигнали у часовій області. Якщо вони рівні, результат у кожний момент часу буде нульовим. Якщо вони не рівні, різниця між ними залишиться після віднімання, і ви можете слухати його безпосередньо. Швидкою мірою того, наскільки вони схожі, було б значення RMS цієї різниці. Це часто робиться при змішуванні звуку та мастерингу, щоб, наприклад, чути різницю файлу MP3 від WAV. (Інвертування фази одного сигналу та додавання їх - це те саме, що віднімання. Це метод, який використовується, коли це робиться в програмному забезпеченні DAW.) Вони повинні бути ідеально вирівняними для того, щоб це працювало. Якщо їх немає, ви можете розробити алгоритм їх вирівнювання, такий як виявлення перших десяти піків, обчислення середнього зміщення піків і зміщення одного сигналу.

Перетворення в частотну область та порівняння спектрів потужності сигналів, як ви пропонуєте, - ігнорування деякої інформації часової області. Наприклад, звук, який відтворюється у зворотному напрямку, матиме однаковий спектр при відтворенні вперед. Таким чином, два дуже різні аудіосигнали можуть мати точно той же спектр.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.