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 + -
显示快捷键?