mirror of
https://gitlab.linphone.org/BC/public/linphone-iphone.git
synced 2026-01-21 13:08:08 +00:00
echo canceler refactoring and improvements.
git-svn-id: svn+ssh://svn.savannah.nongnu.org/linphone/trunk@606 3f6dc0c8-ddfe-455d-9043-3cd528dc4637
This commit is contained in:
parent
3b4a2ffb56
commit
ccf741f1ff
4 changed files with 122 additions and 40 deletions
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
38
linphone/mediastreamer2/include/mediastreamer2/msspeexec.h
Normal file
38
linphone/mediastreamer2/include/mediastreamer2/msspeexec.h
Normal file
|
|
@ -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
|
||||
|
|
@ -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,31 +272,44 @@ static int speex_ec_set_framesize(MSFilter *f, void *arg){
|
|||
SpeexECState *s=(SpeexECState*)f->data;
|
||||
s->framesize = *(int*)arg;
|
||||
|
||||
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->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->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_filterlength(MSFilter *f, void *arg){
|
||||
static int speex_ec_set_delay2(MSFilter *f, void *arg){
|
||||
SpeexECState *s=(SpeexECState*)f->data;
|
||||
s->filterlength = *(int*)arg;
|
||||
s->delay_ms = *(int*)arg;
|
||||
return 0;
|
||||
}
|
||||
|
||||
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);
|
||||
static int speex_ec_set_tail_length2(MSFilter *f, void *arg){
|
||||
SpeexECState *s=(SpeexECState*)f->data;
|
||||
s->tail_length_ms=*(int*)arg;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -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,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue