Skip to main content

An Introduction to Adaptive Echo Cancellers

This article introduces a basic acoustic echo canceller based on the Least Mean Squares (LMS) algorithm. Acoustic echo cancellers are necessary for many modern communications products.  I’m sure you’ve come across a time when you could hear your voice while speaking on the phone, correct? Well, that's an example of an acoustic echo. Acoustic echoes are a common problem that arise from audio signals bouncing off nearby objects and coupling into the microphone when the mic should only be picking up your voice or when directly coupling from a speaker microphone pair (like your phone). Without cancelling these effects, the communication system is pretty annoying to use.

fig. 1

Here, the speech signal from a loudspeaker is acoustically coupled into the microphone of a speaker phone or hands-free cell phone, which is heard at the remote signal source as a return echo. The echo is suppressed by an echo canceller at the echo source by the system modeled in the figure above. Assume the channel has the sampled data impulse response represented by the Z-transform:
H(Z)=1+0.5Z3+0.1Z5
  
and the echo canceller is a tapped delay filter of length 50 samples. First we will let the desired signal s(t) be zero and train the canceling filter with white noise. As a synopsis, the signals in the figure 1 are:
speech signal:s(t)

echo:r(t)

acoustic channel:h(t)

acoustic channel output=r(t)h(t)(convolution)

microphone input:s(t)+r(t)h(t),desired signal plus echo through acoustic channel

echo canceller:h^(t)

desired signal:y(t)

The goal is to match the acoustic channel with our echo canceller so that we can invert the acoustic channels response and create only the desired signal at the microphone inputs (t). So lets see how this looks in Matlab code:

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

In the code, we first add the acoustic channel response into the Hc and Wc variables. Then we build an FM sweep training signal for use in the second part of training the echo canceller. We then define the signals r_t, s_t, Ort_ht, and mic_in to reflect Figure 1. Now comes the bulk of the adaptive canceller: we train it with a simple iterative least mean squares approach.
First, we define a register of depth 50. This is analogous to an array in C or C++ (embedded application). We then define an empty array of weights--wts--and set the 
μ
, which is an important stepping factor in the least mean squares algorithm which takes tiny steps each iteration to find the optimal set of weights which describe the acoustic channel and give the smallest error for each input. The LMS algorithm is simple-- we first add a sample of white noise to the register, then calculate the error:
err=mic_in(n)reg1wts

and then update the weights
wts=wts+μ(reg1err)

The derivation of the weight update is a long-winded explanation which I will not get into in this article, but will post a separate explanation of soon. However, the update reduces to the current weights plus 
μ
 times the contents of the register times the transpose of the error. Letting this run until convergence, we see that our algorithm finds the ultimate set of weights when trained on white noise to reach the desired signal of 0.

And we can see the echo canceller response converges almost exactly to the acoustic channels frequency response.


Now if we train it without the FM signal, we see it converges a little slower, but the error is magnitudes smaller!


And that's it--a pretty decent echo canceller in a couple lines of code. Look out for the Least Mean Squares article for a more thorough investigation into how the algorithm works!

Comments

Popular posts from this blog

Application Engineer- Prototyping at Siemens India

  Hello, Dear Readers, Siemens India has a vacancy for the Application Engineer role. Siemens EDA is a global technology leader in Electronic Design Automation software. Our software tools enable companies around the world to develop highly innovative electronic products faster and more cost-effectively. Our customers use our tools to push the boundaries of technology and physics to deliver better products in the increasingly complex world of chip, board, and system design. This role is based in Bengaluru. But you’ll also get to visit other locations in India and globe, so you’ll need to go where this job takes you. In return, you’ll get the chance to work with teams impacting entire cities, countries, and the shape of things to come We make real what matters! This is your role: Deploy Siemens EDA ProFPGA prototyping software and hardware solutions at customers and guide the customers to successful design bring-up Work closely with R&D to solve problems, review product spe...

Tutorial on EasyEDA desktop software for PCB and schematic design

In this article, I am going to write a tutorial on how to use EasyEDA desktop application for creating a schematic and for PCB design. One of best advantage of this software is that you can create design offline and can automatically synchronize your design with your online EasyEDA account.  It can be used for circuits simulation, PCB deign and electronics circuits design. You can download EasyEDA desktop application by clicking on following link and it will work on windows 7 or its greater version. They are also releasing soon offline application OSX and Linux users. So keep visiting their website for more information.                                                    https://easyeda.com/page/download So let’s start and see how to design a schematic and PCB using EasyEDA offline desktop application. So first of all lets see how to create a schema...

CMOS OPAMP Design Using LTspice

  Hello Dear Reader, Here in this post, I will give an idea about how CMOS OPAMP designing using 180nm technology node and using LTspice. from that opamp I have design switched capacitor integrator. Design Specifications: Here Design specification may be changed according to the application here my target is to design an active lowpass filter so I have chosen an opamp integrator so in the below I have explained how to design an opamp as well as an integrator in a 180nm technology node in LTspice. So let's start design First, we need a technology parameter file so that the file we can insert in the LTspice, in my example it is 180nm so mostly it is available from the  http://ptm.asu.edu/latest.html  and you make one text file using notepad or whatever is fit on your own. Then go to the LTspice and new schematic and then you see .op on the right most upper side click on it and give your text file path after .include  as shown in the below images.  Now first of all...