diff --git a/linphone/coreapi/linphonecore.c b/linphone/coreapi/linphonecore.c index 4e59a56808a27253e914d730d1151f30fc5350dd..2fcb0862a199101517d2c86698333632ffa6cc95 100644 --- a/linphone/coreapi/linphonecore.c +++ b/linphone/coreapi/linphonecore.c @@ -1565,6 +1565,7 @@ static void post_configure_audio_streams(LinphoneCore *lc){ float speed=lp_config_get_float(lc->config,"sound","el_speed",-1); float thres=lp_config_get_float(lc->config,"sound","el_thres",-1); float force=lp_config_get_float(lc->config,"sound","el_force",-1); + int sustain=lp_config_get_int(lc->config,"sound","el_sustain",-1); float gain=lp_config_get_float(lc->config,"sound","mic_gain",-1); MSFilter *f=NULL; if (st->el_type==ELControlMic){ @@ -1583,6 +1584,8 @@ static void post_configure_audio_streams(LinphoneCore *lc){ ms_filter_call_method(f,MS_VOLUME_SET_EA_THRESHOLD,&thres); if (force!=-1) ms_filter_call_method(f,MS_VOLUME_SET_EA_FORCE,&force); + if (sustain!=-1) + ms_filter_call_method(f,MS_VOLUME_SET_EA_SUSTAIN,&sustain); if (gain!=-1) audio_stream_set_mic_gain(st,gain); } diff --git a/linphone/mediastreamer2/include/mediastreamer2/msvolume.h b/linphone/mediastreamer2/include/mediastreamer2/msvolume.h index 7fc46cdcdbac6104fb2edd6b8eba599d6995956f..052e3d1b99eeb325244c0a2cb9ab50ebee9a2e10 100644 --- a/linphone/mediastreamer2/include/mediastreamer2/msvolume.h +++ b/linphone/mediastreamer2/include/mediastreamer2/msvolume.h @@ -54,6 +54,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define MS_VOLUME_SET_NOISE_GATE_THRESHOLD MS_FILTER_METHOD(MS_VOLUME_ID,10,float) +#define MS_VOLUME_SET_EA_SUSTAIN MS_FILTER_METHOD(MS_VOLUME_ID,11,int) + + extern MSFilterDesc ms_volume_desc; #endif diff --git a/linphone/mediastreamer2/src/msvolume.c b/linphone/mediastreamer2/src/msvolume.c index ae642bde08a5ae0fcb1e81827cfe87f1be4b6069..1deb38b58d06ef33cd5f37d7241653c2dc339420 100644 --- a/linphone/mediastreamer2/src/msvolume.c +++ b/linphone/mediastreamer2/src/msvolume.c @@ -22,6 +22,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #endif #include "mediastreamer2/msvolume.h" +#include "mediastreamer2/msticker.h" #include <math.h> #ifdef HAVE_SPEEXDSP @@ -44,6 +45,9 @@ typedef struct Volume{ float thres; float force; float target_gain; /*the target gain choosed by echo limiter and noise gate*/ + float last_peer_en; + int sustain_time; /* time in ms for which echo limiter remains active after resuming from speech to silence.*/ + uint64_t sustain_start; MSFilter *peer; #ifdef HAVE_SPEEXDSP SpeexPreprocessState *speex_pp; @@ -69,6 +73,9 @@ static void volume_init(MSFilter *f){ v->thres=noise_thres; v->force=en_weight; v->peer=NULL; + v->last_peer_en=0; + v->sustain_time=200; + v->sustain_start=0; v->agc_enabled=FALSE; v->buffer=ms_bufferizer_new(); v->sample_rate=8000; @@ -126,7 +133,15 @@ static inline float compute_gain(float static_gain, float energy, float weight){ return ret; } -static void volume_echo_avoider_process(Volume *v){ +/* +The principle of this algorithm is that we apply a gain to the input signal which is opposite to the +energy measured by the peer MSVolume. +For example if some noise is played by the speaker, then the signal captured by the microphone will be lowered. +The gain changes smoothly when the peer energy is decreasing, but is immediately changed when the peer energy is +increasing. +*/ + +static void volume_echo_avoider_process(Volume *v, uint64_t curtime){ float peer_e; float gain; ms_filter_call_method(v->peer,MS_VOLUME_GET_LINEAR,&peer_e); @@ -135,9 +150,12 @@ static void volume_echo_avoider_process(Volume *v){ if (peer_e>v->thres){ /*lower our output*/ gain=compute_gain(v->static_gain,peer_e,v->force); + if (peer_e>v->last_peer_en) + v->gain=gain; }else { - gain=v->static_gain; + v->sustain_start=curtime; v->ea_active=FALSE; + gain=v->gain; } }else{ int peer_active=FALSE; @@ -148,9 +166,15 @@ static void volume_echo_avoider_process(Volume *v){ v->ea_active=TRUE; v->gain=gain; }else { - gain=v->static_gain; + if (curtime!=0 && (curtime-v->sustain_start)<v->sustain_time){ + gain=v->gain; + }else{/*restore normal gain*/ + gain=v->static_gain; + v->sustain_start=0; + } } } + v->last_peer_en=peer_e; v->target_gain=gain; ms_message("ea_active=%i, peer_e=%f gain=%f gain_k=%f force=%f",v->ea_active,peer_e,v->gain, v->gain_k,v->force); } @@ -225,6 +249,12 @@ static int volume_set_ea_force(MSFilter *f, void*arg){ return 0; } +static int volume_set_ea_sustain(MSFilter *f, void *arg){ + Volume *v=(Volume*)f->data; + v->sustain_time=*(int*)arg; + return 0; +} + static int volume_enable_noise_gate(MSFilter *f, void *arg){ Volume *v=(Volume*)f->data; v->noise_gate_enabled=*(int*)arg; @@ -308,7 +338,7 @@ static void volume_process(MSFilter *f){ volume_agc_process(v,om); if (v->peer){ - volume_echo_avoider_process(v); + volume_echo_avoider_process(v,f->ticker->time); }else v->target_gain=v->static_gain; if (v->noise_gate_enabled) @@ -321,7 +351,7 @@ static void volume_process(MSFilter *f){ while((m=ms_queue_get(f->inputs[0]))!=NULL){ en=update_energy((int16_t*)m->b_rptr,(m->b_wptr-m->b_rptr)/2,en); if (v->peer){ - volume_echo_avoider_process(v); + volume_echo_avoider_process(v,f->ticker->time); }else v->target_gain=v->static_gain; if (v->noise_gate_enabled) @@ -342,6 +372,7 @@ static MSFilterMethod methods[]={ { MS_VOLUME_SET_EA_THRESHOLD , volume_set_ea_threshold }, { MS_VOLUME_SET_EA_SPEED , volume_set_ea_speed }, { MS_VOLUME_SET_EA_FORCE , volume_set_ea_force }, + { MS_VOLUME_SET_EA_SUSTAIN, volume_set_ea_sustain }, { MS_FILTER_SET_SAMPLE_RATE, volume_set_sample_rate }, { MS_VOLUME_ENABLE_AGC , volume_set_agc }, { MS_VOLUME_ENABLE_NOISE_GATE, volume_enable_noise_gate},