From ccf741f1ff01ea65dfc65f414718d1b3c05ca58d Mon Sep 17 00:00:00 2001 From: smorlat <smorlat@3f6dc0c8-ddfe-455d-9043-3cd528dc4637> Date: Fri, 28 Aug 2009 16:02:17 +0000 Subject: [PATCH] echo canceler refactoring and improvements. git-svn-id: svn+ssh://svn.savannah.nongnu.org/linphone/trunk@606 3f6dc0c8-ddfe-455d-9043-3cd528dc4637 --- .../include/mediastreamer2/Makefile.am | 3 +- .../include/mediastreamer2/mediastream.h | 3 + .../include/mediastreamer2/msspeexec.h | 38 ++++++ linphone/mediastreamer2/src/speexec.c | 114 ++++++++++++------ 4 files changed, 120 insertions(+), 38 deletions(-) create mode 100644 linphone/mediastreamer2/include/mediastreamer2/msspeexec.h diff --git a/linphone/mediastreamer2/include/mediastreamer2/Makefile.am b/linphone/mediastreamer2/include/mediastreamer2/Makefile.am index 83343ab969..74673ce144 100644 --- a/linphone/mediastreamer2/include/mediastreamer2/Makefile.am +++ b/linphone/mediastreamer2/include/mediastreamer2/Makefile.am @@ -22,7 +22,8 @@ mediastreamer2_include_HEADERS= ice.h \ rfc3984.h \ mswebcam.h \ dsptools.h \ - msequalizer.h + msequalizer.h \ + msspeexec.h EXTRA_DIST=$(mediastreamer2_include_HEADERS) diff --git a/linphone/mediastreamer2/include/mediastreamer2/mediastream.h b/linphone/mediastreamer2/include/mediastreamer2/mediastream.h index 9224d920a2..5a3347ee6b 100644 --- a/linphone/mediastreamer2/include/mediastreamer2/mediastream.h +++ b/linphone/mediastreamer2/include/mediastreamer2/mediastream.h @@ -53,6 +53,9 @@ struct _AudioStream uint64_t last_packet_count; time_t last_packet_time; EchoLimiterType el_type; /*use echo limiter: two MSVolume, measured input level controlling local output level*/ + int ec_tail_len; /*milliseconds*/ + int ec_delay; /*milliseconds*/ + int ec_framesize; /* number of fft points */ bool_t play_dtmfs; bool_t use_gc; bool_t use_agc; diff --git a/linphone/mediastreamer2/include/mediastreamer2/msspeexec.h b/linphone/mediastreamer2/include/mediastreamer2/msspeexec.h new file mode 100644 index 0000000000..e9bc24d26f --- /dev/null +++ b/linphone/mediastreamer2/include/mediastreamer2/msspeexec.h @@ -0,0 +1,38 @@ +/* +mediastreamer2 library - modular sound and video processing and streaming +Copyright (C) 2006-2009 Simon MORLAT (simon.morlat@linphone.org) + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +msspeexec.h : interface of the speex echo canceler integration in mediastreamer2 + +*/ + +#ifndef msspeexec_h +#define msspeexec_h + +#include <mediastreamer2/msfilter.h> + +/** sets the tail length in milliseconds*/ +#define MS_SPEEX_EC_SET_TAIL_LENGTH MS_FILTER_METHOD(MS_SPEEX_EC_ID,0,int) + +/** sets the minimum delay of the echo if known. This optimizes the convergence*/ +#define MS_SPEEX_EC_SET_DELAY MS_FILTER_METHOD(MS_SPEEX_EC_ID,1,int) + +/** sets the frame size for the AU-MDF algorithm, in number of fft points*/ +#define MS_SPEEX_EC_SET_FRAME_SIZE MS_FILTER_METHOD(MS_SPEEX_EC_ID,2,int) + + +#endif diff --git a/linphone/mediastreamer2/src/speexec.c b/linphone/mediastreamer2/src/speexec.c index f897e143fe..aecf99a3a7 100644 --- a/linphone/mediastreamer2/src/speexec.c +++ b/linphone/mediastreamer2/src/speexec.c @@ -17,7 +17,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include "mediastreamer2/msfilter.h" +#include "mediastreamer2/msspeexec.h" #include <speex/speex_echo.h> #include <speex/speex_preprocess.h> @@ -46,6 +46,8 @@ typedef struct SpeexECState{ int ref; int echo; int out; + int delay_ms; + int tail_length_ms; }SpeexECState; static void speex_ec_init(MSFilter *f){ @@ -57,14 +59,14 @@ static void speex_ec_init(MSFilter *f){ ms_bufferizer_init(&s->speak_delay); s->size_delay=0; + s->delay_ms=0; s->playback_delay=0; + s->tail_length_ms=250; ms_bufferizer_init(&s->in[0]); ms_bufferizer_init(&s->in[1]); - s->ecstate=speex_echo_state_init(s->framesize,s->filterlength); - s->den = speex_preprocess_state_init(s->framesize, s->samplerate); - speex_echo_ctl(s->ecstate, SPEEX_ECHO_SET_SAMPLING_RATE, &s->samplerate); - speex_preprocess_ctl(s->den, SPEEX_PREPROCESS_SET_ECHO_STATE, s->ecstate); + s->ecstate=NULL; + s->den = NULL; f->data=s; } @@ -74,13 +76,33 @@ static void speex_ec_uninit(MSFilter *f){ ms_bufferizer_uninit(&s->speak_delay); ms_bufferizer_uninit(&s->in[0]); ms_bufferizer_uninit(&s->in[1]); - speex_echo_state_destroy(s->ecstate); + if (s->ecstate!=NULL) + speex_echo_state_destroy(s->ecstate); if (s->den!=NULL) - speex_preprocess_state_destroy(s->den); + speex_preprocess_state_destroy(s->den); ms_free(s); } + +static void speex_ec_preprocess(MSFilter *f){ + SpeexECState *s=(SpeexECState*)f->data; + if (s->ecstate!=NULL) + speex_echo_state_destroy(s->ecstate); + if (s->den!=NULL) + speex_preprocess_state_destroy(s->den); + + if (s->tail_length_ms!=0) + s->filterlength=(s->tail_length_ms*s->samplerate)/1000; + if (s->delay_ms!=0) + s->playback_delay=s->delay_ms*s->samplerate/1000; + + s->ecstate=speex_echo_state_init(s->framesize,s->filterlength); + s->den = speex_preprocess_state_init(s->framesize, s->samplerate); + speex_echo_ctl(s->ecstate, SPEEX_ECHO_SET_SAMPLING_RATE, &s->samplerate); + speex_preprocess_ctl(s->den, SPEEX_PREPROCESS_SET_ECHO_STATE, s->ecstate); +} + /* inputs[0]= reference signal (sent to soundcard) inputs[1]= echo signal (read from soundcard) */ @@ -210,23 +232,22 @@ static void speex_ec_process(MSFilter *f){ static void speex_ec_postprocess(MSFilter *f){ SpeexECState *s=(SpeexECState*)f->data; - flushq(&s->in[1].q,0); - flushq(&s->in[0].q,0); - flushq(&s->speak_delay.q,0); + ms_bufferizer_uninit(&s->in[0]); + ms_bufferizer_uninit(&s->in[1]); + ms_bufferizer_uninit(&s->speak_delay); ms_bufferizer_init(&s->in[0]); ms_bufferizer_init(&s->in[1]); ms_bufferizer_init(&s->speak_delay); s->size_delay=0; - if (s->ecstate!=NULL) + if (s->ecstate!=NULL){ speex_echo_state_destroy(s->ecstate); - if (s->den!=NULL) - speex_preprocess_state_destroy(s->den); - - s->ecstate=speex_echo_state_init(s->framesize,s->filterlength*(s->samplerate/8000)); - s->den = speex_preprocess_state_init(s->framesize, s->samplerate); - speex_echo_ctl(s->ecstate, SPEEX_ECHO_SET_SAMPLING_RATE, &s->samplerate); - speex_preprocess_ctl(s->den, SPEEX_PREPROCESS_SET_ECHO_STATE, s->ecstate); + s->ecstate=NULL; + } + if (s->den!=NULL){ + speex_preprocess_state_destroy(s->den); + s->den=NULL; + } } static int speex_ec_set_sr(MSFilter *f, void *arg){ @@ -234,15 +255,16 @@ static int speex_ec_set_sr(MSFilter *f, void *arg){ s->samplerate = *(int*)arg; - if (s->ecstate!=NULL) + if (s->ecstate!=NULL){ speex_echo_state_destroy(s->ecstate); - if (s->den!=NULL) - speex_preprocess_state_destroy(s->den); - - s->ecstate=speex_echo_state_init(s->framesize,s->filterlength*(s->samplerate/8000)); - s->den = speex_preprocess_state_init(s->framesize, s->samplerate); - speex_echo_ctl(s->ecstate, SPEEX_ECHO_SET_SAMPLING_RATE, &s->samplerate); - speex_preprocess_ctl(s->den, SPEEX_PREPROCESS_SET_ECHO_STATE, s->ecstate); + if (s->den!=NULL) + speex_preprocess_state_destroy(s->den); + + s->ecstate=speex_echo_state_init(s->framesize,s->filterlength); + s->den = speex_preprocess_state_init(s->framesize, s->samplerate); + speex_echo_ctl(s->ecstate, SPEEX_ECHO_SET_SAMPLING_RATE, &s->samplerate); + speex_preprocess_ctl(s->den, SPEEX_PREPROCESS_SET_ECHO_STATE, s->ecstate); + } return 0; } @@ -250,34 +272,47 @@ static int speex_ec_set_framesize(MSFilter *f, void *arg){ SpeexECState *s=(SpeexECState*)f->data; s->framesize = *(int*)arg; - if (s->ecstate!=NULL) + if (s->ecstate!=NULL){ speex_echo_state_destroy(s->ecstate); - if (s->den!=NULL) - speex_preprocess_state_destroy(s->den); - - s->ecstate=speex_echo_state_init(s->framesize,s->filterlength*(s->samplerate/8000)); - s->den = speex_preprocess_state_init(s->framesize, s->samplerate); - speex_echo_ctl(s->ecstate, SPEEX_ECHO_SET_SAMPLING_RATE, &s->samplerate); - speex_preprocess_ctl(s->den, SPEEX_PREPROCESS_SET_ECHO_STATE, s->ecstate); + if (s->den!=NULL) + speex_preprocess_state_destroy(s->den); + + s->ecstate=speex_echo_state_init(s->framesize,s->filterlength); + s->den = speex_preprocess_state_init(s->framesize, s->samplerate); + speex_echo_ctl(s->ecstate, SPEEX_ECHO_SET_SAMPLING_RATE, &s->samplerate); + speex_preprocess_ctl(s->den, SPEEX_PREPROCESS_SET_ECHO_STATE, s->ecstate); + } return 0; } static int speex_ec_set_filterlength(MSFilter *f, void *arg){ SpeexECState *s=(SpeexECState*)f->data; - s->filterlength = *(int*)arg; + s->filterlength = (*(int*)arg)*(s->samplerate/8000); if (s->ecstate!=NULL) speex_echo_state_destroy(s->ecstate); if (s->den!=NULL) speex_preprocess_state_destroy(s->den); - s->ecstate=speex_echo_state_init(s->framesize,s->filterlength*(s->samplerate/8000)); + s->ecstate=speex_echo_state_init(s->framesize,s->filterlength); s->den = speex_preprocess_state_init(s->framesize, s->samplerate); speex_echo_ctl(s->ecstate, SPEEX_ECHO_SET_SAMPLING_RATE, &s->samplerate); speex_preprocess_ctl(s->den, SPEEX_PREPROCESS_SET_ECHO_STATE, s->ecstate); return 0; } +static int speex_ec_set_delay2(MSFilter *f, void *arg){ + SpeexECState *s=(SpeexECState*)f->data; + s->delay_ms = *(int*)arg; + return 0; +} + +static int speex_ec_set_tail_length2(MSFilter *f, void *arg){ + SpeexECState *s=(SpeexECState*)f->data; + s->tail_length_ms=*(int*)arg; + return 0; +} + static int speex_ec_set_playbackdelay(MSFilter *f, void *arg){ SpeexECState *s=(SpeexECState*)f->data; s->playback_delay = *(int*)arg; @@ -295,6 +330,10 @@ static int speex_ec_set_playbackdelay(MSFilter *f, void *arg){ static MSFilterMethod speex_ec_methods[]={ { MS_FILTER_SET_SAMPLE_RATE, speex_ec_set_sr }, + { MS_SPEEX_EC_SET_TAIL_LENGTH , speex_ec_set_tail_length2 }, + { MS_SPEEX_EC_SET_DELAY , speex_ec_set_delay2 }, + { MS_SPEEX_EC_SET_FRAME_SIZE , speex_ec_set_framesize }, +/*these are kept for backward compatibility */ { MS_FILTER_SET_FRAMESIZE, speex_ec_set_framesize }, { MS_FILTER_SET_FILTERLENGTH, speex_ec_set_filterlength }, { MS_FILTER_SET_PLAYBACKDELAY, speex_ec_set_playbackdelay }, @@ -312,7 +351,7 @@ MSFilterDesc ms_speex_ec_desc={ 2, 2, speex_ec_init, - NULL, + speex_ec_preprocess, speex_ec_process, speex_ec_postprocess, speex_ec_uninit, @@ -329,6 +368,7 @@ MSFilterDesc ms_speex_ec_desc={ .ninputs=2, .noutputs=2, .init=speex_ec_init, + .preprocess=speex_ec_preprocess, .process=speex_ec_process, .postprocess=speex_ec_postprocess, .uninit=speex_ec_uninit, -- GitLab