forked from mirrors/linphone-iphone
add a noise gate function in MSVolume.
git-svn-id: svn+ssh://svn.savannah.nongnu.org/linphone/trunk@601 3f6dc0c8-ddfe-455d-9043-3cd528dc4637
This commit is contained in:
parent
55ba0378c1
commit
94f63f71db
6 changed files with 79 additions and 19 deletions
|
|
@ -387,6 +387,7 @@
|
|||
<path>win32acm/wine/winuser.h</path>
|
||||
<path>win32acm/wineacm.h</path>
|
||||
<path>win32acm/wrapper.h</path>
|
||||
<path>builddate.h</path>
|
||||
</blacklist>
|
||||
<build>
|
||||
<buildtool>make</buildtool>
|
||||
|
|
|
|||
|
|
@ -57,6 +57,7 @@ struct _AudioStream
|
|||
bool_t use_gc;
|
||||
bool_t use_agc;
|
||||
bool_t eq_active;
|
||||
bool_t use_ng;/*noise gate*/
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
@ -114,6 +115,9 @@ void audio_stream_enable_automatic_gain_control(AudioStream *stream, bool_t val)
|
|||
|
||||
void audio_stream_set_mic_gain(AudioStream *stream, float gain);
|
||||
|
||||
/*enable noise gate, must be done before start()*/
|
||||
void audio_stream_enable_noise_gate(AudioStream *stream, bool_t val);
|
||||
|
||||
/*enable parametric equalizer in the stream that goes to the speaker*/
|
||||
void audio_stream_enable_equalizer(AudioStream *stream, bool_t enabled);
|
||||
|
||||
|
|
|
|||
|
|
@ -50,6 +50,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
|
||||
#define MS_VOLUME_ENABLE_AGC MS_FILTER_METHOD(MS_VOLUME_ID,8,int)
|
||||
|
||||
#define MS_VOLUME_ENABLE_NOISE_GATE MS_FILTER_METHOD(MS_VOLUME_ID,9,int)
|
||||
|
||||
extern MSFilterDesc ms_volume_desc;
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -250,7 +250,7 @@ int audio_stream_start_full(AudioStream *stream, RtpProfile *profile, const char
|
|||
ms_filter_call_method(stream->ec,MS_FILTER_SET_SAMPLE_RATE,&pt->clock_rate);
|
||||
}
|
||||
|
||||
if (stream->el_type!=ELInactive || stream->use_gc){
|
||||
if (stream->el_type!=ELInactive || stream->use_gc || stream->use_ng){
|
||||
stream->volsend=ms_filter_new(MS_VOLUME_ID);
|
||||
stream->volrecv=ms_filter_new(MS_VOLUME_ID);
|
||||
if (stream->el_type!=ELInactive){
|
||||
|
|
@ -258,6 +258,10 @@ int audio_stream_start_full(AudioStream *stream, RtpProfile *profile, const char
|
|||
ms_filter_call_method(stream->volrecv,MS_VOLUME_SET_PEER,stream->volsend);
|
||||
else ms_filter_call_method(stream->volsend,MS_VOLUME_SET_PEER,stream->volrecv);
|
||||
}
|
||||
if (stream->use_ng){
|
||||
int tmp=1;
|
||||
ms_filter_call_method(stream->volsend,MS_VOLUME_ENABLE_NOISE_GATE,&tmp);
|
||||
}
|
||||
}
|
||||
|
||||
if (stream->use_agc){
|
||||
|
|
@ -409,6 +413,7 @@ AudioStream *audio_stream_new(int locport, bool_t ipv6){
|
|||
stream->play_dtmfs=TRUE;
|
||||
stream->use_gc=FALSE;
|
||||
stream->use_agc=FALSE;
|
||||
stream->use_ng=FALSE;
|
||||
return stream;
|
||||
}
|
||||
|
||||
|
|
@ -437,6 +442,10 @@ void audio_stream_enable_automatic_gain_control(AudioStream *stream, bool_t val)
|
|||
stream->use_agc=val;
|
||||
}
|
||||
|
||||
void audio_stream_enable_noise_gate(AudioStream *stream, bool_t val){
|
||||
stream->use_ng=val;
|
||||
}
|
||||
|
||||
void audio_stream_set_mic_gain(AudioStream *stream, float gain){
|
||||
if (stream->volsend){
|
||||
ms_filter_call_method(stream->volsend,MS_VOLUME_SET_GAIN,&gain);
|
||||
|
|
|
|||
|
|
@ -38,20 +38,24 @@ static const float noise_thres=0.1;
|
|||
typedef struct Volume{
|
||||
float energy;
|
||||
float norm_en;
|
||||
float gain;
|
||||
float static_gain;
|
||||
float gain; /*the one really applied, smoothed by noise gate and echo limiter*/
|
||||
float static_gain; /*the one fixed by the user*/
|
||||
float gain_k;
|
||||
float thres;
|
||||
float force;
|
||||
float target_gain; /*the target gain choosed by echo limiter and noise gate*/
|
||||
MSFilter *peer;
|
||||
#ifdef HAVE_SPEEXDSP
|
||||
SpeexPreprocessState *speex_pp;
|
||||
#endif
|
||||
int sample_rate;
|
||||
int nsamples;
|
||||
int ng_cut_time; /*noise gate cut time, after last speech detected*/
|
||||
int ng_noise_dur;
|
||||
MSBufferizer *buffer;
|
||||
bool_t ea_active;
|
||||
bool_t agc_enabled;
|
||||
bool_t noise_gate_enabled;
|
||||
}Volume;
|
||||
|
||||
static void volume_init(MSFilter *f){
|
||||
|
|
@ -68,6 +72,9 @@ static void volume_init(MSFilter *f){
|
|||
v->buffer=ms_bufferizer_new();
|
||||
v->sample_rate=8000;
|
||||
v->nsamples=80;
|
||||
v->noise_gate_enabled=FALSE;
|
||||
v->ng_cut_time=100;/*milliseconds*/
|
||||
v->ng_noise_dur=0;
|
||||
#ifdef HAVE_SPEEXDSP
|
||||
v->speex_pp=NULL;
|
||||
#endif
|
||||
|
|
@ -130,7 +137,6 @@ static void volume_echo_avoider_process(Volume *v){
|
|||
gain=v->static_gain;
|
||||
v->ea_active=FALSE;
|
||||
}
|
||||
v->gain=(v->gain*(1-v->gain_k)) + (v->gain_k*gain);
|
||||
}else{
|
||||
int peer_active=FALSE;
|
||||
ms_filter_call_method(v->peer,MS_VOLUME_GET_EA_STATE,&peer_active);
|
||||
|
|
@ -141,17 +147,29 @@ static void volume_echo_avoider_process(Volume *v){
|
|||
v->gain=gain;
|
||||
}else {
|
||||
gain=v->static_gain;
|
||||
v->gain=(v->gain*(1-v->gain_k)) + (v->gain_k*gain);
|
||||
}
|
||||
}
|
||||
|
||||
v->target_gain=gain;
|
||||
ms_message("ea_active=%i, peer_e=%f gain=%f gain_k=%f force=%f",v->ea_active,peer_e,v->gain, v->gain_k,v->force);
|
||||
}
|
||||
|
||||
static void volume_noise_gate_process(Volume *v , float energy, mblk_t *om){
|
||||
int nsamples=((om->b_wptr-om->b_rptr)/2);
|
||||
if ((energy/max_e)<v->thres){
|
||||
v->ng_noise_dur+=(nsamples*1000)/v->sample_rate;
|
||||
if (v->ng_noise_dur>v->ng_cut_time){
|
||||
v->target_gain=0;
|
||||
}
|
||||
}else{
|
||||
v->ng_noise_dur=0;
|
||||
/*let the target gain unchanged, ie let the echo-limiter choose the gain*/
|
||||
}
|
||||
}
|
||||
|
||||
static int volume_set_gain(MSFilter *f, void *arg){
|
||||
float *farg=(float*)arg;
|
||||
Volume *v=(Volume*)f->data;
|
||||
v->gain=v->static_gain=*farg;
|
||||
v->gain=v->static_gain=v->target_gain=*farg;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -205,6 +223,12 @@ static int volume_set_ea_force(MSFilter *f, void*arg){
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int volume_enable_noise_gate(MSFilter *f, void *arg){
|
||||
Volume *v=(Volume*)f->data;
|
||||
v->noise_gate_enabled=*(int*)arg;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int16_t saturate(float val){
|
||||
return (val>32767) ? 32767 : ( (val<-32767) ? -32767 : val);
|
||||
}
|
||||
|
|
@ -219,13 +243,17 @@ static float update_energy(int16_t *signal, int numsamples, float last_energy_va
|
|||
return en;
|
||||
}
|
||||
|
||||
static void apply_gain(mblk_t *m, float gain){
|
||||
static void apply_gain(Volume *v, mblk_t *m){
|
||||
int16_t *sample;
|
||||
float gain=v->target_gain;
|
||||
|
||||
if (gain==1 && v->gain==1) return;
|
||||
v->gain=(v->gain*(1-v->gain_k)) + (v->gain_k*gain);
|
||||
for ( sample=(int16_t*)m->b_rptr;
|
||||
sample<(int16_t*)m->b_wptr;
|
||||
++sample){
|
||||
float s=*sample;
|
||||
*sample=saturate(s*gain);
|
||||
*sample=saturate(s*v->gain);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -273,10 +301,11 @@ static void volume_process(MSFilter *f){
|
|||
|
||||
if (v->peer){
|
||||
volume_echo_avoider_process(v);
|
||||
}
|
||||
if (v->gain!=1){
|
||||
apply_gain(om,v->gain);
|
||||
}
|
||||
}else v->target_gain=v->static_gain;
|
||||
|
||||
if (v->noise_gate_enabled)
|
||||
volume_noise_gate_process(v,en,om);
|
||||
apply_gain(v,om);
|
||||
ms_queue_put(f->outputs[0],om);
|
||||
}
|
||||
}else{
|
||||
|
|
@ -285,10 +314,11 @@ static void volume_process(MSFilter *f){
|
|||
en=update_energy((int16_t*)m->b_rptr,(m->b_wptr-m->b_rptr)/2,en);
|
||||
if (v->peer){
|
||||
volume_echo_avoider_process(v);
|
||||
}
|
||||
if (v->gain!=1){
|
||||
apply_gain(m,v->gain);
|
||||
}
|
||||
}else v->target_gain=v->static_gain;
|
||||
|
||||
if (v->noise_gate_enabled)
|
||||
volume_noise_gate_process(v,en,m);
|
||||
apply_gain(v,m);
|
||||
ms_queue_put(f->outputs[0],m);
|
||||
}
|
||||
}
|
||||
|
|
@ -306,6 +336,7 @@ static MSFilterMethod methods[]={
|
|||
{ MS_VOLUME_SET_EA_FORCE , volume_set_ea_force },
|
||||
{ MS_FILTER_SET_SAMPLE_RATE, volume_set_sample_rate },
|
||||
{ MS_VOLUME_ENABLE_AGC , volume_set_agc },
|
||||
{ MS_VOLUME_ENABLE_NOISE_GATE, volume_enable_noise_gate},
|
||||
{ 0 , NULL }
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -40,6 +40,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
|
||||
static int cond=1;
|
||||
|
||||
static const char * capture_card=NULL;
|
||||
static bool_t use_ng=FALSE;
|
||||
|
||||
static void stop_handler(int signum)
|
||||
{
|
||||
cond--;
|
||||
|
|
@ -127,7 +130,9 @@ const char *usage="mediastream --local <port> --remote <ip:port> --payload <payl
|
|||
"[ --height <pixels> ]\n"
|
||||
"[ --bitrate <bits per seconds>]\n"
|
||||
"[ --ec (enable echo canceller)]\n"
|
||||
"[ --agc (enable automatic gain control)]\n";
|
||||
"[ --agc (enable automatic gain control)]\n"
|
||||
"[ --ng (enable noise gate)]\n"
|
||||
"[ --capture-card <index>] \n";
|
||||
static void run_media_streams(int localport, const char *remote_ip, int remoteport, int payload, const char *fmtp, int jitter, bool_t ec, int bitrate, MSVideoSize vs, bool_t agc, bool_t eq);
|
||||
|
||||
|
||||
|
|
@ -193,12 +198,17 @@ int main(int argc, char * argv[])
|
|||
}else if (strcmp(argv[i],"--height")==0){
|
||||
i++;
|
||||
vs.height=atoi(argv[i]);
|
||||
}else if (strcmp(argv[i],"--capture-card")==0){
|
||||
i++;
|
||||
capture_card=argv[i];
|
||||
}else if (strcmp(argv[i],"--ec")==0){
|
||||
ec=TRUE;
|
||||
}else if (strcmp(argv[i],"--agc")==0){
|
||||
agc=TRUE;
|
||||
}else if (strcmp(argv[i],"--eq")==0){
|
||||
eq=TRUE;
|
||||
}else if (strcmp(argv[i],"--ng")==0){
|
||||
use_ng=1;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -230,11 +240,14 @@ void run_media_streams(int localport, const char *remote_ip, int remoteport, in
|
|||
if (pt->type!=PAYLOAD_VIDEO){
|
||||
printf("Starting audio stream.\n");
|
||||
MSSndCardManager *manager=ms_snd_card_manager_get();
|
||||
MSSndCard *capt= capture_card==NULL ? ms_snd_card_manager_get_default_capture_card(manager) :
|
||||
ms_snd_card_manager_get_card(manager,capture_card);
|
||||
audio=audio_stream_new(localport,ms_is_ipv6(remote_ip));
|
||||
audio_stream_enable_automatic_gain_control(audio,agc);
|
||||
audio_stream_enable_noise_gate(audio,use_ng);
|
||||
audio_stream_start_now(audio,profile,remote_ip,remoteport,remoteport+1,payload,jitter,
|
||||
ms_snd_card_manager_get_default_playback_card(manager),
|
||||
ms_snd_card_manager_get_default_capture_card(manager),
|
||||
capt,
|
||||
ec);
|
||||
if (audio) session=audio->session;
|
||||
}else{
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue