@ -14,12 +14,15 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
@@ -14,12 +14,15 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details .
*/
# include <opus.h>
# include "common.h"
# include "client.h"
# include "voice.h"
wavdata_t * input_file ;
fs_offset_t input_pos ;
static wavdata_t * input_file ;
static fs_offset_t input_pos ;
voice_state_t voice ;
voice_state_t voice = { 0 } ;
CVAR_DEFINE_AUTO ( voice_enable , " 1 " , FCVAR_PRIVILEGED | FCVAR_ARCHIVE , " enable voice chat " ) ;
CVAR_DEFINE_AUTO ( voice_loopback , " 0 " , FCVAR_PRIVILEGED , " loopback voice back to the speaker " ) ;
@ -47,6 +50,12 @@ static void Voice_CodecInfo_f( void )
@@ -47,6 +50,12 @@ static void Voice_CodecInfo_f( void )
opus_int32 encoderBitrate ;
opus_int32 encoderBandwidthType ;
if ( ! voice . initialized )
{
Con_Printf ( " Voice codec is not initialized! \n " ) ;
return ;
}
opus_encoder_ctl ( voice . encoder , OPUS_GET_BITRATE ( & encoderBitrate ) ) ;
opus_encoder_ctl ( voice . encoder , OPUS_GET_COMPLEXITY ( & encoderComplexity ) ) ;
opus_encoder_ctl ( voice . encoder , OPUS_GET_BANDWIDTH ( & encoderBandwidthType ) ) ;
@ -54,8 +63,7 @@ static void Voice_CodecInfo_f( void )
@@ -54,8 +63,7 @@ static void Voice_CodecInfo_f( void )
Con_Printf ( " Encoder: \n " ) ;
Con_Printf ( " Bitrate: %.3f kbps \n " , encoderBitrate / 1000.0f ) ;
Con_Printf ( " Complexity: %d \n " , encoderComplexity ) ;
Con_Printf ( " Bandwidth: " ) ;
Con_Printf ( Voice_GetBandwidthTypeName ( encoderBandwidthType ) ) ;
Con_Printf ( " Bandwidth: %s " , Voice_GetBandwidthTypeName ( encoderBandwidthType ) ) ;
Con_Printf ( " \n " ) ;
}
@ -191,7 +199,7 @@ void Voice_DeInit( void )
@@ -191,7 +199,7 @@ void Voice_DeInit( void )
voice . initialized = false ;
}
uint Voice_GetCompressedData ( byte * out , uint maxsize , uint * frames )
static uint Voice_GetCompressedData ( byte * out , uint maxsize , uint * frames )
{
uint ofs , size = 0 ;
@ -234,7 +242,29 @@ uint Voice_GetCompressedData( byte *out, uint maxsize, uint *frames )
@@ -234,7 +242,29 @@ uint Voice_GetCompressedData( byte *out, uint maxsize, uint *frames )
return size ;
}
void Voice_Idle ( float frametime )
static void Voice_StatusTimeout ( voice_status_t * status , int entindex , double frametime )
{
if ( status - > talking_ack )
{
status - > talking_timeout + = frametime ;
if ( status - > talking_timeout > 0.2 )
{
status - > talking_ack = false ;
Voice_Status ( entindex , false ) ;
}
}
}
void Voice_StatusAck ( voice_status_t * status , int playerIndex )
{
if ( ! status - > talking_ack )
Voice_Status ( playerIndex , true ) ;
status - > talking_ack = true ;
status - > talking_timeout = 0.0 ;
}
void Voice_Idle ( double frametime )
{
int i ;
@ -244,29 +274,11 @@ void Voice_Idle( float frametime )
@@ -244,29 +274,11 @@ void Voice_Idle( float frametime )
return ;
}
if ( voice . talking_ack )
{
voice . talking_timeout + = frametime ;
if ( voice . talking_timeout > 0.2f )
{
voice . talking_ack = false ;
Voice_Status ( - 2 , false ) ;
}
}
// update local player status first
Voice_StatusTimeout ( & voice . local , VOICE_LOCALPLAYER_INDEX , frametime ) ;
for ( i = 0 ; i < 32 ; i + + )
{
if ( voice . players_status [ i ] . talking_ack )
{
voice . players_status [ i ] . talking_timeout + = frametime ;
if ( voice . players_status [ i ] . talking_timeout > 0.2f )
{
voice . players_status [ i ] . talking_ack = false ;
if ( i < cl . maxclients )
Voice_Status ( i , false ) ;
}
}
}
Voice_StatusTimeout ( & voice . players_status [ i ] , i , frametime ) ;
}
qboolean Voice_IsRecording ( void )
@ -333,6 +345,12 @@ void Voice_Disconnect( void )
@@ -333,6 +345,12 @@ void Voice_Disconnect( void )
}
}
static void Voice_StartChannel ( uint samples , byte * data , int entnum )
{
SND_ForceInitMouth ( entnum ) ;
S_RawEntSamples ( entnum , samples , voice . samplerate , voice . width , voice . channels , data , 255 ) ;
}
void Voice_AddIncomingData ( int ent , const byte * data , uint size , uint frames )
{
int samples = opus_decode ( voice . decoder , data , size , ( short * ) voice . decompress_buffer , voice . frame_size / voice . width * frames , false ) ;
@ -353,42 +371,9 @@ void CL_AddVoiceToDatagram( void )
@@ -353,42 +371,9 @@ void CL_AddVoiceToDatagram( void )
if ( size > 0 & & MSG_GetNumBytesLeft ( & cls . datagram ) > = size + 32 )
{
MSG_BeginClientCmd ( & cls . datagram , clc_voicedata ) ;
MSG_WriteByte ( & cls . datagram , Voice_GetLoopback ( ) ) ;
MSG_WriteByte ( & cls . datagram , voice_loopback . value ! = 0 ) ;
MSG_WriteByte ( & cls . datagram , frames ) ;
MSG_WriteShort ( & cls . datagram , size ) ;
MSG_WriteBytes ( & cls . datagram , voice . output_buffer , size ) ;
}
}
qboolean Voice_GetLoopback ( void )
{
return voice_loopback . value ;
}
void Voice_LocalPlayerTalkingAck ( void )
{
if ( ! voice . talking_ack )
{
Voice_Status ( - 2 , true ) ;
}
voice . talking_ack = true ;
voice . talking_timeout = 0.0f ;
}
void Voice_PlayerTalkingAck ( int playerIndex )
{
if ( ! voice . players_status [ playerIndex ] . talking_ack )
{
Voice_Status ( playerIndex , true ) ;
}
voice . players_status [ playerIndex ] . talking_ack = true ;
voice . players_status [ playerIndex ] . talking_timeout = 0.0f ;
}
void Voice_StartChannel ( uint samples , byte * data , int entnum )
{
SND_ForceInitMouth ( entnum ) ;
S_RawEntSamples ( entnum , samples , voice . samplerate , voice . width , voice . channels , data , 255 ) ;
}