mirror of
https://github.com/celisej567/source-engine.git
synced 2026-01-04 18:09:53 +03:00
1
This commit is contained in:
377
engine/audio/private/voice_sound_engine_interface.cpp
Normal file
377
engine/audio/private/voice_sound_engine_interface.cpp
Normal file
@@ -0,0 +1,377 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#include "audio_pch.h"
|
||||
#include <assert.h>
|
||||
#include "voice.h"
|
||||
#include "ivoicecodec.h"
|
||||
|
||||
#if defined( _X360 )
|
||||
#include "xauddefs.h"
|
||||
#endif
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
// ------------------------------------------------------------------------- //
|
||||
// CAudioSourceVoice.
|
||||
// This feeds the data from an incoming voice channel (a guy on the server
|
||||
// who is speaking) into the sound engine.
|
||||
// ------------------------------------------------------------------------- //
|
||||
|
||||
class CAudioSourceVoice : public CAudioSourceWave
|
||||
{
|
||||
public:
|
||||
CAudioSourceVoice(CSfxTable *pSfx, int iEntity);
|
||||
virtual ~CAudioSourceVoice();
|
||||
|
||||
virtual int GetType( void )
|
||||
{
|
||||
return AUDIO_SOURCE_VOICE;
|
||||
}
|
||||
virtual void GetCacheData( CAudioSourceCachedInfo *info )
|
||||
{
|
||||
Assert( 0 );
|
||||
}
|
||||
|
||||
|
||||
virtual CAudioMixer *CreateMixer( int initialStreamPosition = 0 );
|
||||
virtual int GetOutputData( void **pData, int samplePosition, int sampleCount, char copyBuf[AUDIOSOURCE_COPYBUF_SIZE] );
|
||||
virtual int SampleRate( void );
|
||||
|
||||
// Sample size is in bytes. It will not be accurate for compressed audio. This is a best estimate.
|
||||
// The compressed audio mixers understand this, but in general do not assume that SampleSize() * SampleCount() = filesize
|
||||
// or even that SampleSize() is 100% accurate due to compression.
|
||||
virtual int SampleSize( void );
|
||||
|
||||
// Total number of samples in this source. NOTE: Some sources are infinite (mic input), they should return
|
||||
// a count equal to one second of audio at their current rate.
|
||||
virtual int SampleCount( void );
|
||||
|
||||
virtual bool IsVoiceSource() {return true;}
|
||||
|
||||
virtual bool IsLooped() {return false;}
|
||||
virtual bool IsStreaming() {return true;}
|
||||
virtual bool IsStereoWav() {return false;}
|
||||
virtual int GetCacheStatus() {return AUDIO_IS_LOADED;}
|
||||
virtual void CacheLoad() {}
|
||||
virtual void CacheUnload() {}
|
||||
virtual CSentence *GetSentence() {return NULL;}
|
||||
|
||||
virtual int ZeroCrossingBefore( int sample ) {return sample;}
|
||||
virtual int ZeroCrossingAfter( int sample ) {return sample;}
|
||||
|
||||
// mixer's references
|
||||
virtual void ReferenceAdd( CAudioMixer *pMixer );
|
||||
virtual void ReferenceRemove( CAudioMixer *pMixer );
|
||||
|
||||
// check reference count, return true if nothing is referencing this
|
||||
virtual bool CanDelete();
|
||||
|
||||
virtual void Prefetch() {}
|
||||
|
||||
// Nothing, not a cache object...
|
||||
virtual void CheckAudioSourceCache() {}
|
||||
|
||||
private:
|
||||
|
||||
class CWaveDataVoice : public IWaveData
|
||||
{
|
||||
public:
|
||||
CWaveDataVoice( CAudioSourceWave &source ) : m_source(source) {}
|
||||
~CWaveDataVoice( void ) {}
|
||||
|
||||
virtual CAudioSource &Source( void )
|
||||
{
|
||||
return m_source;
|
||||
}
|
||||
|
||||
// this file is in memory, simply pass along the data request to the source
|
||||
virtual int ReadSourceData( void **pData, int sampleIndex, int sampleCount, char copyBuf[AUDIOSOURCE_COPYBUF_SIZE] )
|
||||
{
|
||||
return m_source.GetOutputData( pData, sampleIndex, sampleCount, copyBuf );
|
||||
}
|
||||
|
||||
virtual bool IsReadyToMix()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
CAudioSourceWave &m_source; // pointer to source
|
||||
};
|
||||
|
||||
|
||||
private:
|
||||
CAudioSourceVoice( const CAudioSourceVoice & );
|
||||
|
||||
// Which entity's voice this is for.
|
||||
int m_iChannel;
|
||||
|
||||
// How many mixers are referencing us.
|
||||
int m_refCount;
|
||||
};
|
||||
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------- //
|
||||
// Globals.
|
||||
// ----------------------------------------------------------------------------- //
|
||||
|
||||
// The format we sample voice in.
|
||||
extern WAVEFORMATEX g_VoiceSampleFormat;
|
||||
|
||||
class CVoiceSfx : public CSfxTable
|
||||
{
|
||||
public:
|
||||
virtual const char *getname()
|
||||
{
|
||||
return "?VoiceSfx";
|
||||
}
|
||||
};
|
||||
|
||||
static CVoiceSfx g_CVoiceSfx[VOICE_NUM_CHANNELS];
|
||||
|
||||
static float g_VoiceOverdriveDuration = 0;
|
||||
static bool g_bVoiceOverdriveOn = false;
|
||||
|
||||
// When voice is on, all other sounds are decreased by this factor.
|
||||
static ConVar voice_overdrive( "voice_overdrive", "2" );
|
||||
static ConVar voice_overdrivefadetime( "voice_overdrivefadetime", "0.4" ); // How long it takes to fade in and out of the voice overdrive.
|
||||
|
||||
// The sound engine uses this to lower all sound volumes.
|
||||
// All non-voice sounds are multiplied by this and divided by 256.
|
||||
int g_SND_VoiceOverdriveInt = 256;
|
||||
|
||||
|
||||
extern int Voice_SamplesPerSec();
|
||||
extern int Voice_AvgBytesPerSec();
|
||||
|
||||
// ----------------------------------------------------------------------------- //
|
||||
// CAudioSourceVoice implementation.
|
||||
// ----------------------------------------------------------------------------- //
|
||||
|
||||
CAudioSourceVoice::CAudioSourceVoice( CSfxTable *pSfx, int iChannel )
|
||||
: CAudioSourceWave( pSfx )
|
||||
{
|
||||
m_iChannel = iChannel;
|
||||
m_refCount = 0;
|
||||
|
||||
WAVEFORMATEX tmp = g_VoiceSampleFormat;
|
||||
tmp.nSamplesPerSec = Voice_SamplesPerSec();
|
||||
tmp.nAvgBytesPerSec = Voice_AvgBytesPerSec();
|
||||
Init((char*)&tmp, sizeof(tmp));
|
||||
m_sampleCount = tmp.nSamplesPerSec;
|
||||
}
|
||||
|
||||
CAudioSourceVoice::~CAudioSourceVoice()
|
||||
{
|
||||
Voice_OnAudioSourceShutdown( m_iChannel );
|
||||
}
|
||||
|
||||
CAudioMixer *CAudioSourceVoice::CreateMixer( int initialStreamPosition )
|
||||
{
|
||||
CWaveDataVoice *pVoice = new CWaveDataVoice(*this);
|
||||
if(!pVoice)
|
||||
return NULL;
|
||||
|
||||
CAudioMixer *pMixer = CreateWaveMixer( pVoice, WAVE_FORMAT_PCM, 1, BYTES_PER_SAMPLE*8, 0 );
|
||||
if(!pMixer)
|
||||
{
|
||||
delete pVoice;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return pMixer;
|
||||
}
|
||||
|
||||
int CAudioSourceVoice::GetOutputData( void **pData, int samplePosition, int sampleCount, char copyBuf[AUDIOSOURCE_COPYBUF_SIZE] )
|
||||
{
|
||||
int nSamplesGotten = Voice_GetOutputData(
|
||||
m_iChannel,
|
||||
copyBuf,
|
||||
AUDIOSOURCE_COPYBUF_SIZE,
|
||||
samplePosition,
|
||||
sampleCount );
|
||||
|
||||
// If there weren't enough bytes in the received data channel, pad it with zeros.
|
||||
if( nSamplesGotten < sampleCount )
|
||||
{
|
||||
memset( ©Buf[nSamplesGotten], 0, (sampleCount - nSamplesGotten) * BYTES_PER_SAMPLE );
|
||||
nSamplesGotten = sampleCount;
|
||||
}
|
||||
|
||||
*pData = copyBuf;
|
||||
return nSamplesGotten;
|
||||
}
|
||||
|
||||
int CAudioSourceVoice::SampleRate()
|
||||
{
|
||||
return Voice_SamplesPerSec();
|
||||
}
|
||||
|
||||
int CAudioSourceVoice::SampleSize()
|
||||
{
|
||||
return BYTES_PER_SAMPLE;
|
||||
}
|
||||
|
||||
int CAudioSourceVoice::SampleCount()
|
||||
{
|
||||
return Voice_SamplesPerSec();
|
||||
}
|
||||
|
||||
void CAudioSourceVoice::ReferenceAdd(CAudioMixer *pMixer)
|
||||
{
|
||||
m_refCount++;
|
||||
}
|
||||
|
||||
void CAudioSourceVoice::ReferenceRemove(CAudioMixer *pMixer)
|
||||
{
|
||||
m_refCount--;
|
||||
if ( m_refCount <= 0 )
|
||||
delete this;
|
||||
}
|
||||
|
||||
bool CAudioSourceVoice::CanDelete()
|
||||
{
|
||||
return m_refCount == 0;
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------- //
|
||||
// Interface implementation.
|
||||
// ----------------------------------------------------------------------------- //
|
||||
|
||||
bool VoiceSE_Init()
|
||||
{
|
||||
if( !snd_initialized )
|
||||
return false;
|
||||
|
||||
g_SND_VoiceOverdriveInt = 256;
|
||||
return true;
|
||||
}
|
||||
|
||||
void VoiceSE_Term()
|
||||
{
|
||||
// Disable voice ducking.
|
||||
g_SND_VoiceOverdriveInt = 256;
|
||||
}
|
||||
|
||||
|
||||
void VoiceSE_Idle(float frametime)
|
||||
{
|
||||
g_SND_VoiceOverdriveInt = 256;
|
||||
|
||||
if( g_bVoiceOverdriveOn )
|
||||
{
|
||||
g_VoiceOverdriveDuration = min( g_VoiceOverdriveDuration+frametime, voice_overdrivefadetime.GetFloat() );
|
||||
}
|
||||
else
|
||||
{
|
||||
if(g_VoiceOverdriveDuration == 0)
|
||||
return;
|
||||
|
||||
g_VoiceOverdriveDuration = max(g_VoiceOverdriveDuration-frametime, 0.f);
|
||||
}
|
||||
|
||||
float percent = g_VoiceOverdriveDuration / voice_overdrivefadetime.GetFloat();
|
||||
percent = (float)(-cos(percent * 3.1415926535) * 0.5 + 0.5); // Smooth it out..
|
||||
float voiceOverdrive = 1 + (voice_overdrive.GetFloat() - 1) * percent;
|
||||
g_SND_VoiceOverdriveInt = (int)(256 / voiceOverdrive);
|
||||
}
|
||||
|
||||
|
||||
int VoiceSE_StartChannel(
|
||||
int iChannel, //! Which channel to start.
|
||||
int iEntity,
|
||||
bool bProximity,
|
||||
int nViewEntityIndex )
|
||||
{
|
||||
Assert( iChannel >= 0 && iChannel < VOICE_NUM_CHANNELS );
|
||||
|
||||
// Start the sound.
|
||||
CSfxTable *sfx = &g_CVoiceSfx[iChannel];
|
||||
sfx->pSource = NULL;
|
||||
Vector vOrigin(0,0,0);
|
||||
|
||||
StartSoundParams_t params;
|
||||
params.staticsound = false;
|
||||
params.entchannel = (CHAN_VOICE_BASE+iChannel);
|
||||
params.pSfx = sfx;
|
||||
params.origin = vOrigin;
|
||||
params.fvol = 1.0f;
|
||||
params.flags = 0;
|
||||
params.pitch = PITCH_NORM;
|
||||
|
||||
|
||||
if ( bProximity == true )
|
||||
{
|
||||
params.bUpdatePositions = true;
|
||||
params.soundlevel = SNDLVL_TALKING;
|
||||
params.soundsource = iEntity;
|
||||
}
|
||||
else
|
||||
{
|
||||
params.soundlevel = SNDLVL_IDLE;
|
||||
params.soundsource = nViewEntityIndex;
|
||||
}
|
||||
|
||||
|
||||
return S_StartSound( params );
|
||||
}
|
||||
|
||||
void VoiceSE_EndChannel(
|
||||
int iChannel, //! Which channel to stop.
|
||||
int iEntity
|
||||
)
|
||||
{
|
||||
Assert( iChannel >= 0 && iChannel < VOICE_NUM_CHANNELS );
|
||||
|
||||
S_StopSound( iEntity, CHAN_VOICE_BASE+iChannel );
|
||||
|
||||
// Start the sound.
|
||||
CSfxTable *sfx = &g_CVoiceSfx[iChannel];
|
||||
sfx->pSource = NULL;
|
||||
}
|
||||
|
||||
void VoiceSE_StartOverdrive()
|
||||
{
|
||||
g_bVoiceOverdriveOn = true;
|
||||
}
|
||||
|
||||
void VoiceSE_EndOverdrive()
|
||||
{
|
||||
g_bVoiceOverdriveOn = false;
|
||||
}
|
||||
|
||||
|
||||
void VoiceSE_InitMouth(int entnum)
|
||||
{
|
||||
}
|
||||
|
||||
void VoiceSE_CloseMouth(int entnum)
|
||||
{
|
||||
}
|
||||
|
||||
void VoiceSE_MoveMouth(int entnum, short *pSamples, int nSamples)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
CAudioSource* Voice_SetupAudioSource( int soundsource, int entchannel )
|
||||
{
|
||||
int iChannel = entchannel - CHAN_VOICE_BASE;
|
||||
if( iChannel >= 0 && iChannel < VOICE_NUM_CHANNELS )
|
||||
{
|
||||
CSfxTable *sfx = &g_CVoiceSfx[iChannel];
|
||||
return new CAudioSourceVoice( sfx, iChannel );
|
||||
}
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user