summaryrefslogtreecommitdiff
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
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
-rw-r--r--Makefile2
-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
13 files changed, 254 insertions, 1445 deletions
diff --git a/Makefile b/Makefile
index f4431b0..9b5d5e2 100644
--- a/Makefile
+++ b/Makefile
@@ -372,7 +372,7 @@ wct4xxp/wct4xxp.o:
tor2.o: tor2-hw.h tor2fw.h
-zaptel-base.o: digits.h arith.h sec.h mec.h sec-2.h mec2.h mec3.h zconfig.h
+zaptel-base.o: digits.h arith.h sec.h sec-2.h kb1ec.h mg2ec.h zconfig.h
wcusb.o: wcusb.h
diff --git a/kb1ec.h b/kb1ec.h
index e0f63f6..47ff8ac 100644
--- a/kb1ec.h
+++ b/kb1ec.h
@@ -529,12 +529,19 @@ static inline short echo_can_update(struct echo_can_state *ec, short iref, short
return u;
}
-static inline struct echo_can_state *echo_can_create(int len, int adaption_mode)
+static int echo_can_create(struct zt_echocanparams *ecp, struct zt_echocanparam *p,
+ struct echo_can_state **ec)
{
- struct echo_can_state *ec;
int maxy;
int maxu;
- maxy = len + DEFAULT_M;
+ 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;
maxu = DEFAULT_M;
if (maxy < (1 << DEFAULT_ALPHA_YT_I))
maxy = (1 << DEFAULT_ALPHA_YT_I);
@@ -542,26 +549,24 @@ static inline struct echo_can_state *echo_can_create(int len, int adaption_mode)
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;
+
+ 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;
}
static inline int echo_can_traintap(struct echo_can_state *ec, int pos, short val)
diff --git a/mec.h b/mec.h
deleted file mode 100644
index 09421cd..0000000
--- a/mec.h
+++ /dev/null
@@ -1,322 +0,0 @@
-/*
- * 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
deleted file mode 100644
index 98061ff..0000000
--- a/mec2.h
+++ /dev/null
@@ -1,436 +0,0 @@
-/*
- * 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
deleted file mode 100644
index 4c7e8c9..0000000
--- a/mec2_const.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- 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
deleted file mode 100644
index 12c3038..0000000
--- a/mec3-float.h
+++ /dev/null
@@ -1,229 +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
-
-#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
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
diff --git a/mg2ec.h b/mg2ec.h
index 84d9144..ab414c0 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,12 +650,19 @@ static inline short echo_can_update(struct echo_can_state *ec, short iref, short
return u;
}
-static inline struct echo_can_state *echo_can_create(int len, int adaption_mode)
+static int echo_can_create(struct zt_echocanparams *ecp, struct zt_echocanparam *p,
+ struct echo_can_state **ec)
{
- struct echo_can_state *ec;
int maxy;
int maxu;
- maxy = len + DEFAULT_M;
+ 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;
maxu = DEFAULT_M;
if (maxy < (1 << DEFAULT_ALPHA_YT_I))
maxy = (1 << DEFAULT_ALPHA_YT_I);
@@ -663,30 +670,23 @@ static inline struct echo_can_state *echo_can_create(int len, int adaption_mode)
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 */
- 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;
+ 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;
}
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 a8fed80..49342ea 100644
--- a/sec-2.h
+++ b/sec-2.h
@@ -97,7 +97,6 @@ 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);
@@ -127,36 +126,44 @@ static void echo_can_shutdown(void)
/* #define MIN_TX_POWER_FOR_ADAPTION 4096
#define MIN_RX_POWER_FOR_ADAPTION 64 */
-static inline struct echo_can_state *echo_can_create(int len, int adaption_mode)
+static int echo_can_create(struct zt_echocanparams *ecp, struct zt_echocanparam *p,
+ struct echo_can_state **ec)
{
- 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;
+ 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;
}
/*- 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 f795e4c..6c4b7c0 100644
--- a/sec.h
+++ b/sec.h
@@ -114,7 +114,6 @@ 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);
@@ -131,33 +130,44 @@ 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 inline struct echo_can_state *echo_can_create(int len, int adaption_mode)
+static int echo_can_create(struct zt_echocanparams *ecp, struct zt_echocanparam *p,
+ struct echo_can_state **ec)
{
- 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;
+ 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;
}
/*- 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 309b813..e200d12 100644
--- a/zaptel-base.c
+++ b/zaptel-base.c
@@ -419,18 +419,12 @@ 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)
@@ -4308,6 +4302,95 @@ 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, *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];
@@ -4317,6 +4400,7 @@ 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;
@@ -4481,62 +4565,20 @@ 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;
- 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);
- }
+ 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;
break;
case ZT_ECHOTRAIN:
get_user(j, (int *)data); /* get pre-training time from user */
diff --git a/zaptel.h b/zaptel.h
index fa959a5..d0c2dca 100644
--- a/zaptel.h
+++ b/zaptel.h
@@ -560,11 +560,18 @@ 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 256, it will also set the number of taps in the echo canceller
+ * 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.
*/
-#define ZT_ECHOCANCEL _IOW (ZT_CODE, 33, int)
+#define ZT_ECHOCANCEL_V1 _IOW (ZT_CODE, 33, int)
+#define ZT_ECHOCANCEL _IOW (ZT_CODE, 33, struct zt_echocanparams)
/*
* Return a channel's channel number (useful for the /dev/zap/pseudo type interfaces
@@ -868,6 +875,17 @@ 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 */
@@ -1165,7 +1183,7 @@ struct echo_can_state;
void echo_can_init(void);
void echo_chan_shutdown(void);
void echo_can_identify(char *buf, size_t len);
-struct echo_can_state *echo_can_create(int len, int adaption_mode);
+int echo_can_create(struct zt_echocanparams *ecp, struct zt_echocanparam *p, struct echo_can_state **ec);
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);
@@ -1514,9 +1532,11 @@ struct zt_span {
/* Opt: IOCTL */
int (*ioctl)(struct zt_chan *chan, unsigned int cmd, unsigned long data);
- /* Opt: Native echo cancellation */
+ /* Opt: Native echo cancellation (simple) */
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 e3ef483..4a5d1ef 100644
--- a/zconfig.h
+++ b/zconfig.h
@@ -63,9 +63,6 @@
*/
/* #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