diff --git a/src/libecho/echo_suppress.c b/src/libecho/echo_suppress.c index d067afc..ce00316 100644 --- a/src/libecho/echo_suppress.c +++ b/src/libecho/echo_suppress.c @@ -60,6 +60,7 @@ #include #include +#include #include #include "echo_suppress.h" @@ -70,15 +71,19 @@ #define SUPPRESS_THRESHOLD -31.0 #define RELEASE_SUPPRESS -31.0 #define INSERTION_LOSS 6.0 +#define DT_MIN_LEVEL_DB -20 +#define DT_MAX_OFFSET_DB 0.2 #define SUPPRESS_OPERATE 0.000 #define SUPPRESS_HANGOVER 0.050 #define BREAK_IN_OPERATE 0.030 #define BREAK_IN_HANGOVER 0.050 +#define DT_INTERVAL 0.250 #define LP_FREQUENCY 3400.0 #define HP_FREQUENCY 500.0 #define ENV_FREQUENCY 500.0 +#define DT_ENV_FREQUENCY 10.0 //#define DEBUG_ES @@ -181,6 +186,9 @@ echo_sup_state_t *echo_sup_create(void *ctx, int samplerate) iir_highpass_init(&es->hp_receive, HP_FREQUENCY, samplerate); iir_lowpass_init(&es->env_send, ENV_FREQUENCY, samplerate); iir_lowpass_init(&es->env_receive, ENV_FREQUENCY, samplerate); + iir_lowpass_init(&es->dt_receive, DT_ENV_FREQUENCY, samplerate); + + es->dt_interval = floor(DT_INTERVAL * (double)samplerate); return es; } @@ -194,7 +202,7 @@ void echo_sup_free(echo_sup_state_t *es) /* tx is what we sent to user interface, aka 'receive' */ int16_t echo_sup_update(echo_sup_state_t *es, int16_t tx, int16_t rx) { - float send, receive; + float send, receive, dt, offset; /* convert from integer samples to float (@ 0 dBm scale) */ receive = (float)tx / 23196.0; /* towards user interface */ @@ -208,11 +216,44 @@ int16_t echo_sup_update(echo_sup_state_t *es, int16_t tx, int16_t rx) /* get absolute value (rectifying with 3 dB gain) */ send = fabsf(send) * 1.4142136; - receive = fabsf(receive) * 1.4142136; + receive = dt = fabsf(receive) * 1.4142136; /* filter envelope */ iir_process(&es->env_send, &send, 1); iir_process(&es->env_receive, &receive, 1); + iir_process(&es->dt_receive, &dt, 1); + + /* detect dial tone and do not suppress while it is detected */ + if (++es->dt_timer == es->dt_interval) { +#ifdef DEBUG_ES + printf("dt_level=%.3f dt_offset=%.3f*\n", level2db(es->dt_level), level2db(es->dt_offset)); +#endif + if (level2db(es->dt_level) > DT_MIN_LEVEL_DB && level2db(es->dt_offset) < DT_MAX_OFFSET_DB) { + if (!es->dt_disable) { +#ifdef DEBUG_ES + printf("Detected dial tone, disabling suppressor\n"); +#endif + es->dt_disable = true; + } + } else { + if (es->dt_disable) { +#ifdef DEBUG_ES + printf("dial tone ceases, enabling suppressor\n"); +#endif + es->dt_disable = false; + es->state = SUP_STATE_SILENCE; + es->timer = 0; + } + } + es->dt_timer = 0; + es->dt_level = dt; + es->dt_offset = 0.0; + } + offset = fabsf(es->dt_level / dt); + if (offset > es->dt_offset) + es->dt_offset = offset; + if (es->dt_disable) + return rx; #ifdef DEBUG_ES static int debug_interval = 0; diff --git a/src/libecho/echo_suppress.h b/src/libecho/echo_suppress.h index cbf0f82..b46e555 100644 --- a/src/libecho/echo_suppress.h +++ b/src/libecho/echo_suppress.h @@ -23,6 +23,10 @@ typedef struct echo_sup_state { iir_filter_t lp_send, lp_receive; /* filter to cut off high frequencies */ iir_filter_t hp_send, hp_receive; /* filter to cut off low frequencies */ iir_filter_t env_send, env_receive; /* filter to get the envelope after rectifying */ + iir_filter_t dt_receive; /* filter to detect steady tone (dial tone) */ + int dt_timer, dt_interval; /* timer of dial tone detection interval */ + float dt_level, dt_offset; /* initial level and max offset during interval */ + bool dt_disable; /* true if suppressor is disabled, due to dial tone */ } echo_sup_state_t; echo_sup_state_t *echo_sup_create(void *ctx, int samplerate);