From 9407e6d672a8e661dbbcc2166402c4cb62a166ae Mon Sep 17 00:00:00 2001 From: aymeric Date: Thu, 5 Feb 2009 17:45:02 +0000 Subject: [PATCH] add half duplex simulation with VAD for noisy environment. git-svn-id: svn+ssh://svn.savannah.nongnu.org/linphone/trunk@244 3f6dc0c8-ddfe-455d-9043-3cd528dc4637 --- .../include/mediastreamer2/msfilter.h | 4 + linphone/mediastreamer2/src/msconf.c | 126 ++++++++++++++---- 2 files changed, 105 insertions(+), 25 deletions(-) diff --git a/linphone/mediastreamer2/include/mediastreamer2/msfilter.h b/linphone/mediastreamer2/include/mediastreamer2/msfilter.h index 124f94317..aabd1381d 100644 --- a/linphone/mediastreamer2/include/mediastreamer2/msfilter.h +++ b/linphone/mediastreamer2/include/mediastreamer2/msfilter.h @@ -388,6 +388,10 @@ the method index (_cnt_) and the argument size */ #define MS_FILTER_GET_STAT_OUTPUT MS_FILTER_BASE_METHOD(19,int) #define MS_FILTER_ENABLE_AGC MS_FILTER_BASE_METHOD(20,int) #define MS_FILTER_SET_PLAYBACKDELAY MS_FILTER_BASE_METHOD(21,int) +#define MS_FILTER_ENABLE_HALFDUPLEX MS_FILTER_BASE_METHOD(22,int) +#define MS_FILTER_SET_VAD_PROB_START MS_FILTER_BASE_METHOD(23,int) +#define MS_FILTER_SET_VAD_PROB_CONTINUE MS_FILTER_BASE_METHOD(24,int) + /** @} */ /*private methods*/ diff --git a/linphone/mediastreamer2/src/msconf.c b/linphone/mediastreamer2/src/msconf.c index cfb78cd4e..80172238d 100644 --- a/linphone/mediastreamer2/src/msconf.c +++ b/linphone/mediastreamer2/src/msconf.c @@ -44,6 +44,9 @@ typedef struct Channel{ int16_t input[CONF_NSAMPLES]; bool_t has_contributed; bool_t is_used; + + int is_speaking; + int count; int missed; @@ -62,6 +65,11 @@ typedef struct ConfState{ int sum[CONF_NSAMPLES]; int enable_directmode; int enable_vad; + + int enable_halfduplex; + int vad_prob_start; + int vad_prob_continue; + int agc_level; int mix_mode; int samplerate; @@ -73,6 +81,7 @@ typedef struct ConfState{ static void channel_init(ConfState *s, Channel *chan, int pos){ + memset(chan, 0, sizeof(Channel)); ms_bufferizer_init(&chan->buff); #ifndef DISABLE_SPEEX //chan->speex_pp = speex_preprocess_state_init((s->conf_gran/2) *(s->samplerate/8000), s->samplerate); @@ -91,6 +100,16 @@ static void channel_init(ConfState *s, Channel *chan, int pos){ val=1; speex_preprocess_ctl(chan->speex_pp, SPEEX_PREPROCESS_SET_VAD, &val); } + else if (pos==0 && s->enable_halfduplex>0) + { + val=1; + speex_preprocess_ctl(chan->speex_pp, SPEEX_PREPROCESS_SET_VAD, &val); + val = s->vad_prob_start; // xx% + speex_preprocess_ctl(chan->speex_pp, SPEEX_PREPROCESS_SET_PROB_START, &val); + val = s->vad_prob_continue; // xx% + speex_preprocess_ctl(chan->speex_pp, SPEEX_PREPROCESS_SET_PROB_CONTINUE, &val); + } + /* enable AGC only on local soundcard */ if (s->agc_level>0 && pos==0) { @@ -249,12 +268,6 @@ static void conf_sum(ConfState *s){ chan=&s->channels[i]; /* skip soundread and short buffer entry */ -#if 0 - if (i>0 - && ms_bufferizer_get_avail(&chan->buff)>=s->conf_gran*s->adaptative_msconf_buf) - { - while (ms_bufferizer_get_avail(&chan->buff)>=s->conf_gran*2) -#endif if (i>0 && ms_bufferizer_get_avail(&chan->buff)> s->conf_gran && ms_bufferizer_get_avail(&chan->buff)> (ms_bufferizer_get_avail(&s->channels[0].buff)+s->conf_gran*6) ) @@ -282,10 +295,13 @@ static void conf_sum(ConfState *s){ chan->stat_discarded++; } - for(j=0;jconf_nsamples;++j){ - s->sum[j]+=chan->input[j]; + if (s->channels[0].is_speaking<=0) + { + for(j=0;jconf_nsamples;++j){ + s->sum[j]+=chan->input[j]; + } + chan->has_contributed=TRUE; } - chan->has_contributed=TRUE; chan->stat_processed++; } else if (ms_bufferizer_get_avail(&chan->buff)>=s->conf_gran) @@ -296,17 +312,41 @@ static void conf_sum(ConfState *s){ { int vad; vad = speex_preprocess(chan->speex_pp, (short*)chan->input, NULL); + if (s->enable_halfduplex>0) + { + if (vad>0) + { + /* speech detected */ + chan->is_speaking++; + if (chan->is_speaking>5) + chan->is_speaking=5; + } + else + { + chan->is_speaking--; + if (chan->is_speaking<-5) + chan->is_speaking=-5; + } + if (chan->is_speaking<=0) + ms_message("silence on! (%i)", chan->is_speaking); + else + ms_message("speech on! (%i)", chan->is_speaking); + } + } + else if (chan->speex_pp!=NULL && s->enable_vad==TRUE) + { + speex_preprocess_estimate_update(chan->speex_pp, (short*)chan->input); } - else if (chan->speex_pp!=NULL && s->enable_vad==TRUE) - { - speex_preprocess_estimate_update(chan->speex_pp, (short*)chan->input); - } #endif - for(j=0;jconf_nsamples;++j){ - s->sum[j]+=chan->input[j]; + if (i==0 + || s->channels[0].is_speaking<=0) + { + for(j=0;jconf_nsamples;++j){ + s->sum[j]+=chan->input[j]; + } + chan->has_contributed=TRUE; } - chan->has_contributed=TRUE; chan->stat_processed++; } else { chan->stat_missed++; @@ -444,16 +484,12 @@ static void conf_process(MSFilter *f){ static void conf_postprocess(MSFilter *f){ int i; ConfState *s=(ConfState*)f->data; - Channel *chan; - /*read from all inputs and put into bufferizers*/ - for (i=0;iinputs[i]!=NULL){ - chan=&s->channels[i]; - ms_bufferizer_uninit(&chan->buff); - ms_bufferizer_init(&chan->buff); - } - } + for (i=0;ichannels[i]); + for (i=0;ichannels[i], i); } + static int msconf_set_sr(MSFilter *f, void *arg){ ConfState *s=(ConfState*)f->data; int i; @@ -486,6 +522,42 @@ static int msconf_enable_agc(MSFilter *f, void *arg){ return 0; } +static int msconf_enable_halfduplex(MSFilter *f, void *arg){ + ConfState *s=(ConfState*)f->data; + int i; + s->enable_halfduplex = *(int*)arg; + + for (i=0;ichannels[i]); + for (i=0;ichannels[i], i); + return 0; +} + +static int msconf_set_vad_prob_start(MSFilter *f, void *arg){ + ConfState *s=(ConfState*)f->data; + int i; + s->vad_prob_start = *(int*)arg; + + for (i=0;ichannels[i]); + for (i=0;ichannels[i], i); + return 0; +} + +static int msconf_set_vad_prob_continue(MSFilter *f, void *arg){ + ConfState *s=(ConfState*)f->data; + int i; + s->vad_prob_continue = *(int*)arg; + + for (i=0;ichannels[i]); + for (i=0;ichannels[i], i); + return 0; +} + static int msconf_enable_vad(MSFilter *f, void *arg){ ConfState *s=(ConfState*)f->data; int i; @@ -554,6 +626,10 @@ static MSFilterMethod msconf_methods[]={ { MS_FILTER_GET_STAT_DISCARDED, msconf_get_stat_discarded }, { MS_FILTER_GET_STAT_MISSED, msconf_get_stat_missed }, { MS_FILTER_GET_STAT_OUTPUT, msconf_get_stat_processed }, + + { MS_FILTER_ENABLE_HALFDUPLEX, msconf_enable_halfduplex }, + { MS_FILTER_SET_VAD_PROB_START, msconf_set_vad_prob_start }, + { MS_FILTER_SET_VAD_PROB_CONTINUE, msconf_set_vad_prob_continue }, { 0 , NULL} };