Введение в адаптивные эхоподавители
В этой статье представлен базовый акустический эхоподавитель на основе алгоритма наименьших квадратов (LMS). Акустические эхоподавители необходимы для многих современных коммуникационных продуктов. Я уверен, что вы натолкнулись на время, когда вы слышали свой голос, разговаривая по телефону, исправьте «text-align: center;»>

Рисунок 1
Здесь речевой сигнал от громкоговорителя акустически подключается к микрофону громкоговорящего телефона или громкоговорящего сотового телефона, который слышен в источнике дистанционного сигнала как обратное эхо. Эхо подавляется эхоподавителем в источнике эха системой, смоделированной на рисунке выше. Предположим, что канал имеет импульсный отклик выборки данных, представленный Z-преобразованием:
$$ H (Z) = 1 + 0.5Z ^ {- 3} + 0.1Z ^ {- 5} $$
и эхоподавитель является фильтром задержки на выборку длиной 50 выборок. Сначала мы дадим искомый сигнал s (t) равным нулю и тренируем фильтр отмены с белым шумом. В качестве краткого обзора сигналы на рисунке 1:
$$ \ text {речевой сигнал}: s (t) $$
$$ \ text {echo}: r (t) $$
$$ \ text {Акустический канал}: h (t) $$
$$ \ text {выход акустического канала} = r (t) * h (t) text {(convolution)} $$
$$ \ text {микрофонный вход}: s (t) + r (t) * h (t), \ text {желаемый сигнал плюс эхо через акустический канал} $$
$$ \ text {echo canceller}: \ hat {h} (t) $$
$$ \ text {желаемый сигнал}: y (t) $$
Цель состоит в том, чтобы сопоставить акустический канал с нашим эхоподавителем, чтобы мы могли инвертировать ответ акустических каналов и создавать только желаемый сигнал на входах микрофона (t). Итак, посмотрим, как это выглядит в коде Matlab:
clear all; clf; close all; %acoustic channel frequency response num = (1 0 0 0.5 0.1); den = (1 0 0 0 0 0); (Hc, Wc) = freqz(num, den); %---BUILD FM SWEEP---% fs = 2*pi; tmax = 10000; f1=0; f2 =.5; tsweep = 0:499; slope = (f2-f1)/1000; F = slope.*(mod(tsweep, 500)); t = 0:1:tmax; fm = cos(2*pi*slope*t); F = slope.*(mod(tsweep, 500)); fm2 = cos(2*pi*(F).*tsweep); fm2c = repmat(fm2, 20, 1); fm2 = reshape(fm2c', 1, 10000); figure plot((0:999), fm2(2001:3000)) %subplot(212) %plot((-512:511)*1/(2*pi), 20*log10(abs(fft(fm2(1:500), 1024)))) grid on %End building of FM sweep trainlen = tmax; %training signal r_t = 1*rand(1, tmax); %desired signal s_t = 0; %signal through channel rt_ht = filter(num, den, r_t); %signal through channel + desired mic_in = s_t + rt_ht; %LMS algorithm of echo canceller reg1=zeros(1, 50); wts = (zeros(1, 50)); mu =.07; for n = 1:trainlen wts_sv = wts; reg1 = (r_t(n) reg1(1:49)); err = mic_in(n) - reg1*(wts'); y(n) = err; wts = wts + mu*(reg1*(err')); end %plots figure subplot(211) plot(1:length(y), (y)) hold on plot(1:10000, zeros(1, 10000), 'color', 'r', 'linewidth', 2, 'MarkerSize', 2) hold off axis((-.5 10000 -1 1.1)) grid on title('Steady State (time response) Desired Signal = 0, trained with white noise') subplot(212) plot(1:length(y), 20*log10(abs(y))) grid on title('Log Magnitude Training Curve, trained with white noise') (Hf, Wf) = freqz(wts_sv); figure subplot(211) plot(Wc/pi, 20*log10(abs(Hc))) grid on title('Frequency Response of Channel') subplot(212) plot(Wf/pi, 20*log10(abs(Hf)), 'color', 'r') title('Frequency Response of Adaptive Canceller, trained with white noise') grid on
Скачать код
В коде мы сначала добавляем ответ акустического канала в переменные Hc и Wc. Затем мы создаем сигнал обучения развертки FM для использования во второй части тренировки эхоподавителя. Затем мы определяем сигналы r_t, s_t, Ort_ht и mic_in, чтобы отразить Рисунок 1. Теперь идет основная часть адаптивного компенсатора: мы обучаем его простым итеративным методом наименьших квадратов.
Сначала мы определяем регистр глубины 50. Это аналогично массиву в C или C + (встроенное приложение). Затем мы определяем пустой массив весов - wts - и устанавливаем $$ \ mu $$, что является важным степенным фактором в алгоритме наименьших квадратов, который выполняет крошечные шаги на каждой итерации, чтобы найти оптимальный набор весов, которые описывают акустический канал и дать наименьшую ошибку для каждого входа. Алгоритм LMS прост - сначала добавим в регистр образец белого шума, затем вычислим ошибку:
$$ err = \ text {mic_in} (n) - reg1 * wts '$$
а затем обновить весы
$$ wts = wts + \ mu * (reg1 * err ') $$
Вывод обновления веса - это длинное объяснение, которое я не буду вдаваться в эту статью, но опубликую отдельное объяснение в ближайшее время. Тем не менее, обновление сводится к текущим весам плюс $$ \ mu $$ раз, когда содержимое регистра переставляет транспонирование ошибки. Позволяя этому прогонку до сближения, мы видим, что наш алгоритм находит конечный набор весов при обучении на белом шуме для достижения желаемого сигнала 0.

И мы можем видеть, что реакция эхоподавителя почти точно сходится к частотной характеристике акустических каналов.

Теперь, если мы тренируем его без сигнала FM, мы видим, что он сходится немного медленнее, но ошибка меньше величин!


И это все - довольно приличный эхоподавитель в нескольких строках кода. Посмотрите на статью «Маленькие средние квадраты» для более тщательного изучения того, как работает алгоритм!