summaryrefslogtreecommitdiff
path: root/mec3.h
diff options
context:
space:
mode:
authorkpfleming <kpfleming@5390a7c7-147a-4af0-8ec9-7488f05a26cb>2007-12-19 04:04:16 +0000
committerkpfleming <kpfleming@5390a7c7-147a-4af0-8ec9-7488f05a26cb>2007-12-19 04:04:16 +0000
commit4a8f1fb6fa4e4ad06f171c30d129dfeef6d07867 (patch)
tree9489f3307b1958505c482cccf5c5a06fe7da6fdf /mec3.h
parente68e5ec9adb20f793ad0319b181cfdeea336826d (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.h257
1 files changed, 0 insertions, 257 deletions
diff --git a/mec3.h b/mec3.h
deleted file mode 100644
index 6de41f5..0000000
--- a/mec3.h
+++ /dev/null
@@ -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