Оценка временной задержки между двумя аудиосигналами
У меня есть две аудиозаписи одного и того же сигнала на 2 разных микрофонах (например, в формате WAV), но один из них записывается с задержкой, например, несколько секунд.
Легко определить такую задержку визуально, просматривая эти сигналы в каком-либо средстве просмотра формы сигнала, то есть просто обнаруживая первый видимый пик в каждом сигнале и гарантируя, что они имеют одинаковую форму:
http://www.greycat.ru/temp/time-delay-peaks.png
Но как мне сделать это программно - узнать, что это за задержка (t)? Два оцифрованных сигнала немного отличаются (потому что микрофоны разные, были в разных положениях, из-за настроек АЦП и т. Д.).
Я немного покопался и обнаружил, что эту проблему обычно называют "оценкой задержки", и у нее есть множество подходов к ней - например, один из них.
Но есть ли простые и готовые решения, такие как утилита командной строки, библиотека или простой алгоритм?
Вывод: я не нашел простой реализации и сам создал простую утилиту командной строки - она доступна по адресу https://bitbucket.org/GreyCat/calc-sound-delay (GPLv3-licensed). Он реализует очень простой алгоритм поиска максимума, описанный в Википедии.
3 ответа
Техника, которую вы ищете, называется кросс-корреляцией. Это очень простой, хотя и довольно сложный метод, который можно использовать для решения различных задач, в том числе измерения разницы во времени (также известной как задержка) между двумя одинаковыми сигналами (сигналы не обязательно должны быть идентичными).
Если у вас есть разумное представление о вашем значении лага (или, по крайней мере, о диапазоне ожидаемых значений лага), вы можете значительно сократить общий объем вычислений. То же самое, если вы можете поставить определенный предел, насколько вам нужна точность.
Столкнувшись с той же проблемой и безуспешно найдя инструмент для автоматической синхронизации начала видео / аудиозаписей, я решил сделать syncstart ( github ).
Это инструмент командной строки. Основной код, стоящий за этим, таков:
import numpy as np
from scipy import fft
from scipy.io import wavfile
r1,s1 = wavfile.read(in1)
r2,s2 = wavfile.read(in2)
assert r1==r2, "syncstart normalizes using ffmpeg"
fs = r1
ls1 = len(s1)
ls2 = len(s2)
padsize = ls1+ls2+1
padsize = 2**(int(np.log(padsize)/np.log(2))+1)
s1pad = np.zeros(padsize)
s1pad[:ls1] = s1
s2pad = np.zeros(padsize)
s2pad[:ls2] = s2
corr = fft.ifft(fft.fft(s1pad)*np.conj(fft.fft(s2pad)))
ca = np.absolute(corr)
xmax = np.argmax(ca)
if xmax > padsize // 2:
file,offset = in2,(padsize-xmax)/fs
else:
file,offset = in1,xmax/fs
Очень простая задача состоит в том, чтобы просто проверить, превышают ли пики какой-либо порог, время между высоким пиком в линии A и верхним пиком в линии B, вероятно, является твоей задержкой. Просто попробуйте немного поработать с пороговыми значениями, и если графики обычно такие же четкие, как и картинка, которую вы разместили, у вас все будет хорошо.