diff options
author | kpfleming <kpfleming@5390a7c7-147a-4af0-8ec9-7488f05a26cb> | 2007-12-19 04:04:16 +0000 |
---|---|---|
committer | kpfleming <kpfleming@5390a7c7-147a-4af0-8ec9-7488f05a26cb> | 2007-12-19 04:04:16 +0000 |
commit | 4a8f1fb6fa4e4ad06f171c30d129dfeef6d07867 (patch) | |
tree | 9489f3307b1958505c482cccf5c5a06fe7da6fdf /mec3.h | |
parent | e68e5ec9adb20f793ad0319b181cfdeea336826d (diff) |
add ability to provide parameters to echo cancelers on a per-channel basis, and remove the three versions of the 'Mark' echo canceler (later replaced by KB1 and then by MG2)
git-svn-id: http://svn.digium.com/svn/zaptel/branches/1.4@3524 5390a7c7-147a-4af0-8ec9-7488f05a26cb
Diffstat (limited to 'mec3.h')
-rw-r--r-- | mec3.h | 257 |
1 files changed, 0 insertions, 257 deletions
@@ -1,257 +0,0 @@ -/* - * Mark's Third Echo Canceller - * - * Copyright (C) 2003, Digium, Inc. - * - * This program is free software and may be used - * and distributed under the terms of the GNU General Public - * License, incorporated herein by reference. - * - * Dedicated to the crew of the Columbia, STS-107 for their - * bravery and courageous sacrifice for science. - * - */ - -#ifndef _MARK3_ECHO_H -#define _MARK3_ECHO_H - - - -#ifdef __KERNEL__ -#include <linux/kernel.h> -#include <linux/slab.h> -#define MALLOC(a) kmalloc((a), GFP_KERNEL) -#define FREE(a) kfree(a) -#else -#include <stdlib.h> -#include <unistd.h> -#include <stdint.h> -#include <string.h> -#include <math.h> -#define MALLOC(a) malloc(a) -#define FREE(a) free(a) -#endif - -/* Features */ - -/* - * DO_BACKUP -- Backup coefficients, and revert in the presense of double talk to try to prevent - * them from diverging during the ramp-up before the DTD kicks in - */ -/* #define DO_BACKUP */ - -#define STEP_SHIFT 2 /* Convergence rate higher = slower / better (as a shift) */ - -#define SIGMA_REF_PWR 655 /* Keep denominator from being 0 */ - -#define MIN_TX_ENERGY 256 /* Must have at least this much reference */ -#define MIN_RX_ENERGY 32 /* Must have at least this much receive energy */ - -#define MAX_ATTENUATION_SHIFT 6 /* Maximum amount of loss we care about */ -#define MAX_BETA 1024 - -#define SUPPR_SHIFT 4 /* Amount of loss at which we suppress audio */ - -#define HANG_TIME 600 /* Hangover time */ - -#define NTAPS 256 /* Number of echo can taps */ - -#define BACKUP 256 /* Backup every this number of samples */ - -#define POWER_OFFSET 5 /* Shift power by this amount to be sure we don't overflow the - reference power. Higher = less likely to overflow, lower = more accurage */ - -#include "arith.h" - -typedef struct { - short buf[NTAPS * 2]; - short max; - int maxexp; -} cbuf_s; - -struct echo_can_state { - short a_s[NTAPS]; /* Coefficients in shorts */ - int a_i[NTAPS]; /* Coefficients in ints*/ -#ifdef DO_BACKUP - int b_i[NTAPS]; /* Coefficients (backup1) */ - int c_i[NTAPS]; /* Coefficients (backup2) */ -#endif - cbuf_s ref; /* Reference excitation */ - cbuf_s sig; /* Signal (echo + near end + noise) */ - cbuf_s e; /* Error */ - int refpwr; /* Reference power */ - int taps; /* Number of taps */ - int tappwr; /* Power of taps */ - int hcntr; /* Hangtime counter */ - int pos; /* Position in curcular buffers */ - int backup; /* Backup timer */ -}; - -static void echo_can_init(void) -{ - printk("Zaptel Echo Canceller: MARK3%s\n", ZAPTEL_ECHO_AGGRESSIVE); -} - -static void echo_can_identify(char *buf, size_t len) -{ - strncpy(buf, "MARK3", len); -} - -static void echo_can_shutdown(void) -{ -} - -static inline void echo_can_free(struct echo_can_state *ec) -{ - FREE(ec); -} - -static inline void buf_add(cbuf_s *b, short sample, int pos, int taps) -{ - /* Store and keep track of maxima */ - int x; - b->buf[pos] = sample; - b->buf[pos + taps] = sample; - if (sample > b->max) { - b->max = sample; - b->maxexp = taps; - } else { - b->maxexp--; - if (!b->maxexp) { - b->max = 0; - for (x=0;x<taps;x++) - if (b->max < abs(b->buf[pos + x])) { - b->max = abs(b->buf[pos + x]); - b->maxexp = x + 1; - } - } - } -} - -static inline short echo_can_update(struct echo_can_state *ec, short ref, short sig) -{ - int x; - short u; - int refpwr; - int beta; /* Factor */ - int se; /* Simulated echo */ -#ifdef DO_BACKUP - if (!ec->backup) { - /* Backup coefficients periodically */ - ec->backup = BACKUP; - memcpy(ec->c_i,ec->b_i,sizeof(ec->c_i)); - memcpy(ec->b_i,ec->a_i,sizeof(ec->b_i)); - } else - ec->backup--; -#endif - /* Remove old samples from reference power calculation */ - ec->refpwr -= ((ec->ref.buf[ec->pos] * ec->ref.buf[ec->pos]) >> POWER_OFFSET); - - /* Store signal and reference */ - buf_add(&ec->ref, ref, ec->pos, ec->taps); - buf_add(&ec->sig, sig, ec->pos, ec->taps); - - /* Add new reference power */ - ec->refpwr += ((ec->ref.buf[ec->pos] * ec->ref.buf[ec->pos]) >> POWER_OFFSET); - - - /* Calculate simulated echo */ - se = CONVOLVE2(ec->a_s, ec->ref.buf + ec->pos, ec->taps); - se >>= 15; - - u = sig - se; - if (ec->hcntr) - ec->hcntr--; - - /* Store error */ - buf_add(&ec->e, u, ec->pos, ec->taps); - if ((ec->ref.max > MIN_TX_ENERGY) && - (ec->sig.max > MIN_RX_ENERGY) && - (ec->e.max > (ec->ref.max >> MAX_ATTENUATION_SHIFT))) { - /* We have sufficient energy */ - if (ec->sig.max < (ec->ref.max >> 1)) { - /* No double talk */ - if (!ec->hcntr) { - refpwr = ec->refpwr >> (16 - POWER_OFFSET); - if (refpwr < SIGMA_REF_PWR) - refpwr = SIGMA_REF_PWR; - beta = (u << 16) / refpwr; - beta >>= STEP_SHIFT; - if (beta > MAX_BETA) - beta = MAX_BETA; - if (beta < -MAX_BETA) - beta = -MAX_BETA; - /* Update coefficients */ - for (x=0;x<ec->taps;x++) { - ec->a_i[x] += beta * ec->ref.buf[ec->pos + x]; - ec->a_s[x] = ec->a_i[x] >> 16; - } - } - } else { -#ifdef DO_BACKUP - if (!ec->hcntr) { - /* Our double talk detector is turning on for the first time. Revert - our coefficients, since we're probably well into the double talk by now */ - memcpy(ec->a_i, ec->c_i, sizeof(ec->a_i)); - for (x=0;x<ec->taps;x++) { - ec->a_s[x] = ec->a_i[x] >> 16; - } - } -#endif - /* Reset hang-time counter, and prevent backups */ - ec->hcntr = HANG_TIME; -#ifdef DO_BACKUP - ec->backup = BACKUP; -#endif - } - } -#ifndef NO_ECHO__SUPPRESSOR - if (ec->e.max < (ec->ref.max >> SUPPR_SHIFT)) { - /* Suppress residual echo */ - u *= u; - u >>= 16; - } -#endif - ec->pos--; - if (ec->pos < 0) - ec->pos = ec->taps-1; - return u; -} - -static inline struct echo_can_state *echo_can_create(int taps, int adaption_mode) -{ - struct echo_can_state *ec; - int x; - - taps = NTAPS; - ec = MALLOC(sizeof(struct echo_can_state)); - if (ec) { - memset(ec, 0, sizeof(struct echo_can_state)); - ec->taps = taps; - ec->pos = ec->taps-1; - for (x=0;x<31;x++) { - if ((1 << x) >= ec->taps) { - ec->tappwr = x; - break; - } - } - } - return ec; -} - -static inline int echo_can_traintap(struct echo_can_state *ec, int pos, short val) -{ - /* Reset hang counter to avoid adjustments after - initial forced training */ - ec->hcntr = ec->taps << 1; - if (pos >= ec->taps) - return 1; - ec->a_i[pos] = val << 17; - ec->a_s[pos] = val << 1; - if (++pos >= ec->taps) - return 1; - return 0; -} - - -#endif |