Commit 0f945183 authored by smorlat's avatar smorlat

integrate echo-limiter



git-svn-id: svn+ssh://svn.savannah.nongnu.org/linphone/trunk@357 3f6dc0c8-ddfe-455d-9043-3cd528dc4637
parent 037c99fb
......@@ -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 }
};
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment