Mercurial > hg > audiostuff
comparison spandsp-0.0.6pre17/src/spandsp/echo.h @ 4:26cd8f1ef0b1
import spandsp-0.0.6pre17
| author | Peter Meerwald <pmeerw@cosy.sbg.ac.at> |
|---|---|
| date | Fri, 25 Jun 2010 15:50:58 +0200 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 3:c6c5a16ce2f2 | 4:26cd8f1ef0b1 |
|---|---|
| 1 /* | |
| 2 * SpanDSP - a series of DSP components for telephony | |
| 3 * | |
| 4 * echo.h - An echo cancellor, suitable for electrical and acoustic | |
| 5 * cancellation. This code does not currently comply with | |
| 6 * any relevant standards (e.g. G.164/5/7/8). | |
| 7 * | |
| 8 * Written by Steve Underwood <steveu@coppice.org> | |
| 9 * | |
| 10 * Copyright (C) 2001 Steve Underwood | |
| 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 Lesser General Public License version 2.1, | |
| 16 * as 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 Lesser General Public License for more details. | |
| 22 * | |
| 23 * You should have received a copy of the GNU Lesser General Public | |
| 24 * License 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.20 2009/09/22 13:11:04 steveu Exp $ | |
| 28 */ | |
| 29 | |
| 30 /*! \file */ | |
| 31 | |
| 32 #if !defined(_SPANDSP_ECHO_H_) | |
| 33 #define _SPANDSP_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 enum | |
| 121 { | |
| 122 ECHO_CAN_USE_ADAPTION = 0x01, | |
| 123 ECHO_CAN_USE_NLP = 0x02, | |
| 124 ECHO_CAN_USE_CNG = 0x04, | |
| 125 ECHO_CAN_USE_CLIP = 0x08, | |
| 126 ECHO_CAN_USE_SUPPRESSOR = 0x10, | |
| 127 ECHO_CAN_USE_TX_HPF = 0x20, | |
| 128 ECHO_CAN_USE_RX_HPF = 0x40, | |
| 129 ECHO_CAN_DISABLE = 0x80 | |
| 130 }; | |
| 131 | |
| 132 /*! | |
| 133 G.168 echo canceller descriptor. This defines the working state for a line | |
| 134 echo canceller. | |
| 135 */ | |
| 136 typedef struct echo_can_state_s echo_can_state_t; | |
| 137 | |
| 138 #if defined(__cplusplus) | |
| 139 extern "C" | |
| 140 { | |
| 141 #endif | |
| 142 | |
| 143 /*! Create a voice echo canceller context. | |
| 144 \param len The length of the canceller, in samples. | |
| 145 \return The new canceller context, or NULL if the canceller could not be created. | |
| 146 */ | |
| 147 SPAN_DECLARE(echo_can_state_t *) echo_can_init(int len, int adaption_mode); | |
| 148 | |
| 149 /*! Release a voice echo canceller context. | |
| 150 \param ec The echo canceller context. | |
| 151 \return 0 for OK, else -1. | |
| 152 */ | |
| 153 SPAN_DECLARE(int) echo_can_release(echo_can_state_t *ec); | |
| 154 | |
| 155 /*! Free a voice echo canceller context. | |
| 156 \param ec The echo canceller context. | |
| 157 \return 0 for OK, else -1. | |
| 158 */ | |
| 159 SPAN_DECLARE(int) echo_can_free(echo_can_state_t *ec); | |
| 160 | |
| 161 /*! Flush (reinitialise) a voice echo canceller context. | |
| 162 \param ec The echo canceller context. | |
| 163 */ | |
| 164 SPAN_DECLARE(void) echo_can_flush(echo_can_state_t *ec); | |
| 165 | |
| 166 /*! Set the adaption mode of a voice echo canceller context. | |
| 167 \param ec The echo canceller context. | |
| 168 \param adaption_mode The mode. | |
| 169 */ | |
| 170 SPAN_DECLARE(void) echo_can_adaption_mode(echo_can_state_t *ec, int adaption_mode); | |
| 171 | |
| 172 /*! Process a sample through a voice echo canceller. | |
| 173 \param ec The echo canceller context. | |
| 174 \param tx The transmitted audio sample. | |
| 175 \param rx The received audio sample. | |
| 176 \return The clean (echo cancelled) received sample. | |
| 177 */ | |
| 178 SPAN_DECLARE(int16_t) echo_can_update(echo_can_state_t *ec, int16_t tx, int16_t rx); | |
| 179 | |
| 180 /*! Process to high pass filter the tx signal. | |
| 181 \param ec The echo canceller context. | |
| 182 \param tx The transmitted auio sample. | |
| 183 \return The HP filtered transmit sample, send this to your D/A. | |
| 184 */ | |
| 185 SPAN_DECLARE(int16_t) echo_can_hpf_tx(echo_can_state_t *ec, int16_t tx); | |
| 186 | |
| 187 SPAN_DECLARE(void) echo_can_snapshot(echo_can_state_t *ec); | |
| 188 | |
| 189 #if defined(__cplusplus) | |
| 190 } | |
| 191 #endif | |
| 192 | |
| 193 #endif | |
| 194 /*- End of file ------------------------------------------------------------*/ |
