⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mec3.h

📁 This a SOFTWARE pbx DRIVER
💻 H
字号:
/* * 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;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 = 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 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;}#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -