You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
279 lines
7.2 KiB
279 lines
7.2 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
|
|
#include "audio_pch.h" |
|
|
|
//#include "matchmaking/IMatchFramework.h" |
|
#include "tier2/tier2.h" |
|
|
|
#include "audio/public/voice.h" |
|
|
|
#if !defined( DEDICATED ) && ( defined( OSX ) || defined( _WIN32 ) ) && !defined( NO_STEAM ) |
|
#include "cl_steamauth.h" |
|
#endif |
|
|
|
// memdbgon must be the last include file in a .cpp file!!! |
|
#include "tier0/memdbgon.h" |
|
|
|
CEngineVoiceStub *Audio_GetEngineVoiceStub() |
|
{ |
|
static CEngineVoiceStub s_EngineVoiceStub; |
|
return &s_EngineVoiceStub; |
|
} |
|
|
|
|
|
#if !defined( DEDICATED ) && ( defined( OSX ) || defined( _WIN32 ) ) && !defined( NO_STEAM ) |
|
|
|
class CEngineVoiceSteam : public IEngineVoice |
|
{ |
|
public: |
|
CEngineVoiceSteam(); |
|
|
|
public: |
|
virtual bool IsHeadsetPresent( int iController ); |
|
virtual bool IsLocalPlayerTalking( int iController ); |
|
|
|
virtual void AddPlayerToVoiceList( XUID xPlayer, int iController ); |
|
virtual void RemovePlayerFromVoiceList( XUID xPlayer, int iController ); |
|
|
|
virtual void GetRemoteTalkers( int *pNumTalkers, XUID *pRemoteTalkers ); |
|
|
|
virtual bool VoiceUpdateData( int iController ); |
|
virtual void GetVoiceData( int iController, const byte **ppvVoiceDataBuffer, unsigned int *pnumVoiceDataBytes ); |
|
virtual void VoiceResetLocalData( int iController ); |
|
|
|
virtual void SetPlaybackPriority( XUID remoteTalker, int iController, int iAllowPlayback ); |
|
virtual void PlayIncomingVoiceData( XUID xuid, const byte *pbData, unsigned int dwDataSize, const bool *bAudiblePlayers = NULL ); |
|
|
|
virtual void RemoveAllTalkers(); |
|
|
|
protected: |
|
void AudioInitializationUpdate(); |
|
|
|
public: |
|
bool m_bLocalVoice[ XUSER_MAX_COUNT ]; |
|
CUtlVector< XUID > m_arrRemoteVoice; |
|
bool m_bInitializedAudio; |
|
byte m_pbVoiceData[ 1024 * XUSER_MAX_COUNT ]; |
|
}; |
|
|
|
CEngineVoiceSteam::CEngineVoiceSteam() |
|
{ |
|
memset( m_bLocalVoice, 0, sizeof( m_bLocalVoice ) ); |
|
memset( m_pbVoiceData, 0, sizeof( m_pbVoiceData ) ); |
|
m_bInitializedAudio = false; |
|
} |
|
|
|
bool CEngineVoiceSteam::IsHeadsetPresent( int iController ) |
|
{ |
|
return false; |
|
} |
|
|
|
bool CEngineVoiceSteam::IsLocalPlayerTalking( int iController ) |
|
{ |
|
uint32 nBytes = 0; |
|
EVoiceResult res = Steam3Client().SteamUser()->GetAvailableVoice( &nBytes, NULL, 0 ); |
|
switch ( res ) |
|
{ |
|
case k_EVoiceResultOK: |
|
case k_EVoiceResultNoData: |
|
case k_EVoiceResultBufferTooSmall: |
|
return true; |
|
default: |
|
return false; |
|
} |
|
} |
|
|
|
void CEngineVoiceSteam::AddPlayerToVoiceList( XUID xPlayer, int iController ) |
|
{ |
|
if ( !xPlayer && iController >= 0 && iController < XUSER_MAX_COUNT ) |
|
{ |
|
// Add local player |
|
m_bLocalVoice[ iController ] = true; |
|
AudioInitializationUpdate(); |
|
} |
|
|
|
if ( xPlayer ) |
|
{ |
|
if ( m_arrRemoteVoice.Find( xPlayer ) == m_arrRemoteVoice.InvalidIndex() ) |
|
{ |
|
m_arrRemoteVoice.AddToTail( xPlayer ); |
|
AudioInitializationUpdate(); |
|
} |
|
} |
|
} |
|
|
|
void CEngineVoiceSteam::RemovePlayerFromVoiceList( XUID xPlayer, int iController ) |
|
{ |
|
if ( !xPlayer && iController >= 0 && iController < XUSER_MAX_COUNT ) |
|
{ |
|
// Remove local player |
|
m_bLocalVoice[ iController ] = false; |
|
AudioInitializationUpdate(); |
|
} |
|
|
|
if ( xPlayer ) |
|
{ |
|
int idx = m_arrRemoteVoice.Find( xPlayer ); |
|
if ( idx != m_arrRemoteVoice.InvalidIndex() ) |
|
{ |
|
m_arrRemoteVoice.FastRemove( idx ); |
|
AudioInitializationUpdate(); |
|
} |
|
} |
|
} |
|
|
|
void CEngineVoiceSteam::GetRemoteTalkers( int *pNumTalkers, XUID *pRemoteTalkers ) |
|
{ |
|
if ( pNumTalkers ) |
|
*pNumTalkers = m_arrRemoteVoice.Count(); |
|
|
|
if ( pRemoteTalkers ) |
|
{ |
|
for ( int k = 0; k < m_arrRemoteVoice.Count(); ++ k ) |
|
pRemoteTalkers[k] = m_arrRemoteVoice[k]; |
|
} |
|
} |
|
|
|
bool CEngineVoiceSteam::VoiceUpdateData( int iController ) |
|
{ |
|
uint32 nBytes = 0; |
|
EVoiceResult res = Steam3Client().SteamUser()->GetAvailableVoice( &nBytes, NULL, 0 ); |
|
switch ( res ) |
|
{ |
|
case k_EVoiceResultOK: |
|
// case k_EVoiceResultNoData: - no data means false |
|
case k_EVoiceResultBufferTooSmall: |
|
return true; |
|
default: |
|
return false; |
|
} |
|
} |
|
|
|
void CEngineVoiceSteam::GetVoiceData( int iController, const byte **ppvVoiceDataBuffer, unsigned int *pnumVoiceDataBytes ) |
|
{ |
|
const int size = ARRAYSIZE( m_pbVoiceData ) / XUSER_MAX_COUNT; |
|
byte *pbVoiceData = m_pbVoiceData + iController * ARRAYSIZE( m_pbVoiceData ) / XUSER_MAX_COUNT; |
|
*ppvVoiceDataBuffer = pbVoiceData; |
|
|
|
EVoiceResult res = Steam3Client().SteamUser()->GetVoice( true, pbVoiceData, size, pnumVoiceDataBytes, false, NULL, 0, NULL, 0 ); |
|
switch ( res ) |
|
{ |
|
case k_EVoiceResultNoData: |
|
case k_EVoiceResultOK: |
|
return; |
|
default: |
|
*pnumVoiceDataBytes = 0; |
|
*ppvVoiceDataBuffer = NULL; |
|
return; |
|
} |
|
} |
|
|
|
void CEngineVoiceSteam::VoiceResetLocalData( int iController ) |
|
{ |
|
const int size = ARRAYSIZE( m_pbVoiceData ) / XUSER_MAX_COUNT; |
|
byte *pbVoiceData = m_pbVoiceData + iController * ARRAYSIZE( m_pbVoiceData ) / XUSER_MAX_COUNT; |
|
memset( pbVoiceData, 0, size ); |
|
} |
|
|
|
void CEngineVoiceSteam::SetPlaybackPriority( XUID remoteTalker, int iController, int iAllowPlayback ) |
|
{ |
|
; |
|
} |
|
|
|
void CEngineVoiceSteam::PlayIncomingVoiceData( XUID xuid, const byte *pbData, unsigned int dwDataSize, const bool *bAudiblePlayers /* = NULL */ ) |
|
{ |
|
for ( DWORD dwSlot = 0; dwSlot < XBX_GetNumGameUsers(); ++ dwSlot ) |
|
{ |
|
IPlayerLocal *pPlayer = g_pMatchFramework->GetMatchSystem()->GetPlayerManager()->GetLocalPlayer( dwSlot ); |
|
if ( pPlayer && pPlayer->GetXUID() == xuid ) |
|
//Hack: Don't play stuff that comes from ourselves. |
|
return; |
|
} |
|
|
|
// Make sure voice playback is allowed for the specified user |
|
if ( !g_pMatchFramework->GetMatchSystem()->GetMatchVoice()->CanPlaybackTalker( xuid ) ) |
|
return; |
|
|
|
// Uncompress the voice data |
|
char pbUncompressedVoice[ 11025 * 2 ]; |
|
uint32 numUncompressedBytes; |
|
EVoiceResult res = Steam3Client().SteamUser()->DecompressVoice( const_cast< byte * >( pbData ), dwDataSize, |
|
pbUncompressedVoice, sizeof( pbUncompressedVoice ), &numUncompressedBytes, 0 ); |
|
|
|
if ( res != k_EVoiceResultOK ) |
|
return; |
|
|
|
// Voice channel index |
|
int idxVoiceChan = 0; |
|
int idxRemoteTalker = m_arrRemoteVoice.Find( xuid ); |
|
if ( idxRemoteTalker != m_arrRemoteVoice.InvalidIndex() ) |
|
idxVoiceChan = idxRemoteTalker; |
|
|
|
int nChannel = Voice_GetChannel( idxVoiceChan ); |
|
if ( nChannel == VOICE_CHANNEL_ERROR ) |
|
{ |
|
// Create a channel in the voice engine and a channel in the sound engine for this guy. |
|
nChannel = Voice_AssignChannel( idxVoiceChan, false, 0.0f ); |
|
} |
|
|
|
// Give the voice engine the data (it in turn gives it to the mixer for the sound engine). |
|
if ( nChannel != VOICE_CHANNEL_ERROR ) |
|
{ |
|
Voice_AddIncomingData( nChannel, pbUncompressedVoice, numUncompressedBytes, 0, false ); |
|
} |
|
} |
|
|
|
void CEngineVoiceSteam::RemoveAllTalkers() |
|
{ |
|
memset( m_bLocalVoice, 0, sizeof( m_bLocalVoice ) ); |
|
m_arrRemoteVoice.RemoveAll(); |
|
AudioInitializationUpdate(); |
|
} |
|
|
|
void CEngineVoiceSteam::AudioInitializationUpdate() |
|
{ |
|
bool bHasTalkers = ( m_arrRemoteVoice.Count() > 0 ); |
|
for ( int k = 0; k < ARRAYSIZE( m_bLocalVoice ); ++ k ) |
|
{ |
|
if ( m_bLocalVoice[k] ) |
|
{ |
|
bHasTalkers = true; |
|
break; |
|
} |
|
} |
|
|
|
// Initialized already |
|
if ( bHasTalkers == m_bInitializedAudio ) |
|
return; |
|
|
|
// Clear out voice buffers |
|
memset( m_pbVoiceData, 0, sizeof( m_pbVoiceData ) ); |
|
|
|
// Init or deinit voice system |
|
if ( bHasTalkers ) |
|
{ |
|
Voice_ForceInit(); |
|
} |
|
else |
|
{ |
|
Voice_Deinit(); |
|
} |
|
|
|
m_bInitializedAudio = bHasTalkers; |
|
} |
|
|
|
|
|
IEngineVoice *Audio_GetEngineVoiceSteam() |
|
{ |
|
static CEngineVoiceSteam s_EngineVoiceSteam; |
|
return &s_EngineVoiceSteam; |
|
} |
|
|
|
#else |
|
|
|
IEngineVoice *Audio_GetEngineVoiceSteam() |
|
{ |
|
return Audio_GetEngineVoiceStub(); |
|
} |
|
|
|
#endif |