Add dial tone detection to disable echo suppressor

This commit is contained in:
Andreas Eversberg 2023-03-05 11:02:00 +01:00
parent 71d73d9885
commit a8ec7578c7
2 changed files with 47 additions and 2 deletions

View File

@ -60,6 +60,7 @@
#include <osmocom/core/talloc.h>
#include <stdio.h>
#include <stdbool.h>
#include <math.h>
#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;

View File

@ -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);