diff options
-rwxr-xr-x | sec.h | 77 |
1 files changed, 38 insertions, 39 deletions
@@ -6,6 +6,7 @@ * any relevant standards (e.g. G.164/5/7/8). One day.... * * Written by Steve Underwood <steveu@coppice.org> + * Various optimizations and improvements by Mark Spencer <markster@digium.com> * * Copyright (C) 2001 Steve Underwood * @@ -53,6 +54,8 @@ #define FREE(a) free(a) #endif +#include "arith.h" + #ifndef NULL #define NULL 0 #endif @@ -63,6 +66,8 @@ #define TRUE (!FALSE) #endif +#define USE_SHORTS + #define NONUPDATE_DWELL_TIME 600 /* 600 samples, or 75ms */ typedef struct @@ -76,6 +81,7 @@ typedef struct int16_t *tx_history; /* Last N tx samples */ int32_t *fir_taps; /* Echo FIR taps */ + int16_t *fir_taps_short; /* Echo FIR taps, shorts instead of ints */ int curr_pos; @@ -98,14 +104,18 @@ static echo_can_state_t *echo_can_create(int len, int adaption_mode); static void echo_can_free(echo_can_state_t *ec); static int16_t echo_can_update(echo_can_state_t *ec, int16_t tx, int16_t rx); -/* Original parameters : +/* Original parameters : #define MIN_TX_POWER_FOR_ADAPTION 256 #define MIN_RX_POWER_FOR_ADAPTION 128 */ -/* Better ones found by Jim */ +#define MIN_TX_POWER_FOR_ADAPTION 256 +#define MIN_RX_POWER_FOR_ADAPTION 64 + +/* Better ones found by Jim #define MIN_TX_POWER_FOR_ADAPTION 128 #define MIN_RX_POWER_FOR_ADAPTION 64 +*/ static inline echo_can_state_t *echo_can_create(int len, int adaption_mode) { @@ -113,19 +123,20 @@ static inline echo_can_state_t *echo_can_create(int len, int adaption_mode) void *ptr; ptr = ec = (echo_can_state_t *) MALLOC(sizeof(*ec) + len * sizeof(int32_t) + - len * sizeof(int16_t)); + len * 3 * sizeof(int16_t)); if (ec == NULL) return NULL; - memset(ec, 0, sizeof(*ec) + len * sizeof(int32_t) + len * sizeof(int16_t)); + memset(ec, 0, sizeof(*ec) + len * sizeof(int32_t) + len * 3 * sizeof(int16_t)); ec->taps = len; ec->tap_mask = len - 1; - ec->fir_taps = (int32_t *) (ptr + sizeof(*ec)); - ec->tx_history = (int16_t *) (ptr + sizeof(*ec) + len * sizeof(int32_t)); + ec->tx_history = (int16_t *) (ptr + sizeof(*ec) ); + ec->fir_taps = (int32_t *) (ptr + sizeof(*ec) + len * 2 * sizeof(int16_t)); + ec->fir_taps_short = (int16_t *) (ptr + sizeof(*ec) + len * sizeof(int32_t) + len * 2 * sizeof(int16_t)); ec->rx_power_threshold = 10000000; ec->use_suppressor = FALSE; /* Non-linear processor - a fancy way to say "zap small signals, to avoid accumulating noise". */ - ec->use_nlp = FALSE; + ec->use_nlp = TRUE; return ec; } /*- End of function --------------------------------------------------------*/ @@ -138,15 +149,12 @@ static inline void echo_can_free(echo_can_state_t *ec) static inline int16_t echo_can_update(echo_can_state_t *ec, int16_t tx, int16_t rx) { - int offset; - int limit; int32_t echo_value; int clean_rx; int nsuppr; - int i; - int correction; ec->tx_history[ec->curr_pos] = tx; + ec->tx_history[ec->curr_pos + ec->taps] = tx; /* Evaluate the echo - i.e. apply the FIR filter */ /* Assume the gain of the FIR does not exceed unity. Exceeding unity @@ -162,14 +170,11 @@ static inline int16_t echo_can_update(echo_can_state_t *ec, int16_t tx, int16_t /* 16 bit coeffs for the LMS give lousy results (maths good, actual sound bad!), but 32 bit coeffs require some shifting. On balance 32 bit seems best */ - offset = ec->curr_pos; - limit = ec->taps - offset; - echo_value = 0; - for (i = 0; i < limit; i++) - echo_value += (ec->fir_taps[i] >> 16)*ec->tx_history[i + offset]; - offset = ec->taps - ec->curr_pos; - for ( ; i < ec->taps; i++) - echo_value += (ec->fir_taps[i] >> 16)*ec->tx_history[i - offset]; +#ifdef USE_SHORTS + echo_value = CONVOLVE2(ec->fir_taps_short, ec->tx_history + ec->curr_pos, ec->taps); +#else + echo_value = CONVOLVE(ec->fir_taps, ec->tx_history + ec->curr_pos, ec->taps); +#endif echo_value >>= 16; /* And the answer is..... */ @@ -193,34 +198,28 @@ static inline int16_t echo_can_update(echo_can_state_t *ec, int16_t tx, int16_t { /* This is a really crude piece of decision logic, but it does OK for now. */ - if (ec->tx_power > 2*ec->rx_power) + if (ec->tx_power > ec->rx_power << 1) { /* There is no far-end speech detected */ if (ec->nonupdate_dwell == 0) { /* ... and we are not in the dwell time from previous speech. */ //nsuppr = saturate((clean_rx << 16)/ec->tx_power); - nsuppr = clean_rx >> 3; + nsuppr = (clean_rx << 16) / ec->tx_power; + nsuppr >>= 4; + if (nsuppr > 512) + nsuppr = 512; + if (nsuppr < -512) + nsuppr = -512; /* Update the FIR taps */ - offset = ec->curr_pos; - limit = ec->taps - offset; ec->latest_correction = 0; - for (i = 0; i < limit; i++) - { - correction = ec->tx_history[i + offset]*nsuppr; - ec->fir_taps[i] += correction; - //ec->latest_correction += abs(correction); - } - offset = ec->taps - ec->curr_pos; - for ( ; i < ec->taps; i++) - { - correction = ec->tx_history[i - offset]*nsuppr; - ec->fir_taps[i] += correction; - //ec->latest_correction += abs(correction); - } - } - else +#ifdef USE_SHORTS + UPDATE2(ec->fir_taps, ec->fir_taps_short, ec->tx_history + ec->curr_pos, nsuppr, ec->taps); +#else + UPDATE(ec->fir_taps, ec->fir_taps_short, ec->tx_history + ec->curr_pos, nsuppr, ec->taps); +#endif + } else { ec->latest_correction = -3; } @@ -263,7 +262,7 @@ static inline int16_t echo_can_update(echo_can_state_t *ec, int16_t tx, int16_t clean_rx = 0; /* Roll around the rolling buffer */ - ec->curr_pos = (ec->curr_pos + 1) & ec->tap_mask; + ec->curr_pos = (ec->curr_pos - 1) & ec->tap_mask; return clean_rx; } |