Index: mg2ec_const.h =================================================================== --- mg2ec_const.h (revision 876) +++ mg2ec_const.h (working copy) @@ -57,7 +57,20 @@ #define RESIDUAL_SUPRESSION_PASSES 1 #endif +/* Treat sample as error if it has a different sign as the + * input signal and is this number larger in ABS() as + * the input-signal */ +#define MAX_SIGN_ERROR 3000 +/* Filter out coefficients which are smaller than this + * percentage of the second biggest coefficient. + * If you comment out this define, the filtering-code will + * not be used */ +#define FILTER_PERCENT 1 + +/* Backup coefficients every this number of samples */ +#define BACKUP 256 + /***************************************************************/ /* The following knobs are not implemented in the current code */ Index: mg2ec.h =================================================================== --- mg2ec.h (revision 876) +++ mg2ec.h (working copy) @@ -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;xN_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 @@ 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 @@ #endif short lastsig[256]; int lastpos; + int backup; } echo_can_state_t; @@ -193,6 +206,12 @@ 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 @@ 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,7 +346,15 @@ /* 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 */ /* ------------------------------------------------------------------- */ /* Delete the oldest sample from the power estimate accumulator */ @@ -415,6 +439,7 @@ && (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 @@ !(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 @@ /* 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 @@ 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 @@ 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 @@ */ 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; }