diff options
author | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2014-02-28 17:08:42 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2014-02-28 17:08:42 -0500 |
commit | 6e2055a9e56e292715f935a85f381e54c1f54269 (patch) | |
tree | 5cdb033f7da95ba47c37a42602c6d88d55e11db5 /drivers/misc/echo/echo.h | |
parent | dc93c85235efa5201e9a3c116bc3fbd1afc1a182 (diff) |
staging: echo: move to drivers/misc/
The code is clean, there are users of it, so it doesn't belong in
staging anymore, move it to drivers/misc/.
Cc: Steve Underwood <steveu@coppice.org>
Cc: David Rowe <david@rowetel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/misc/echo/echo.h')
-rw-r--r-- | drivers/misc/echo/echo.h | 187 |
1 files changed, 187 insertions, 0 deletions
diff --git a/drivers/misc/echo/echo.h b/drivers/misc/echo/echo.h new file mode 100644 index 000000000000..9b08c63e6369 --- /dev/null +++ b/drivers/misc/echo/echo.h | |||
@@ -0,0 +1,187 @@ | |||
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 | |||
28 | #ifndef __ECHO_H | ||
29 | #define __ECHO_H | ||
30 | |||
31 | /* | ||
32 | Line echo cancellation for voice | ||
33 | |||
34 | What does it do? | ||
35 | |||
36 | This module aims to provide G.168-2002 compliant echo cancellation, to remove | ||
37 | electrical echoes (e.g. from 2-4 wire hybrids) from voice calls. | ||
38 | |||
39 | How does it work? | ||
40 | |||
41 | The heart of the echo cancellor is FIR filter. This is adapted to match the | ||
42 | echo impulse response of the telephone line. It must be long enough to | ||
43 | adequately cover the duration of that impulse response. The signal transmitted | ||
44 | to the telephone line is passed through the FIR filter. Once the FIR is | ||
45 | properly adapted, the resulting output is an estimate of the echo signal | ||
46 | received from the line. This is subtracted from the received signal. The result | ||
47 | is an estimate of the signal which originated at the far end of the line, free | ||
48 | from echos of our own transmitted signal. | ||
49 | |||
50 | The least mean squares (LMS) algorithm is attributed to Widrow and Hoff, and | ||
51 | was introduced in 1960. It is the commonest form of filter adaption used in | ||
52 | things like modem line equalisers and line echo cancellers. There it works very | ||
53 | well. However, it only works well for signals of constant amplitude. It works | ||
54 | very poorly for things like speech echo cancellation, where the signal level | ||
55 | varies widely. This is quite easy to fix. If the signal level is normalised - | ||
56 | similar to applying AGC - LMS can work as well for a signal of varying | ||
57 | amplitude as it does for a modem signal. This normalised least mean squares | ||
58 | (NLMS) algorithm is the commonest one used for speech echo cancellation. Many | ||
59 | other algorithms exist - e.g. RLS (essentially the same as Kalman filtering), | ||
60 | FAP, etc. Some perform significantly better than NLMS. However, factors such | ||
61 | as computational complexity and patents favour the use of NLMS. | ||
62 | |||
63 | A simple refinement to NLMS can improve its performance with speech. NLMS tends | ||
64 | to adapt best to the strongest parts of a signal. If the signal is white noise, | ||
65 | the NLMS algorithm works very well. However, speech has more low frequency than | ||
66 | high frequency content. Pre-whitening (i.e. filtering the signal to flatten its | ||
67 | spectrum) the echo signal improves the adapt rate for speech, and ensures the | ||
68 | final residual signal is not heavily biased towards high frequencies. A very | ||
69 | low complexity filter is adequate for this, so pre-whitening adds little to the | ||
70 | compute requirements of the echo canceller. | ||
71 | |||
72 | An FIR filter adapted using pre-whitened NLMS performs well, provided certain | ||
73 | conditions are met: | ||
74 | |||
75 | - The transmitted signal has poor self-correlation. | ||
76 | - There is no signal being generated within the environment being | ||
77 | cancelled. | ||
78 | |||
79 | The difficulty is that neither of these can be guaranteed. | ||
80 | |||
81 | If the adaption is performed while transmitting noise (or something fairly | ||
82 | noise like, such as voice) the adaption works very well. If the adaption is | ||
83 | performed while transmitting something highly correlative (typically narrow | ||
84 | band energy such as signalling tones or DTMF), the adaption can go seriously | ||
85 | wrong. The reason is there is only one solution for the adaption on a near | ||
86 | random signal - the impulse response of the line. For a repetitive signal, | ||
87 | there are any number of solutions which converge the adaption, and nothing | ||
88 | guides the adaption to choose the generalised one. Allowing an untrained | ||
89 | canceller to converge on this kind of narrowband energy probably a good thing, | ||
90 | since at least it cancels the tones. Allowing a well converged canceller to | ||
91 | continue converging on such energy is just a way to ruin its generalised | ||
92 | adaption. A narrowband detector is needed, so adapation can be suspended at | ||
93 | appropriate times. | ||
94 | |||
95 | The adaption process is based on trying to eliminate the received signal. When | ||
96 | there is any signal from within the environment being cancelled it may upset | ||
97 | the adaption process. Similarly, if the signal we are transmitting is small, | ||
98 | noise may dominate and disturb the adaption process. If we can ensure that the | ||
99 | adaption is only performed when we are transmitting a significant signal level, | ||
100 | and the environment is not, things will be OK. Clearly, it is easy to tell when | ||
101 | we are sending a significant signal. Telling, if the environment is generating | ||
102 | a significant signal, and doing it with sufficient speed that the adaption will | ||
103 | not have diverged too much more we stop it, is a little harder. | ||
104 | |||
105 | The key problem in detecting when the environment is sourcing significant | ||
106 | energy is that we must do this very quickly. Given a reasonably long sample of | ||
107 | the received signal, there are a number of strategies which may be used to | ||
108 | assess whether that signal contains a strong far end component. However, by the | ||
109 | time that assessment is complete the far end signal will have already caused | ||
110 | major mis-convergence in the adaption process. An assessment algorithm is | ||
111 | needed which produces a fairly accurate result from a very short burst of far | ||
112 | end energy. | ||
113 | |||
114 | How do I use it? | ||
115 | |||
116 | The echo cancellor processes both the transmit and receive streams sample by | ||
117 | sample. The processing function is not declared inline. Unfortunately, | ||
118 | cancellation requires many operations per sample, so the call overhead is only | ||
119 | a minor burden. | ||
120 | */ | ||
121 | |||
122 | #include "fir.h" | ||
123 | #include "oslec.h" | ||
124 | |||
125 | /* | ||
126 | G.168 echo canceller descriptor. This defines the working state for a line | ||
127 | echo canceller. | ||
128 | */ | ||
129 | struct oslec_state { | ||
130 | int16_t tx; | ||
131 | int16_t rx; | ||
132 | int16_t clean; | ||
133 | int16_t clean_nlp; | ||
134 | |||
135 | int nonupdate_dwell; | ||
136 | int curr_pos; | ||
137 | int taps; | ||
138 | int log2taps; | ||
139 | int adaption_mode; | ||
140 | |||
141 | int cond_met; | ||
142 | int32_t pstates; | ||
143 | int16_t adapt; | ||
144 | int32_t factor; | ||
145 | int16_t shift; | ||
146 | |||
147 | /* Average levels and averaging filter states */ | ||
148 | int ltxacc; | ||
149 | int lrxacc; | ||
150 | int lcleanacc; | ||
151 | int lclean_bgacc; | ||
152 | int ltx; | ||
153 | int lrx; | ||
154 | int lclean; | ||
155 | int lclean_bg; | ||
156 | int lbgn; | ||
157 | int lbgn_acc; | ||
158 | int lbgn_upper; | ||
159 | int lbgn_upper_acc; | ||
160 | |||
161 | /* foreground and background filter states */ | ||
162 | struct fir16_state_t fir_state; | ||
163 | struct fir16_state_t fir_state_bg; | ||
164 | int16_t *fir_taps16[2]; | ||
165 | |||
166 | /* DC blocking filter states */ | ||
167 | int tx_1; | ||
168 | int tx_2; | ||
169 | int rx_1; | ||
170 | int rx_2; | ||
171 | |||
172 | /* optional High Pass Filter states */ | ||
173 | int32_t xvtx[5]; | ||
174 | int32_t yvtx[5]; | ||
175 | int32_t xvrx[5]; | ||
176 | int32_t yvrx[5]; | ||
177 | |||
178 | /* Parameters for the optional Hoth noise generator */ | ||
179 | int cng_level; | ||
180 | int cng_rndnum; | ||
181 | int cng_filter; | ||
182 | |||
183 | /* snapshot sample of coeffs used for development */ | ||
184 | int16_t *snapshot; | ||
185 | }; | ||
186 | |||
187 | #endif /* __ECHO_H */ | ||