linux/drivers/isdn/mISDN/dsp_ecdis.h
<<
>>
Prefs
   1/*
   2 * SpanDSP - a series of DSP components for telephony
   3 *
   4 * ec_disable_detector.h - A detector which should eventually meet the
   5 *                         G.164/G.165 requirements for detecting the
   6 *                         2100Hz echo cancellor disable tone.
   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 General Public License as published by
  16 * the Free Software Foundation; either version 2 of the License, or
  17 * (at your option) any later version.
  18 *
  19 * This program is distributed in the hope that it will be useful,
  20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  22 * GNU General Public License for more details.
  23 *
  24 * You should have received a copy of the GNU General Public License
  25 * along with this program; if not, write to the Free Software
  26 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  27 *
  28 */
  29
  30#include "dsp_biquad.h"
  31
  32struct ec_disable_detector_state {
  33        struct biquad2_state notch;
  34        int notch_level;
  35        int channel_level;
  36        int tone_present;
  37        int tone_cycle_duration;
  38        int good_cycles;
  39        int hit;
  40};
  41
  42
  43#define FALSE 0
  44#define TRUE (!FALSE)
  45
  46static inline void
  47echo_can_disable_detector_init(struct ec_disable_detector_state *det)
  48{
  49        /* Elliptic notch */
  50        /* This is actually centred at 2095Hz, but gets the balance we want, due
  51           to the asymmetric walls of the notch */
  52        biquad2_init(&det->notch,
  53                     (int32_t)(-0.7600000 * 32768.0),
  54                     (int32_t)(-0.1183852 * 32768.0),
  55                     (int32_t)(-0.5104039 * 32768.0),
  56                     (int32_t)(0.1567596 * 32768.0),
  57                     (int32_t)(1.0000000 * 32768.0));
  58
  59        det->channel_level = 0;
  60        det->notch_level = 0;
  61        det->tone_present = FALSE;
  62        det->tone_cycle_duration = 0;
  63        det->good_cycles = 0;
  64        det->hit = 0;
  65}
  66/*- End of function --------------------------------------------------------*/
  67
  68static inline int
  69echo_can_disable_detector_update(struct ec_disable_detector_state *det,
  70                                 int16_t amp)
  71{
  72        int16_t notched;
  73
  74        notched = biquad2(&det->notch, amp);
  75        /* Estimate the overall energy in the channel, and the energy in
  76           the notch (i.e. overall channel energy - tone energy => noise).
  77           Use abs instead of multiply for speed (is it really faster?).
  78           Damp the overall energy a little more for a stable result.
  79           Damp the notch energy a little less, so we don't damp out the
  80           blip every time the phase reverses */
  81        det->channel_level += ((abs(amp) - det->channel_level) >> 5);
  82        det->notch_level += ((abs(notched) - det->notch_level) >> 4);
  83        if (det->channel_level > 280) {
  84                /* There is adequate energy in the channel.
  85                   Is it mostly at 2100Hz? */
  86                if (det->notch_level * 6 < det->channel_level) {
  87                        /* The notch says yes, so we have the tone. */
  88                        if (!det->tone_present) {
  89                                /* Do we get a kick every 450+-25ms? */
  90                                if (det->tone_cycle_duration >= 425 * 8
  91                                    && det->tone_cycle_duration <= 475 * 8) {
  92                                        det->good_cycles++;
  93                                        if (det->good_cycles > 2)
  94                                                det->hit = TRUE;
  95                                }
  96                                det->tone_cycle_duration = 0;
  97                        }
  98                        det->tone_present = TRUE;
  99                } else
 100                        det->tone_present = FALSE;
 101                det->tone_cycle_duration++;
 102        } else {
 103                det->tone_present = FALSE;
 104                det->tone_cycle_duration = 0;
 105                det->good_cycles = 0;
 106        }
 107        return det->hit;
 108}
 109/*- End of function --------------------------------------------------------*/
 110/*- End of file ------------------------------------------------------------*/
 111