From 5f8a7295e220373097ab73658d853dda2643b84e Mon Sep 17 00:00:00 2001 From: Benny Prijono Date: Sun, 6 Aug 2006 14:15:47 +0000 Subject: Change the silence suppressor to use the adaptive silence detector. git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@655 74dad513-b988-da41-8d7b-12977e46ad98 --- pjmedia/include/pjmedia/conference.h | 10 ++++++++ pjmedia/include/pjmedia/silencedet.h | 19 +++++++++++++--- pjmedia/src/pjmedia/conference.c | 13 ++++++++++- pjmedia/src/pjmedia/echo_common.c | 2 +- pjmedia/src/pjmedia/echo_suppress.c | 44 +++++++++++++++++++++--------------- pjmedia/src/pjmedia/silencedet.c | 32 ++++++++++++++++++++------ 6 files changed, 90 insertions(+), 30 deletions(-) diff --git a/pjmedia/include/pjmedia/conference.h b/pjmedia/include/pjmedia/conference.h index 8b1f2e35..936d2294 100644 --- a/pjmedia/include/pjmedia/conference.h +++ b/pjmedia/include/pjmedia/conference.h @@ -292,6 +292,16 @@ PJ_DECL(pj_status_t) pjmedia_conf_disconnect_port( pjmedia_conf *conf, unsigned sink_slot ); +/** + * Get total number of ports connections currently set up in the bridge. + * + * @param conf The conference bridge. + * + * @return PJ_SUCCESS on success. + */ +PJ_DECL(unsigned) pjmedia_conf_get_connect_count(pjmedia_conf *conf); + + /** * Remove the specified port from the conference bridge. * diff --git a/pjmedia/include/pjmedia/silencedet.h b/pjmedia/include/pjmedia/silencedet.h index a4958cc5..15cb8460 100644 --- a/pjmedia/include/pjmedia/silencedet.h +++ b/pjmedia/include/pjmedia/silencedet.h @@ -72,6 +72,19 @@ PJ_DECL(pj_status_t) pjmedia_silence_det_create( pj_pool_t *pool, pjmedia_silence_det **p_sd ); +/** + * Set silence detector name to identify the particular silence detector + * instance in the log. + * + * @param sd The silence detector. + * @param name Name. + * + * @return PJ_SUCCESS on success. + */ +PJ_DECL(pj_status_t) pjmedia_silence_det_set_name(pjmedia_silence_det *sd, + const char *name); + + /** * Set the sd to operate in fixed threshold mode. With fixed threshold mode, * the threshold will not be changed adaptively. @@ -109,7 +122,7 @@ PJ_DECL(pj_status_t) pjmedia_silence_det_set_adaptive(pjmedia_silence_det *sd, * @param min_signal Minimum duration of signal (in msec) before * signal is reported. If -1 is specified, then * the default value will be used. The default is - * one frame. + * equal to one frame. * @param recalc_time The interval to recalculate signal and silence * proportion and to readjust the silence threshold * when adaptive silence detection is set. If -1 @@ -144,7 +157,7 @@ PJ_DECL(pj_status_t) pjmedia_silence_det_disable( pjmedia_silence_det *sd ); * @param p_level Optional pointer to receive average signal level * of the input samples. * - * @return PJ_SUCCESS on success. + * @return Non zero if signal is silence. */ PJ_DECL(pj_bool_t) pjmedia_silence_det_detect( pjmedia_silence_det *sd, const pj_int16_t samples[], @@ -173,7 +186,7 @@ PJ_DECL(pj_int32_t) pjmedia_calc_avg_signal( const pj_int16_t samples[], * @param sd The silence detector instance. * @param level Signal level. * - * @return PJ_SUCCESS on success. + * @return Non zero if signal is silence. */ PJ_DECL(pj_bool_t) pjmedia_silence_det_apply( pjmedia_silence_det *sd, pj_uint32_t level); diff --git a/pjmedia/src/pjmedia/conference.c b/pjmedia/src/pjmedia/conference.c index b888573d..a0743b6a 100644 --- a/pjmedia/src/pjmedia/conference.c +++ b/pjmedia/src/pjmedia/conference.c @@ -221,7 +221,7 @@ static pj_status_t create_conf_port( pj_pool_t *pool, PJ_ASSERT_RETURN(conf_port, PJ_ENOMEM); /* Set name */ - pj_strdup(pool, &conf_port->name, name); + pj_strdup_with_null(pool, &conf_port->name, name); /* Default has tx and rx enabled. */ conf_port->rx_setting = PJMEDIA_PORT_ENABLE; @@ -258,6 +258,8 @@ static pj_status_t create_conf_port( pj_pool_t *pool, /* Set fixed */ pjmedia_silence_det_set_fixed(conf_port->vad, 2); + /* Set VAD name */ + pjmedia_silence_det_set_name(conf_port->vad, conf_port->name.ptr); /* If port's clock rate is different than conference's clock rate, * create a resample sessions. @@ -897,6 +899,15 @@ PJ_DEF(pj_status_t) pjmedia_conf_disconnect_port( pjmedia_conf *conf, } +/* + * Get total number of ports connections currently set up in the bridge. + */ +PJ_DECL(unsigned) pjmedia_conf_get_connect_count(pjmedia_conf *conf) +{ + return conf->connect_cnt; +} + + /* * Remove the specified port. */ diff --git a/pjmedia/src/pjmedia/echo_common.c b/pjmedia/src/pjmedia/echo_common.c index b84fa953..7dad3037 100644 --- a/pjmedia/src/pjmedia/echo_common.c +++ b/pjmedia/src/pjmedia/echo_common.c @@ -118,7 +118,7 @@ static struct ec_operations aec_op = }; #else -static struct ec_operations aec_op = echo_supp_op; +#define aec_op echo_supp_op #endif diff --git a/pjmedia/src/pjmedia/echo_suppress.c b/pjmedia/src/pjmedia/echo_suppress.c index 8cc6ab7b..199324cb 100644 --- a/pjmedia/src/pjmedia/echo_suppress.c +++ b/pjmedia/src/pjmedia/echo_suppress.c @@ -27,7 +27,7 @@ #define THIS_FILE "echo_suppress.c" -#define PJMEDIA_ECHO_SUPPRESS_THRESHOLD 20 +#define PJMEDIA_ECHO_SUPPRESS_THRESHOLD PJMEDIA_SILENCE_DET_THRESHOLD /* @@ -35,11 +35,11 @@ */ typedef struct echo_supp { - unsigned threshold; - pj_bool_t suppressing; - pj_time_val last_signal; - unsigned samples_per_frame; - unsigned tail_ms; + pj_bool_t suppressing; + pjmedia_silence_det *sd; + pj_time_val last_signal; + unsigned samples_per_frame; + unsigned tail_ms; } echo_supp; @@ -78,15 +78,24 @@ PJ_DEF(pj_status_t) echo_supp_create( pj_pool_t *pool, void **p_state ) { echo_supp *ec; + pj_status_t status; PJ_UNUSED_ARG(clock_rate); PJ_UNUSED_ARG(options); ec = pj_pool_zalloc(pool, sizeof(struct echo_supp)); - ec->threshold = PJMEDIA_ECHO_SUPPRESS_THRESHOLD; ec->samples_per_frame = samples_per_frame; ec->tail_ms = tail_ms; + status = pjmedia_silence_det_create(pool, clock_rate, samples_per_frame, + &ec->sd); + if (status != PJ_SUCCESS) + return status; + + pjmedia_silence_det_set_name(ec->sd, "ecsu%p"); + pjmedia_silence_det_set_adaptive(ec->sd, PJMEDIA_ECHO_SUPPRESS_THRESHOLD); + pjmedia_silence_det_set_params(ec->sd, 0, 500, 3000); + *p_state = ec; return PJ_SUCCESS; } @@ -109,17 +118,16 @@ PJ_DEF(pj_status_t) echo_supp_playback( void *state, pj_int16_t *play_frm ) { echo_supp *ec = state; + pj_bool_t silence; pj_bool_t last_suppressing = ec->suppressing; - unsigned level; - level = pjmedia_calc_avg_signal(play_frm, ec->samples_per_frame); - level = linear2ulaw(level) ^ 0xff; + silence = pjmedia_silence_det_detect(ec->sd, play_frm, + ec->samples_per_frame, NULL); + + ec->suppressing = !silence; - if (level >= ec->threshold) { + if (ec->suppressing) { pj_gettimeofday(&ec->last_signal); - ec->suppressing = 1; - } else { - ec->suppressing = 0; } if (ec->suppressing!=0 && last_suppressing==0) { @@ -168,15 +176,15 @@ PJ_DEF(pj_status_t) echo_supp_cancel_echo( void *state, void *reserved ) { echo_supp *ec = state; - unsigned level; + pj_bool_t silence; PJ_UNUSED_ARG(options); PJ_UNUSED_ARG(reserved); - level = pjmedia_calc_avg_signal(play_frm, ec->samples_per_frame); - level = linear2ulaw(level) ^ 0xff; + silence = pjmedia_silence_det_detect(ec->sd, play_frm, + ec->samples_per_frame, NULL); - if (level >= ec->threshold) { + if (!silence) { pjmedia_zero_samples(rec_frm, ec->samples_per_frame); } diff --git a/pjmedia/src/pjmedia/silencedet.c b/pjmedia/src/pjmedia/silencedet.c index e8f4952c..c0b5d2c3 100644 --- a/pjmedia/src/pjmedia/silencedet.c +++ b/pjmedia/src/pjmedia/silencedet.c @@ -38,6 +38,8 @@ typedef enum pjmedia_silence_det_mode { */ struct pjmedia_silence_det { + char objname[PJ_MAX_OBJ_NAME]; /**< VAD name. */ + int mode; /**< VAD mode. */ unsigned ptime; /**< Frame time, in msec. */ @@ -70,6 +72,9 @@ PJ_DEF(pj_status_t) pjmedia_silence_det_create( pj_pool_t *pool, sd = pj_pool_zalloc(pool, sizeof(struct pjmedia_silence_det)); + pj_ansi_strncpy(sd->objname, THIS_FILE, PJ_MAX_OBJ_NAME); + sd->objname[PJ_MAX_OBJ_NAME-1] = '\0'; + sd->ptime = samples_per_frame * 1000 / clock_rate; sd->signal_cnt = 0; sd->silence_cnt = 0; @@ -87,6 +92,18 @@ PJ_DEF(pj_status_t) pjmedia_silence_det_create( pj_pool_t *pool, return PJ_SUCCESS; } + +PJ_DEF(pj_status_t) pjmedia_silence_det_set_name( pjmedia_silence_det *sd, + const char *name) +{ + PJ_ASSERT_RETURN(sd && name, PJ_EINVAL); + + pj_ansi_snprintf(sd->objname, PJ_MAX_OBJ_NAME, name, sd); + sd->objname[PJ_MAX_OBJ_NAME-1] = '\0'; + return PJ_SUCCESS; +} + + PJ_DEF(pj_status_t) pjmedia_silence_det_set_adaptive(pjmedia_silence_det *sd, int threshold) { @@ -233,7 +250,7 @@ PJ_DEF(pj_bool_t) pjmedia_silence_det_apply( pjmedia_silence_det *sd, if (sd->mode == VAD_MODE_ADAPTIVE) { pj_bool_t updated = PJ_TRUE; - unsigned pct_signal; + unsigned pct_signal, new_threshold = sd->cur_threshold; /* Get percentage of signal */ pct_signal = sd->signal_cnt * 100 / @@ -241,19 +258,20 @@ PJ_DEF(pj_bool_t) pjmedia_silence_det_apply( pjmedia_silence_det *sd, /* Adjust according to signal/silence proportions. */ if (pct_signal > 95) { - sd->cur_threshold += (sd->weakest_signal - sd->cur_threshold)/4; + new_threshold += (sd->weakest_signal - sd->cur_threshold)/4; } else if (pct_signal < 5) { - sd->cur_threshold = (sd->cur_threshold+sd->loudest_silence)/2+1; + new_threshold = (sd->cur_threshold+sd->loudest_silence)/2+1; } else if (pct_signal > 90) { - sd->cur_threshold++; + new_threshold++; } else if (pct_signal < 10) { - sd->cur_threshold--; + new_threshold--; } else { updated = PJ_FALSE; } - if (updated) { - PJ_LOG(5,(THIS_FILE, "Vad cur_threshold updated to %d", + if (updated && sd->cur_threshold != new_threshold) { + sd->cur_threshold = new_threshold; + PJ_LOG(5,(sd->objname, "Vad cur_threshold updated to %d", sd->cur_threshold)); } } -- cgit v1.2.3