Введение
Определение задержки между двумя дискретными сигналами необходимо в большом числе задач цифровой обработки сигналов: в исследованиях радиосигналов, обработке аудиоданных, измерении различных величин. Эта задержка может быть вычислена корреляционными, спектральными или фазовыми методами или же с помощью определения характерных точек.
В ситуации, когда полезные сигналы состоят, преимущественно, из одной частоты, а время задержки между ними мало (не превышает одного периода основной частоты), наибольшую точность обеспечивают фазовые методы: по преобразованию Фурье [1] и по преобразованию Гильберта [2]. И если вычисление фазовой задержки по преобразованию Гильберта выполняется, фактически, в одно действие, а его реализация широко известна и многократно описана, то вычисление фазовой задержки по преобразованию Фурье выполняется в несколько этапов, а информация о его программной реализации практически не встречается в работах.
Суть метода и алгоритм
Метод вычисления фазовой задержки с помощью преобразования Фурье основывается на том, что комплексный спектр преобразования Фурье содержит не только амплитудный, но и фазовый спектр. Это свойство не составляет труда использовать при выполнении важного условия — один сигнал должен отставать от другого не более чем на один период основной частоты.
Как упоминалось ранее, вычисление фазовой задержки между сигналами по преобразованию Фурье происходит в несколько этапов:
1) По формуле (1) вычисляется дискретное преобразование Фурье (в программной реализации — в виде быстрого преобразования Фурье алгоритмом Кули-Тьюки) для обоих сигналов:
|
|
(1) |
где:
2) По дискретному преобразованию Фурье определяются индексы частот с максимальной амплитудой (основных частот) для обоих сигналов, то есть выбираются
|
|
(2) |
где
|
|
(3) |
где
|
|
(4) |
где
Условие (4) является ключевым для работы алгоритма, поскольку вычисление фазовой задержки возможно только при условии точного совпадения частот (при преобразовании Фурье; с реальной основной частотой частота, определённая по преобразованию Фурье, может совпадать лишь приблизительно — точность зависит от
3) Наконец, фазовая задержка
|
|
(5) |
В свою очередь численное значение задержки в секундах
|
|
(6) |
Реализация
Описанный алгоритм реализован на языке Python 3 с использованием библиотек numpy (операции с комплексными числами), scipy (быстрое преобразование Фурье) и matplotlib (построение графика).
В коде, представленном ниже, создаются два тоновых синусоидальных сигнала длиной 9999 отсчётов (30 секунд при частоте дискретизации 333,3 отсчёта/сек), один из которых отстаёт от другого. После выполнения выводится сравнение значений задержки — реального и вычисленного представленным методом:
|
Частота сигнала: 0.15916905444126075Гц Частота 1 по БПФ: 0.16666666666666669Гц Частота 2 по БПФ: 0.16666666666666669Гц Реальная задержка: 2.25022502250225 с Вычисленная задержка: 2.2502250225022506 с |
На рисунке представлены графики созданных тоновых синусоидальных сигналов:
Код программы
N = 9999
t = np.linspace(0, 30, N)
samplerate = len(t) / (max(t) - min(t))
sin_length = int(np.pi * 2 * N/10)
print("Частота сигнала: " + str(1 / ((sin_length / samplerate) / 3)) + "Гц")
signal_1 = np.zeros((N,))
T_start_1 = int(N/10)
signal_1[T_start_1:T_start_1 + sin_length] = np.sin(t[T_start_1:T_start_1 + sin_length] - t[T_start_1])
yf = sc.fft.rfft(signal_1)
yf_1 = yf
xf = sc.fft.rfftfreq(N, 1 / samplerate)
p = np.angle(yf)
print("Частота 1 по БПФ: " + str(xf[np.argmax(np.abs(yf))]) + "Гц")
signal_2 = np.zeros((N,))
T_start_2 = int(1.75*N/10)
signal_2[T_start_2:T_start_2 + sin_length] = np.sin(t[T_start_2:T_start_2 + sin_length] - t[T_start_2])
yf = sc.fft.rfft(signal_2)
yf_2 = yf
xf = sc.fft.rfftfreq(N, 1 / samplerate)
p = np.angle(yf)
print("Частота 2 по БПФ: " + str(xf[np.argmax(np.abs(yf))]) + "Гц")
print("Реальная задержка: " + str((np.argmax(signal_2 != 0) - np.argmax(signal_1 != 0)) / samplerate) + " с")
plt.figure(figsize=(10, 7))
plt.plot(t, signal_1, color="black", linewidth=1.5)
plt.plot(t, signal_2, color="blue", linewidth=1.5)
plt.grid()
plt.xlim(t[0], t[-1])
# Разработанный метод
I_1 = np.argmax(np.abs(yf_1))
I_2 = np.argmax(np.abs(yf_2))
ph = np.angle(yf_2[I_2]) - np.angle(yf_1[I_1])
tm = - ph / (2 * np.pi * xf[np.argmax(np.abs(yf))])
print("Вычисленная задержка: " + str(tm.real) + " с")
Литература:
- Быстрое преобразование Фурье // ВикипедиЯ URL: https://ru.wikipedia.org/wiki/Быстрое_преобразование_Фурье (дата обращения: 16.03.2026).
- Преобразование Гильберта // ВикипедиЯ URL: https://ru.wikipedia.org/wiki/Преобразование_Гильберта (дата обращения: 16.03.2026).

