diff --git a/linphone/coreapi/linphonecore.c b/linphone/coreapi/linphonecore.c
index 2f9803f25dc4f9b5e89cab05c04e10125644f52c..1f5b910159e19f5cfe0ee64b5d6af32114774b25 100644
--- a/linphone/coreapi/linphonecore.c
+++ b/linphone/coreapi/linphonecore.c
@@ -411,6 +411,8 @@ void sound_config_read(LinphoneCore *lc)
 
 	linphone_core_enable_echo_limiter(lc,
 		lp_config_get_int(lc->config,"sound","echolimiter",0));
+	linphone_core_enable_agc(lc,
+		lp_config_get_int(lc->config,"sound","agc",0));
 }
 
 void sip_config_read(LinphoneCore *lc)
@@ -1435,6 +1437,7 @@ void linphone_core_init_media_streams(LinphoneCore *lc){
 		}
 		
 	}
+	audio_stream_enable_automatic_gain_control(lc->audiostream,linphone_core_agc_enabled(lc));
 #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));
@@ -1951,6 +1954,14 @@ bool_t linphone_core_echo_limiter_enabled(const LinphoneCore *lc){
 	return lc->sound_conf.ea;
 }
 
+void linphone_core_enable_agc(LinphoneCore *lc, bool_t val){
+	lc->sound_conf.agc=val;
+}
+
+bool_t linphone_core_agc_enabled(const LinphoneCore *lc){
+	return lc->sound_conf.agc;
+}
+
 
 void linphone_core_send_dtmf(LinphoneCore *lc,char dtmf)
 {
diff --git a/linphone/coreapi/linphonecore.h b/linphone/coreapi/linphonecore.h
index 8334d9bd81d8d55aa7a21a38fd2955f04ff18680..ab7b5641f98469f7b3a1c3277f53e7aeb63257c5 100644
--- a/linphone/coreapi/linphonecore.h
+++ b/linphone/coreapi/linphonecore.h
@@ -107,6 +107,7 @@ typedef struct sound_config
 	char *remote_ring;
 	bool_t ec;
 	bool_t ea;
+	bool_t agc;
 } sound_config_t;
 
 typedef struct codecs_config
@@ -713,6 +714,9 @@ 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_enable_agc(LinphoneCore *lc, bool_t val);
+bool_t linphone_core_agc_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);
diff --git a/linphone/linphone.kdevelop b/linphone/linphone.kdevelop
index 23f8b7837a9874ded986cb204f5b6163c5dd85cd..5068dc8f674aad49223f61bb552c090deaf52fc8 100644
--- a/linphone/linphone.kdevelop
+++ b/linphone/linphone.kdevelop
@@ -8,10 +8,24 @@
     <primarylanguage>C</primarylanguage>
     <ignoreparts/>
     <projectname>linphone</projectname>
+    <projectdirectory>.</projectdirectory>
+    <absoluteprojectpath>false</absoluteprojectpath>
+    <description></description>
+    <defaultencoding></defaultencoding>
   </general>
   <kdevcustomproject>
     <run>
       <directoryradio>executable</directoryradio>
+      <mainprogram>/home/smorlat/sources/git/linphone/linphone</mainprogram>
+      <programargs></programargs>
+      <globaldebugarguments></globaldebugarguments>
+      <globalcwd>/home/smorlat/sources/git/linphone/linphone</globalcwd>
+      <useglobalprogram>false</useglobalprogram>
+      <terminal>false</terminal>
+      <autocompile>false</autocompile>
+      <autoinstall>false</autoinstall>
+      <autokdesu>false</autokdesu>
+      <envvars/>
     </run>
     <filetypes>
       <filetype>*.java</filetype>
@@ -374,11 +388,51 @@
       <path>win32acm/wineacm.h</path>
       <path>win32acm/wrapper.h</path>
     </blacklist>
+    <build>
+      <buildtool>make</buildtool>
+      <builddir></builddir>
+    </build>
+    <other>
+      <prio>0</prio>
+      <otherbin></otherbin>
+      <defaulttarget></defaulttarget>
+      <otheroptions></otheroptions>
+      <selectedenvironment>default</selectedenvironment>
+      <environments>
+        <default/>
+      </environments>
+    </other>
+    <make>
+      <abortonerror>true</abortonerror>
+      <numberofjobs>0</numberofjobs>
+      <prio>0</prio>
+      <dontact>false</dontact>
+      <makebin></makebin>
+      <defaulttarget></defaulttarget>
+      <makeoptions></makeoptions>
+      <selectedenvironment>default</selectedenvironment>
+      <environments>
+        <default/>
+      </environments>
+    </make>
   </kdevcustomproject>
   <kdevdebugger>
     <general>
-      <dbgshell/>
+      <dbgshell></dbgshell>
+      <gdbpath></gdbpath>
+      <configGdbScript></configGdbScript>
+      <runShellScript></runShellScript>
+      <runGdbScript></runGdbScript>
+      <breakonloadinglibs>true</breakonloadinglibs>
+      <separatetty>false</separatetty>
+      <floatingtoolbar>false</floatingtoolbar>
+      <raiseGDBOnStart>false</raiseGDBOnStart>
     </general>
+    <display>
+      <staticmembers>false</staticmembers>
+      <demanglenames>true</demanglenames>
+      <outputradix>10</outputradix>
+    </display>
   </kdevdebugger>
   <kdevdoctreeview>
     <ignoretocs>
@@ -470,6 +524,19 @@
       <alwaysIncludeNamespaces>false</alwaysIncludeNamespaces>
       <includePaths>.;</includePaths>
     </codecompletion>
+    <creategettersetter>
+      <prefixGet></prefixGet>
+      <prefixSet>set</prefixSet>
+      <prefixVariable>m_,_</prefixVariable>
+      <parameterName>theValue</parameterName>
+      <inlineGet>true</inlineGet>
+      <inlineSet>true</inlineSet>
+    </creategettersetter>
+    <splitheadersource>
+      <enabled>false</enabled>
+      <synchronize>true</synchronize>
+      <orientation>Vertical</orientation>
+    </splitheadersource>
   </kdevcppsupport>
   <kdevfileview>
     <groups>
@@ -481,4 +548,10 @@
       <hidenonprojectfiles>false</hidenonprojectfiles>
     </tree>
   </kdevfileview>
+  <cppsupportpart>
+    <filetemplates>
+      <interfacesuffix>.h</interfacesuffix>
+      <implementationsuffix>.cpp</implementationsuffix>
+    </filetemplates>
+  </cppsupportpart>
 </kdevelop>
diff --git a/linphone/mediastreamer2/include/mediastreamer2/mediastream.h b/linphone/mediastreamer2/include/mediastreamer2/mediastream.h
index e41f939da2822ad0d9c9adcd69da79b9860b768c..61d7dab974b46fd25b8393a6e95aad0ecb2dbd0e 100644
--- a/linphone/mediastreamer2/include/mediastreamer2/mediastream.h
+++ b/linphone/mediastreamer2/include/mediastreamer2/mediastream.h
@@ -53,6 +53,7 @@ struct _AudioStream
 	EchoLimiterType el_type; /*use echo limiter: two MSVolume, measured input level controlling local output level*/
 	bool_t play_dtmfs;
 	bool_t use_gc;
+	bool_t use_agc;
 };
 
 #ifdef __cplusplus
@@ -105,6 +106,9 @@ void audio_stream_enable_echo_limiter(AudioStream *stream, EchoLimiterType type)
 /*enable gain control, to be done before start() */
 void audio_stream_enable_gain_control(AudioStream *stream, bool_t val);
 
+/*enable automatic gain control, to be done before start() */
+void audio_stream_enable_automatic_gain_control(AudioStream *stream, bool_t val);
+
 void audio_stream_set_mic_gain(AudioStream *stream, float gain);
 
 /* stop the audio streaming thread and free everything*/
diff --git a/linphone/mediastreamer2/include/mediastreamer2/msvolume.h b/linphone/mediastreamer2/include/mediastreamer2/msvolume.h
index 1bb208dc7c5d790c894d30c1aa85e54107c03d2f..14574eecdd1785029d24403ab14e022d337d68d9 100644
--- a/linphone/mediastreamer2/include/mediastreamer2/msvolume.h
+++ b/linphone/mediastreamer2/include/mediastreamer2/msvolume.h
@@ -48,6 +48,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
 #define MS_VOLUME_SET_EA_FORCE		MS_FILTER_METHOD(MS_VOLUME_ID,7,float)
 
+#define MS_VOLUME_ENABLE_AGC		MS_FILTER_METHOD(MS_VOLUME_ID,8,int)
+
 extern MSFilterDesc ms_volume_desc;
 
 #endif
diff --git a/linphone/mediastreamer2/src/audiostream.c b/linphone/mediastreamer2/src/audiostream.c
index bb0edda7cb5fa384577e672a611a19009fbe24ba..516d6498031b7a8b3a6b8ef115693d441a3a6273 100644
--- a/linphone/mediastreamer2/src/audiostream.c
+++ b/linphone/mediastreamer2/src/audiostream.c
@@ -257,6 +257,13 @@ int audio_stream_start_full(AudioStream *stream, RtpProfile *profile, const char
 		}
 	}
 
+	if (stream->use_agc){
+		int tmp=1;
+		if (stream->volsend==NULL)
+			stream->volsend=ms_filter_new(MS_VOLUME_ID);
+		ms_filter_call_method(stream->volsend,MS_VOLUME_ENABLE_AGC,&tmp);
+	}
+
 	/* give the sound filters some properties */
 	ms_filter_call_method(stream->soundread,MS_FILTER_SET_SAMPLE_RATE,&pt->clock_rate);
 	ms_filter_call_method(stream->soundwrite,MS_FILTER_SET_SAMPLE_RATE,&pt->clock_rate);
@@ -382,6 +389,7 @@ AudioStream *audio_stream_new(int locport, bool_t ipv6){
 	stream->rtpsend=ms_filter_new(MS_RTP_SEND_ID);
 	stream->play_dtmfs=TRUE;
 	stream->use_gc=FALSE;
+	stream->use_agc=FALSE;
 	return stream;
 }
 
@@ -406,6 +414,10 @@ void audio_stream_enable_gain_control(AudioStream *stream, bool_t val){
 	stream->use_gc=val;
 }
 
+void audio_stream_enable_automatic_gain_control(AudioStream *stream, bool_t val){
+	stream->use_agc=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);
diff --git a/linphone/mediastreamer2/src/msvolume.c b/linphone/mediastreamer2/src/msvolume.c
index 3de030e5ee674822ece994e918078c446882062e..a816bc89cd2206b6b9d04a73824946f97c501493 100644
--- a/linphone/mediastreamer2/src/msvolume.c
+++ b/linphone/mediastreamer2/src/msvolume.c
@@ -17,9 +17,17 @@ along with this program; if not, write to the Free Software
 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */
 
+#ifdef HAVE_CONFIG_H
+#include "mediastreamer-config.h"
+#endif
+
 #include "mediastreamer2/msvolume.h"
 #include <math.h>
 
+#ifdef HAVE_SPEEXDSP
+#include <speex/speex_preprocess.h>
+#endif
+
 static const float max_e=32767*32767;
 static const float coef=0.1;
 static const float gain_k=0.02;
@@ -36,7 +44,14 @@ typedef struct Volume{
 	float thres;
 	float force;
 	MSFilter *peer;
+#ifdef HAVE_SPEEXDSP
+	SpeexPreprocessState *speex_pp;
+#endif
+	int sample_rate;
+	int nsamples;
+	MSBufferizer *buffer;
 	bool_t ea_active;
+	bool_t agc_enabled;
 }Volume;
 
 static void volume_init(MSFilter *f){
@@ -49,10 +64,19 @@ static void volume_init(MSFilter *f){
 	v->thres=noise_thres;
 	v->force=en_weight;
 	v->peer=NULL;
+	v->agc_enabled=FALSE;
+	v->buffer=ms_bufferizer_new();
+	v->sample_rate=8000;
+	v->nsamples=80;
+#ifdef HAVE_SPEEXDSP
+	v->speex_pp=NULL;
+#endif
 	f->data=v;
 }
 
 static void volume_uninit(MSFilter *f){
+	Volume *v=(Volume*)f->data;
+	ms_bufferizer_destroy(v->buffer);
 	ms_free(f->data);
 }
 
@@ -63,12 +87,29 @@ static int volume_get(MSFilter *f, void *arg){
 	return 0;
 }
 
+static int volume_set_sample_rate(MSFilter *f, void *arg){
+	Volume *v=(Volume*)f->data;
+	v->sample_rate=*(int*)arg;
+	return 0;
+}
+
 static int volume_get_linear(MSFilter *f, void *arg){
 	float *farg=(float*)arg;
 	Volume *v=(Volume*)f->data;
 	*farg=(v->energy+1)/max_e;
 	return 0;
 }
+#ifdef HAVE_SPEEXDSP
+static void volume_agc_process(Volume *v, mblk_t *om){
+	speex_preprocess_run(v->speex_pp,(int16_t*)om->b_rptr);
+}
+#else
+
+static void volume_agc_process(Volume *v, mblk_t *om){
+}
+
+#endif
+
 
 static inline float compute_gain(float static_gain, float energy, float weight){
 	float ret=static_gain*(1 - (energy*weight));
@@ -129,6 +170,12 @@ static int volume_set_peer(MSFilter *f, void *arg){
 	return 0;
 }
 
+static int volume_set_agc(MSFilter *f, void *arg){
+	Volume *v=(Volume*)f->data;
+	v->agc_enabled=*(int*)arg;
+	return 0;
+}
+
 static int volume_set_ea_threshold(MSFilter *f, void*arg){
 	Volume *v=(Volume*)f->data;
 	float val=*(float*)arg;
@@ -162,30 +209,88 @@ static inline int16_t saturate(float val){
 	return (val>32767) ? 32767 : ( (val<-32767) ? -32767 : val);
 }
 
+static float update_energy(int16_t *signal, int numsamples, float last_energy_value){
+	int i;
+	float en=last_energy_value;
+	for (i=0;i<numsamples;++i){
+		float s=(float)signal[i];
+		en=(s*s*coef) + (1.0-coef)*en;
+	}
+	return en;
+}
+
+static void apply_gain(mblk_t *m, float gain){
+	int16_t *sample;
+	for (	sample=(int16_t*)m->b_rptr;
+				sample<(int16_t*)m->b_wptr;
+				++sample){
+		float s=*sample;
+		*sample=saturate(s*gain);
+	}
+}
+
+static void volume_preprocess(MSFilter *f){
+	Volume *v=(Volume*)f->data;
+	/*process agc by chunks of 10 ms*/
+	v->nsamples=(int)(0.01*(float)v->sample_rate);
+	if (v->agc_enabled){
+		ms_message("AGC is enabled.");
+#ifdef HAVE_SPEEXDSP
+		if (v->speex_pp==NULL){
+			int tmp=1;
+			v->speex_pp=speex_preprocess_state_init(v->nsamples,v->sample_rate);
+			if (speex_preprocess_ctl(v->speex_pp,SPEEX_PREPROCESS_SET_AGC,&tmp)==-1){
+				ms_warning("Speex AGC is not available.");
+			}
+			tmp=0;
+			speex_preprocess_ctl(v->speex_pp,SPEEX_PREPROCESS_SET_VAD,&tmp);
+			speex_preprocess_ctl(v->speex_pp,SPEEX_PREPROCESS_SET_DENOISE,&tmp);
+			speex_preprocess_ctl(v->speex_pp,SPEEX_PREPROCESS_SET_DEREVERB,&tmp);
+		}
+#else
+		ms_error("No AGC possible, mediastreamer2 was compiled without libspeexdsp.");
+#endif
+	}
+}
+
+
+
 static void volume_process(MSFilter *f){
 	mblk_t *m;
-	int16_t *sample;
 	Volume *v=(Volume*)f->data;
 	float en=v->energy;
-	while((m=ms_queue_get(f->inputs[0]))!=NULL){
-		for (	sample=(int16_t*)m->b_rptr;
-			sample<(int16_t*)m->b_wptr;
-			++sample){
-			float s=*sample;
-			en=(s*s*coef) + (1.0-coef)*en;
-		}
-		if (v->peer){
-			volume_echo_avoider_process(v);	
+
+	if (v->agc_enabled){
+		mblk_t *om;
+		int nbytes=v->nsamples*2;
+		ms_bufferizer_put_from_queue(v->buffer,f->inputs[0]);
+		while(ms_bufferizer_get_avail(v->buffer)>=nbytes){
+			om=allocb(nbytes,0);
+			ms_bufferizer_read(v->buffer,om->b_wptr,nbytes);
+			om->b_wptr+=nbytes;
+			en=update_energy((int16_t*)om->b_rptr,om->b_wptr-om->b_rptr,en);
+			volume_agc_process(v,om);
+	
+			if (v->peer){
+				volume_echo_avoider_process(v);	
+			}
+			if (v->gain!=1){
+				apply_gain(om,v->gain);
+			}
+			ms_queue_put(f->outputs[0],om);
 		}
-		if (v->gain!=1){
-			for (	sample=(int16_t*)m->b_rptr;
-				sample<(int16_t*)m->b_wptr;
-				++sample){
-				float s=*sample;
-				*sample=saturate(s*v->gain);
+	}else{
+		/*light processing: no agc. Work in place in the input buffer*/
+		while((m=ms_queue_get(f->inputs[0]))!=NULL){
+			en=update_energy((int16_t*)m->b_rptr,m->b_wptr-m->b_rptr,en);
+			if (v->peer){
+				volume_echo_avoider_process(v);	
+			}
+			if (v->gain!=1){
+				apply_gain(m,v->gain);
 			}
+			ms_queue_put(f->outputs[0],m);
 		}
-		ms_queue_put(f->outputs[0],m);
 	}
 	v->energy=en;
 }
@@ -199,19 +304,22 @@ static MSFilterMethod methods[]={
 	{	MS_VOLUME_SET_EA_THRESHOLD , 	volume_set_ea_threshold	},
 	{	MS_VOLUME_SET_EA_SPEED	,	volume_set_ea_speed	},
 	{	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		},
 	{	0			,	NULL			}
 };
 
 #ifndef _MSC_VER
 MSFilterDesc ms_volume_desc={
 	.name="MSVolume",
-	.text=N_("A filter to make level measurements on 16 bits pcm audio stream"),
+	.text=N_("A filter that controls and measure sound volume"),
 	.id=MS_VOLUME_ID,
 	.category=MS_FILTER_OTHER,
 	.ninputs=1,
 	.noutputs=1,
 	.init=volume_init,
 	.uninit=volume_uninit,
+	.preprocess=volume_preprocess,
 	.process=volume_process,
 	.methods=methods
 };
@@ -219,7 +327,7 @@ MSFilterDesc ms_volume_desc={
 MSFilterDesc ms_volume_desc={
 	MS_VOLUME_ID,
 	"MSVolume",
-	N_("A filter to make level measurements on 16 bits pcm audio stream"),
+	N_("A filter that controls and measure sound volume"),
 	MS_FILTER_OTHER,
 	NULL,
 	1,
diff --git a/linphone/mediastreamer2/tests/mediastream.c b/linphone/mediastreamer2/tests/mediastream.c
index 4edd0e01a516d1a65b0b499153e3bc8c68a4b62c..065113fba52fdd4f9306a553754b73e39d8d62f9 100644
--- a/linphone/mediastreamer2/tests/mediastream.c
+++ b/linphone/mediastreamer2/tests/mediastream.c
@@ -122,8 +122,10 @@ const char *usage="mediastream --local <port> --remote <ip:port> --payload <payl
 								"[ --jitter <miliseconds>]\n"
 								"[ --width <pixels>]\n"
 								"[ --height <pixels> ]\n"
-								"[ --bitrate <bits per seconds>]\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);
+								"[ --bitrate <bits per seconds>]\n"
+								"[ --ec (enable echo canceller)]\n"
+								"[ --agc (enable automatic gain control)]\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);
 
 
 int main(int argc, char * argv[])
@@ -136,6 +138,7 @@ int main(int argc, char * argv[])
 	int bitrate=0;
 	MSVideoSize vs;
 	bool_t ec=FALSE;
+	bool_t agc=FALSE;
 	/*create the rtp session */
 	ortp_init();
 	ortp_set_log_level_mask(ORTP_MESSAGE|ORTP_WARNING|ORTP_ERROR|ORTP_FATAL);
@@ -188,14 +191,16 @@ int main(int argc, char * argv[])
 			vs.height=atoi(argv[i]);
 		}else if (strcmp(argv[i],"--ec")==0){
 			ec=TRUE;
+		}else if (strcmp(argv[i],"--agc")==0){
+			agc=TRUE;
 		}
 	}
 
-	run_media_streams(localport,ip,remoteport,payload,fmtp,jitter,ec,bitrate,vs);
+	run_media_streams(localport,ip,remoteport,payload,fmtp,jitter,ec,bitrate,vs, agc);
 	return 0;
 }
 
-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)
+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)
 {
 	AudioStream *audio=NULL;
 #ifdef VIDEO_ENABLED
@@ -218,7 +223,13 @@ void run_media_streams(int localport,  const char *remote_ip, int remoteport, in
 
 	if (pt->type!=PAYLOAD_VIDEO){
 		printf("Starting audio stream.\n");
-		audio=audio_stream_start(profile,localport,remote_ip,remoteport,payload,jitter, ec);
+		MSSndCardManager *manager=ms_snd_card_manager_get();
+		audio=audio_stream_new(localport,ms_is_ipv6(remote_ip));
+		audio_stream_enable_automatic_gain_control(audio,agc);
+		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),
+			 ec);
 		if (audio) session=audio->session;
 	}else{
 #ifdef VIDEO_ENABLED