Mercurial > hg > audiostuff
comparison spandsp-0.0.3/spandsp-0.0.3/src/spandsp/echo.h @ 5:f762bf195c4b
import spandsp-0.0.3
author | Peter Meerwald <pmeerw@cosy.sbg.ac.at> |
---|---|
date | Fri, 25 Jun 2010 16:00:21 +0200 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
4:26cd8f1ef0b1 | 5:f762bf195c4b |
---|---|
1 /* | |
2 * SpanDSP - a series of DSP components for telephony | |
3 * | |
4 * echo.c - A line echo canceller. This code is being developed | |
5 * against and partially complies with G168. | |
6 * | |
7 * Written by Steve Underwood <steveu@coppice.org> | |
8 * and David Rowe <david_at_rowetel_dot_com> | |
9 * | |
10 * Copyright (C) 2001 Steve Underwood and 2007 David Rowe | |
11 * | |
12 * All rights reserved. | |
13 * | |
14 * This program is free software; you can redistribute it and/or modify | |
15 * it under the terms of the GNU General Public License version 2, as | |
16 * published by the Free Software Foundation. | |
17 * | |
18 * This program is distributed in the hope that it will be useful, | |
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
21 * GNU General Public License for more details. | |
22 * | |
23 * You should have received a copy of the GNU General Public License | |
24 * along with this program; if not, write to the Free Software | |
25 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
26 * | |
27 * $Id: echo.h,v 1.9 2006/10/24 13:45:28 steveu Exp $ | |
28 */ | |
29 | |
30 /*! \file */ | |
31 | |
32 #if !defined(_ECHO_H_) | |
33 #define _ECHO_H_ | |
34 | |
35 /*! \page echo_can_page Line echo cancellation for voice | |
36 | |
37 \section echo_can_page_sec_1 What does it do? | |
38 This module aims to provide G.168-2002 compliant echo cancellation, to remove | |
39 electrical echoes (e.g. from 2-4 wire hybrids) from voice calls. | |
40 | |
41 \section echo_can_page_sec_2 How does it work? | |
42 The heart of the echo cancellor is FIR filter. This is adapted to match the echo | |
43 impulse response of the telephone line. It must be long enough to adequately cover | |
44 the duration of that impulse response. The signal transmitted to the telephone line | |
45 is passed through the FIR filter. Once the FIR is properly adapted, the resulting | |
46 output is an estimate of the echo signal received from the line. This is subtracted | |
47 from the received signal. The result is an estimate of the signal which originated | |
48 at the far end of the line, free from echos of our own transmitted signal. | |
49 | |
50 The least mean squares (LMS) algorithm is attributed to Widrow and Hoff, and was | |
51 introduced in 1960. It is the commonest form of filter adaption used in things | |
52 like modem line equalisers and line echo cancellers. There it works very well. | |
53 However, it only works well for signals of constant amplitude. It works very poorly | |
54 for things like speech echo cancellation, where the signal level varies widely. | |
55 This is quite easy to fix. If the signal level is normalised - similar to applying | |
56 AGC - LMS can work as well for a signal of varying amplitude as it does for a modem | |
57 signal. This normalised least mean squares (NLMS) algorithm is the commonest one used | |
58 for speech echo cancellation. Many other algorithms exist - e.g. RLS (essentially | |
59 the same as Kalman filtering), FAP, etc. Some perform significantly better than NLMS. | |
60 However, factors such as computational complexity and patents favour the use of NLMS. | |
61 | |
62 A simple refinement to NLMS can improve its performance with speech. NLMS tends | |
63 to adapt best to the strongest parts of a signal. If the signal is white noise, | |
64 the NLMS algorithm works very well. However, speech has more low frequency than | |
65 high frequency content. Pre-whitening (i.e. filtering the signal to flatten | |
66 its spectrum) the echo signal improves the adapt rate for speech, and ensures the | |
67 final residual signal is not heavily biased towards high frequencies. A very low | |
68 complexity filter is adequate for this, so pre-whitening adds little to the | |
69 compute requirements of the echo canceller. | |
70 | |
71 An FIR filter adapted using pre-whitened NLMS performs well, provided certain | |
72 conditions are met: | |
73 | |
74 - The transmitted signal has poor self-correlation. | |
75 - There is no signal being generated within the environment being cancelled. | |
76 | |
77 The difficulty is that neither of these can be guaranteed. | |
78 | |
79 If the adaption is performed while transmitting noise (or something fairly noise | |
80 like, such as voice) the adaption works very well. If the adaption is performed | |
81 while transmitting something highly correlative (typically narrow band energy | |
82 such as signalling tones or DTMF), the adaption can go seriously wrong. The reason | |
83 is there is only one solution for the adaption on a near random signal - the impulse | |
84 response of the line. For a repetitive signal, there are any number of solutions | |
85 which converge the adaption, and nothing guides the adaption to choose the generalised | |
86 one. Allowing an untrained canceller to converge on this kind of narrowband | |
87 energy probably a good thing, since at least it cancels the tones. Allowing a well | |
88 converged canceller to continue converging on such energy is just a way to ruin | |
89 its generalised adaption. A narrowband detector is needed, so adapation can be | |
90 suspended at appropriate times. | |
91 | |
92 The adaption process is based on trying to eliminate the received signal. When | |
93 there is any signal from within the environment being cancelled it may upset the | |
94 adaption process. Similarly, if the signal we are transmitting is small, noise | |
95 may dominate and disturb the adaption process. If we can ensure that the | |
96 adaption is only performed when we are transmitting a significant signal level, | |
97 and the environment is not, things will be OK. Clearly, it is easy to tell when | |
98 we are sending a significant signal. Telling, if the environment is generating a | |
99 significant signal, and doing it with sufficient speed that the adaption will | |
100 not have diverged too much more we stop it, is a little harder. | |
101 | |
102 The key problem in detecting when the environment is sourcing significant energy | |
103 is that we must do this very quickly. Given a reasonably long sample of the | |
104 received signal, there are a number of strategies which may be used to assess | |
105 whether that signal contains a strong far end component. However, by the time | |
106 that assessment is complete the far end signal will have already caused major | |
107 mis-convergence in the adaption process. An assessment algorithm is needed which | |
108 produces a fairly accurate result from a very short burst of far end energy. | |
109 | |
110 \section echo_can_page_sec_3 How do I use it? | |
111 The echo cancellor processes both the transmit and receive streams sample by | |
112 sample. The processing function is not declared inline. Unfortunately, | |
113 cancellation requires many operations per sample, so the call overhead is only a | |
114 minor burden. | |
115 */ | |
116 | |
117 #include "fir.h" | |
118 | |
119 /* Mask bits for the adaption mode */ | |
120 | |
121 #define ECHO_CAN_USE_ADAPTION 0x01 | |
122 #define ECHO_CAN_USE_NLP 0x02 | |
123 #define ECHO_CAN_USE_CNG 0x04 | |
124 #define ECHO_CAN_USE_CLIP 0x08 | |
125 #define ECHO_CAN_USE_TX_HPF 0x10 | |
126 #define ECHO_CAN_USE_RX_HPF 0x20 | |
127 #define ECHO_CAN_DISABLE 0x40 | |
128 | |
129 /*! | |
130 G.168 echo canceller descriptor. This defines the working state for a line | |
131 echo canceller. | |
132 */ | |
133 typedef struct | |
134 { | |
135 int16_t tx,rx; | |
136 int16_t clean; | |
137 int16_t clean_nlp; | |
138 | |
139 int nonupdate_dwell; | |
140 int curr_pos; | |
141 int taps; | |
142 int log2taps; | |
143 int adaption_mode; | |
144 | |
145 int cond_met; | |
146 int32_t Pstates; | |
147 int16_t adapt; | |
148 int32_t factor; | |
149 int16_t shift; | |
150 | |
151 /* Average levels and averaging filter states */ | |
152 int Ltxacc, Lrxacc, Lcleanacc, Lclean_bgacc; | |
153 int Ltx, Lrx; | |
154 int Lclean; | |
155 int Lclean_bg; | |
156 int Lbgn, Lbgn_acc, Lbgn_upper, Lbgn_upper_acc; | |
157 | |
158 /* foreground and background filter states */ | |
159 fir16_state_t fir_state; | |
160 fir16_state_t fir_state_bg; | |
161 int16_t *fir_taps16[2]; | |
162 | |
163 /* DC blocking filter states */ | |
164 int tx_1, tx_2, rx_1, rx_2; | |
165 | |
166 /* optional High Pass Filter states */ | |
167 int32_t xvtx[5], yvtx[5]; | |
168 int32_t xvrx[5], yvrx[5]; | |
169 | |
170 /* Parameters for the optional Hoth noise generator */ | |
171 int cng_level; | |
172 int cng_rndnum; | |
173 int cng_filter; | |
174 | |
175 /* snapshot sample of coeffs used for development */ | |
176 int16_t *snapshot; | |
177 | |
178 } echo_can_state_t; | |
179 | |
180 /*! Create a voice echo canceller context. | |
181 \param len The length of the canceller, in samples. | |
182 \return The new canceller context, or NULL if the canceller could not be created. | |
183 */ | |
184 echo_can_state_t *echo_can_create(int len, int adaption_mode); | |
185 | |
186 /*! Free a voice echo canceller context. | |
187 \param ec The echo canceller context. | |
188 */ | |
189 void echo_can_free(echo_can_state_t *ec); | |
190 | |
191 /*! Flush (reinitialise) a voice echo canceller context. | |
192 \param ec The echo canceller context. | |
193 */ | |
194 void echo_can_flush(echo_can_state_t *ec); | |
195 | |
196 /*! Set the adaption mode of a voice echo canceller context. | |
197 \param ec The echo canceller context. | |
198 \param adapt The mode. | |
199 */ | |
200 void echo_can_adaption_mode(echo_can_state_t *ec, int adaption_mode); | |
201 | |
202 void echo_can_snapshot(echo_can_state_t *ec); | |
203 | |
204 /*! Process a sample through a voice echo canceller. | |
205 \param ec The echo canceller context. | |
206 \param tx The transmitted audio sample. | |
207 \param rx The received audio sample. | |
208 \return The clean (echo cancelled) received sample. | |
209 */ | |
210 int16_t echo_can_update(echo_can_state_t *ec, int16_t tx, int16_t rx); | |
211 | |
212 /*! Process to high pass filter the tx signal. | |
213 \param ec The echo canceller context. | |
214 \param tx The transmitted auio sample. | |
215 \return The HP filtered transmit sample, send this to your D/A. | |
216 */ | |
217 int16_t echo_can_hpf_tx(echo_can_state_t *ec, int16_t tx); | |
218 | |
219 #endif | |
220 /*- End of file ------------------------------------------------------------*/ |