summaryrefslogtreecommitdiff
path: root/mg2ec.h
diff options
context:
space:
mode:
authormattf <mattf@5390a7c7-147a-4af0-8ec9-7488f05a26cb>2005-12-28 20:28:28 +0000
committermattf <mattf@5390a7c7-147a-4af0-8ec9-7488f05a26cb>2005-12-28 20:28:28 +0000
commit9762f08c3e05e28570a32b94f6004136f464d22f (patch)
tree7779a8d97102c8bbdd90f110694b4a5680fbd727 /mg2ec.h
parentd37f2c1ce74bb392ba861326f20e69efb04749d5 (diff)
Updating MG2 to latest set of tweaks and optimizatons. See bug #5520 for more details on changes.
git-svn-id: http://svn.digium.com/svn/zaptel/trunk@878 5390a7c7-147a-4af0-8ec9-7488f05a26cb
Diffstat (limited to 'mg2ec.h')
-rw-r--r--mg2ec.h72
1 files changed, 63 insertions, 9 deletions
diff --git a/mg2ec.h b/mg2ec.h
index e08adaf..03bb56b 100644
--- a/mg2ec.h
+++ b/mg2ec.h
@@ -43,6 +43,15 @@
#define ABS(a) abs(a!=-32768?a:-32767)
+#define RESTORE_COEFFS {\
+ int x;\
+ memcpy(ec->a_i, ec->c_i, ec->N_d*sizeof(int));\
+ for (x=0;x<ec->N_d;x++) {\
+ ec->a_s[x] = ec->a_i[x] >> 16;\
+ }\
+ ec->backup = BACKUP;\
+ }
+
/* Uncomment to provide summary statistics for overall echo can performance every 4000 samples */
/* #define MEC2_STATS 4000 */
@@ -113,6 +122,9 @@ struct echo_can_state {
int *a_i;
/* ... */
short *a_s;
+ /* Backups */
+ int *b_i;
+ int *c_i;
/* Reference samples of far-end receive signal */
echo_can_cb_s y_s;
/* Reference samples of near-end signal */
@@ -142,6 +154,7 @@ struct echo_can_state {
#endif
short lastsig[256];
int lastpos;
+ int backup;
};
@@ -193,6 +206,12 @@ static inline void init_cc(struct echo_can_state *ec, int N, int maxy, int maxu)
ec->a_s = ptr;
ptr += (sizeof(short) * ec->N_d);
+ /* Allocate backup memory */
+ ec->b_i = ptr;
+ ptr += (sizeof(int) * ec->N_d);
+ ec->c_i = ptr;
+ ptr += (sizeof(int) * ec->N_d);
+
/* Reset Y circular buffer (short version) */
init_cb_s(&ec->y_s, maxy, ptr);
ptr += (sizeof(short) * (maxy) * 2);
@@ -301,20 +320,17 @@ static inline short echo_can_update(struct echo_can_state *ec, short iref, short
if (rs < -32768) {
rs = -32768;
ec->HCNTR_d = DEFAULT_HANGT;
- memset(ec->a_i, 0, sizeof(int) * ec->N_d);
- memset(ec->a_s, 0, sizeof(short) * ec->N_d);
+ RESTORE_COEFFS;
} else if (rs > 32767) {
rs = 32767;
ec->HCNTR_d = DEFAULT_HANGT;
- memset(ec->a_i, 0, sizeof(int) * ec->N_d);
- memset(ec->a_s, 0, sizeof(short) * ec->N_d);
+ RESTORE_COEFFS;
}
- if (ABS(ABS(rs)-ABS(isig)) > 3000)
+ if (ABS(ABS(rs)-ABS(isig)) > MAX_SIGN_ERROR)
{
rs = 0;
- memset(ec->a_i, 0, sizeof(int) * ec->N_d);
- memset(ec->a_s, 0, sizeof(short) * ec->N_d);
+ RESTORE_COEFFS;
}
/* eq. (3): compute the output value (see figure 3) and the error
@@ -330,6 +346,14 @@ static inline short echo_can_update(struct echo_can_state *ec, short iref, short
/* Push a copy of the output value sample into its circular buffer */
add_cc_s(&ec->u_s, u);
+ if (!ec->backup) {
+ /* Backup coefficients periodically */
+ ec->backup = BACKUP;
+ memcpy(ec->c_i,ec->b_i,ec->N_d*sizeof(int));
+ memcpy(ec->b_i,ec->a_i,ec->N_d*sizeof(int));
+ } else
+ ec->backup--;
+
/* Update the Near-end hybrid signal circular buffers and accumulators */
/* ------------------------------------------------------------------- */
@@ -415,6 +439,7 @@ static inline short echo_can_update(struct echo_can_state *ec, short iref, short
&& (ec->max_y_tilde > 0)) {
/* Then start the Hangover counter */
ec->HCNTR_d = DEFAULT_HANGT;
+ RESTORE_COEFFS;
#ifdef MEC2_STATS_DETAILED
printk(KERN_INFO "Reset near end speech timer with: s_tilde_i %d, stmnt %d, max_y_tilde %d\n", ec->s_tilde_i, (ec->s_tilde_i >> (DEFAULT_ALPHA_ST_I - 1)), ec->max_y_tilde);
#endif
@@ -437,6 +462,9 @@ static inline short echo_can_update(struct echo_can_state *ec, short iref, short
!(ec->i_d % DEFAULT_M)) { /* we only update on every DEFAULM_M'th sample from the stream */
if (ec->Lu_i > MIN_UPDATE_THRESH_I) { /* there is sufficient energy above the noise floor to contain meaningful data */
/* so loop over all the filter coefficients */
+#ifdef FILTER_PERCENT
+ int max = 0, max2 = 0;
+#endif
#ifdef MEC2_STATS_DETAILED
printk( KERN_INFO "updating coefficients with: ec->Lu_i %9d\n", ec->Lu_i);
#endif
@@ -453,7 +481,23 @@ static inline short echo_can_update(struct echo_can_state *ec, short iref, short
/* eq. (7): update the coefficient */
ec->a_i[k] += grad2 / two_beta_i;
ec->a_s[k] = ec->a_i[k] >> 16;
+
+#ifdef FILTER_PERCENT
+ /* Find the peaks */
+ if (abs(ec->a_i[k]) > max)
+ {
+ max2 = max;
+ max = abs(ec->a_i[k]);
+ }
+#endif
}
+
+#ifdef FILTER_PERCENT
+ /* Filter out irrelevant coefficients */
+ for (k=0; k < ec->N_d; k++)
+ if (abs(ec->a_i[k]) < (max2*FILTER_PERCENT)/100)
+ ec->a_i[k] = ec->a_s[k] = 0;
+#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);
@@ -573,6 +617,8 @@ static inline struct echo_can_state *echo_can_create(int len, int adaption_mode)
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 */
@@ -582,6 +628,8 @@ static inline struct echo_can_state *echo_can_create(int len, int adaption_mode)
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 */
@@ -598,14 +646,20 @@ static inline int echo_can_traintap(struct echo_can_state *ec, int pos, short va
*/
ec->HCNTR_d = ec->N_d << 1;
- if (pos >= ec->N_d)
+ if (pos >= ec->N_d) {
+ memcpy(ec->b_i,ec->a_i,ec->N_d*sizeof(int));
+ memcpy(ec->c_i,ec->a_i,ec->N_d*sizeof(int));
return 1;
+ }
ec->a_i[pos] = val << 17;
ec->a_s[pos] = val << 1;
- if (++pos >= ec->N_d)
+ if (++pos >= ec->N_d) {
+ memcpy(ec->b_i,ec->a_i,ec->N_d*sizeof(int));
+ memcpy(ec->c_i,ec->a_i,ec->N_d*sizeof(int));
return 1;
+ }
return 0;
}