linux/drivers/misc/echo/echo.h
<<
>>
Prefs
   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/*
  32Line echo cancellation for voice
  33
  34What does it do?
  35
  36This module aims to provide G.168-2002 compliant echo cancellation, to remove
  37electrical echoes (e.g. from 2-4 wire hybrids) from voice calls.
  38
  39How does it work?
  40
  41The heart of the echo cancellor is FIR filter. This is adapted to match the
  42echo impulse response of the telephone line. It must be long enough to
  43adequately cover the duration of that impulse response. The signal transmitted
  44to the telephone line is passed through the FIR filter. Once the FIR is
  45properly adapted, the resulting output is an estimate of the echo signal
  46received from the line. This is subtracted from the received signal. The result
  47is an estimate of the signal which originated at the far end of the line, free
  48from echos of our own transmitted signal.
  49
  50The least mean squares (LMS) algorithm is attributed to Widrow and Hoff, and
  51was introduced in 1960. It is the commonest form of filter adaption used in
  52things like modem line equalisers and line echo cancellers. There it works very
  53well.  However, it only works well for signals of constant amplitude. It works
  54very poorly for things like speech echo cancellation, where the signal level
  55varies widely.  This is quite easy to fix. If the signal level is normalised -
  56similar to applying AGC - LMS can work as well for a signal of varying
  57amplitude 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
  59other algorithms exist - e.g. RLS (essentially the same as Kalman filtering),
  60FAP, etc. Some perform significantly better than NLMS.  However, factors such
  61as computational complexity and patents favour the use of NLMS.
  62
  63A simple refinement to NLMS can improve its performance with speech. NLMS tends
  64to adapt best to the strongest parts of a signal. If the signal is white noise,
  65the NLMS algorithm works very well. However, speech has more low frequency than
  66high frequency content. Pre-whitening (i.e. filtering the signal to flatten its
  67spectrum) the echo signal improves the adapt rate for speech, and ensures the
  68final residual signal is not heavily biased towards high frequencies. A very
  69low complexity filter is adequate for this, so pre-whitening adds little to the
  70compute requirements of the echo canceller.
  71
  72An FIR filter adapted using pre-whitened NLMS performs well, provided certain
  73conditions 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
  79The difficulty is that neither of these can be guaranteed.
  80
  81If the adaption is performed while transmitting noise (or something fairly
  82noise like, such as voice) the adaption works very well. If the adaption is
  83performed while transmitting something highly correlative (typically narrow
  84band energy such as signalling tones or DTMF), the adaption can go seriously
  85wrong. The reason is there is only one solution for the adaption on a near
  86random signal - the impulse response of the line. For a repetitive signal,
  87there are any number of solutions which converge the adaption, and nothing
  88guides the adaption to choose the generalised one. Allowing an untrained
  89canceller to converge on this kind of narrowband energy probably a good thing,
  90since at least it cancels the tones. Allowing a well converged canceller to
  91continue converging on such energy is just a way to ruin its generalised
  92adaption. A narrowband detector is needed, so adapation can be suspended at
  93appropriate times.
  94
  95The adaption process is based on trying to eliminate the received signal. When
  96there is any signal from within the environment being cancelled it may upset
  97the adaption process. Similarly, if the signal we are transmitting is small,
  98noise may dominate and disturb the adaption process. If we can ensure that the
  99adaption is only performed when we are transmitting a significant signal level,
 100and the environment is not, things will be OK. Clearly, it is easy to tell when
 101we are sending a significant signal. Telling, if the environment is generating
 102a significant signal, and doing it with sufficient speed that the adaption will
 103not have diverged too much more we stop it, is a little harder.
 104
 105The key problem in detecting when the environment is sourcing significant
 106energy is that we must do this very quickly. Given a reasonably long sample of
 107the received signal, there are a number of strategies which may be used to
 108assess whether that signal contains a strong far end component. However, by the
 109time that assessment is complete the far end signal will have already caused
 110major mis-convergence in the adaption process. An assessment algorithm is
 111needed which produces a fairly accurate result from a very short burst of far
 112end energy.
 113
 114How do I use it?
 115
 116The echo cancellor processes both the transmit and receive streams sample by
 117sample. The processing function is not declared inline. Unfortunately,
 118cancellation requires many operations per sample, so the call overhead is only
 119a 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*/
 129struct 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 */
 188