diff --git kb1ec.h kb1ec.h index e0f63f6..c2d46fc 100644 --- kb1ec.h +++ kb1ec.h @@ -41,6 +41,8 @@ #define FREE(a) free(a) #endif +#define ABS(a) abs(a!=-32768?a:-32767) + /* Uncomment to provide summary statistics for overall echo can performance every 4000 samples */ /* #define MEC2_STATS 4000 */ @@ -138,6 +140,8 @@ struct echo_can_state { int avg_Lu_i_toolow; int avg_Lu_i_ok; #endif + short lastsig[256]; + int lastpos; }; @@ -294,12 +298,49 @@ static inline short echo_can_update(struct echo_can_state *ec, short iref, short ec->N_d); rs >>= 15; - /* eq. (3): compute the output value (see figure 3) and the error - * note: the error is the same as the output signal when near-end - * speech is not present - */ - u = isig - rs; - + ec->lastsig[ec->lastpos++] = isig; + if (ec->lastpos >= 256) + ec->lastpos = 0; + + for (k=0; k < 256; k++) { + if (isig != ec->lastsig[k]) + break; + } + + if (isig == 0) { + u = 0; + } else if (k == 256) { + u = isig; + } else { + 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); + } 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); + } + + if (ABS(ABS(rs)-ABS(isig)) > 3000) + { + rs = 0; + memset(ec->a_i, 0, sizeof(int) * ec->N_d); + memset(ec->a_s, 0, sizeof(short) * ec->N_d); + } + + /* eq. (3): compute the output value (see figure 3) and the error + * note: the error is the same as the output signal when near-end + * speech is not present + */ + u = isig - rs; + + if (u / isig < 0) + u = isig - (rs >> 1); + } + /* Push a copy of the output value sample into its circular buffer */ add_cc_s(&ec->u_s, u); diff --git zaptel-base.c zaptel-base.c index 9777ba6..fd0652c 100644 --- zaptel-base.c +++ zaptel-base.c @@ -371,6 +371,8 @@ struct zt_zone { static struct zt_span *spans[ZT_MAX_SPANS]; static struct zt_chan *chans[ZT_MAX_CHANNELS]; +static struct zt_ec_data ec_data_preload[ZT_MAX_CHANNELS]; +static struct zt_ec_data ec_data_dump[ZT_MAX_CHANNELS]; static int maxspans = 0; static int maxchans = 0; @@ -3217,6 +3219,25 @@ static int zt_common_ioctl(struct inode *node, struct file *file, unsigned int c #endif #endif /* ALLOW_CHAN_DIAG */ break; + case ZT_EC_PRELOAD: + if (copy_from_user(&j, (void *)data, sizeof(int))) + return -EFAULT; + if (copy_from_user(&ec_data_preload[j], (void *)data, sizeof(struct zt_ec_data))) + return -EFAULT; + return 0; + case ZT_EC_DUMP: + if (copy_from_user(&j, (void *)data, sizeof(int))) + return -EFAULT; + chan = chans[j]; + if (chan && chan->ec && chan->ec->a_i && chan->ec->a_s) { + memset(&ec_data_dump[j], 0, sizeof(struct zt_ec_data)); + ec_data_dump[j].N_d = chan->ec->N_d; + memcpy(ec_data_dump[j].a_i, chan->ec->a_i, chan->ec->N_d * sizeof(int)); + memcpy(ec_data_dump[j].a_s, chan->ec->a_s, chan->ec->N_d * sizeof(short)); + } + if (copy_to_user((void *)data, &ec_data_dump[j], sizeof(struct zt_ec_data))) + return -EFAULT; + return 0; default: return -ENOTTY; } @@ -4402,6 +4423,16 @@ static int zt_chan_ioctl(struct inode *inode, struct file *file, unsigned int cm ec = echo_can_create(j, 0); if (!ec) return -ENOMEM; + if (ec_data_preload[chan->channo].N_d == ec->N_d) + { + printk("Using preloaded ec data for channel %d\n", chan->channo); + memcpy(ec->a_i, ec_data_preload[chan->channo].a_i, ec->N_d*sizeof(int)); + memcpy(ec->a_s, ec_data_preload[chan->channo].a_s, ec->N_d*sizeof(short)); + } + else + { + printk("No preloaded ec data for channel %d\n", chan->channo); + } spin_lock_irqsave(&chan->lock, flags); chan->echocancel = j; chan->ec = ec;