summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorkpfleming <kpfleming@5390a7c7-147a-4af0-8ec9-7488f05a26cb>2007-12-20 01:19:37 +0000
committerkpfleming <kpfleming@5390a7c7-147a-4af0-8ec9-7488f05a26cb>2007-12-20 01:19:37 +0000
commit1cdd316d671dac981ace7ecae43a389a5883978f (patch)
tree24f1432ecf6ee8151ddffa78a2987872dc30089c
parentb5c7c251f68b9d0c508ab0d36cd26c8b9ce8bc79 (diff)
revert the echocanparams code for now... it's not ready to be used
git-svn-id: http://svn.digium.com/svn/zaptel/branches/1.4@3545 5390a7c7-147a-4af0-8ec9-7488f05a26cb
-rw-r--r--Makefile2
-rw-r--r--hpec/hpec_zaptel.h14
-rw-r--r--kb1ec.h51
-rw-r--r--mec.h322
-rw-r--r--mec2.h436
-rw-r--r--mec2_const.h28
-rw-r--r--mec3-float.h229
-rw-r--r--mec3.h257
-rw-r--r--mg2ec.h66
-rw-r--r--sec-2.h57
-rw-r--r--sec.h54
-rw-r--r--zaptel-base.c166
-rw-r--r--zaptel.h28
-rw-r--r--zconfig.h3
14 files changed, 1450 insertions, 263 deletions
diff --git a/Makefile b/Makefile
index 213b368..4fff02a 100644
--- a/Makefile
+++ b/Makefile
@@ -375,7 +375,7 @@ wct4xxp/wct4xxp.o:
tor2.o: tor2-hw.h tor2fw.h
-zaptel-base.o: digits.h arith.h sec.h sec-2.h kb1ec.h mg2ec.h zconfig.h
+zaptel-base.o: digits.h arith.h sec.h mec.h sec-2.h mec2.h mec3.h zconfig.h
wcusb.o: wcusb.h
diff --git a/hpec/hpec_zaptel.h b/hpec/hpec_zaptel.h
index 2fb5a14..80004da 100644
--- a/hpec/hpec_zaptel.h
+++ b/hpec/hpec_zaptel.h
@@ -87,22 +87,18 @@ static inline void echo_can_array_update(struct echo_can_state *ec, short *iref,
DECLARE_MUTEX(alloc_lock);
-static int echo_can_create(struct zt_echocanparams *ecp, struct zt_echocanparam *p,
- struct echo_can_state **ec)
+static inline struct echo_can_state *echo_can_create(int len, int adaption_mode)
{
- if (ecp->param_count > 0) {
- printk(KERN_WARNING "HPEC does not support parameters; failing request\n");
- return -EINVAL;
- }
+ struct echo_can_state *result = NULL;
if (down_interruptible(&alloc_lock))
- return -ENOTTY;
+ return NULL;
- *ec = hpec_channel_alloc(ecp->tap_length);
+ result = hpec_channel_alloc(len);
up(&alloc_lock);
- return *ec ? 0 : -ENOTTY;
+ return result;
}
static inline int echo_can_traintap(struct echo_can_state *ec, int pos, short val)
diff --git a/kb1ec.h b/kb1ec.h
index 47ff8ac..e0f63f6 100644
--- a/kb1ec.h
+++ b/kb1ec.h
@@ -529,19 +529,12 @@ static inline short echo_can_update(struct echo_can_state *ec, short iref, short
return u;
}
-static int echo_can_create(struct zt_echocanparams *ecp, struct zt_echocanparam *p,
- struct echo_can_state **ec)
+static inline struct echo_can_state *echo_can_create(int len, int adaption_mode)
{
+ struct echo_can_state *ec;
int maxy;
int maxu;
- size_t size;
-
- if (ecp->param_count > 0) {
- printk(KERN_WARNING "KB1 echo canceler does not support parameters; failing request\n");
- return -EINVAL;
- }
-
- maxy = ecp->tap_length + DEFAULT_M;
+ maxy = len + DEFAULT_M;
maxu = DEFAULT_M;
if (maxy < (1 << DEFAULT_ALPHA_YT_I))
maxy = (1 << DEFAULT_ALPHA_YT_I);
@@ -549,24 +542,26 @@ static int echo_can_create(struct zt_echocanparams *ecp, struct zt_echocanparam
maxy = (1 << DEFAULT_SIGMA_LY_I);
if (maxu < (1 << DEFAULT_SIGMA_LU_I))
maxu = (1 << DEFAULT_SIGMA_LU_I);
-
- size = sizeof(*ec) +
- 4 + /* align */
- sizeof(int) * ecp->tap_length + /* a_i */
- sizeof(short) * ecp->tap_length + /* a_s */
- 2 * sizeof(short) * (maxy) + /* y_s */
- 2 * sizeof(short) * (1 << DEFAULT_ALPHA_ST_I) + /* s_s */
- 2 * sizeof(short) * (maxu) + /* u_s */
- 2 * sizeof(short) * ecp->tap_length; /* y_tilde_s */
-
- if (!(*ec = MALLOC(size)))
- return -ENOMEM;
-
- memset(*ec, 0, size);
-
- init_cc(*ec, ecp->tap_length, maxy, maxu);
-
- return 0;
+ ec = (struct echo_can_state *)MALLOC(sizeof(struct echo_can_state) +
+ 4 + /* align */
+ sizeof(int) * len + /* a_i */
+ sizeof(short) * len + /* a_s */
+ 2 * sizeof(short) * (maxy) + /* y_s */
+ 2 * sizeof(short) * (1 << DEFAULT_ALPHA_ST_I) + /* s_s */
+ 2 * sizeof(short) * (maxu) + /* u_s */
+ 2 * sizeof(short) * len); /* y_tilde_s */
+ if (ec) {
+ memset(ec, 0, sizeof(struct echo_can_state) +
+ 4 + /* align */
+ sizeof(int) * len + /* a_i */
+ sizeof(short) * len + /* a_s */
+ 2 * sizeof(short) * (maxy) + /* y_s */
+ 2 * sizeof(short) * (1 << DEFAULT_ALPHA_ST_I) + /* s_s */
+ 2 * sizeof(short) * (maxu) + /* u_s */
+ 2 * sizeof(short) * len); /* y_tilde_s */
+ init_cc(ec, len, maxy, maxu);
+ }
+ return ec;
}
static inline int echo_can_traintap(struct echo_can_state *ec, int pos, short val)
diff --git a/mec.h b/mec.h
new file mode 100644
index 0000000..09421cd
--- /dev/null
+++ b/mec.h
@@ -0,0 +1,322 @@
+/*
+ * Mark's Echo Canceller
+ *
+ * Mark Spencer <markster@linux-support.net>
+ *
+ * Simple, LMS Echo Canceller with double talk detection.
+ * Partly based on the TI App note:
+ * "Digital Voice Echo Canceller with a TMS 32020"
+ *
+ * Special additional thanks to:
+ * Jim Dixon (Lambda Telecommunications)
+ * Iman Ghobrial (Adtran, Inc.)
+ *
+ * Copyright (C) 2001, Linux Support Services, Inc.
+ *
+ * This program is free software and may be used and
+ * distributed according to the terms of the GNU
+ * General Public License, incorporated herein by
+ * reference.
+ *
+ */
+
+#ifndef _MEC_H
+#define _MEC_H
+
+/* You have to express the size of the echo canceller in taps as
+ a power of 2 (6 = 64 taps, 7 = 128 taps, 8 = 256 taps) */
+#define NUM_TAPS_POW2 6 /* Size of echo canceller in power of 2 (taps) */
+#define NUM_TAPS (1 << NUM_TAPS_POW2) /* Actual number of taps */
+#define TAP_MASK (NUM_TAPS-1)
+
+
+#define SIGMA_LU_POW NUM_TAPS_POW2
+#define SIGMA_LY_POW NUM_TAPS_POW2
+#define SIGMA_YT_POW (NUM_TAPS_POW2 - 1)
+#define SIGMA_ST_POW (NUM_TAPS_POW2 - 1)
+
+#define BETA_POW 8
+
+#define CUTOFF_S 4
+
+/* The higher you make this, the better the quality, but the more CPU time required */
+#define MIN_QUALITY 100
+
+/* This optimization saves a lot of processor but may degrade quality */
+#define OPTIMIZEDIV
+
+#if 0
+/* This converges much more slowly but saves processor */
+#define MIN_UPDATE 256
+#define MIN_SKIP 8
+#endif
+
+#define HANG_T 600 /* 600 samples, or 75ms */
+
+struct echo_can_state {
+ /* Circular position */
+ int cpos;
+ short y[NUM_TAPS]; /* Last N samples (relative to cpos) transmitted */
+ short y_abs[NUM_TAPS]; /* Last N samples (relative to cpos) transmitted (abs value) */
+ short s[NUM_TAPS]; /* Last N samples (relative to cpos) received */
+ short s_abs[NUM_TAPS]; /* Last N samples (relative to cpos) received (abs value) */
+ short u[NUM_TAPS]; /* Last N samples (relative to cpos) with echo removed */
+ short u_abs[NUM_TAPS]; /* Last N samples (relative to cpos) with echo removed */
+
+ int Ly; /* tx power */
+ int Lu; /* Power of echo-cancelled output */
+
+ int Ty[NUM_TAPS]; /* Short term power estimate of transmit */
+ int Ts; /* Short term power estimate of received signal */
+
+ int a[NUM_TAPS]; /* Tap weight coefficients (not relative) */
+
+ short sdc[NUM_TAPS]; /* Near end signal before High Pass Filter */
+
+ int samples; /* Sample count */
+ int pass; /* Number of passes we've made */
+
+ int hangt;
+
+ int lastmax; /* Optimize maximum search */
+ int maxTy; /* Maximum Ty */
+};
+
+#define INLINE inline
+
+#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>
+#define MALLOC(a) malloc(a)
+#define FREE(a) free(a)
+#endif
+
+static void echo_can_init(void)
+{
+ printk("Zaptel Echo Canceller: MARK%s\n", ZAPTEL_ECHO_AGGRESSIVE);
+}
+
+static void echo_can_identify(char *buf, size_t len)
+{
+ strncpy(buf, "MARK2", len);
+}
+
+static void echo_can_shutdown(void)
+{
+}
+
+static INLINE struct echo_can_state *echo_can_create(int len, int adaption_mode)
+{
+ struct echo_can_state *ec;
+ /* Uhm, we're only one length, sorry. */
+ ec = MALLOC(sizeof(struct echo_can_state));
+ if (ec)
+ memset(ec, 0, sizeof(*ec));
+ return ec;
+}
+
+#define PASSPOS 32000
+#undef PASSPOS
+
+static INLINE void echo_can_free(struct echo_can_state *ec)
+{
+ FREE(ec);
+}
+
+static INLINE int16_t echo_can_update(struct echo_can_state *ec, int16_t tx, int16_t rx)
+{
+ /* Process a sample, where tx is the near end and rx is the far end + echo */
+
+ int suppr;
+ int nsuppr;
+ short rxabs, txabs;
+ register int Lu;
+ register int x;
+ register int pos;
+ register int r_hat; /* Estimated echo */
+ int oldrxabs;
+ int oldtxabs;
+ int oldsupprabs;
+ int supprabs;
+#ifdef MIN_UPDATE
+ int totalupd;
+#endif
+
+ txabs = abs(tx);
+ rxabs = abs(rx);
+
+ ec->pass++;
+
+ r_hat = 0;
+
+ /* Load next value */
+ ec->y[ec->cpos] = tx;
+
+ /* Load next abs value */
+ oldtxabs = ec->y_abs[ec->cpos];
+ ec->y_abs[ec->cpos] = txabs;
+
+ /* Bring in receive value (near-end signal) */
+ ec->sdc[ec->cpos] = rx;
+
+ /* Bring in receive value absolute value */
+ oldrxabs = ec->s_abs[ec->cpos];
+ ec->s_abs[ec->cpos] = rxabs;
+
+ Lu = ec->Lu | 1;
+
+#if 0
+ /* Apply first order high pass filter (3 dB @ 160 Hz) */
+ tx = ec->s[ec->cpos] = (1.0-DEFGAMMA) * ec->s[(ec->cpos - 1) & TAP_MASK] +
+ 0.5 * (1.0-DEFGAMMA) * ( ec->sdc[(ec->cpos - 1) & TAP_MASK] - ec->sdc[(ec->cpos - 2) & TAP_MASK]);
+#endif
+
+ /* Estimate echo */
+ pos = ec->cpos;
+ for (x=0;x<NUM_TAPS;x++) {
+ r_hat += ec->a[x] * ec->y[pos];
+ /* Go backwards in time and loop around circular buffer */
+ pos = (pos - 1) & TAP_MASK;
+ }
+
+ r_hat >>= 16;
+
+ if (ec->hangt > 0)
+ ec->hangt--;
+
+ /* printf("rx: %F, rhat: %F\n", rx, r_hat); */
+ /* Calculate suppressed amount */
+ suppr = rx - r_hat;
+
+ if (ec->pass > NUM_TAPS) {
+ /* Have to have enough taps to start with */
+ if (ec->maxTy > ec->Ts) {
+ /* There is no near-end speech detected */
+ if (!ec->hangt) {
+ /* We're not in the hang-time from the end of near-end speech */
+ if ((ec->Ly > 1024) && ((ec->Ly / Lu) < MIN_QUALITY)) {
+#ifdef OPTIMIZEDIV
+ /* We both have enough signal on the transmit */
+ nsuppr = (suppr << 18) / ec->Ly;
+
+ if (nsuppr > 32767)
+ nsuppr = 32767;
+ if (nsuppr < -32768)
+ nsuppr = -32768;
+
+ nsuppr /= ec->Ly;
+#else
+ /* We both have enough signal on the transmit */
+ nsuppr = (suppr << 16) / ec->Ly;
+
+ if (nsuppr > 32767)
+ nsuppr = 32767;
+ if (nsuppr < -32768)
+ nsuppr = -32768;
+
+#endif
+
+ /* Update coefficients */
+ pos = ec->cpos;
+#ifdef MIN_UPDATE
+ totalupd =0;
+#endif
+ for (x=0;x<NUM_TAPS;x++) {
+ register int adj;
+ adj = ec->y[pos] * nsuppr;
+#ifndef OPTIMIZEDIV
+ adj /= ec->Ly;
+ adj >>= BETA_POW;
+#else
+ adj >>= BETA_POW + 2;
+#endif
+#ifdef PASSPOS
+ if (ec->pass > PASSPOS)
+ printf("tx: %d, old %d: %d, adj %d, nsuppr: %d, power: %d\n", tx, x, ec->a[x], adj, nsuppr, ec->Ly);
+#endif
+ ec->a[x] += adj;
+#ifdef MIN_UPDATE
+ totalupd += abs(adj);
+#endif
+ /* Go backwards in time and loop around circular buffer */
+ pos = (pos - 1) & TAP_MASK;
+ }
+#ifdef MIN_UPDATE
+ /* If we didn't update at least this much, delay for many more taps */
+ if (totalupd < MIN_UPDATE) {
+ ec->hangt += MIN_SKIP;
+ }
+#endif
+ }
+
+ }
+ } else
+ /* Near end speech detected */
+ ec->hangt = HANG_T;
+ }
+
+ /* Save supression and absolute values */
+ supprabs = abs(suppr);
+ oldsupprabs = ec->u_abs[ec->cpos];
+ ec->u[ec->cpos] = suppr;
+ ec->u_abs[ec->cpos] = supprabs;
+
+ /* Update tx power */
+ ec->Ly += (txabs >> SIGMA_LY_POW) - (oldtxabs >> SIGMA_LY_POW);
+
+ /* Update rx power */
+ ec->Lu += (supprabs >> SIGMA_LU_POW) - (oldsupprabs >> SIGMA_LU_POW);
+
+ /* Short term power of tx */
+ ec->Ty[ec->cpos] = ec->Ty[(ec->cpos - 1) & TAP_MASK] +
+ ((txabs >> SIGMA_YT_POW ) - (oldtxabs >> SIGMA_YT_POW));
+
+ /* Keep track of highest */
+ if (ec->lastmax == ec->cpos) {
+ register int maxTy = 0;
+ /* Have to loop through and find the new highest since our old highest expired */
+ /* Estimate echo */
+ pos = ec->cpos;
+ for (x=0;x<NUM_TAPS;x++) {
+ if (ec->Ty[pos] > maxTy)
+ maxTy = ec->Ty[pos];
+ /* Go backwards in time and loop around circular buffer */
+ pos = (pos - 1) & TAP_MASK;
+ }
+ ec->maxTy = maxTy;
+ } else {
+ /* Just keep the highest */
+ if (ec->Ty[ec->cpos] > ec->maxTy) {
+ ec->maxTy = ec->Ty[ec->cpos];
+ ec->lastmax = ec->cpos;
+ }
+ }
+ ec->Ts += (rxabs >> SIGMA_ST_POW) - (oldrxabs >> SIGMA_ST_POW) ;
+
+ /* Increment position memory */
+ ec->cpos = (ec->cpos + 1 ) & TAP_MASK;
+
+ return suppr;
+}
+
+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->hangt = NUM_TAPS << 1;
+ if (pos >= NUM_TAPS)
+ return 1;
+ ec->a[pos] = val << 17;
+ if (++pos >= NUM_TAPS)
+ return 1;
+ return 0;
+}
+
+#endif
diff --git a/mec2.h b/mec2.h
new file mode 100644
index 0000000..98061ff
--- /dev/null
+++ b/mec2.h
@@ -0,0 +1,436 @@
+/*
+ * Mark's Second Echo Canceller
+ *
+ * Copyright (C) 2002, Digium, Inc.
+ *
+ * This program is free software and may be used and
+ * distributed according to the terms of the GNU
+ * General Public License, incorporated herein by
+ * reference.
+ *
+ */
+#ifndef _MARK2_ECHO_H
+#define _MARK2_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
+
+/* Get optimized routines for math */
+#include "arith.h"
+
+#ifndef NULL
+#define NULL 0
+#endif
+#ifndef FALSE
+#define FALSE 0
+#endif
+#ifndef TRUE
+#define TRUE (!FALSE)
+#endif
+
+#include "mec2_const.h"
+
+/* Circular buffer definition */
+typedef struct {
+ int idx_d;
+ int size_d;
+ short *buf_d; /* Twice as large as we need */
+} echo_can_cb_s;
+
+// class definition
+//
+struct echo_can_state {
+ /* Echo canceller definition */
+
+ /* absolute time */
+ int i_d;
+
+ /* pre-computed constants */
+
+ int N_d;
+ int beta2_i;
+
+ // declare accumulators for power computations
+ //
+ int Ly_i;
+ int Lu_i;
+
+ // declare an accumulator for the near-end signal detector
+ //
+ int s_tilde_i;
+ int HCNTR_d;
+
+ // circular buffers and coefficients
+ //
+ int *a_i;
+ short *a_s;
+ echo_can_cb_s y_s;
+ echo_can_cb_s s_s;
+ echo_can_cb_s u_s;
+ echo_can_cb_s y_tilde_s;
+ int y_tilde_i;
+
+ /* Max memory */
+ short max_y_tilde;
+ int max_y_tilde_pos;
+
+};
+
+static void echo_can_init(void)
+{
+ printk("Zaptel Echo Canceller: MARK2%s\n", ZAPTEL_ECHO_AGGRESSIVE);
+}
+
+static void echo_can_identify(char *buf, size_t len)
+{
+ strncpy(buf, "MARK2", len);
+}
+
+static void echo_can_shutdown(void)
+{
+}
+
+static inline void init_cb_s(echo_can_cb_s *cb, int len, void *where)
+{
+ cb->buf_d = (short *)where;
+ cb->idx_d = 0;
+ cb->size_d = len;
+}
+
+static inline void add_cc_s(echo_can_cb_s *cb, short newval)
+{
+ /* Can't use modulus because N+M isn't a power of two (generally) */
+ cb->idx_d--;
+ if (cb->idx_d < (int)0)
+ {cb->idx_d += cb->size_d;}
+ /* Load two copies into memory */
+ cb->buf_d[cb->idx_d] = newval;
+ cb->buf_d[cb->idx_d + cb->size_d] = newval;
+}
+
+static inline short get_cc_s(echo_can_cb_s *cb, int pos)
+{
+ /* Load two copies into memory */
+ return cb->buf_d[cb->idx_d + pos];
+}
+
+static inline void init_cc(struct echo_can_state *ec, int N, int maxy, int maxu) {
+
+ void *ptr = ec;
+ unsigned long tmp;
+ /* double-word align past end of state */
+ ptr += sizeof(struct echo_can_state);
+ tmp = (unsigned long)ptr;
+ tmp += 3;
+ tmp &= ~3L;
+ ptr = (void *)tmp;
+
+ // reset parameters
+ //
+ ec->N_d = N;
+ ec->beta2_i = DEFAULT_BETA1_I;
+
+ // allocate coefficient memory
+ //
+ ec->a_i = ptr;
+ ptr += (sizeof(int) * ec->N_d);
+ ec->a_s = ptr;
+ ptr += (sizeof(short) * ec->N_d);
+
+ /* Reset Y circular buffer (short version) */
+ init_cb_s(&ec->y_s, maxy, ptr);
+ ptr += (sizeof(short) * (maxy) * 2);
+
+ /* Reset Sig circular buffer (short version for FIR filter) */
+ init_cb_s(&ec->s_s, (1 << DEFAULT_ALPHA_ST_I), ptr);
+ ptr += (sizeof(short) * (1 << DEFAULT_ALPHA_ST_I) * 2);
+
+ init_cb_s(&ec->u_s, maxu, ptr);
+ ptr += (sizeof(short) * maxu * 2);
+
+ // allocate a buffer for the reference signal power computation
+ //
+ init_cb_s(&ec->y_tilde_s, ec->N_d, ptr);
+
+
+ // reset absolute time
+ //
+ ec->i_d = (int)0;
+
+ // reset the power computations (for y and u)
+ //
+ ec->Ly_i = DEFAULT_CUTOFF_I;
+ ec->Lu_i = DEFAULT_CUTOFF_I;
+
+ // reset the near-end speech detector
+ //
+ ec->s_tilde_i = 0;
+ ec->y_tilde_i = 0;
+ ec->HCNTR_d = (int)0;
+
+ // exit gracefully
+ //
+}
+
+static inline void echo_can_free(struct echo_can_state *ec)
+{
+ FREE(ec);
+}
+
+static inline short echo_can_update(struct echo_can_state *ec, short iref, short isig) {
+
+ /* declare local variables that are used more than once
+ */
+ int k;
+ int rs;
+ short u;
+ int Py_i;
+ int two_beta_i;
+
+ /***************************************************************************
+ //
+ // flow A on pg. 428
+ //
+ ***************************************************************************/
+
+ /* eq. (16): high-pass filter the input to generate the next value;
+ // push the current value into the circular buffer
+ //
+ // sdc_im1_d = sdc_d;
+ // sdc_d = sig;
+ // s_i_d = sdc_d;
+ // s_d = s_i_d;
+ // s_i_d = (float)(1.0 - gamma_d) * s_i_d
+ + (float)(0.5 * (1.0 - gamma_d)) * (sdc_d - sdc_im1_d); */
+
+
+ /* Delete last sample from power estimate */
+ ec->y_tilde_i -= abs(get_cc_s(&ec->y_s, (1 << DEFAULT_ALPHA_YT_I) - 1 )) >> DEFAULT_ALPHA_YT_I;
+ /* push the reference data onto the circular buffer */
+ add_cc_s(&ec->y_s, iref);
+
+ /* eq. (2): compute r in fixed-point */
+ rs = CONVOLVE2(ec->a_s, ec->y_s.buf_d + ec->y_s.idx_d, ec->N_d);
+ rs >>= 15;
+
+ /* eq. (3): compute the output value (see figure 3) and the error
+ // note: the error is the same as the output signal when near-end
+ // speech is not present
+ */
+ u = isig - rs;
+
+ add_cc_s(&ec->u_s, u);
+
+
+
+ /* Delete oldest part of received s_tilde */
+ ec->s_tilde_i -= abs(get_cc_s(&ec->s_s, (1 << DEFAULT_ALPHA_ST_I) - 1 ));
+
+ /* push the signal on the circular buffer, too */
+ add_cc_s(&ec->s_s, isig);
+ ec->s_tilde_i += abs(isig);
+ ec->y_tilde_i += abs(iref) >> DEFAULT_ALPHA_YT_I;
+
+ /* Add to our list of recent y_tilde's */
+ add_cc_s(&ec->y_tilde_s, ec->y_tilde_i);
+
+ /****************************************************************************
+ //
+ // flow B on pg. 428
+ //
+ ****************************************************************************/
+
+ /* compute the new convergence factor
+ */
+ if (!ec->HCNTR_d) {
+ Py_i = (ec->Ly_i >> DEFAULT_SIGMA_LY_I) * (ec->Ly_i >> DEFAULT_SIGMA_LY_I);
+ Py_i >>= 15;
+ } else {
+ Py_i = (1 << 15);
+ }
+
+#if 0
+ printf("Py: %e, Py_i: %e\n", Py, Py_i * AMPL_SCALE_1);
+#endif
+
+ /* Vary rate of adaptation depending on position in the file
+ // Do not do this for the first (DEFAULT_UPDATE_TIME) secs after speech
+ // has begun of the file to allow the echo cancellor to estimate the
+ // channel accurately
+ */
+#if 0
+ if (ec->start_speech_d != 0 ){
+ if ( ec->i_d > (DEFAULT_T0 + ec->start_speech_d)*(SAMPLE_FREQ) ){
+ ec->beta2_d = max_cc_float(MIN_BETA,
+ DEFAULT_BETA1 * exp((-1/DEFAULT_TAU)*((ec->i_d/(float)SAMPLE_FREQ) -
+ DEFAULT_T0 -
+ ec->start_speech_d)));
+ }
+ }
+ else {ec->beta2_d = DEFAULT_BETA1;}
+#endif
+
+ ec->beta2_i = DEFAULT_BETA1_I; /* Fixed point, inverted */
+
+ two_beta_i = (ec->beta2_i * Py_i) >> 15; /* Fixed point version, inverted */
+ if (!two_beta_i)
+ two_beta_i++;
+
+ /* Update Lu_i (Suppressed power estimate) */
+ ec->Lu_i -= abs(get_cc_s(&ec->u_s, (1 << DEFAULT_SIGMA_LU_I) - 1 )) ;
+ ec->Lu_i += abs(u);
+
+ /* eq. (10): update power estimate of the reference
+ */
+ ec->Ly_i -= abs(get_cc_s(&ec->y_s, (1 << DEFAULT_SIGMA_LY_I) - 1)) ;
+ ec->Ly_i += abs(iref);
+
+ if (ec->Ly_i < DEFAULT_CUTOFF_I)
+ ec->Ly_i = DEFAULT_CUTOFF_I;
+
+#if 0
+ printf("Float: %e, Int: %e\n", ec->Ly_d, (ec->Ly_i >> DEFAULT_SIGMA_LY_I) * AMPL_SCALE_1);
+#endif
+
+ if (ec->y_tilde_i > ec->max_y_tilde) {
+ /* New highest y_tilde with full life */
+ ec->max_y_tilde = ec->y_tilde_i;
+ ec->max_y_tilde_pos = ec->N_d - 1;
+ } else if (--ec->max_y_tilde_pos < 0) {
+ /* Time to find new max y tilde... */
+ ec->max_y_tilde = MAX16(ec->y_tilde_s.buf_d + ec->y_tilde_s.idx_d, ec->N_d, &ec->max_y_tilde_pos);
+ }
+
+ if ((ec->s_tilde_i >> (DEFAULT_ALPHA_ST_I - 1)) > ec->max_y_tilde)
+ {
+ ec->HCNTR_d = DEFAULT_HANGT;
+ }
+ else if (ec->HCNTR_d > (int)0)
+ {
+ ec->HCNTR_d--;
+ }
+
+ /* update coefficients if no near-end speech and we have enough signal
+ * to bother trying to update.
+ */
+ if (!ec->HCNTR_d && !(ec->i_d % DEFAULT_M) &&
+ (ec->Lu_i > MIN_UPDATE_THRESH_I)) {
+ // loop over all filter coefficients
+ //
+ for (k=0; k<ec->N_d; k++) {
+
+ // eq. (7): compute an expectation over M_d samples
+ //
+ int grad2;
+ grad2 = CONVOLVE2(ec->u_s.buf_d + ec->u_s.idx_d,
+ ec->y_s.buf_d + ec->y_s.idx_d + k, DEFAULT_M);
+ // eq. (7): update the coefficient
+ //
+ ec->a_i[k] += grad2 / two_beta_i;
+ ec->a_s[k] = ec->a_i[k] >> 16;
+ }
+ }
+
+ /* paragraph below eq. (15): if no near-end speech,
+ // check for residual error suppression
+ */
+#ifndef NO_ECHO_SUPPRESSOR
+#ifdef AGGRESSIVE_SUPPRESSOR
+#ifdef AGGRESSIVE_TIMELIMIT /* This allows the aggressive suppressor to turn off after set amount of time */
+ if (ec->i_d > AGGRESSIVE_TIMELIMIT ) {
+ if ((ec->HCNTR_d == 0) && ((ec->Ly_i/(ec->Lu_i + 1)) > DEFAULT_SUPPR_I)) {
+ u = u * (ec->Lu_i >> DEFAULT_SIGMA_LU_I) / ((ec->Ly_i >> (DEFAULT_SIGMA_LY_I + 2)) + 1);
+ }
+ }
+ else {
+#endif
+ if ((ec->HCNTR_d < AGGRESSIVE_HCNTR) && (ec->Ly_i > (ec->Lu_i << 1))) {
+ u = u * (ec->Lu_i >> DEFAULT_SIGMA_LU_I) / ((ec->Ly_i >> (DEFAULT_SIGMA_LY_I)) + 1);
+ u = u * (ec->Lu_i >> DEFAULT_SIGMA_LU_I) / ((ec->Ly_i >> (DEFAULT_SIGMA_LY_I)) + 1);
+ }
+#ifdef AGGRESSIVE_TIMELIMIT
+ }
+#endif
+#else
+ if ((ec->HCNTR_d == 0) && ((ec->Ly_i/(ec->Lu_i + 1)) > DEFAULT_SUPPR_I)) {
+ u = u * (ec->Lu_i >> DEFAULT_SIGMA_LU_I) / ((ec->Ly_i >> (DEFAULT_SIGMA_LY_I + 2)) + 1);
+ }
+#endif
+#endif
+
+#if 0
+ if ((ec->HCNTR_d == 0) && ((ec->Lu_d/ec->Ly_d) < DEFAULT_SUPPR) &&
+ (ec->Lu_d/ec->Ly_d > EC_MIN_DB_VALUE)) {
+ suppr_factor = (10/(float)(SUPPR_FLOOR-SUPPR_CEIL))*log(ec->Lu_d/ec->Ly_d)
+ - SUPPR_CEIL/(float)(SUPPR_FLOOR - SUPPR_CEIL);
+
+ u_suppr = pow(10.0,(suppr_factor)*RES_SUPR_FACTOR/10.0)*u_suppr;
+
+ }
+#endif
+ ec->i_d++;
+ return u;
+}
+
+static inline struct echo_can_state *echo_can_create(int len, int adaption_mode)
+{
+ struct echo_can_state *ec;
+ int maxy;
+ int maxu;
+ maxy = len + DEFAULT_M;
+ maxu = DEFAULT_M;
+ if (maxy < (1 << DEFAULT_ALPHA_YT_I))
+ maxy = (1 << DEFAULT_ALPHA_YT_I);
+ if (maxy < (1 << DEFAULT_SIGMA_LY_I))
+ maxy = (1 << DEFAULT_SIGMA_LY_I);
+ if (maxu < (1 << DEFAULT_SIGMA_LU_I))
+ maxu = (1 << DEFAULT_SIGMA_LU_I);
+ ec = (struct echo_can_state *)MALLOC(sizeof(struct echo_can_state) +
+ 4 + /* align */
+ sizeof(int) * len + /* a_i */
+ sizeof(short) * len + /* a_s */
+ 2 * sizeof(short) * (maxy) + /* y_s */
+ 2 * sizeof(short) * (1 << DEFAULT_ALPHA_ST_I) + /* s_s */
+ 2 * sizeof(short) * (maxu) + /* u_s */
+ 2 * sizeof(short) * len); /* y_tilde_s */
+ if (ec) {
+ memset(ec, 0, sizeof(struct echo_can_state) +
+ 4 + /* align */
+ sizeof(int) * len + /* a_i */
+ sizeof(short) * len + /* a_s */
+ 2 * sizeof(short) * (maxy) + /* y_s */
+ 2 * sizeof(short) * (1 << DEFAULT_ALPHA_ST_I) + /* s_s */
+ 2 * sizeof(short) * (maxu) + /* u_s */
+ 2 * sizeof(short) * len); /* y_tilde_s */
+ init_cc(ec, len, maxy, maxu);
+ }
+ 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_d = ec->N_d << 1;
+ if (pos >= ec->N_d)
+ return 1;
+ ec->a_i[pos] = val << 17;
+ ec->a_s[pos] = val << 1;
+ if (++pos >= ec->N_d)
+ return 1;
+ return 0;
+}
+
+#endif
diff --git a/mec2_const.h b/mec2_const.h
new file mode 100644
index 0000000..4c7e8c9
--- /dev/null
+++ b/mec2_const.h
@@ -0,0 +1,28 @@
+/*
+ Important constants for tuning mec2 echo can
+ */
+#ifndef _MEC2_CONST_H
+#define _MEC2_CONST_H
+
+
+/* Convergence speed -- higher means slower */
+#define DEFAULT_BETA1_I 2048
+#define DEFAULT_SIGMA_LY_I 7
+#define DEFAULT_SIGMA_LU_I 7
+#define DEFAULT_ALPHA_ST_I 5
+#define DEFAULT_ALPHA_YT_I 5
+#define DEFAULT_CUTOFF_I 128
+#define DEFAULT_HANGT 600
+#define DEFAULT_SUPPR_I 16
+#define MIN_UPDATE_THRESH_I 4096
+#define DEFAULT_M 16
+#define SUPPR_FLOOR -64
+#define SUPPR_CEIL -24
+#define RES_SUPR_FACTOR -20
+#define AGGRESSIVE_HCNTR 160 /* 20ms */
+
+/* Only use agressive echo cancellation for this amount of time then go back to normal cancelation */
+/* #define AGGRESSIVE_TIMELIMIT 150000 */ /* 8 = 1ms */
+
+#endif /* _MEC2_CONST_H */
+
diff --git a/mec3-float.h b/mec3-float.h
new file mode 100644
index 0000000..12c3038
--- /dev/null
+++ b/mec3-float.h
@@ -0,0 +1,229 @@
+/*
+ * 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
+
+#define ECHO_CAN_FP
+
+#ifdef __KERNEL__
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#define MALLOC(a) kmalloc((a), GFP_KERNEL)
+#define FREE(a) kfree(a)
+#include <math.h>
+#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
+
+/*
+ * Define COEFF_BACKUP for experimental coefficient backup code
+ */
+
+
+#define STEP_SIZE 0.4 /* Convergence rate */
+
+#define SIGMA_P 0.01 /* Minimum adjustment */
+#define SIGMA_REF_PWR 0.01 /* Keep denominator from being 0 */
+
+#define MIN_TX_ENERGY 256.0/32767.0 /* Must have at least this much reference */
+#define MIN_RX_ENERGY 32.0/32767.0 /* Must have at least this much receive energy */
+
+#define MAX_ATTENUATION 64.0 /* Maximum amount of loss we care about */
+#define MAX_BETA 0.1
+
+#define SUPPR_ATTENUATION 16.0 /* 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 */
+
+typedef struct {
+ float buf[NTAPS * 2];
+ float max;
+ int maxexp;
+} cbuf_f;
+
+struct echo_can_state {
+ float a[NTAPS]; /* Coefficients */
+#ifdef COEFF_BACKUP
+ float b[NTAPS]; /* Coefficients */
+ float c[NTAPS]; /* Coefficients */
+ int backup; /* Backup timer */
+#endif
+ cbuf_f ref; /* Reference excitation */
+ cbuf_f sig; /* Signal (echo + near end + noise) */
+ cbuf_f e; /* Error */
+ float refpwr; /* Reference power */
+ int taps; /* Number of taps */
+ int hcntr; /* Hangtime counter */
+ int pos; /* Position in curcular buffers */
+};
+
+static inline void echo_can_free(struct echo_can_state *ec)
+{
+ FREE(ec);
+}
+
+static inline void buf_add(cbuf_f *b, float 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 < fabs(b->buf[pos + x])) {
+ b->max = fabs(b->buf[pos + x]);
+ b->maxexp = x + 1;
+ }
+ }
+ }
+}
+
+static inline short echo_can_update(struct echo_can_state *ec, short iref, short isig)
+{
+ int x;
+ float ref;
+ float sig;
+ float u;
+ float refpwr;
+ float beta; /* Factor */
+ float se; /* Simulated echo */
+ /* Convert to floats about 1.0 */
+ ref = (((float)iref)/32767.0);
+ sig = (((float)isig)/32767.0);
+
+#if 0
+ printf("start: %d, finish: %d\n", ec->start, ec->finish);
+#endif
+
+#ifdef COEFF_BACKUP
+ if (!ec->backup) {
+ /* Backup coefficients periodically */
+ ec->backup = BACKUP;
+ memcpy(ec->c,ec->b,sizeof(ec->c));
+ memcpy(ec->b,ec->a,sizeof(ec->b));
+ } else
+ ec->backup--;
+#endif
+ /* Remove old samples from reference power calculation */
+ ec->refpwr -= (ec->ref.buf[ec->pos] * ec->ref.buf[ec->pos]);
+
+ /* 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]);
+
+
+ /* Calculate simulated echo */
+ se = 0.0;
+ for (x=0;x<ec->taps;x++)
+ se += ec->a[x] * ec->ref.buf[ec->pos + x];
+
+#if 0
+ if (!(ec->pos2++ % 1024)) {
+ printk("sig: %d, se: %d\n", (int)(32768.0 * sig), (int)(32768.0 * se));
+ }
+#endif
+ 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 * MAX_ATTENUATION > ec->ref.max)) {
+ /* We have sufficient energy */
+ if (ec->sig.max * 2.0 < ec->ref.max) {
+ /* No double talk */
+ if (!ec->hcntr) {
+ if (ec->refpwr < SIGMA_REF_PWR)
+ refpwr = SIGMA_REF_PWR;
+ else
+ refpwr = ec->refpwr;
+ beta = STEP_SIZE * u / refpwr;
+ 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[x] += beta * ec->ref.buf[ec->pos + x];
+ }
+ }
+ } else {
+#ifdef COEFF_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, ec->c, sizeof(ec->a));
+ }
+ ec->backup = BACKUP;
+#endif
+ /* Reset hang-time counter, and prevent backups */
+ ec->hcntr = HANG_TIME;
+ }
+ }
+#ifndef NO_ECHO_SUPPRESSOR
+ if (ec->e.max * SUPPR_ATTENUATION < ec->ref.max) {
+ /* Suppress residual echo */
+ u *= u;
+ }
+#endif
+ ec->pos--;
+ if (ec->pos < 0)
+ ec->pos = ec->taps-1;
+ u *= 32767.0;
+ if (u < -32768.0)
+ u = -32768.0;
+ if (u > 32767.0)
+ u = 32767.0;
+ return (short)(u);
+}
+
+static inline struct echo_can_state *echo_can_create(int taps, int adaption_mode)
+{
+ struct echo_can_state *ec;
+ taps = NTAPS;
+ ec = MALLOC(sizeof(struct echo_can_state));
+ if (ec) {
+ printk("Allocating MEC3 canceller (%d)\n", taps);
+ memset(ec, 0, sizeof(struct echo_can_state));
+ ec->taps = taps;
+ if (ec->taps > NTAPS)
+ ec->taps = NTAPS;
+ ec->pos = ec->taps-1;
+ }
+ return ec;
+}
+
+#endif
diff --git a/mec3.h b/mec3.h
new file mode 100644
index 0000000..6de41f5
--- /dev/null
+++ b/mec3.h
@@ -0,0 +1,257 @@
+/*
+ * 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
diff --git a/mg2ec.h b/mg2ec.h
index ab414c0..84d9144 100644
--- a/mg2ec.h
+++ b/mg2ec.h
@@ -508,7 +508,7 @@ static inline short echo_can_update(struct echo_can_state *ec, short iref, short
memset(max_coeffs, 0, USED_COEFFS*sizeof(int));
#endif
#ifdef MEC2_STATS_DETAILED
- printk(KERN_INFO "updating coefficients with: ec->Lu_i %9d\n", ec->Lu_i);
+ printk( KERN_INFO "updating coefficients with: ec->Lu_i %9d\n", ec->Lu_i);
#endif
#ifdef MEC2_STATS
ec->avg_Lu_i_ok = ec->avg_Lu_i_ok + ec->Lu_i;
@@ -550,7 +550,7 @@ static inline short echo_can_update(struct echo_can_state *ec, short iref, short
#endif
} else {
#ifdef MEC2_STATS_DETAILED
- printk(KERN_INFO "insufficient signal to update coefficients ec->Lu_i %5d < %5d\n", ec->Lu_i, MIN_UPDATE_THRESH_I);
+ printk( KERN_INFO "insufficient signal to update coefficients ec->Lu_i %5d < %5d\n", ec->Lu_i, MIN_UPDATE_THRESH_I);
#endif
#ifdef MEC2_STATS
ec->avg_Lu_i_toolow = ec->avg_Lu_i_toolow + ec->Lu_i;
@@ -565,7 +565,7 @@ static inline short echo_can_update(struct echo_can_state *ec, short iref, short
*/
#ifdef MEC2_STATS_DETAILED
if (ec->HCNTR_d == 0)
- printk(KERN_INFO "possibily correcting frame with ec->Ly_i %9d ec->Lu_i %9d and expression %d\n", ec->Ly_i, ec->Lu_i, (ec->Ly_i/(ec->Lu_i + 1)));
+ printk( KERN_INFO "possibily correcting frame with ec->Ly_i %9d ec->Lu_i %9d and expression %d\n", ec->Ly_i, ec->Lu_i, (ec->Ly_i/(ec->Lu_i + 1)));
#endif
#ifndef NO_ECHO_SUPPRESSOR
@@ -575,7 +575,7 @@ static inline short echo_can_update(struct echo_can_state *ec, short iref, short
u = u * (ec->Lu_i >> DEFAULT_SIGMA_LU_I) / ((ec->Ly_i >> (DEFAULT_SIGMA_LY_I)) + 1);
}
#ifdef MEC2_STATS_DETAILED
- printk(KERN_INFO "aggresively correcting frame with ec->Ly_i %9d ec->Lu_i %9d expression %d\n", ec->Ly_i, ec->Lu_i, (ec->Ly_i/(ec->Lu_i + 1)));
+ printk( KERN_INFO "aggresively correcting frame with ec->Ly_i %9d ec->Lu_i %9d expression %d\n", ec->Ly_i, ec->Lu_i, (ec->Ly_i/(ec->Lu_i + 1)));
#endif
#ifdef MEC2_STATS
++ec->cntr_residualcorrected_frames;
@@ -588,7 +588,7 @@ static inline short echo_can_update(struct echo_can_state *ec, short iref, short
u = u * (ec->Lu_i >> DEFAULT_SIGMA_LU_I) / ((ec->Ly_i >> (DEFAULT_SIGMA_LY_I + 2)) + 1);
}
#ifdef MEC2_STATS_DETAILED
- printk(KERN_INFO "correcting frame with ec->Ly_i %9d ec->Lu_i %9d expression %d\n", ec->Ly_i, ec->Lu_i, (ec->Ly_i/(ec->Lu_i + 1)));
+ printk( KERN_INFO "correcting frame with ec->Ly_i %9d ec->Lu_i %9d expression %d\n", ec->Ly_i, ec->Lu_i, (ec->Ly_i/(ec->Lu_i + 1)));
#endif
#ifdef MEC2_STATS
++ec->cntr_residualcorrected_frames;
@@ -628,7 +628,7 @@ static inline short echo_can_update(struct echo_can_state *ec, short iref, short
else
ec->avg_Lu_i_ok = -1;
- printk(KERN_INFO "%d: Near end speech: %5d Residuals corrected/skipped: %5d/%5d Coefficients updated ok/low sig: %3d/%3d Lu_i avg ok/low sig %6d/%5d\n",
+ printk( KERN_INFO "%d: Near end speech: %5d Residuals corrected/skipped: %5d/%5d Coefficients updated ok/low sig: %3d/%3d Lu_i avg ok/low sig %6d/%5d\n",
ec->id,
ec->cntr_nearend_speech_frames,
ec->cntr_residualcorrected_frames, ec->cntr_residualcorrected_framesskipped,
@@ -650,19 +650,12 @@ static inline short echo_can_update(struct echo_can_state *ec, short iref, short
return u;
}
-static int echo_can_create(struct zt_echocanparams *ecp, struct zt_echocanparam *p,
- struct echo_can_state **ec)
+static inline struct echo_can_state *echo_can_create(int len, int adaption_mode)
{
+ struct echo_can_state *ec;
int maxy;
int maxu;
- size_t size;
-
- if (ecp->param_count > 0) {
- printk(KERN_WARNING "MG2 echo canceler does not support parameters; failing request\n");
- return -EINVAL;
- }
-
- maxy = ecp->tap_length + DEFAULT_M;
+ maxy = len + DEFAULT_M;
maxu = DEFAULT_M;
if (maxy < (1 << DEFAULT_ALPHA_YT_I))
maxy = (1 << DEFAULT_ALPHA_YT_I);
@@ -670,23 +663,30 @@ static int echo_can_create(struct zt_echocanparams *ecp, struct zt_echocanparam
maxy = (1 << DEFAULT_SIGMA_LY_I);
if (maxu < (1 << DEFAULT_SIGMA_LU_I))
maxu = (1 << DEFAULT_SIGMA_LU_I);
- size = sizeof(**ec) +
- 4 + /* align */
- sizeof(int) * ecp->tap_length + /* a_i */
- sizeof(short) * ecp->tap_length + /* a_s */
- sizeof(int) * ecp->tap_length + /* b_i */
- sizeof(int) * ecp->tap_length + /* c_i */
- 2 * sizeof(short) * (maxy) + /* y_s */
- 2 * sizeof(short) * (1 << DEFAULT_ALPHA_ST_I) + /* s_s */
- 2 * sizeof(short) * (maxu) + /* u_s */
- 2 * sizeof(short) * ecp->tap_length; /* y_tilde_s */
-
- if (!(*ec = MALLOC(size)))
- return -ENOMEM;
-
- memset(*ec, 0, size);
-
- return 0;
+ ec = (struct echo_can_state *)MALLOC(sizeof(struct echo_can_state) +
+ 4 + /* align */
+ sizeof(int) * len + /* a_i */
+ sizeof(short) * len + /* a_s */
+ sizeof(int) * len + /* b_i */
+ sizeof(int) * len + /* c_i */
+ 2 * sizeof(short) * (maxy) + /* y_s */
+ 2 * sizeof(short) * (1 << DEFAULT_ALPHA_ST_I) + /* s_s */
+ 2 * sizeof(short) * (maxu) + /* u_s */
+ 2 * sizeof(short) * len); /* y_tilde_s */
+ if (ec) {
+ memset(ec, 0, sizeof(struct echo_can_state) +
+ 4 + /* align */
+ sizeof(int) * len + /* a_i */
+ sizeof(short) * len + /* a_s */
+ sizeof(int) * len + /* b_i */
+ sizeof(int) * len + /* c_i */
+ 2 * sizeof(short) * (maxy) + /* y_s */
+ 2 * sizeof(short) * (1 << DEFAULT_ALPHA_ST_I) + /* s_s */
+ 2 * sizeof(short) * (maxu) + /* u_s */
+ 2 * sizeof(short) * len); /* y_tilde_s */
+ init_cc(ec, len, maxy, maxu);
+ }
+ return ec;
}
static inline int echo_can_traintap(struct echo_can_state *ec, int pos, short val)
diff --git a/sec-2.h b/sec-2.h
index 49342ea..a8fed80 100644
--- a/sec-2.h
+++ b/sec-2.h
@@ -97,6 +97,7 @@ struct echo_can_state
was skipped, for test purposes */
};
+static struct echo_can_state *echo_can_create(int len, int adaption_mode);
static void echo_can_free(struct echo_can_state *ec);
static int16_t echo_can_update(struct echo_can_state *ec, int16_t tx, int16_t rx);
@@ -126,44 +127,36 @@ static void echo_can_shutdown(void)
/* #define MIN_TX_POWER_FOR_ADAPTION 4096
#define MIN_RX_POWER_FOR_ADAPTION 64 */
-static int echo_can_create(struct zt_echocanparams *ecp, struct zt_echocanparam *p,
- struct echo_can_state **ec)
+static inline struct echo_can_state *echo_can_create(int len, int adaption_mode)
{
- size_t size;
-
- if (ecp->param_count > 0) {
- printk(KERN_WARNING "SEC-2 echo canceler does not support parameters; failing request\n");
- return -EINVAL;
- }
-
- size = sizeof(**ec) + ecp->tap_length * sizeof(int32_t) + ecp->tap_length * 3 * sizeof(int16_t);
-
- if (!(*ec = MALLOC(size)))
- return -ENOMEM;
-
- memset(*ec, 0, size);
-
- (*ec)->taps = ecp->tap_length;
- (*ec)->curr_pos = ecp->tap_length - 1;
- (*ec)->tap_mask = ecp->tap_length - 1;
- (*ec)->fir_taps32 = (int32_t *) (*ec + sizeof(**ec));
- (*ec)->fir_taps16 = (int16_t *) (*ec + sizeof(**ec) + ecp->tap_length * sizeof(int32_t));
- /* Create FIR filter */
- fir16_create(&(*ec)->fir_state, (*ec)->fir_taps16, (*ec)->taps);
- (*ec)->rx_power_threshold = 10000000;
- (*ec)->use_suppressor = FALSE;
- /* Non-linear processor - a fancy way to say "zap small signals, to avoid
- accumulating noise". */
- (*ec)->use_nlp = FALSE;
-
- return 0;
+ struct echo_can_state *ec;
+ void *ptr;
+
+ ptr = ec = (struct echo_can_state *) MALLOC(sizeof(*ec) + len * sizeof(int32_t) +
+ len * sizeof(int16_t));
+ if (ec == NULL)
+ return NULL;
+ memset(ec, 0, sizeof(*ec) + len * sizeof(int32_t) + len * sizeof(int16_t));
+ ec->taps = len;
+ ec->curr_pos = len - 1;
+ ec->tap_mask = len - 1;
+ ec->fir_taps32 = (int32_t *) (ptr + sizeof(*ec));
+ ec->fir_taps16 = (int16_t *) (ptr + sizeof(*ec) + len * sizeof(int32_t));
+ /* Create FIR filter */
+ fir16_create(&ec->fir_state, ec->fir_taps16, ec->taps);
+ ec->rx_power_threshold = 10000000;
+ ec->use_suppressor = FALSE;
+ /* Non-linear processor - a fancy way to say "zap small signals, to avoid
+ accumulating noise". */
+ ec->use_nlp = FALSE;
+ return ec;
}
/*- End of function --------------------------------------------------------*/
static inline void echo_can_free(struct echo_can_state *ec)
{
- fir16_free(&ec->fir_state);
- FREE(ec);
+ fir16_free(&ec->fir_state);
+ FREE(ec);
}
/*- End of function --------------------------------------------------------*/
diff --git a/sec.h b/sec.h
index 6c4b7c0..f795e4c 100644
--- a/sec.h
+++ b/sec.h
@@ -114,6 +114,7 @@ static void echo_can_shutdown(void)
{
}
+static struct echo_can_state *echo_can_create(int len, int adaption_mode);
static void echo_can_free(struct echo_can_state *ec);
static int16_t echo_can_update(struct echo_can_state *ec, int16_t tx, int16_t rx);
@@ -130,44 +131,33 @@ static int16_t echo_can_update(struct echo_can_state *ec, int16_t tx, int16_t rx
#define MIN_RX_POWER_FOR_ADAPTION 64
*/
-static int echo_can_create(struct zt_echocanparams *ecp, struct zt_echocanparam *p,
- struct echo_can_state **ec)
+static inline struct echo_can_state *echo_can_create(int len, int adaption_mode)
{
- size_t size;
-
- if (ecp->param_count > 0) {
- printk(KERN_WARNING "SEC echo canceler does not support parameters; failing request\n");
- return -EINVAL;
- }
-
- size = sizeof(**ec) + ecp->tap_length * sizeof(int32_t) + ecp->tap_length * 3 * sizeof(int16_t);
-
- if (!(*ec = MALLOC(size)))
- return -ENOMEM;
-
- memset(*ec, 0, size);
-
- (*ec)->taps = ecp->tap_length;
- (*ec)->tap_mask = ecp->tap_length - 1;
- (*ec)->tx_history = (int16_t *) (*ec + sizeof(**ec));
- (*ec)->fir_taps = (int32_t *) (*ec + sizeof(**ec) +
- ecp->tap_length * 2 * sizeof(int16_t));
- (*ec)->fir_taps_short = (int16_t *) (*ec + sizeof(**ec) +
- ecp->tap_length * sizeof(int32_t) +
- ecp->tap_length * 2 * sizeof(int16_t));
- (*ec)->rx_power_threshold = 10000000;
- (*ec)->use_suppressor = FALSE;
- /* Non-linear processor - a fancy way to say "zap small signals, to avoid
- accumulating noise". */
- (*ec)->use_nlp = TRUE;
-
- return 0;
+ struct echo_can_state *ec;
+ void *ptr;
+
+ ptr = ec = (struct echo_can_state *) MALLOC(sizeof(*ec) + len * sizeof(int32_t) +
+ len * 3 * sizeof(int16_t));
+ if (ec == NULL)
+ return NULL;
+ memset(ec, 0, sizeof(*ec) + len * sizeof(int32_t) + len * 3 * sizeof(int16_t));
+ ec->taps = len;
+ ec->tap_mask = len - 1;
+ ec->tx_history = (int16_t *) (ptr + sizeof(*ec) );
+ ec->fir_taps = (int32_t *) (ptr + sizeof(*ec) + len * 2 * sizeof(int16_t));
+ ec->fir_taps_short = (int16_t *) (ptr + sizeof(*ec) + len * sizeof(int32_t) + len * 2 * sizeof(int16_t));
+ ec->rx_power_threshold = 10000000;
+ ec->use_suppressor = FALSE;
+ /* Non-linear processor - a fancy way to say "zap small signals, to avoid
+ accumulating noise". */
+ ec->use_nlp = TRUE;
+ return ec;
}
/*- End of function --------------------------------------------------------*/
static inline void echo_can_free(struct echo_can_state *ec)
{
- FREE(ec);
+ FREE(ec);
}
/*- End of function --------------------------------------------------------*/
diff --git a/zaptel-base.c b/zaptel-base.c
index b90eb42..309b813 100644
--- a/zaptel-base.c
+++ b/zaptel-base.c
@@ -419,12 +419,18 @@ static struct zt_zone *tone_zones[ZT_TONE_ZONE_MAX];
#include "sec.h"
#elif defined(ECHO_CAN_STEVE2)
#include "sec-2.h"
+#elif defined(ECHO_CAN_MARK)
+#include "mec.h"
+#elif defined(ECHO_CAN_MARK2)
+#include "mec2.h"
#elif defined(ECHO_CAN_KB1)
#include "kb1ec.h"
#elif defined(ECHO_CAN_MG2)
#include "mg2ec.h"
#elif defined(ECHO_CAN_JP1)
#include "jpah.h"
+#else
+#include "mec3.h"
#endif
static inline void rotate_sums(void)
@@ -4302,95 +4308,6 @@ static void do_ppp_calls(unsigned long data)
}
#endif
-#define MAX_ECHOCANPARAMS 8
-
-static int ioctl_echocancel(struct zt_chan *chan, struct zt_echocanparams *ecp, void *data)
-{
- struct echo_can_state *ec = NULL, *tec;
- struct zt_echocanparam params[MAX_ECHOCANPARAMS];
- int ret;
- unsigned long flags;
-
- if (ecp->param_count > MAX_ECHOCANPARAMS)
- return -E2BIG;
-
- if (ecp->tap_length == 0) {
- /* disable mode, don't need to inspect params */
- spin_lock_irqsave(&chan->lock, flags);
- tec = chan->ec;
- chan->echocancel = 0;
- chan->ec = NULL;
- chan->echostate = ECHO_STATE_IDLE;
- chan->echolastupdate = 0;
- chan->echotimer = 0;
- spin_unlock_irqrestore(&chan->lock, flags);
- if (chan->span && chan->span->echocan)
- chan->span->echocan(chan, 0);
- if (tec)
- echo_can_free(tec);
-
- return 0;
- }
-
- /* if parameters were supplied and this channel's span provides an echocan,
- but not one that takes params, then we must punt here and return an error */
- if (ecp->param_count && chan->span && chan->span->echocan &&
- !chan->span->echocan_with_params)
- return -EINVAL;
-
- /* enable mode, need the params */
-
- if (copy_from_user(params, (struct zt_echocanparam *) data, sizeof(params[0]) * ecp->param_count))
- return -EFAULT;
-
- spin_lock_irqsave(&chan->lock, flags);
- tec = chan->ec;
- chan->ec = NULL;
- spin_unlock_irqrestore(&chan->lock, flags);
-
- ret = -ENOTTY;
-
- /* attempt to use the span's echo canceler; fall back to built-in
- if it fails (but not if an error occurs) */
- if (chan->span && chan->span->echocan_with_params)
- ret = chan->span->echocan_with_params(chan, ecp, params);
-
- if (ret == -ENOTTY) {
- switch (ecp->tap_length) {
- case 32:
- case 64:
- case 128:
- case 256:
- case 512:
- case 1024:
- break;
- default:
- ecp->tap_length = deftaps;
- }
-
- if ((ret = echo_can_create(ecp, params, &ec))) {
- if (tec)
- echo_can_free(tec);
- return ret;
- }
-
- spin_lock_irqsave(&chan->lock, flags);
- chan->echocancel = ecp->tap_length;
- chan->ec = ec;
- chan->echostate = ECHO_STATE_IDLE;
- chan->echolastupdate = 0;
- chan->echotimer = 0;
- echo_can_disable_detector_init(&chan->txecdis);
- echo_can_disable_detector_init(&chan->rxecdis);
- spin_unlock_irqrestore(&chan->lock, flags);
- }
-
- if (tec)
- echo_can_free(tec);
-
- return 0;
-}
-
static int zt_chan_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long data, int unit)
{
struct zt_chan *chan = chans[unit];
@@ -4400,7 +4317,6 @@ static int zt_chan_ioctl(struct inode *inode, struct file *file, unsigned int cm
int oldconf;
void *rxgain=NULL;
struct echo_can_state *ec, *tec;
- struct zt_echocanparams ecp;
if (!chan)
return -ENOSYS;
@@ -4565,20 +4481,62 @@ static int zt_chan_ioctl(struct inode *inode, struct file *file, unsigned int cm
case ZT_ECHOCANCEL:
if (!(chan->flags & ZT_FLAG_AUDIO))
return -EINVAL;
- if (copy_from_user(&ecp, (struct zt_echocanparams *) data, sizeof(ecp)))
- return -EFAULT;
- data += sizeof(ecp);
- if ((ret = ioctl_echocancel(chan, &ecp, (void *) data)))
- return ret;
- break;
- case ZT_ECHOCANCEL_V1:
- if (!(chan->flags & ZT_FLAG_AUDIO))
- return -EINVAL;
- get_user(j, (int *) data);
- ecp.tap_length = j;
- ecp.param_count = 0;
- if ((ret = ioctl_echocancel(chan, &ecp, (void *) data)))
- return ret;
+ get_user(j, (int *)data);
+ if (j) {
+ spin_lock_irqsave(&chan->lock, flags);
+ /* If we had an old echo can, zap it now */
+ tec = chan->ec;
+ chan->ec = NULL;
+ /* Attempt hardware native echo can */
+ spin_unlock_irqrestore(&chan->lock, flags);
+
+ if (chan->span && chan->span->echocan)
+ ret = chan->span->echocan(chan, j);
+ else
+ ret = -ENOTTY;
+
+ if (ret) {
+ /* Use built-in echo can */
+ if ((j == 32) ||
+ (j == 64) ||
+ (j == 128) ||
+ (j == 256) ||
+ (j == 512) ||
+ (j == 1024)) {
+ /* Okay */
+ } else {
+ j = deftaps;
+ }
+ ec = echo_can_create(j, 0);
+ if (!ec)
+ return -ENOMEM;
+ spin_lock_irqsave(&chan->lock, flags);
+ chan->echocancel = j;
+ chan->ec = ec;
+ chan->echostate = ECHO_STATE_IDLE;
+ chan->echolastupdate = 0;
+ chan->echotimer = 0;
+ echo_can_disable_detector_init(&chan->txecdis);
+ echo_can_disable_detector_init(&chan->rxecdis);
+ spin_unlock_irqrestore(&chan->lock, flags);
+ }
+ if (tec)
+ echo_can_free(tec);
+ } else {
+ spin_lock_irqsave(&chan->lock, flags);
+ tec = chan->ec;
+ chan->echocancel = 0;
+ chan->ec = NULL;
+ chan->echostate = ECHO_STATE_IDLE;
+ chan->echolastupdate = 0;
+ chan->echotimer = 0;
+ spin_unlock_irqrestore(&chan->lock, flags);
+ /* Attempt hardware native echo can */
+ if (chan->span && chan->span->echocan)
+ chan->span->echocan(chan, 0);
+ if (tec)
+ echo_can_free(tec);
+ }
break;
case ZT_ECHOTRAIN:
get_user(j, (int *)data); /* get pre-training time from user */
diff --git a/zaptel.h b/zaptel.h
index d0c2dca..fa959a5 100644
--- a/zaptel.h
+++ b/zaptel.h
@@ -560,18 +560,11 @@ struct zt_hwgain{
/*
* Enable or disable echo cancellation on a channel
- *
- * For ECHOCANCEL_V1:
* The number is zero to disable echo cancellation and non-zero
* to enable echo cancellation. If the number is between 32
- * and 1024, it will also set the number of taps in the echo canceller
- *
- * For ECHOCANCEL:
- * The structure contains parameters that should be passed to the
- * echo canceler instance for the selected channel.
+ * and 256, it will also set the number of taps in the echo canceller
*/
-#define ZT_ECHOCANCEL_V1 _IOW (ZT_CODE, 33, int)
-#define ZT_ECHOCANCEL _IOW (ZT_CODE, 33, struct zt_echocanparams)
+#define ZT_ECHOCANCEL _IOW (ZT_CODE, 33, int)
/*
* Return a channel's channel number (useful for the /dev/zap/pseudo type interfaces
@@ -875,17 +868,6 @@ struct zt_ring_cadence {
int ringcadence[ZT_MAX_CADENCE];
};
-struct zt_echocanparam {
- char name[8];
- unsigned int value;
-};
-
-struct zt_echocanparams {
- unsigned int tap_length; /* 8 taps per millisecond */
- unsigned int param_count; /* number of parameters supplied */
- /* immediately follow this structure with zt_echocanparam structures */
-};
-
struct zt_tone_def_header {
int count; /* How many samples follow */
int zone; /* Which zone we are loading */
@@ -1183,7 +1165,7 @@ struct echo_can_state;
void echo_can_init(void);
void echo_chan_shutdown(void);
void echo_can_identify(char *buf, size_t len);
-int echo_can_create(struct zt_echocanparams *ecp, struct zt_echocanparam *p, struct echo_can_state **ec);
+struct echo_can_state *echo_can_create(int len, int adaption_mode);
void echo_can_free(struct echo_can_state *ec);
short echo_can_update(struct echo_can_state *ec, short iref, short isig);
void echo_can_array_update(struct echo_can_state *ec, short *iref, short *isig);
@@ -1532,11 +1514,9 @@ struct zt_span {
/* Opt: IOCTL */
int (*ioctl)(struct zt_chan *chan, unsigned int cmd, unsigned long data);
- /* Opt: Native echo cancellation (simple) */
+ /* Opt: Native echo cancellation */
int (*echocan)(struct zt_chan *chan, int ecval);
- int (*echocan_with_params)(struct zt_chan *chan, struct zt_echocanparams *ecp, struct zt_echocanparam *p);
-
/* Okay, now we get to the signalling. You have several options: */
/* Option 1: If you're a T1 like interface, you can just provide a
diff --git a/zconfig.h b/zconfig.h
index 4a5d1ef..e3ef483 100644
--- a/zconfig.h
+++ b/zconfig.h
@@ -63,6 +63,9 @@
*/
/* #define ECHO_CAN_STEVE */
/* #define ECHO_CAN_STEVE2 */
+/* #define ECHO_CAN_MARK */
+/* #define ECHO_CAN_MARK2 */
+/* #define ECHO_CAN_MARK3 */
/* #define ECHO_CAN_KB1 */
/* This is the new latest and greatest */
#define ECHO_CAN_MG2