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");