r1375 - trunk/code/client

DONOTREPLY at icculus.org DONOTREPLY at icculus.org
Sat Jun 7 10:40:59 EDT 2008


Author: icculus
Date: 2008-06-07 10:40:59 -0400 (Sat, 07 Jun 2008)
New Revision: 1375

Modified:
   trunk/code/client/cl_cgame.c
   trunk/code/client/cl_input.c
   trunk/code/client/cl_main.c
   trunk/code/client/client.h
Log:
VoIP: initial shot at voice activation.


Modified: trunk/code/client/cl_cgame.c
===================================================================
--- trunk/code/client/cl_cgame.c	2008-06-07 14:40:30 UTC (rev 1374)
+++ trunk/code/client/cl_cgame.c	2008-06-07 14:40:59 UTC (rev 1375)
@@ -937,6 +937,10 @@
 		speex_preprocess_ctl(clc.speexPreprocessor,
 		                     SPEEX_PREPROCESS_SET_DENOISE, &i);
 
+		i = (cl_voipUseVAD->integer != 0);
+		speex_preprocess_ctl(clc.speexPreprocessor,
+		                     SPEEX_PREPROCESS_SET_VAD, &i);
+
 		for (i = 0; i < MAX_CLIENTS; i++) {
 			speex_bits_init(&clc.speexDecoderBits[i]);
 			speex_bits_reset(&clc.speexDecoderBits[i]);

Modified: trunk/code/client/cl_input.c
===================================================================
--- trunk/code/client/cl_input.c	2008-06-07 14:40:30 UTC (rev 1374)
+++ trunk/code/client/cl_input.c	2008-06-07 14:40:59 UTC (rev 1375)
@@ -221,8 +221,17 @@
 void IN_StrafeUp(void) {IN_KeyUp(&in_strafe);}
 
 #if USE_VOIP
-void IN_VoipRecordDown(void) {IN_KeyDown(&in_voiprecord);}
-void IN_VoipRecordUp(void) {IN_KeyUp(&in_voiprecord);}
+void IN_VoipRecordDown(void)
+{
+	IN_KeyDown(&in_voiprecord);
+	Cvar_Set("cl_voipSend", "1");
+}
+
+void IN_VoipRecordUp(void)
+{
+	IN_KeyUp(&in_voiprecord);
+	Cvar_Set("cl_voipSend", "0");
+}
 #endif
 
 void IN_Button0Down(void) {IN_KeyDown(&in_buttons[0]);}
@@ -556,14 +565,6 @@
 	// get basic movement from joystick
 	CL_JoystickMove( &cmd );
 
-#if USE_VOIP
-	if ( ( in_voiprecord.active ) && ( !cl_voipSend->integer ) ) {
-		Cvar_Set("cl_voipSend", "1");
-	} else if ( ( !in_voiprecord.active ) && ( cl_voipSend->integer ) ) {
-		Cvar_Set("cl_voipSend", "0");
-	}
-#endif
-
 	// check to make sure the angles haven't wrapped
 	if ( cl.viewangles[PITCH] - oldAngles[PITCH] > 90 ) {
 		cl.viewangles[PITCH] = oldAngles[PITCH] + 90;

Modified: trunk/code/client/cl_main.c
===================================================================
--- trunk/code/client/cl_main.c	2008-06-07 14:40:30 UTC (rev 1374)
+++ trunk/code/client/cl_main.c	2008-06-07 14:40:59 UTC (rev 1375)
@@ -34,6 +34,7 @@
 #endif
 
 #if USE_VOIP
+cvar_t	*cl_voipUseVAD;
 cvar_t	*cl_voipSend;
 cvar_t	*cl_voipSendTarget;
 cvar_t	*cl_voipGainDuringCapture;
@@ -242,6 +243,18 @@
 }
 
 
+static
+void CL_VoipNewGeneration(void)
+{
+	// don't have a zero generation so new clients won't match, and don't
+	//  wrap to negative so MSG_ReadLong() doesn't "fail."
+	clc.voipOutgoingGeneration++;
+	if (clc.voipOutgoingGeneration <= 0)
+		clc.voipOutgoingGeneration = 1;
+	clc.voipPower = 0.0f;
+	clc.voipOutgoingSequence = 0;
+}
+
 /*
 ===============
 CL_CaptureVoip
@@ -253,6 +266,7 @@
 static
 void CL_CaptureVoip(void)
 {
+	const qboolean useVad = (cl_voipUseVAD->integer != 0);
 	qboolean initialFrame = qfalse;
 	qboolean finalFrame = qfalse;
 
@@ -268,6 +282,17 @@
 	if (clc.voipOutgoingDataSize > 0)
 		return;  // packet is pending transmission, don't record more yet.
 
+	if (cl_voipUseVAD->modified) {
+		int useVadi = (int) useVad;
+		speex_preprocess_ctl(clc.speexPreprocessor,
+		                     SPEEX_PREPROCESS_SET_VAD, &useVadi);
+		cl_voipUseVAD->modified = qfalse;
+		Cvar_Set("cl_voipSend", (useVad) ? "1" : "0");
+	}
+
+	if ((useVad) && (!cl_voipSend->integer))
+		Cvar_Set("cl_voipSend", "1");  // lots of things reset this.
+
 	if (cl_voipSend->modified) {
 		qboolean dontCapture = qfalse;
 		if (cls.state != CA_ACTIVE)
@@ -302,11 +327,7 @@
 		if (gain < 0.0f) gain = 0.0f; else if (gain >= 1.0f) gain = 1.0f;
 		S_MasterGain(cl_voipGainDuringCapture->value);
 		S_StartCapture();
-		clc.voipPower = 0.0f;
-		clc.voipOutgoingSequence = 0;
-		clc.voipOutgoingGeneration++;
-		if (clc.voipOutgoingGeneration == 0) // don't have a zero generation...
-			clc.voipOutgoingGeneration = 1;  //  ...so new clients won't match.
+		CL_VoipNewGeneration();
 	}
 
 	if ((cl_voipSend->integer) || (finalFrame)) { // user wants to capture audio?
@@ -318,6 +339,7 @@
 			// audio capture is always MONO16 (and that's what speex wants!).
 			//  2048 will cover 12 uncompressed frames in narrowband mode.
 			static int16_t sampbuffer[2048];
+			qboolean isVoice = qfalse;
 			int16_t voipPower = 0;
 			int speexFrames = 0;
 			int wpos = 0;
@@ -334,22 +356,25 @@
 
 			// this will probably generate multiple speex packets each time.
 			while (samples > 0) {
+				int16_t *sampptr = &sampbuffer[pos];
 				int i, bytes;
 
-				// Check the "power" of this packet...
+				// check the "power" of this packet...
 				for (i = 0; i < clc.speexFrameSize; i++) {
-					int16_t s = sampbuffer[i+pos];
+					int16_t s = sampptr[i];
 					if (s < 0)
 						s = -s;
 					if (s > voipPower)
 						voipPower = s;  // !!! FIXME: this isn't very clever.
 				}
 
-				speex_preprocess_run(clc.speexPreprocessor, &sampbuffer[pos]);
+				// preprocess samples to remove noise, check for voice...
+				if (speex_preprocess_run(clc.speexPreprocessor, sampptr))
+					isVoice = qtrue;  // player is probably speaking.
 
-				// Encode raw audio samples into Speex data...
+				// encode raw audio samples into Speex data...
 				speex_bits_reset(&clc.speexEncoderBits);
-				speex_encode_int(clc.speexEncoder, &sampbuffer[pos],
+				speex_encode_int(clc.speexEncoder, sampptr,
 				                 &clc.speexEncoderBits);
 				bytes = speex_bits_write(&clc.speexEncoderBits,
 				                         (char *) &clc.voipOutgoingData[wpos+1],
@@ -363,21 +388,26 @@
 				samples -= clc.speexFrameSize;
 				speexFrames++;
 			}
-			clc.voipPower = ((float) voipPower) / 32767.0f;
-			clc.voipOutgoingDataSize = wpos;
-			clc.voipOutgoingDataFrames = speexFrames;
 
-			Com_DPrintf("Outgoing VoIP data: %d frames, %d bytes, %f power\n",
-			            speexFrames, wpos, clc.voipPower);
+			if ((useVad) && (!isVoice)) {
+				CL_VoipNewGeneration();  // no talk for at least 1/4 second.
+			} else {
+				clc.voipPower = ((float) voipPower) / 32767.0f;
+				clc.voipOutgoingDataSize = wpos;
+				clc.voipOutgoingDataFrames = speexFrames;
 
-			#if 0
-			static FILE *encio = NULL;
-			if (encio == NULL) encio = fopen("outgoing-encoded.bin", "wb");
-			if (encio != NULL) { fwrite(clc.voipOutgoingData, wpos, 1, encio); fflush(encio); }
-			static FILE *decio = NULL;
-			if (decio == NULL) decio = fopen("outgoing-decoded.bin", "wb");
-			if (decio != NULL) { fwrite(sampbuffer, speexFrames * clc.speexFrameSize * 2, 1, decio); fflush(decio); }
-			#endif
+				Com_DPrintf("VoIP: Send %d frames, %d bytes, %f power\n",
+				            speexFrames, wpos, clc.voipPower);
+
+				#if 0
+				static FILE *encio = NULL;
+				if (encio == NULL) encio = fopen("voip-outgoing-encoded.bin", "wb");
+				if (encio != NULL) { fwrite(clc.voipOutgoingData, wpos, 1, encio); fflush(encio); }
+				static FILE *decio = NULL;
+				if (decio == NULL) decio = fopen("voip-outgoing-decoded.bin", "wb");
+				if (decio != NULL) { fwrite(sampbuffer, speexFrames * clc.speexFrameSize * 2, 1, decio); fflush(decio); }
+				#endif
+			}
 		}
 	}
 
@@ -3057,6 +3087,7 @@
 	cl_voipSend = Cvar_Get ("cl_voipSend", "0", 0);
 	cl_voipSendTarget = Cvar_Get ("cl_voipSendTarget", "all", 0);
 	cl_voipGainDuringCapture = Cvar_Get ("cl_voipGainDuringCapture", "0.2", CVAR_ARCHIVE);
+	cl_voipUseVAD = Cvar_Get ("cl_voipUseVAD", "0", CVAR_ARCHIVE);
 	voip = Cvar_Get ("voip", "1", CVAR_USERINFO | CVAR_ARCHIVE | CVAR_LATCH);
 
 	// This is a protocol version number.

Modified: trunk/code/client/client.h
===================================================================
--- trunk/code/client/client.h	2008-06-07 14:40:30 UTC (rev 1374)
+++ trunk/code/client/client.h	2008-06-07 14:40:59 UTC (rev 1375)
@@ -411,6 +411,7 @@
 // cl_voipSendTarget is a string: "all" to broadcast to everyone, "none" to
 //  send to no one, or a comma-separated list of client numbers:
 //  "0,7,2,23" ... an empty string is treated like "all".
+extern	cvar_t	*cl_voipUseVAD;
 extern	cvar_t	*cl_voipSend;
 extern	cvar_t	*cl_voipSendTarget;
 extern	cvar_t	*cl_voipGainDuringCapture;




More information about the quake3-commits mailing list