mirror of
https://gitlab.linphone.org/BC/public/linphone-iphone.git
synced 2026-05-06 21:33:08 +00:00
integrate echo-limiter
git-svn-id: svn+ssh://svn.savannah.nongnu.org/linphone/trunk@357 3f6dc0c8-ddfe-455d-9043-3cd528dc4637
This commit is contained in:
parent
037c99fb84
commit
0f94518313
8 changed files with 85 additions and 14 deletions
|
|
@ -22,6 +22,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
#include "lpconfig.h"
|
||||
#include "private.h"
|
||||
#include "mediastreamer2/mediastream.h"
|
||||
#include "mediastreamer2/msvolume.h"
|
||||
#include <eXosip2/eXosip.h>
|
||||
#include "sdphandler.h"
|
||||
|
||||
|
|
@ -407,6 +408,9 @@ void sound_config_read(LinphoneCore *lc)
|
|||
|
||||
linphone_core_enable_echo_cancelation(lc,
|
||||
lp_config_get_int(lc->config,"sound","echocancelation",0));
|
||||
|
||||
linphone_core_enable_echo_limiter(lc,
|
||||
lp_config_get_int(lc->config,"sound","echolimiter",0));
|
||||
}
|
||||
|
||||
void sip_config_read(LinphoneCore *lc)
|
||||
|
|
@ -1409,6 +1413,9 @@ int linphone_core_change_qos(LinphoneCore *lc, int answer)
|
|||
|
||||
void linphone_core_init_media_streams(LinphoneCore *lc){
|
||||
lc->audiostream=audio_stream_new(linphone_core_get_audio_port(lc),linphone_core_ipv6_enabled(lc));
|
||||
if (linphone_core_echo_limiter_enabled(lc)){
|
||||
audio_stream_enable_echo_limiter(lc->audiostream,TRUE);
|
||||
}
|
||||
#ifdef VIDEO_ENABLED
|
||||
if (lc->video_conf.display || lc->video_conf.capture)
|
||||
lc->videostream=video_stream_new(linphone_core_get_video_port(lc),linphone_core_ipv6_enabled(lc));
|
||||
|
|
@ -1423,6 +1430,23 @@ static void linphone_core_dtmf_received(RtpSession* s, int dtmf, void* user_data
|
|||
lc->vtable.dtmf_received(lc, dtmf);
|
||||
}
|
||||
|
||||
static void post_configure_audio_streams(LinphoneCore *lc){
|
||||
AudioStream *st=lc->audiostream;
|
||||
if (st->volrecv && st->volsend){
|
||||
float speed=lp_config_get_float(lc->config,"sound","el_speed",-1);
|
||||
float thres=lp_config_get_float(lc->config,"sound","el_thres",-1);
|
||||
if (speed!=-1)
|
||||
ms_filter_call_method(st->volsend,MS_VOLUME_SET_EA_SPEED,&speed);
|
||||
if (thres!=-1)
|
||||
ms_filter_call_method(st->volrecv,MS_VOLUME_SET_EA_THRESHOLD,&thres);
|
||||
}
|
||||
if (lc->vtable.dtmf_received!=NULL){
|
||||
/* replace by our default action*/
|
||||
audio_stream_play_received_dtmfs(lc->audiostream,FALSE);
|
||||
rtp_session_signal_connect(lc->audiostream->session,"telephone-event",(RtpCallback)linphone_core_dtmf_received,(unsigned long)lc);
|
||||
}
|
||||
}
|
||||
|
||||
void linphone_core_start_media_streams(LinphoneCore *lc, LinphoneCall *call){
|
||||
osip_from_t *me=linphone_core_get_primary_contact_parsed(lc);
|
||||
const char *tool="linphone-" LINPHONE_VERSION;
|
||||
|
|
@ -1467,11 +1491,7 @@ void linphone_core_start_media_streams(LinphoneCore *lc, LinphoneCall *call){
|
|||
lc->play_file,
|
||||
lc->rec_file);
|
||||
}
|
||||
if (lc->vtable.dtmf_received!=NULL){
|
||||
/* replace by our default action*/
|
||||
audio_stream_play_received_dtmfs(lc->audiostream,FALSE);
|
||||
rtp_session_signal_connect(lc->audiostream->session,"telephone-event",(RtpCallback)linphone_core_dtmf_received,(unsigned long)lc);
|
||||
}
|
||||
post_configure_audio_streams(lc);
|
||||
audio_stream_set_rtcp_information(lc->audiostream, cname, tool);
|
||||
}
|
||||
#ifdef VIDEO_ENABLED
|
||||
|
|
@ -1884,6 +1904,14 @@ bool_t linphone_core_echo_cancelation_enabled(LinphoneCore *lc){
|
|||
return lc->sound_conf.ec;
|
||||
}
|
||||
|
||||
void linphone_core_enable_echo_limiter(LinphoneCore *lc, bool_t val){
|
||||
lc->sound_conf.ea=val;
|
||||
}
|
||||
|
||||
bool_t linphone_core_echo_limiter_enabled(const LinphoneCore *lc){
|
||||
return lc->sound_conf.ea;
|
||||
}
|
||||
|
||||
|
||||
void linphone_core_send_dtmf(LinphoneCore *lc,char dtmf)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -103,10 +103,10 @@ typedef struct sound_config
|
|||
char play_lev;
|
||||
char ring_lev;
|
||||
char source;
|
||||
char pad;
|
||||
char *local_ring;
|
||||
char *remote_ring;
|
||||
bool_t ec;
|
||||
bool_t ea;
|
||||
} sound_config_t;
|
||||
|
||||
typedef struct codecs_config
|
||||
|
|
@ -681,6 +681,9 @@ int linphone_core_preview_ring(LinphoneCore *lc, const char *ring,LinphoneCoreCb
|
|||
void linphone_core_enable_echo_cancelation(LinphoneCore *lc, bool_t val);
|
||||
bool_t linphone_core_echo_cancelation_enabled(LinphoneCore *lc);
|
||||
|
||||
void linphone_core_enable_echo_limiter(LinphoneCore *lc, bool_t val);
|
||||
bool_t linphone_core_echo_limiter_enabled(const LinphoneCore *lc);
|
||||
|
||||
void linphone_core_set_presence_info(LinphoneCore *lc,int minutes_away,const char *contact,LinphoneOnlineStatus os);
|
||||
|
||||
LinphoneOnlineStatus linphone_core_get_presence_info(const LinphoneCore *lc);
|
||||
|
|
|
|||
|
|
@ -290,6 +290,14 @@ int lp_config_get_int(LpConfig *lpconfig,const char *section, const char *key, i
|
|||
else return default_value;
|
||||
}
|
||||
|
||||
float lp_config_get_float(LpConfig *lpconfig,const char *section, const char *key, float default_value){
|
||||
const char *str=lp_config_get_string(lpconfig,section,key,NULL);
|
||||
float ret;
|
||||
if (str==NULL) return default_value;
|
||||
sscanf(str,"%f",&ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void lp_config_set_string(LpConfig *lpconfig,const char *section, const char *key, const char *value){
|
||||
LpItem *item;
|
||||
LpSection *sec=lp_config_find_section(lpconfig,section);
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ extern "C" {
|
|||
LpConfig * lp_config_new(const char *filename);
|
||||
const char *lp_config_get_string(LpConfig *lpconfig, const char *section, const char *key, const char *default_string);
|
||||
int lp_config_get_int(LpConfig *lpconfig,const char *section, const char *key, int default_value);
|
||||
float lp_config_get_float(LpConfig *lpconfig,const char *section, const char *key, float default_value);
|
||||
void lp_config_set_string(LpConfig *lpconfig,const char *section, const char *key, const char *value);
|
||||
void lp_config_set_int(LpConfig *lpconfig,const char *section, const char *key, int value);
|
||||
int lp_config_sync(LpConfig *lpconfig);
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ struct _AudioStream
|
|||
unsigned int last_packet_count;
|
||||
time_t last_packet_time;
|
||||
bool_t play_dtmfs;
|
||||
bool_t use_ea; /*use echo avoider: two MSVolume, measured input level controlling local output level*/
|
||||
bool_t use_ea; /*use echo limiter: two MSVolume, measured input level controlling local output level*/
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
@ -92,8 +92,8 @@ void audio_stream_set_relay_session_id(AudioStream *stream, const char *relay_se
|
|||
/*returns true if we are still receiving some data from remote end in the last timeout seconds*/
|
||||
bool_t audio_stream_alive(AudioStream * stream, int timeout);
|
||||
|
||||
/*enable echo-avoider dispositve: one MSVolume in input branch controls a MSVolume in the output branch*/
|
||||
void audio_stream_enable_echo_avoider(AudioStream *stream, bool_t enabled);
|
||||
/*enable echo-limiter dispositve: one MSVolume in input branch controls a MSVolume in the output branch*/
|
||||
void audio_stream_enable_echo_limiter(AudioStream *stream, bool_t enabled);
|
||||
|
||||
/* stop the above process*/
|
||||
void audio_stream_stop (AudioStream * stream);
|
||||
|
|
|
|||
|
|
@ -42,6 +42,10 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
|
||||
#define MS_VOLUME_SET_PEER MS_FILTER_METHOD(MS_VOLUME_ID,4, MSFilter )
|
||||
|
||||
#define MS_VOLUME_SET_EA_THRESHOLD MS_FILTER_METHOD(MS_VOLUME_ID,5,float)
|
||||
|
||||
#define MS_VOLUME_SET_EA_SPEED MS_FILTER_METHOD(MS_VOLUME_ID,6,float)
|
||||
|
||||
extern MSFilterDesc ms_volume_desc;
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -393,7 +393,7 @@ void audio_stream_set_relay_session_id(AudioStream *stream, const char *id){
|
|||
ms_filter_call_method(stream->rtpsend, MS_RTP_SEND_SET_RELAY_SESSION_ID,(void*)id);
|
||||
}
|
||||
|
||||
void audio_stream_enable_echo_avoider(AudioStream *stream, bool_t enabled){
|
||||
void audio_stream_enable_echo_limiter(AudioStream *stream, bool_t enabled){
|
||||
stream->use_ea=enabled;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -32,6 +32,8 @@ typedef struct Volume{
|
|||
float norm_en;
|
||||
float gain;
|
||||
float static_gain;
|
||||
float gain_k;
|
||||
float thres;
|
||||
MSFilter *peer;
|
||||
bool_t ea_active;
|
||||
}Volume;
|
||||
|
|
@ -42,8 +44,9 @@ static void volume_init(MSFilter *f){
|
|||
v->norm_en=0;
|
||||
v->static_gain=v->gain=1;
|
||||
v->ea_active=FALSE;
|
||||
v->gain_k=gain_k;
|
||||
v->thres=noise_thres;
|
||||
f->data=v;
|
||||
|
||||
}
|
||||
|
||||
static void volume_uninit(MSFilter *f){
|
||||
|
|
@ -69,7 +72,7 @@ static void volume_echo_avoider_process(Volume *v){
|
|||
float gain;
|
||||
ms_filter_call_method(v->peer,MS_VOLUME_GET_LINEAR,&peer_e);
|
||||
if (v->ea_active){
|
||||
if (peer_e>noise_thres){
|
||||
if (peer_e>v->thres){
|
||||
/*lower our output*/
|
||||
gain=v->static_gain*(1-peer_e);
|
||||
}else {
|
||||
|
|
@ -79,13 +82,13 @@ static void volume_echo_avoider_process(Volume *v){
|
|||
}else{
|
||||
int peer_active=FALSE;
|
||||
ms_filter_call_method(v->peer,MS_VOLUME_GET_EA_STATE,&peer_active);
|
||||
if (peer_e>noise_thres && ! peer_active){
|
||||
if (peer_e>v->thres && ! peer_active){
|
||||
/*lower our output*/
|
||||
gain=v->static_gain*(1-peer_e);
|
||||
v->ea_active=TRUE;
|
||||
}else gain=v->static_gain;
|
||||
}
|
||||
v->gain=(v->gain*(1-gain_k)) + (gain_k*coef);
|
||||
v->gain=(v->gain*(1-v->gain_k)) + (v->gain_k*v->gain);
|
||||
}
|
||||
|
||||
static int volume_set_gain(MSFilter *f, void *arg){
|
||||
|
|
@ -110,6 +113,28 @@ static int volume_set_peer(MSFilter *f, void *arg){
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int volume_set_ea_threshold(MSFilter *f, void*arg){
|
||||
Volume *v=(Volume*)f->data;
|
||||
float val=*(float*)arg;
|
||||
if (val<0 || val>1) {
|
||||
ms_error("Error: threshold must be in range [0..1]");
|
||||
return -1;
|
||||
}
|
||||
v->thres=val;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int volume_set_ea_speed(MSFilter *f, void*arg){
|
||||
Volume *v=(Volume*)f->data;
|
||||
float val=*(float*)arg;
|
||||
if (val<0 || val>1) {
|
||||
ms_error("Error: speed must be in range [0..1]");
|
||||
return -1;
|
||||
}
|
||||
v->gain_k=val;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int16_t saturate(float val){
|
||||
return (val>32767) ? 32767 : ( (val<-32767) ? -32767 : val);
|
||||
}
|
||||
|
|
@ -148,6 +173,8 @@ static MSFilterMethod methods[]={
|
|||
{ MS_VOLUME_SET_GAIN , volume_set_gain },
|
||||
{ MS_VOLUME_GET_EA_STATE , volume_get_ea_state },
|
||||
{ MS_VOLUME_SET_PEER , volume_set_peer },
|
||||
{ MS_VOLUME_SET_EA_THRESHOLD , volume_set_ea_threshold },
|
||||
{ MS_VOLUME_SET_EA_SPEED , volume_set_ea_speed },
|
||||
{ 0 , NULL }
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue