summaryrefslogtreecommitdiff
path: root/engine/audio/private/voice_sound_engine_interface.cpp
diff options
context:
space:
mode:
authorFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
committerFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
commit3bf9df6b2785fa6d951086978a3e66f49427166a (patch)
tree2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /engine/audio/private/voice_sound_engine_interface.cpp
downloadarchived-source-engine-2018-hl2-src-master.tar.xz
archived-source-engine-2018-hl2-src-master.zip
Diffstat (limited to 'engine/audio/private/voice_sound_engine_interface.cpp')
-rw-r--r--engine/audio/private/voice_sound_engine_interface.cpp377
1 files changed, 377 insertions, 0 deletions
diff --git a/engine/audio/private/voice_sound_engine_interface.cpp b/engine/audio/private/voice_sound_engine_interface.cpp
new file mode 100644
index 0000000..3ee5e59
--- /dev/null
+++ b/engine/audio/private/voice_sound_engine_interface.cpp
@@ -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( &copyBuf[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;
+}
+
+