diff --git a/engine/client/cl_parse.c b/engine/client/cl_parse.c
index 296a5cc43..19bb9a988 100644
--- a/engine/client/cl_parse.c
+++ b/engine/client/cl_parse.c
@@ -2256,6 +2256,10 @@ void CL_ParseServerData (void)
 
 	cl.sendprespawn = false;
 
+#ifdef VOICECHAT
+	S_Voip_MapChange();
+#endif
+
 #ifdef VM_CG
 	CG_Stop();
 #endif
diff --git a/engine/client/snd_directx.c b/engine/client/snd_directx.c
index 93fb38c54..734b0cd11 100644
--- a/engine/client/snd_directx.c
+++ b/engine/client/snd_directx.c
@@ -905,6 +905,7 @@ static WAVEFORMATEX  wfxFormat;
 
 qboolean SNDDMA_InitCapture (void)
 {
+	DWORD capturePos;
 	DSCBUFFERDESC bufdesc;
 
 	wfxFormat.wFormatTag = WAVE_FORMAT_PCM;
@@ -970,7 +971,7 @@ qboolean SNDDMA_InitCapture (void)
 	IDirectSoundCaptureBuffer_Start(DSCaptureBuffer, DSBPLAY_LOOPING);
 
 	lastreadpos = 0;
-
+	IDirectSoundCaptureBuffer_GetCurrentPosition(DSCaptureBuffer, &capturePos, &lastreadpos);
 	return true;
 }
 
diff --git a/engine/client/snd_dma.c b/engine/client/snd_dma.c
index d32fe040c..1d3e7db3e 100644
--- a/engine/client/snd_dma.c
+++ b/engine/client/snd_dma.c
@@ -106,8 +106,9 @@ cvar_t snd_usemultipledevices	= CVARAF(	"s_multipledevices", "0",
 											"snd_multipledevices", 0);
 
 #ifdef VOICECHAT
+static void S_Voip_Play_Callback(cvar_t *var, char *oldval);
 cvar_t cl_voip_send = CVAR("cl_voip_send", "0");
-cvar_t cl_voip_play = CVAR("cl_voip_play", "1");
+cvar_t cl_voip_play = CVARC("cl_voip_play", "1", S_Voip_Play_Callback);
 cvar_t cl_voip_micamp = CVAR("cl_voip_micamp", "2");
 #endif
 
@@ -159,7 +160,7 @@ void S_SoundInfo_f(void)
 #ifdef VOICECHAT
 #include "speex/speex.h"
 #include "speex/speex_preprocess.h"
-struct
+static struct
 {
 	qboolean inited;
 	qboolean loaded;
@@ -175,26 +176,27 @@ struct
 	SpeexBits decbits[MAX_CLIENTS];
 	void *decoder[MAX_CLIENTS];
 	unsigned char decseq[MAX_CLIENTS];
+	float decamp[MAX_CLIENTS];
 } s_speex;
 
-const SpeexMode *(VARGS *qspeex_lib_get_mode)(int mode);
-void (VARGS *qspeex_bits_init)(SpeexBits *bits);
-void (VARGS *qspeex_bits_reset)(SpeexBits *bits);
-int (VARGS *qspeex_bits_write)(SpeexBits *bits, char *bytes, int max_len);
+static const SpeexMode *(VARGS *qspeex_lib_get_mode)(int mode);
+static void (VARGS *qspeex_bits_init)(SpeexBits *bits);
+static void (VARGS *qspeex_bits_reset)(SpeexBits *bits);
+static int (VARGS *qspeex_bits_write)(SpeexBits *bits, char *bytes, int max_len);
 
-SpeexPreprocessState *(VARGS *qspeex_preprocess_state_init)(int frame_size, int sampling_rate);
-int (VARGS *qspeex_preprocess_ctl)(SpeexPreprocessState *st, int request, void *ptr);
-int (VARGS *qspeex_preprocess_run)(SpeexPreprocessState *st, spx_int16_t *x);
+static SpeexPreprocessState *(VARGS *qspeex_preprocess_state_init)(int frame_size, int sampling_rate);
+static int (VARGS *qspeex_preprocess_ctl)(SpeexPreprocessState *st, int request, void *ptr);
+static int (VARGS *qspeex_preprocess_run)(SpeexPreprocessState *st, spx_int16_t *x);
 
-void * (VARGS *qspeex_encoder_init)(const SpeexMode *mode);
-int (VARGS *qspeex_encoder_ctl)(void *state, int request, void *ptr);
-int (VARGS *qspeex_encode_int)(void *state, spx_int16_t *in, SpeexBits *bits);
+static void * (VARGS *qspeex_encoder_init)(const SpeexMode *mode);
+static int (VARGS *qspeex_encoder_ctl)(void *state, int request, void *ptr);
+static int (VARGS *qspeex_encode_int)(void *state, spx_int16_t *in, SpeexBits *bits);
 
-void *(VARGS *qspeex_decoder_init)(const SpeexMode *mode);
-int (VARGS *qspeex_decode_int)(void *state, SpeexBits *bits, spx_int16_t *out);
-void (VARGS *qspeex_bits_read_from)(SpeexBits *bits, char *bytes, int len);
+static void *(VARGS *qspeex_decoder_init)(const SpeexMode *mode);
+static int (VARGS *qspeex_decode_int)(void *state, SpeexBits *bits, spx_int16_t *out);
+static void (VARGS *qspeex_bits_read_from)(SpeexBits *bits, char *bytes, int len);
 
-dllfunction_t qspeexfuncs[] =
+static dllfunction_t qspeexfuncs[] =
 {
 	{(void*)&qspeex_lib_get_mode, "speex_lib_get_mode"},
 	{(void*)&qspeex_bits_init, "speex_bits_init"},
@@ -211,7 +213,7 @@ dllfunction_t qspeexfuncs[] =
 
 	{NULL}
 };
-dllfunction_t qspeexdspfuncs[] =
+static dllfunction_t qspeexdspfuncs[] =
 {
 	{(void*)&qspeex_preprocess_state_init, "speex_preprocess_state_init"},
 	{(void*)&qspeex_preprocess_ctl, "speex_preprocess_ctl"},
@@ -220,7 +222,7 @@ dllfunction_t qspeexdspfuncs[] =
 	{NULL}
 };
 
-qboolean S_Speex_Init(void)
+static qboolean S_Speex_Init(void)
 {
 	int i;
 	const SpeexMode *mode;
@@ -266,6 +268,7 @@ qboolean S_Speex_Init(void)
 		qspeex_bits_init(&s_speex.decbits[i]);
 		qspeex_bits_reset(&s_speex.decbits[i]);
 		s_speex.decoder[i] = qspeex_decoder_init(mode);
+		s_speex.decamp[i] = 1;
 	}
 	s_speex.loaded = true;
 	return s_speex.loaded;
@@ -279,6 +282,8 @@ void S_ParseVoiceChat(void)
 	short decodebuf[1024];
 	unsigned int decodesamps, len, newseq, drops;
 	unsigned char seq;
+	float amp = 1;
+	unsigned int i;
 	seq = MSG_ReadByte();
 	bytes = MSG_ReadShort();
 	if (bytes > sizeof(data) || !cl_voip_play.ival)
@@ -290,6 +295,8 @@ void S_ParseVoiceChat(void)
 
 	sender &= MAX_CLIENTS-1;
 
+	amp = s_speex.decamp[sender];
+
 	decodesamps = 0;
 	newseq = 0;
 	drops = 0;
@@ -318,6 +325,11 @@ void S_ParseVoiceChat(void)
 			qspeex_decode_int(s_speex.decoder[sender], &s_speex.decbits[sender], decodebuf + decodesamps);
 			newseq++;
 		}
+		if (amp != 1)
+		{
+			for (i = decodesamps; i < decodesamps+s_speex.framesize; i++)
+				decodebuf[i] *= amp;
+		}
 		decodesamps += s_speex.framesize;
 	}
 	s_speex.decseq[sender] += newseq;
@@ -346,13 +358,19 @@ void S_TransmitVoiceChat(unsigned char clc, sizebuf_t *buf)
 	//add new drivers in order or desirability.
 	if (pDSOUND_UpdateCapture)
 	{
-		capturepos += pDSOUND_UpdateCapture(cl_voip_send.ival, (unsigned char*)capturebuf + capturepos, 64, sizeof(capturebuf) - capturepos);
+		capturepos += pDSOUND_UpdateCapture(1, (unsigned char*)capturebuf + capturepos, 64, sizeof(capturebuf) - capturepos);
 	}
 	else
 	{
 		return;
 	}
 
+	if (!cl_voip_send.ival)
+	{
+		capturepos = 0;
+		return;
+	}
+
 	if (!S_Speex_Init())
 		return;
 
@@ -392,14 +410,31 @@ void S_TransmitVoiceChat(unsigned char clc, sizebuf_t *buf)
 	capturepos -= encpos;
 }
 
-void S_Voip_Enable_f(void)
+static void S_Voip_Enable_f(void)
 {
 	Cvar_Set(&cl_voip_send, "1");
 }
-void S_Voip_Disable_f(void)
+static void S_Voip_Disable_f(void)
 {
 	Cvar_Set(&cl_voip_send, "0");
 }
+static void S_Voip_f(void)
+{
+}
+static void S_Voip_Play_Callback(cvar_t *var, char *oldval)
+{
+	if (cls.fteprotocolextensions2 & PEXT2_VOICECHAT)
+	{
+		if (var->ival)
+			CL_SendClientCommand(true, "unmuteall");
+		else
+			CL_SendClientCommand(true, "muteall");
+	}
+}
+void S_Voip_MapChange(void)
+{
+	Cvar_ForceCallback(&cl_voip_play);
+}
 #endif
 
 
diff --git a/engine/client/sound.h b/engine/client/sound.h
index 4a6bc13ac..07f4a7012 100644
--- a/engine/client/sound.h
+++ b/engine/client/sound.h
@@ -150,6 +150,7 @@ void S_ResetFailedLoad(void);
 #ifdef VOICECHAT
 void S_ParseVoiceChat(void);
 void S_TransmitVoiceChat(unsigned char clc, sizebuf_t *buf);
+void S_Voip_MapChange(void);
 #endif
 
 qboolean S_IsPlayingSomewhere(sfx_t *s);
diff --git a/engine/server/sv_user.c b/engine/server/sv_user.c
index 7b0429b09..6e281ecbc 100644
--- a/engine/server/sv_user.c
+++ b/engine/server/sv_user.c
@@ -44,17 +44,17 @@ cvar_t	sv_spectalk	= SCVAR("sv_spectalk", "1");
 
 cvar_t	sv_mapcheck	= SCVAR("sv_mapcheck", "1");
 
-cvar_t	sv_antilag			= SCVARF("sv_antilag", "0", CVAR_SERVERINFO);
-cvar_t	sv_antilag_frac		= SCVARF("sv_antilag_frac", "1", CVAR_SERVERINFO);
-cvar_t	sv_cheatpc				= SCVAR("sv_cheatpc", "125");
-cvar_t	sv_cheatspeedchecktime	= SCVAR("sv_cheatspeedchecktime", "30");
-cvar_t	sv_playermodelchecks	= SCVAR("sv_playermodelchecks", "1");
+cvar_t	sv_antilag			= CVARFD("sv_antilag", "0", CVAR_SERVERINFO, "Attempt to backdate impacts to compensate for lag.");
+cvar_t	sv_antilag_frac		= CVARF("sv_antilag_frac", "1", CVAR_SERVERINFO);
+cvar_t	sv_cheatpc				= CVAR("sv_cheatpc", "125");
+cvar_t	sv_cheatspeedchecktime	= CVAR("sv_cheatspeedchecktime", "30");
+cvar_t	sv_playermodelchecks	= CVAR("sv_playermodelchecks", "1");
 
 cvar_t	sv_cmdlikercon	= SCVAR("sv_cmdlikercon", "0");	//set to 1 to allow a password of username:password instead of the correct rcon password.
 cvar_t cmd_allowaccess	= SCVAR("cmd_allowaccess", "0");	//set to 1 to allow cmd to execute console commands on the server.
 cvar_t cmd_gamecodelevel	= SCVAR("cmd_gamecodelevel", "50");	//execution level which gamecode is told about (for unrecognised commands)
 
-cvar_t	sv_nomsec	= SCVAR("sv_nomsec", "0");
+cvar_t	sv_nomsec	= CVARD("sv_nomsec", "0", "Ignore client msec times, runs using NQ physics instead.");
 cvar_t	sv_edgefriction	= CVARAF("sv_edgefriction", "2",
 								 "edgefriction", 0);
 
@@ -88,14 +88,15 @@ extern cvar_t	pm_walljump;
 cvar_t sv_pushplayers = SCVAR("sv_pushplayers", "0");
 
 //yes, realip cvars need to be fully initialised or realip will be disabled
-cvar_t sv_getrealip = SCVAR("sv_getrealip", "0");
+cvar_t sv_getrealip = CVARD("sv_getrealip", "0", "Attempt to obtain a more reliable IP for clients, rather than just their proxy.");
 cvar_t sv_realip_kick = SCVAR("sv_realip_kick", "0");
 cvar_t sv_realiphostname_ipv4 = SCVAR("sv_realiphostname_ipv4", "");
 cvar_t sv_realiphostname_ipv6 = SCVAR("sv_realiphostname_ipv6", "");
 cvar_t sv_realip_timeout = SCVAR("sv_realip_timeout", "10");
 
 #ifdef VOICECHAT
-cvar_t sv_voip = CVAR("sv_voip", "1");
+cvar_t sv_voip = CVARD("sv_voip", "1", "Enable reception of voice packets.");
+cvar_t sv_voip_echo = CVARD("sv_voip_echo", "0", "Echo voice packets back to their sender, a debug/test setting.");
 #endif
 
 char sv_votinggroup[] = "server voting";
@@ -2134,8 +2135,8 @@ void SV_VoiceReadPacket(void)
 		ring->receiver[j] = 0;
 	for (j = 0, cl = svs.clients; j < sv.allocated_client_slots; j++, cl++)
 	{
-//		if (cl == host_client)
-//			continue;
+		if (cl == host_client && !sv_voip_echo.ival)
+			continue;
 
 		if (cl->state != cs_spawned && cl->state != cs_connected)
 			continue;
@@ -2208,16 +2209,17 @@ void SV_VoiceSendPacket(client_t *client, sizebuf_t *buf)
 		if (client->download)
 			send = false;
 
-		client->voice_read++;
-
 		if (send)
 		{
+			if (buf->maxsize - buf->cursize < ring->datalen+5)
+				break;
 			MSG_WriteByte(buf, svcfte_voicechat);
 			MSG_WriteByte(buf, ring->sender);
 			MSG_WriteByte(buf, ring->seq);
 			MSG_WriteShort(buf, ring->datalen);
 			SZ_Write(buf, ring->data, ring->datalen);
 		}
+		client->voice_read++;
 	}
 }
 
@@ -6364,6 +6366,7 @@ void SV_UserInit (void)
 {
 #ifdef VOICECHAT
 	Cvar_Register (&sv_voip, cvargroup_serverpermissions);
+	Cvar_Register (&sv_voip_echo, cvargroup_serverpermissions);
 #endif
 #ifdef SERVERONLY
 	Cvar_Register (&cl_rollspeed, "Prediction stuff");