misdn.patch
来自「一个非常美妙的proxy。功能强大。基于sip的协议。如果还要的话」· PATCH 代码 · 共 2,345 行 · 第 1/5 页
PATCH
2,345 行
+#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 2048 /* Maximum 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;++typedef struct {+ 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 */+} echo_can_state_t;++static inline void echo_can_free(echo_can_state_t *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(echo_can_state_t *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, sig, 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 = 0;+ if (beta < -MAX_BETA)+ beta = 0;+ /* 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 echo_can_state_t *echo_can_create(int taps, int adaption_mode)+{+ echo_can_state_t *ec;+ int x;++ //taps = NTAPS;+ ec = MALLOC(sizeof(echo_can_state_t));+ if (ec) {+ memset(ec, 0, sizeof(echo_can_state_t));+ 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(echo_can_state_t *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;+}+++#endifdiff -u -r -P /tmp/mISDN/drivers/isdn/hardware/mISDN/mec.h mISDN/drivers/isdn/hardware/mISDN/mec.h--- /tmp/mISDN/drivers/isdn/hardware/mISDN/mec.h 1970-01-01 01:00:00.000000000 +0100+++ mISDN/drivers/isdn/hardware/mISDN/mec.h 2005-12-02 09:57:08.000000000 +0100@@ -0,0 +1,308 @@+/*+ * 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 */++typedef struct mark_ec {+ /* 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 */+} echo_can_state_t;++#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 INLINE echo_can_state_t *echo_can_create(int len, int adaption_mode)+{+ echo_can_state_t *ec;+ /* Uhm, we're only one length, sorry. */+ ec = MALLOC(sizeof(echo_can_state_t));+ if (ec)+ memset(ec, 0, sizeof(*ec));+ return ec;+}++#define PASSPOS 32000+#undef PASSPOS++static INLINE void echo_can_free(echo_can_state_t *ec)+{+ FREE(ec);+}++static INLINE int16_t echo_can_update(echo_can_state_t *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;+ } +
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?