engine: client: create separate Opus decoders for each player

Turns out, we can't re-use same decoder for different streams.
This commit is contained in:
Alibek Omarov 2024-03-20 18:40:17 +03:00
parent 288cac69de
commit ff21fb42e6
2 changed files with 54 additions and 25 deletions

View File

@ -39,6 +39,25 @@ static void Voice_ApplyGainAdjust( int16_t *samples, int count );
=============================================================================== ===============================================================================
*/ */
static qboolean Voice_InitCustomMode( void )
{
int err = 0;
voice.width = sizeof( opus_int16 );
voice.samplerate = VOICE_OPUS_CUSTOM_SAMPLERATE;
voice.frame_size = VOICE_OPUS_CUSTOM_FRAME_SIZE;
voice.custom_mode = opus_custom_mode_create( SOUND_44k, voice.frame_size, &err );
if( !voice.custom_mode )
{
Con_Printf( S_ERROR "Can't create Opus Custom mode: %s\n", opus_strerror( err ));
return false;
}
return true;
}
/* /*
========================= =========================
Voice_InitOpusDecoder Voice_InitOpusDecoder
@ -47,24 +66,17 @@ Voice_InitOpusDecoder
*/ */
static qboolean Voice_InitOpusDecoder( void ) static qboolean Voice_InitOpusDecoder( void )
{ {
int err; int err = 0;
voice.width = sizeof( opus_int16 ); for( int i = 0; i < cl.maxclients; i++ )
voice.samplerate = VOICE_OPUS_CUSTOM_SAMPLERATE;
voice.frame_size = VOICE_OPUS_CUSTOM_FRAME_SIZE;
voice.custom_mode = opus_custom_mode_create( SOUND_44k, voice.frame_size, &err );
if( !voice.custom_mode )
{ {
Con_Printf( S_ERROR "Can't create Opus Custom mode: %s\n", opus_strerror( err )); voice.decoders[i] = opus_custom_decoder_create( voice.custom_mode, VOICE_PCM_CHANNELS, &err );
if( !voice.decoders[i] )
{
Con_Printf( S_ERROR "Can't create Opus decoder for %i: %s\n", i, opus_strerror( err ));
return false; return false;
} }
voice.decoder = opus_custom_decoder_create( voice.custom_mode, VOICE_PCM_CHANNELS, &err );
if( !voice.decoder )
{
Con_Printf( S_ERROR "Can't create Opus encoder: %s\n", opus_strerror( err ));
return false;
} }
return true; return true;
@ -78,7 +90,7 @@ Voice_InitOpusEncoder
*/ */
static qboolean Voice_InitOpusEncoder( int quality ) static qboolean Voice_InitOpusEncoder( int quality )
{ {
int err; int err = 0;
voice.encoder = opus_custom_encoder_create( voice.custom_mode, VOICE_PCM_CHANNELS, &err ); voice.encoder = opus_custom_encoder_create( voice.custom_mode, VOICE_PCM_CHANNELS, &err );
if( !voice.encoder ) if( !voice.encoder )
@ -117,10 +129,13 @@ Voice_ShutdownOpusDecoder
*/ */
static void Voice_ShutdownOpusDecoder( void ) static void Voice_ShutdownOpusDecoder( void )
{ {
if( voice.decoder ) for( int i = 0; i < MAX_CLIENTS; i++ )
{ {
opus_custom_decoder_destroy( voice.decoder ); if( !voice.decoders[i] )
voice.decoder = NULL; continue;
opus_custom_decoder_destroy( voice.decoders[i] );
voice.decoders[i] = NULL;
} }
} }
@ -137,7 +152,10 @@ static void Voice_ShutdownOpusEncoder( void )
opus_custom_encoder_destroy( voice.encoder ); opus_custom_encoder_destroy( voice.encoder );
voice.encoder = NULL; voice.encoder = NULL;
} }
}
static void Voice_ShutdownCustomMode( void )
{
if( voice.custom_mode ) if( voice.custom_mode )
{ {
opus_custom_mode_destroy( voice.custom_mode ); opus_custom_mode_destroy( voice.custom_mode );
@ -455,10 +473,11 @@ Received encoded voice data, decode it
*/ */
void Voice_AddIncomingData( int ent, const byte *data, uint size, uint frames ) void Voice_AddIncomingData( int ent, const byte *data, uint size, uint frames )
{ {
const int playernum = ent - 1;
int samples = 0; int samples = 0;
int ofs = 0; int ofs = 0;
if( !voice.decoder ) if( playernum < 0 || playernum >= cl.maxclients || !voice.decoders[playernum] )
return; return;
// decode frame by frame // decode frame by frame
@ -478,7 +497,7 @@ void Voice_AddIncomingData( int ent, const byte *data, uint size, uint frames )
if( ofs + compressed_size > size ) if( ofs + compressed_size > size )
break; break;
frame_samples = opus_custom_decode( voice.decoder, data + ofs, compressed_size, frame_samples = opus_custom_decode( voice.decoders[playernum], data + ofs, compressed_size,
(opus_int16*)voice.decompress_buffer + samples, voice.frame_size ); (opus_int16*)voice.decompress_buffer + samples, voice.frame_size );
ofs += compressed_size; ofs += compressed_size;
@ -544,8 +563,9 @@ static void Voice_Shutdown( void )
int i; int i;
Voice_RecordStop(); Voice_RecordStop();
Voice_ShutdownOpusEncoder();
Voice_ShutdownOpusDecoder(); Voice_ShutdownOpusDecoder();
Voice_ShutdownOpusEncoder();
Voice_ShutdownCustomMode();
VoiceCapture_Shutdown(); VoiceCapture_Shutdown();
if( voice.local.talking_ack ) if( voice.local.talking_ack )
@ -609,11 +629,10 @@ qboolean Voice_Init( const char *pszCodecName, int quality, qboolean preinit )
voice.autogain.block_size = 128; voice.autogain.block_size = 128;
if( !Voice_InitOpusDecoder( )) if( !Voice_InitCustomMode( ))
{ {
// no reason to init encoder and open audio device // no reason to init encoder and open audio device
// if we can't hear other players // if we can't hear other players
Con_Printf( S_ERROR "Voice chat disabled.\n" );
Voice_Shutdown(); Voice_Shutdown();
return false; return false;
} }
@ -633,6 +652,16 @@ qboolean Voice_Init( const char *pszCodecName, int quality, qboolean preinit )
if( !preinit ) if( !preinit )
{ {
Voice_ShutdownOpusDecoder();
if( !Voice_InitOpusDecoder())
{
// no reason to init encoder and open audio device
// if we can't hear other players
Con_Printf( S_ERROR "Can't create decoders, voice chat is disabled.\n" );
Voice_Shutdown();
return false;
}
voice.device_opened = VoiceCapture_Init(); voice.device_opened = VoiceCapture_Init();
if( !voice.device_opened ) if( !voice.device_opened )

View File

@ -62,7 +62,7 @@ typedef struct voice_state_s
// opus stuff // opus stuff
OpusCustomMode *custom_mode; OpusCustomMode *custom_mode;
OpusCustomEncoder *encoder; OpusCustomEncoder *encoder;
OpusCustomDecoder *decoder; OpusCustomDecoder *decoders[MAX_CLIENTS];
// audio info // audio info
uint width; uint width;