[quake3-commits] r2102 - in trunk: . code/client code/qcommon code/server
DONOTREPLY at icculus.org
DONOTREPLY at icculus.org
Wed Jul 27 11:47:30 EDT 2011
Author: thilo
Date: 2011-07-27 11:47:29 -0400 (Wed, 27 Jul 2011)
New Revision: 2102
Modified:
trunk/code/client/cl_cgame.c
trunk/code/client/cl_cin.c
trunk/code/client/cl_input.c
trunk/code/client/cl_main.c
trunk/code/client/cl_parse.c
trunk/code/client/client.h
trunk/code/client/snd_dma.c
trunk/code/client/snd_local.h
trunk/code/client/snd_main.c
trunk/code/client/snd_openal.c
trunk/code/client/snd_public.h
trunk/code/qcommon/common.c
trunk/code/qcommon/q_shared.h
trunk/code/qcommon/qcommon.h
trunk/code/server/server.h
trunk/code/server/sv_client.c
trunk/code/server/sv_init.c
trunk/code/server/sv_snapshot.c
trunk/voip-readme.txt
Log:
- Apply parts of Ben Millwood's target bitfield patch (#3787)
- Fix Ryan's FIXME and have voip packet buffer on the server dynamically allocated via Z_Malloc and store pointers in a circular buffer
- Improve voip target parsing on top of Ben Millwood's patch
- Add new "spatial" target where speaker is spatialized in 3d space and can be heard by all clients in hearing range (s_alMaxDistance)
(#4467)
- Decrease voip sound lengths from 240ms to 80ms per voip packet to mitigate udp packet loss and decrease latency
- Protocol version incremented to 71
Modified: trunk/code/client/cl_cgame.c
===================================================================
--- trunk/code/client/cl_cgame.c 2011-07-27 00:04:29 UTC (rev 2101)
+++ trunk/code/client/cl_cgame.c 2011-07-27 15:47:29 UTC (rev 2102)
@@ -952,8 +952,8 @@
clc.speexInitialized = qtrue;
clc.voipMuteAll = qfalse;
Cmd_AddCommand ("voip", CL_Voip_f);
- Cvar_Set("cl_voipSendTarget", "all");
- clc.voipTarget1 = clc.voipTarget2 = clc.voipTarget3 = 0x7FFFFFFF;
+ Cvar_Set("cl_voipSendTarget", "spatial");
+ Com_Memset(clc.voipTargets, ~0, sizeof(clc.voipTargets));
}
#endif
}
Modified: trunk/code/client/cl_cin.c
===================================================================
--- trunk/code/client/cl_cin.c 2011-07-27 00:04:29 UTC (rev 2101)
+++ trunk/code/client/cl_cin.c 2011-07-27 15:47:29 UTC (rev 2102)
@@ -1147,7 +1147,7 @@
case ZA_SOUND_MONO:
if (!cinTable[currentHandle].silent) {
ssize = RllDecodeMonoToStereo( framedata, sbuf, cinTable[currentHandle].RoQFrameSize, 0, (unsigned short)cinTable[currentHandle].roq_flags);
- S_RawSamples( 0, ssize, 22050, 2, 1, (byte *)sbuf, 1.0f );
+ S_RawSamples(0, ssize, 22050, 2, 1, (byte *)sbuf, 1.0f, -1);
}
break;
case ZA_SOUND_STEREO:
@@ -1157,7 +1157,7 @@
s_rawend[0] = s_soundtime;
}
ssize = RllDecodeStereoToStereo( framedata, sbuf, cinTable[currentHandle].RoQFrameSize, 0, (unsigned short)cinTable[currentHandle].roq_flags);
- S_RawSamples( 0, ssize, 22050, 2, 2, (byte *)sbuf, 1.0f );
+ S_RawSamples(0, ssize, 22050, 2, 2, (byte *)sbuf, 1.0f, -1);
}
break;
case ROQ_QUAD_INFO:
Modified: trunk/code/client/cl_input.c
===================================================================
--- trunk/code/client/cl_input.c 2011-07-27 00:04:29 UTC (rev 2101)
+++ trunk/code/client/cl_input.c 2011-07-27 15:47:29 UTC (rev 2102)
@@ -799,83 +799,53 @@
}
#ifdef USE_VOIP
- if (clc.voipOutgoingDataSize > 0) { // only send if data.
- // Move cl_voipSendTarget from a string to the bitmasks if needed.
- if (cl_voipSendTarget->modified) {
- char buffer[32];
- const char *target = cl_voipSendTarget->string;
+ if (clc.voipOutgoingDataSize > 0)
+ {
+ if((clc.voipFlags & VOIP_SPATIAL) || Com_IsVoipTarget(clc.voipTargets, sizeof(clc.voipTargets), -1))
+ {
+ MSG_WriteByte (&buf, clc_voip);
+ MSG_WriteByte (&buf, clc.voipOutgoingGeneration);
+ MSG_WriteLong (&buf, clc.voipOutgoingSequence);
+ MSG_WriteByte (&buf, clc.voipOutgoingDataFrames);
+ MSG_WriteData (&buf, clc.voipTargets, sizeof(clc.voipTargets));
+ MSG_WriteByte(&buf, clc.voipFlags);
+ MSG_WriteShort (&buf, clc.voipOutgoingDataSize);
+ MSG_WriteData (&buf, clc.voipOutgoingData, clc.voipOutgoingDataSize);
- if (Q_stricmp(target, "attacker") == 0) {
- int player = VM_Call( cgvm, CG_LAST_ATTACKER );
- Com_sprintf(buffer, sizeof (buffer), "%d", player);
- target = buffer;
- } else if (Q_stricmp(target, "crosshair") == 0) {
- int player = VM_Call( cgvm, CG_CROSSHAIR_PLAYER );
- Com_sprintf(buffer, sizeof (buffer), "%d", player);
- target = buffer;
+ // If we're recording a demo, we have to fake a server packet with
+ // this VoIP data so it gets to disk; the server doesn't send it
+ // back to us, and we might as well eliminate concerns about dropped
+ // and misordered packets here.
+ if(clc.demorecording && !clc.demowaiting)
+ {
+ const int voipSize = clc.voipOutgoingDataSize;
+ msg_t fakemsg;
+ byte fakedata[MAX_MSGLEN];
+ MSG_Init (&fakemsg, fakedata, sizeof (fakedata));
+ MSG_Bitstream (&fakemsg);
+ MSG_WriteLong (&fakemsg, clc.reliableAcknowledge);
+ MSG_WriteByte (&fakemsg, svc_voip);
+ MSG_WriteShort (&fakemsg, clc.clientNum);
+ MSG_WriteByte (&fakemsg, clc.voipOutgoingGeneration);
+ MSG_WriteLong (&fakemsg, clc.voipOutgoingSequence);
+ MSG_WriteByte (&fakemsg, clc.voipOutgoingDataFrames);
+ MSG_WriteShort (&fakemsg, clc.voipOutgoingDataSize );
+ MSG_WriteData (&fakemsg, clc.voipOutgoingData, voipSize);
+ MSG_WriteByte (&fakemsg, svc_EOF);
+ CL_WriteDemoMessage (&fakemsg, 0);
}
- if ((*target == '\0') || (Q_stricmp(target, "all") == 0)) {
- const int all = 0x7FFFFFFF;
- clc.voipTarget1 = clc.voipTarget2 = clc.voipTarget3 = all;
- } else if (Q_stricmp(target, "none") == 0) {
- clc.voipTarget1 = clc.voipTarget2 = clc.voipTarget3 = 0;
- } else {
- const char *ptr = target;
- clc.voipTarget1 = clc.voipTarget2 = clc.voipTarget3 = 0;
- do {
- if ((*ptr == ',') || (*ptr == '\0')) {
- const int val = atoi(target);
- target = ptr + 1;
- if ((val >= 0) && (val < 31)) {
- clc.voipTarget1 |= (1 << (val-0));
- } else if ((val >= 31) && (val < 62)) {
- clc.voipTarget2 |= (1 << (val-31));
- } else if ((val >= 62) && (val < 93)) {
- clc.voipTarget3 |= (1 << (val-62));
- }
- }
- } while (*(ptr++));
- }
- cl_voipSendTarget->modified = qfalse;
+ clc.voipOutgoingSequence += clc.voipOutgoingDataFrames;
+ clc.voipOutgoingDataSize = 0;
+ clc.voipOutgoingDataFrames = 0;
}
-
- MSG_WriteByte (&buf, clc_voip);
- MSG_WriteByte (&buf, clc.voipOutgoingGeneration);
- MSG_WriteLong (&buf, clc.voipOutgoingSequence);
- MSG_WriteByte (&buf, clc.voipOutgoingDataFrames);
- MSG_WriteLong (&buf, clc.voipTarget1);
- MSG_WriteLong (&buf, clc.voipTarget2);
- MSG_WriteLong (&buf, clc.voipTarget3);
- MSG_WriteShort (&buf, clc.voipOutgoingDataSize);
- MSG_WriteData (&buf, clc.voipOutgoingData, clc.voipOutgoingDataSize);
-
- // If we're recording a demo, we have to fake a server packet with
- // this VoIP data so it gets to disk; the server doesn't send it
- // back to us, and we might as well eliminate concerns about dropped
- // and misordered packets here.
- if ( clc.demorecording && !clc.demowaiting ) {
- const int voipSize = clc.voipOutgoingDataSize;
- msg_t fakemsg;
- byte fakedata[MAX_MSGLEN];
- MSG_Init (&fakemsg, fakedata, sizeof (fakedata));
- MSG_Bitstream (&fakemsg);
- MSG_WriteLong (&fakemsg, clc.reliableAcknowledge);
- MSG_WriteByte (&fakemsg, svc_voip);
- MSG_WriteShort (&fakemsg, clc.clientNum);
- MSG_WriteByte (&fakemsg, clc.voipOutgoingGeneration);
- MSG_WriteLong (&fakemsg, clc.voipOutgoingSequence);
- MSG_WriteByte (&fakemsg, clc.voipOutgoingDataFrames);
- MSG_WriteShort (&fakemsg, clc.voipOutgoingDataSize );
- MSG_WriteData (&fakemsg, clc.voipOutgoingData, voipSize);
- MSG_WriteByte (&fakemsg, svc_EOF);
- CL_WriteDemoMessage (&fakemsg, 0);
+ else
+ {
+ // We have data, but no targets. Silently discard all data
+ clc.voipOutgoingDataSize = 0;
+ clc.voipOutgoingDataFrames = 0;
}
-
- clc.voipOutgoingSequence += clc.voipOutgoingDataFrames;
- clc.voipOutgoingDataSize = 0;
- clc.voipOutgoingDataFrames = 0;
- } else
+ }
#endif
if ( count >= 1 ) {
Modified: trunk/code/client/cl_main.c
===================================================================
--- trunk/code/client/cl_main.c 2011-07-27 00:04:29 UTC (rev 2101)
+++ trunk/code/client/cl_main.c 2011-07-27 15:47:29 UTC (rev 2102)
@@ -293,6 +293,88 @@
/*
===============
+CL_VoipParseTargets
+
+sets clc.voipTargets according to cl_voipSendTarget
+Generally we don't want who's listening to change during a transmission,
+so this is only called when the key is first pressed
+===============
+*/
+void CL_VoipParseTargets(void)
+{
+ const char *target = cl_voipSendTarget->string;
+ char *end;
+ int val;
+
+ Com_Memset(clc.voipTargets, 0, sizeof(clc.voipTargets));
+ clc.voipFlags &= ~VOIP_SPATIAL;
+
+ while(target)
+ {
+ while(*target == ',' || *target == ' ')
+ target++;
+
+ if(!*target)
+ break;
+
+ if(isdigit(*target))
+ {
+ val = strtol(target, &end, 10);
+ target = end;
+ }
+ else
+ {
+ if(!Q_stricmpn(target, "all", 3))
+ {
+ Com_Memset(clc.voipTargets, ~0, sizeof(clc.voipTargets));
+ return;
+ }
+ if(!Q_stricmpn(target, "spatial", 7))
+ {
+ clc.voipFlags |= VOIP_SPATIAL;
+ target += 7;
+ continue;
+ }
+ else
+ {
+ if(!Q_stricmpn(target, "attacker", 8))
+ {
+ val = VM_Call(cgvm, CG_LAST_ATTACKER);
+ target += 8;
+ }
+ else if(!Q_stricmpn(target, "crosshair", 9))
+ {
+ val = VM_Call(cgvm, CG_CROSSHAIR_PLAYER);
+ target += 9;
+ }
+ else
+ {
+ while(*target && *target != ',' && *target != ' ')
+ target++;
+
+ continue;
+ }
+
+ if(val < 0)
+ continue;
+ }
+ }
+
+ if(val < 0 || val >= MAX_CLIENTS)
+ {
+ Com_Printf(S_COLOR_YELLOW "WARNING: VoIP "
+ "target %d is not a valid client "
+ "number\n", val);
+
+ continue;
+ }
+
+ clc.voipTargets[val / 8] |= 1 << (val % 8);
+ }
+}
+
+/*
+===============
CL_CaptureVoip
Record more audio from the hardware if required and encode it into Speex
@@ -342,8 +424,9 @@
cl_voipSend->modified = qfalse;
- if (dontCapture) {
- cl_voipSend->integer = 0;
+ if(dontCapture)
+ {
+ Cvar_Set("cl_voipSend", "0");
return;
}
@@ -362,11 +445,12 @@
S_MasterGain(cl_voipGainDuringCapture->value);
S_StartCapture();
CL_VoipNewGeneration();
+ CL_VoipParseTargets();
}
if ((cl_voipSend->integer) || (finalFrame)) { // user wants to capture audio?
int samples = S_AvailableCaptureSamples();
- const int mult = (finalFrame) ? 1 : 12; // 12 == 240ms of audio.
+ const int mult = (finalFrame) ? 1 : 4; // 4 == 80ms of audio.
// enough data buffered in audio hardware to process yet?
if (samples >= (clc.speexFrameSize * mult)) {
@@ -378,8 +462,8 @@
int wpos = 0;
int pos = 0;
- if (samples > (clc.speexFrameSize * 12))
- samples = (clc.speexFrameSize * 12);
+ if (samples > (clc.speexFrameSize * 4))
+ samples = (clc.speexFrameSize * 4);
// !!! FIXME: maybe separate recording from encoding, so voipPower
// !!! FIXME: updates faster than 4Hz?
@@ -3420,7 +3504,7 @@
#ifdef USE_VOIP
cl_voipSend = Cvar_Get ("cl_voipSend", "0", 0);
- cl_voipSendTarget = Cvar_Get ("cl_voipSendTarget", "all", 0);
+ cl_voipSendTarget = Cvar_Get ("cl_voipSendTarget", "spatial", 0);
cl_voipGainDuringCapture = Cvar_Get ("cl_voipGainDuringCapture", "0.2", CVAR_ARCHIVE);
cl_voipCaptureMult = Cvar_Get ("cl_voipCaptureMult", "2.0", CVAR_ARCHIVE);
cl_voipUseVAD = Cvar_Get ("cl_voipUseVAD", "0", CVAR_ARCHIVE);
Modified: trunk/code/client/cl_parse.c
===================================================================
--- trunk/code/client/cl_parse.c 2011-07-27 00:04:29 UTC (rev 2101)
+++ trunk/code/client/cl_parse.c 2011-07-27 15:47:29 UTC (rev 2102)
@@ -665,6 +665,29 @@
/*
=====================
+CL_PlayVoip
+
+Play raw data
+=====================
+*/
+
+static void CL_PlayVoip(int sender, int samplecnt, const byte *data, int flags)
+{
+ if(flags & VOIP_DIRECT)
+ {
+ S_RawSamples(sender + 1, samplecnt, clc.speexSampleRate, 2, 1,
+ data, clc.voipGain[sender], -1);
+ }
+
+ if(flags & VOIP_SPATIAL)
+ {
+ S_RawSamples(sender + MAX_CLIENTS + 1, samplecnt, clc.speexSampleRate, 2, 1,
+ data, 1.0f, sender);
+ }
+}
+
+/*
+=====================
CL_ParseVoip
A VoIP message has been received from the server
@@ -679,6 +702,7 @@
const int sequence = MSG_ReadLong(msg);
const int frames = MSG_ReadByte(msg);
const int packetsize = MSG_ReadShort(msg);
+ const int flags = MSG_ReadBits(msg, VOIP_FLAGCNT);
char encoded[1024];
int seqdiff = sequence - clc.voipIncomingSequence[sender];
int written = 0;
@@ -769,8 +793,8 @@
if ((written + clc.speexFrameSize) * 2 > sizeof (decoded)) {
Com_DPrintf("VoIP: playback %d bytes, %d samples, %d frames\n",
written * 2, written, i);
- S_RawSamples(sender + 1, written, clc.speexSampleRate, 2, 1,
- (const byte *) decoded, clc.voipGain[sender]);
+
+ CL_PlayVoip(sender, written, (const byte *) decoded, flags);
written = 0;
}
@@ -793,10 +817,8 @@
Com_DPrintf("VoIP: playback %d bytes, %d samples, %d frames\n",
written * 2, written, i);
- if (written > 0) {
- S_RawSamples(sender + 1, written, clc.speexSampleRate, 2, 1,
- (const byte *) decoded, clc.voipGain[sender]);
- }
+ if(written > 0)
+ CL_PlayVoip(sender, written, (const byte *) decoded, flags);
clc.voipIncomingSequence[sender] = sequence + frames;
}
Modified: trunk/code/client/client.h
===================================================================
--- trunk/code/client/client.h 2011-07-27 00:04:29 UTC (rev 2101)
+++ trunk/code/client/client.h 2011-07-27 15:47:29 UTC (rev 2102)
@@ -250,9 +250,10 @@
qboolean voipMuteAll;
// outgoing data...
- int voipTarget1; // these three ints make up a bit mask of 92 bits.
- int voipTarget2; // the bits say who a VoIP pack is addressed to:
- int voipTarget3; // (1 << clientnum). See cl_voipSendTarget cvar.
+ // if voipTargets[i / 8] & (1 << (i % 8)),
+ // then we are sending to clientnum i.
+ uint8_t voipTargets[(MAX_CLIENTS + 7) / 8];
+ uint8_t voipFlags;
SpeexPreprocessState *speexPreprocessor;
SpeexBits speexEncoderBits;
void *speexEncoder;
Modified: trunk/code/client/snd_dma.c
===================================================================
--- trunk/code/client/snd_dma.c 2011-07-27 00:04:29 UTC (rev 2101)
+++ trunk/code/client/snd_dma.c 2011-07-27 15:47:29 UTC (rev 2102)
@@ -916,7 +916,8 @@
Music streaming
============
*/
-void S_Base_RawSamples( int stream, int samples, int rate, int width, int s_channels, const byte *data, float volume ) {
+void S_Base_RawSamples( int stream, int samples, int rate, int width, int s_channels, const byte *data, float volume, int entityNum)
+{
int i;
int src, dst;
float scale;
@@ -927,9 +928,16 @@
return;
}
+ if(entityNum >= 0)
+ {
+ // FIXME: support spatialized raw streams, e.g. for VoIP
+ return;
+ }
+
if ( (stream < 0) || (stream >= MAX_RAW_STREAMS) ) {
return;
}
+
rawsamples = s_rawsamples[stream];
if(s_muted->integer)
@@ -1395,8 +1403,8 @@
if(r > 0)
{
// add to raw buffer
- S_Base_RawSamples( 0, fileSamples, s_backgroundStream->info.rate,
- s_backgroundStream->info.width, s_backgroundStream->info.channels, raw, s_musicVolume->value );
+ S_Base_RawSamples(0, fileSamples, s_backgroundStream->info.rate,
+ s_backgroundStream->info.width, s_backgroundStream->info.channels, raw, s_musicVolume->value, -1);
}
else
{
Modified: trunk/code/client/snd_local.h
===================================================================
--- trunk/code/client/snd_local.h 2011-07-27 00:04:29 UTC (rev 2101)
+++ trunk/code/client/snd_local.h 2011-07-27 15:47:29 UTC (rev 2102)
@@ -125,7 +125,7 @@
void (*StartLocalSound)( sfxHandle_t sfx, int channelNum );
void (*StartBackgroundTrack)( const char *intro, const char *loop );
void (*StopBackgroundTrack)( void );
- void (*RawSamples)(int stream, int samples, int rate, int width, int channels, const byte *data, float volume);
+ void (*RawSamples)(int stream, int samples, int rate, int width, int channels, const byte *data, float volume, int entityNum);
void (*StopAllSounds)( void );
void (*ClearLoopingSounds)( qboolean killall );
void (*AddLoopingSound)( int entityNum, const vec3_t origin, const vec3_t velocity, sfxHandle_t sfx );
@@ -186,7 +186,7 @@
extern dma_t dma;
#define MAX_RAW_SAMPLES 16384
-#define MAX_RAW_STREAMS 128
+#define MAX_RAW_STREAMS (MAX_CLIENTS * 2 + 1)
extern portable_samplepair_t s_rawsamples[MAX_RAW_STREAMS][MAX_RAW_SAMPLES];
extern int s_rawend[MAX_RAW_STREAMS];
Modified: trunk/code/client/snd_main.c
===================================================================
--- trunk/code/client/snd_main.c 2011-07-27 00:04:29 UTC (rev 2101)
+++ trunk/code/client/snd_main.c 2011-07-27 15:47:29 UTC (rev 2102)
@@ -129,11 +129,10 @@
=================
*/
void S_RawSamples (int stream, int samples, int rate, int width, int channels,
- const byte *data, float volume)
+ const byte *data, float volume, int entityNum)
{
- if( si.RawSamples ) {
- si.RawSamples( stream, samples, rate, width, channels, data, volume );
- }
+ if(si.RawSamples)
+ si.RawSamples(stream, samples, rate, width, channels, data, volume, entityNum);
}
/*
Modified: trunk/code/client/snd_openal.c
===================================================================
--- trunk/code/client/snd_openal.c 2011-07-27 00:04:29 UTC (rev 2101)
+++ trunk/code/client/snd_openal.c 2011-07-27 15:47:29 UTC (rev 2102)
@@ -521,6 +521,7 @@
qboolean isLocked; // This is locked (un-allocatable)
qboolean isLooping; // Is this a looping effect (attached to an entity)
qboolean isTracking; // Is this object tracking its owner
+ qboolean isStream; // Is this source a stream
float curGain; // gain employed if source is within maxdistance.
float scaleGain; // Last gain value for this source. 0 if muted.
@@ -744,13 +745,8 @@
static void S_AL_SrcSetup(srcHandle_t src, sfxHandle_t sfx, alSrcPriority_t priority,
int entity, int channel, qboolean local)
{
- ALuint buffer;
src_t *curSource;
- // Mark the SFX as used, and grab the raw AL buffer
- S_AL_BufferUse(sfx);
- buffer = S_AL_BufferGet(sfx);
-
// Set up src struct
curSource = &srcList[src];
@@ -763,12 +759,19 @@
curSource->isLocked = qfalse;
curSource->isLooping = qfalse;
curSource->isTracking = qfalse;
+ curSource->isStream = qfalse;
curSource->curGain = s_alGain->value * s_volume->value;
curSource->scaleGain = curSource->curGain;
curSource->local = local;
// Set up OpenAL source
- qalSourcei(curSource->alSource, AL_BUFFER, buffer);
+ if(sfx >= 0)
+ {
+ // Mark the SFX as used, and grab the raw AL buffer
+ S_AL_BufferUse(sfx);
+ qalSourcei(curSource->alSource, AL_BUFFER, S_AL_BufferGet(sfx));
+ }
+
qalSourcef(curSource->alSource, AL_PITCH, 1.0f);
S_AL_Gain(curSource->alSource, curSource->curGain);
qalSourcefv(curSource->alSource, AL_POSITION, vec3_origin);
@@ -1320,7 +1323,7 @@
VectorClear(sorigin);
qalSourcefv(curSource->alSource, AL_POSITION, sorigin);
- qalSourcefv(curSource->alSource, AL_VELOCITY, sorigin);
+ qalSourcefv(curSource->alSource, AL_VELOCITY, vec3_origin);
}
else
{
@@ -1343,8 +1346,8 @@
else
VectorClear(svelocity);
- qalSourcefv( curSource->alSource, AL_POSITION, (ALfloat *)sorigin );
- qalSourcefv( curSource->alSource, AL_VELOCITY, (ALfloat *)velocity );
+ qalSourcefv(curSource->alSource, AL_POSITION, (ALfloat *) sorigin);
+ qalSourcefv(curSource->alSource, AL_VELOCITY, (ALfloat *) svelocity);
}
}
@@ -1557,14 +1560,17 @@
continue;
}
- // Check if it's done, and flag it
- qalGetSourcei(curSource->alSource, AL_SOURCE_STATE, &state);
- if(state == AL_STOPPED)
+ if(!curSource->isStream)
{
- curSource->isPlaying = qfalse;
- S_AL_SrcKill(i);
- continue;
- }
+ // Check if it's done, and flag it
+ qalGetSourcei(curSource->alSource, AL_SOURCE_STATE, &state);
+ if(state == AL_STOPPED)
+ {
+ curSource->isPlaying = qfalse;
+ S_AL_SrcKill(i);
+ continue;
+ }
+ }
// Query relativity of source, don't move if it's true
qalGetSourcei(curSource->alSource, AL_SOURCE_RELATIVE, &state);
@@ -1614,32 +1620,57 @@
S_AL_AllocateStreamChannel
=================
*/
-static void S_AL_AllocateStreamChannel( int stream )
+static void S_AL_AllocateStreamChannel(int stream, int entityNum)
{
+ srcHandle_t cursrc;
+ ALuint alsrc;
+
if ((stream < 0) || (stream >= MAX_RAW_STREAMS))
return;
- // Allocate a streamSource at high priority
- streamSourceHandles[stream] = S_AL_SrcAlloc(SRCPRI_STREAM, -2, 0);
- if(streamSourceHandles[stream] == -1)
- return;
+ if(entityNum >= 0)
+ {
+ // This is a stream that tracks an entity
+ // Allocate a streamSource at normal priority
+ cursrc = S_AL_SrcAlloc(SRCPRI_ENTITY, entityNum, 0);
+ if(cursrc < 0)
+ return;
- // Lock the streamSource so nobody else can use it, and get the raw streamSource
- S_AL_SrcLock(streamSourceHandles[stream]);
- streamSources[stream] = S_AL_SrcGet(streamSourceHandles[stream]);
+ S_AL_SrcSetup(cursrc, -1, SRCPRI_ENTITY, entityNum, 0, qfalse);
+ alsrc = S_AL_SrcGet(cursrc);
+ srcList[cursrc].isTracking = qtrue;
+ srcList[cursrc].isStream = qtrue;
+ }
+ else
+ {
+ // Unspatialized stream source
- // make sure that after unmuting the S_AL_Gain in S_Update() does not turn
- // volume up prematurely for this source
- srcList[streamSourceHandles[stream]].scaleGain = 0.0f;
+ // Allocate a streamSource at high priority
+ cursrc = S_AL_SrcAlloc(SRCPRI_STREAM, -2, 0);
+ if(cursrc < 0)
+ return;
- // Set some streamSource parameters
- qalSourcei (streamSources[stream], AL_BUFFER, 0 );
- qalSourcei (streamSources[stream], AL_LOOPING, AL_FALSE );
- qalSource3f(streamSources[stream], AL_POSITION, 0.0, 0.0, 0.0);
- qalSource3f(streamSources[stream], AL_VELOCITY, 0.0, 0.0, 0.0);
- qalSource3f(streamSources[stream], AL_DIRECTION, 0.0, 0.0, 0.0);
- qalSourcef (streamSources[stream], AL_ROLLOFF_FACTOR, 0.0 );
- qalSourcei (streamSources[stream], AL_SOURCE_RELATIVE, AL_TRUE );
+ alsrc = S_AL_SrcGet(cursrc);
+
+ // Lock the streamSource so nobody else can use it, and get the raw streamSource
+ S_AL_SrcLock(cursrc);
+
+ // make sure that after unmuting the S_AL_Gain in S_Update() does not turn
+ // volume up prematurely for this source
+ srcList[cursrc].scaleGain = 0.0f;
+
+ // Set some streamSource parameters
+ qalSourcei (alsrc, AL_BUFFER, 0 );
+ qalSourcei (alsrc, AL_LOOPING, AL_FALSE );
+ qalSource3f(alsrc, AL_POSITION, 0.0, 0.0, 0.0);
+ qalSource3f(alsrc, AL_VELOCITY, 0.0, 0.0, 0.0);
+ qalSource3f(alsrc, AL_DIRECTION, 0.0, 0.0, 0.0);
+ qalSourcef (alsrc, AL_ROLLOFF_FACTOR, 0.0 );
+ qalSourcei (alsrc, AL_SOURCE_RELATIVE, AL_TRUE );
+ }
+
+ streamSourceHandles[stream] = cursrc;
+ streamSources[stream] = alsrc;
}
/*
@@ -1654,6 +1685,7 @@
// Release the output streamSource
S_AL_SrcUnlock(streamSourceHandles[stream]);
+ S_AL_SrcKill(streamSourceHandles[stream]);
streamSources[stream] = 0;
streamSourceHandles[stream] = -1;
}
@@ -1664,7 +1696,7 @@
=================
*/
static
-void S_AL_RawSamples(int stream, int samples, int rate, int width, int channels, const byte *data, float volume)
+void S_AL_RawSamples(int stream, int samples, int rate, int width, int channels, const byte *data, float volume, int entityNum)
{
ALuint buffer;
ALuint format;
@@ -1677,7 +1709,7 @@
// Create the streamSource if necessary
if(streamSourceHandles[stream] == -1)
{
- S_AL_AllocateStreamChannel(stream);
+ S_AL_AllocateStreamChannel(stream, entityNum);
// Failed?
if(streamSourceHandles[stream] == -1)
@@ -1694,8 +1726,11 @@
// Shove the data onto the streamSource
qalSourceQueueBuffers(streamSources[stream], 1, &buffer);
- // Volume
- S_AL_Gain (streamSources[stream], volume * s_volume->value * s_alGain->value);
+ if(entityNum < 0)
+ {
+ // Volume
+ S_AL_Gain (streamSources[stream], volume * s_volume->value * s_alGain->value);
+ }
}
/*
@@ -2106,7 +2141,6 @@
static
void S_AL_Respatialize( int entityNum, const vec3_t origin, vec3_t axis[3], int inwater )
{
- float velocity[3] = {0.0f, 0.0f, 0.0f};
float orientation[6];
vec3_t sorigin;
@@ -2124,7 +2158,7 @@
// Set OpenAL listener paramaters
qalListenerfv(AL_POSITION, (ALfloat *)sorigin);
- qalListenerfv(AL_VELOCITY, velocity);
+ qalListenerfv(AL_VELOCITY, vec3_origin);
qalListenerfv(AL_ORIENTATION, orientation);
}
Modified: trunk/code/client/snd_public.h
===================================================================
--- trunk/code/client/snd_public.h 2011-07-27 00:04:29 UTC (rev 2101)
+++ trunk/code/client/snd_public.h 2011-07-27 15:47:29 UTC (rev 2102)
@@ -33,8 +33,8 @@
// cinematics and voice-over-network will send raw samples
// 1.0 volume will be direct output of source samples
-void S_RawSamples (int stream, int samples, int rate, int width, int channels,
- const byte *data, float volume);
+void S_RawSamples(int stream, int samples, int rate, int width, int channels,
+ const byte *data, float volume, int entityNum);
// stop all sounds and the background track
void S_StopAllSounds( void );
Modified: trunk/code/qcommon/common.c
===================================================================
--- trunk/code/qcommon/common.c 2011-07-27 00:04:29 UTC (rev 2101)
+++ trunk/code/qcommon/common.c 2011-07-27 15:47:29 UTC (rev 2102)
@@ -3585,3 +3585,33 @@
string[i] = (unsigned char)( rand() % 255 );
}
+
+/*
+==================
+Com_IsVoipTarget
+
+Returns non-zero if given clientNum is enabled in voipTargets, zero otherwise.
+If clientNum is negative return if any bit is set.
+==================
+*/
+qboolean Com_IsVoipTarget(uint8_t *voipTargets, int voipTargetsSize, int clientNum)
+{
+ int index;
+ if(clientNum < 0)
+ {
+ for(index = 0; index < voipTargetsSize; index++)
+ {
+ if(voipTargets[index])
+ return qtrue;
+ }
+
+ return qfalse;
+ }
+
+ index = clientNum >> 3;
+
+ if(index < voipTargetsSize)
+ return (voipTargets[index] & (1 << (clientNum & 0x07)));
+
+ return qfalse;
+}
Modified: trunk/code/qcommon/q_shared.h
===================================================================
--- trunk/code/qcommon/q_shared.h 2011-07-27 00:04:29 UTC (rev 2101)
+++ trunk/code/qcommon/q_shared.h 2011-07-27 15:47:29 UTC (rev 2102)
@@ -928,9 +928,26 @@
char string[MAX_CVAR_VALUE_STRING];
} vmCvar_t;
+
/*
==============================================================
+VoIP
+
+==============================================================
+*/
+
+// if you change the count of flags be sure to also change VOIP_FLAGNUM
+#define VOIP_SPATIAL 0x01 // spatialized voip message
+#define VOIP_DIRECT 0x02 // non-spatialized voip message
+
+// number of flags voip knows. You will have to bump protocol version number if you
+// change this.
+#define VOIP_FLAGCNT 2
+
+/*
+==============================================================
+
COLLISION DETECTION
==============================================================
Modified: trunk/code/qcommon/qcommon.h
===================================================================
--- trunk/code/qcommon/qcommon.h 2011-07-27 00:04:29 UTC (rev 2101)
+++ trunk/code/qcommon/qcommon.h 2011-07-27 15:47:29 UTC (rev 2102)
@@ -252,7 +252,7 @@
==============================================================
*/
-#define PROTOCOL_VERSION 70
+#define PROTOCOL_VERSION 71
#define PROTOCOL_LEGACY_VERSION 68
// 1.31 - 67
@@ -834,6 +834,8 @@
qboolean Com_SafeMode( void );
void Com_RunAndTimeServerPacket(netadr_t *evFrom, msg_t *buf);
+qboolean Com_IsVoipTarget(uint8_t *voipTargets, int voipTargetsSize, int clientNum);
+
void Com_StartupVariable( const char *match );
// checks for and removes command line "+set var arg" constructs
// if match is NULL, all set commands will be executed, otherwise
Modified: trunk/code/server/server.h
===================================================================
--- trunk/code/server/server.h 2011-07-27 00:04:29 UTC (rev 2101)
+++ trunk/code/server/server.h 2011-07-27 15:47:29 UTC (rev 2102)
@@ -43,6 +43,7 @@
int frames;
int len;
int sender;
+ int flags;
byte data[1024];
} voipServerPacket_t;
#endif
@@ -362,11 +363,7 @@
int SV_SendDownloadMessages(void);
int SV_SendQueuedMessages(void);
-#ifdef USE_VOIP
-void SV_WriteVoipToClient( client_t *cl, msg_t *msg );
-#endif
-
//
// sv_ccmds.c
//
Modified: trunk/code/server/sv_client.c
===================================================================
--- trunk/code/server/sv_client.c 2011-07-27 00:04:29 UTC (rev 2101)
+++ trunk/code/server/sv_client.c 2011-07-27 15:47:29 UTC (rev 2102)
@@ -1176,57 +1176,7 @@
return numDLs;
}
-#ifdef USE_VOIP
/*
-==================
-SV_WriteVoipToClient
-
-Check to see if there is any VoIP queued for a client, and send if there is.
-==================
-*/
-void SV_WriteVoipToClient( client_t *cl, msg_t *msg )
-{
- if(*cl->downloadName)
- {
- cl->queuedVoipPackets = 0;
- return; // no VoIP allowed if download is going, to save bandwidth.
- }
-
- if(cl->queuedVoipPackets)
- {
- int totalbytes = 0;
- int i;
- voipServerPacket_t *packet;
-
- // Write as many VoIP packets as we reasonably can...
- for(i = cl->queuedVoipIndex; i < cl->queuedVoipPackets; i++)
- {
- packet = cl->voipPacket[i % ARRAY_LEN(cl->voipPacket)];
-
- totalbytes += packet->len;
- if (totalbytes > (msg->maxsize - msg->cursize) / 2)
- break;
-
- MSG_WriteByte(msg, svc_voip);
- MSG_WriteShort(msg, packet->sender);
- MSG_WriteByte(msg, (byte) packet->generation);
- MSG_WriteLong(msg, packet->sequence);
- MSG_WriteByte(msg, packet->frames);
- MSG_WriteShort(msg, packet->len);
- MSG_WriteData(msg, packet->data, packet->len);
-
- Z_Free(packet);
- }
-
- cl->queuedVoipPackets -= i;
- cl->queuedVoipIndex += i;
- cl->queuedVoipIndex %= ARRAY_LEN(cl->voipPacket);
- }
-}
-#endif
-
-
-/*
=================
SV_Disconnect_f
@@ -1800,8 +1750,15 @@
#ifdef USE_VOIP
-static
-qboolean SV_ShouldIgnoreVoipSender(const client_t *cl)
+/*
+==================
+SV_ShouldIgnoreVoipSender
+
+Blocking of voip packets based on source client
+==================
+*/
+
+static qboolean SV_ShouldIgnoreVoipSender(const client_t *cl)
{
if (!sv_voip->integer)
return qtrue; // VoIP disabled on this server.
@@ -1814,34 +1771,26 @@
}
static
-void SV_UserVoip( client_t *cl, msg_t *msg ) {
- const int sender = (int) (cl - svs.clients);
- const int generation = MSG_ReadByte(msg);
- const int sequence = MSG_ReadLong(msg);
- const int frames = MSG_ReadByte(msg);
- const int recip1 = MSG_ReadLong(msg);
- const int recip2 = MSG_ReadLong(msg);
- const int recip3 = MSG_ReadLong(msg);
- const int packetsize = MSG_ReadShort(msg);
+void SV_UserVoip(client_t *cl, msg_t *msg)
+{
+ int sender, generation, sequence, frames, packetsize;
+ uint8_t recips[(MAX_CLIENTS + 7) / 8];
+ int flags;
byte encoded[sizeof(cl->voipPacket[0]->data)];
client_t *client = NULL;
voipServerPacket_t *packet = NULL;
int i;
- if (generation < 0)
+ sender = cl - svs.clients;
+ generation = MSG_ReadByte(msg);
+ sequence = MSG_ReadLong(msg);
+ frames = MSG_ReadByte(msg);
+ MSG_ReadData(msg, recips, sizeof(recips));
+ flags = MSG_ReadByte(msg);
+ packetsize = MSG_ReadShort(msg);
+
+ if (msg->readcount > msg->cursize)
return; // short/invalid packet, bail.
- else if (sequence < 0)
- return; // short/invalid packet, bail.
- else if (frames < 0)
- return; // short/invalid packet, bail.
- else if (recip1 < 0)
- return; // short/invalid packet, bail.
- else if (recip2 < 0)
- return; // short/invalid packet, bail.
- else if (recip3 < 0)
- return; // short/invalid packet, bail.
- else if (packetsize < 0)
- return; // short/invalid packet, bail.
if (packetsize > sizeof (encoded)) { // overlarge packet?
int bytesleft = packetsize;
@@ -1865,10 +1814,6 @@
// !!! FIXME: reject if not speex narrowband codec.
// !!! FIXME: decide if this is bogus data?
- // (the three recip* values are 31 bits each (ignores sign bit so we can
- // get a -1 error from MSG_ReadLong() ... ), allowing for 93 clients.)
- assert( sv_maxclients->integer < 93 );
-
// decide who needs this VoIP packet sent to them...
for (i = 0, client = svs.clients; i < sv_maxclients->integer ; i++, client++) {
if (client->state != CS_ACTIVE)
@@ -1876,19 +1821,21 @@
else if (i == sender)
continue; // don't send voice packet back to original author.
else if (!client->hasVoip)
- continue; // no VoIP support, or support disabled.
+ continue; // no VoIP support, or unsupported protocol
else if (client->muteAllVoip)
continue; // client is ignoring everyone.
else if (client->ignoreVoipFromClient[sender])
continue; // client is ignoring this talker.
else if (*cl->downloadName) // !!! FIXME: possible to DoS?
continue; // no VoIP allowed if downloading, to save bandwidth.
- else if ( ((i >= 0) && (i < 31)) && ((recip1 & (1 << (i-0))) == 0) )
+
+ if(Com_IsVoipTarget(recips, sizeof(recips), i))
+ flags |= VOIP_DIRECT;
+ else
+ flags &= ~VOIP_DIRECT;
+
+ if (!(flags & (VOIP_SPATIAL | VOIP_DIRECT)))
continue; // not addressed to this player.
- else if ( ((i >= 31) && (i < 62)) && ((recip2 & (1 << (i-31))) == 0) )
- continue; // not addressed to this player.
- else if ( ((i >= 62) && (i < 93)) && ((recip3 & (1 << (i-62))) == 0) )
- continue; // not addressed to this player.
// Transmit this packet to the client.
if (client->queuedVoipPackets >= ARRAY_LEN(client->voipPacket)) {
@@ -1902,6 +1849,7 @@
packet->len = packetsize;
packet->generation = generation;
packet->sequence = sequence;
+ packet->flags = flags;
memcpy(packet->data, encoded, packetsize);
client->voipPacket[(client->queuedVoipIndex + client->queuedVoipPackets) % ARRAY_LEN(client->voipPacket)] = packet;
Modified: trunk/code/server/sv_init.c
===================================================================
--- trunk/code/server/sv_init.c 2011-07-27 00:04:29 UTC (rev 2101)
+++ trunk/code/server/sv_init.c 2011-07-27 15:47:29 UTC (rev 2102)
@@ -653,8 +653,8 @@
sv_serverid = Cvar_Get ("sv_serverid", "0", CVAR_SYSTEMINFO | CVAR_ROM );
sv_pure = Cvar_Get ("sv_pure", "1", CVAR_SYSTEMINFO );
#ifdef USE_VOIP
- sv_voip = Cvar_Get ("sv_voip", "1", CVAR_SYSTEMINFO | CVAR_LATCH);
- Cvar_CheckRange( sv_voip, 0, 1, qtrue );
+ sv_voip = Cvar_Get("sv_voip", "1", CVAR_SYSTEMINFO | CVAR_LATCH);
+ Cvar_CheckRange(sv_voip, 0, 1, qtrue);
#endif
Cvar_Get ("sv_paks", "", CVAR_SYSTEMINFO | CVAR_ROM );
Cvar_Get ("sv_pakNames", "", CVAR_SYSTEMINFO | CVAR_ROM );
Modified: trunk/code/server/sv_snapshot.c
===================================================================
--- trunk/code/server/sv_snapshot.c 2011-07-27 00:04:29 UTC (rev 2101)
+++ trunk/code/server/sv_snapshot.c 2011-07-27 15:47:29 UTC (rev 2102)
@@ -521,7 +521,54 @@
}
}
+#ifdef USE_VOIP
/*
+==================
+SV_WriteVoipToClient
+
+Check to see if there is any VoIP queued for a client, and send if there is.
+==================
+*/
+static void SV_WriteVoipToClient(client_t *cl, msg_t *msg)
+{
+ int totalbytes = 0;
+ int i;
+ voipServerPacket_t *packet;
+
+ if(cl->queuedVoipPackets)
+ {
+ // Write as many VoIP packets as we reasonably can...
+ for(i = 0; i < cl->queuedVoipPackets; i++)
+ {
+ packet = cl->voipPacket[(i + cl->queuedVoipIndex) % ARRAY_LEN(cl->voipPacket)];
+
+ if(!*cl->downloadName)
+ {
+ totalbytes += packet->len;
+ if (totalbytes > (msg->maxsize - msg->cursize) / 2)
+ break;
+
+ MSG_WriteByte(msg, svc_voip);
+ MSG_WriteShort(msg, packet->sender);
+ MSG_WriteByte(msg, (byte) packet->generation);
+ MSG_WriteLong(msg, packet->sequence);
+ MSG_WriteByte(msg, packet->frames);
+ MSG_WriteShort(msg, packet->len);
+ MSG_WriteBits(msg, packet->flags, VOIP_FLAGCNT);
+ MSG_WriteData(msg, packet->data, packet->len);
+ }
+
+ Z_Free(packet);
+ }
+
+ cl->queuedVoipPackets -= i;
+ cl->queuedVoipIndex += i;
+ cl->queuedVoipIndex %= ARRAY_LEN(cl->voipPacket);
+ }
+}
+#endif
+
+/*
=======================
SV_SendMessageToClient
@@ -610,11 +657,11 @@
if(*c->downloadName)
continue; // Client is downloading, don't send snapshots
- if(c->netchan.unsentFragments || c->netchan_start_queue)
- {
- c->rateDelayed = qtrue;
+ if(c->netchan.unsentFragments || c->netchan_start_queue)
+ {
+ c->rateDelayed = qtrue;
continue; // Drop this snapshot if the packet queue is still full or delta compression will break
- }
+ }
if(!(c->netchan.remoteAddress.type == NA_LOOPBACK ||
(sv_lanForceRate->integer && Sys_IsLANAddress(c->netchan.remoteAddress))))
Modified: trunk/voip-readme.txt
===================================================================
--- trunk/voip-readme.txt 2011-07-27 00:04:29 UTC (rev 2101)
+++ trunk/voip-readme.txt 2011-07-27 15:47:29 UTC (rev 2102)
@@ -49,9 +49,12 @@
cl_voipSendTarget: a string: "all" to broadcast to everyone, "none" to send
to no one, "attacker" to send to the last person that hit
you, "crosshair" to send to the people currently in your
- crosshair, or a comma-separated list of client numbers, like
- "0,7,2,23" ... an empty string is treated like "all". This
- is reset to "all" when connecting to a new server.
+ crosshair, "spatial" to talk to all people in hearing
+ range or a comma-separated list of client numbers, like
+ "0,7,2,23" ... an empty string is treated like "spatial".
+ You can also use a mixed string like
+ "0, spatial, 2, crosshair".
+ This is reset to "spatial" when connecting to a new server.
Presumably mods will manage this cvar, not people, but
keybind could be useful for the general cases. To send to
just your team, or the opposing team, or a buddy list, you
More information about the quake3-commits
mailing list