Counter Strike : Global Offensive Source Code
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.

397 lines
9.8 KiB

  1. //========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #include "audio_pch.h"
  8. #include <assert.h>
  9. #include "voice.h"
  10. #include "ivoicecodec.h"
  11. #if defined( _X360 )
  12. #include "xauddefs.h"
  13. #endif
  14. // memdbgon must be the last include file in a .cpp file!!!
  15. #include "tier0/memdbgon.h"
  16. // ------------------------------------------------------------------------- //
  17. // CAudioSourceVoice.
  18. // This feeds the data from an incoming voice channel (a guy on the server
  19. // who is speaking) into the sound engine.
  20. // ------------------------------------------------------------------------- //
  21. class CAudioSourceVoice : public CAudioSourceWave
  22. {
  23. public:
  24. CAudioSourceVoice(CSfxTable *pSfx, int iEntity);
  25. virtual ~CAudioSourceVoice();
  26. virtual int GetType( void )
  27. {
  28. return AUDIO_SOURCE_VOICE;
  29. }
  30. virtual void GetCacheData( CAudioSourceCachedInfo *info )
  31. {
  32. Assert( 0 );
  33. }
  34. virtual CAudioMixer *CreateMixer( int initialStreamPosition, int skipInitialSamples, bool bUpdateDelayForChoreo, SoundError &soundError, struct hrtf_info_t* pHRTFVec );
  35. virtual int GetOutputData( void **pData, int64 samplePosition, int sampleCount, char copyBuf[AUDIOSOURCE_COPYBUF_SIZE] );
  36. virtual int SampleRate( void );
  37. // Sample size is in bytes. It will not be accurate for compressed audio. This is a best estimate.
  38. // The compressed audio mixers understand this, but in general do not assume that SampleSize() * SampleCount() = filesize
  39. // or even that SampleSize() is 100% accurate due to compression.
  40. virtual int SampleSize( void );
  41. // Total number of samples in this source. NOTE: Some sources are infinite (mic input), they should return
  42. // a count equal to one second of audio at their current rate.
  43. virtual int SampleCount( void );
  44. virtual bool IsVoiceSource() {return true;}
  45. virtual bool IsPlayerVoice() {return true;}
  46. virtual bool IsLooped() {return false;}
  47. virtual bool IsStreaming() {return true;}
  48. virtual bool IsStereoWav() {return false;}
  49. virtual int GetCacheStatus() {return AUDIO_IS_LOADED;}
  50. virtual void CacheLoad() {}
  51. virtual void CacheUnload() {}
  52. virtual CSentence *GetSentence() {return NULL;}
  53. virtual int GetQuality() { return 0; }
  54. virtual int ZeroCrossingBefore( int sample ) {return sample;}
  55. virtual int ZeroCrossingAfter( int sample ) {return sample;}
  56. // mixer's references
  57. virtual void ReferenceAdd( CAudioMixer *pMixer );
  58. virtual void ReferenceRemove( CAudioMixer *pMixer );
  59. // check reference count, return true if nothing is referencing this
  60. virtual bool CanDelete();
  61. virtual void Prefetch() {}
  62. // Nothing, not a cache object...
  63. virtual void CheckAudioSourceCache() {}
  64. private:
  65. class CWaveDataVoice : public IWaveData
  66. {
  67. public:
  68. CWaveDataVoice( CAudioSourceWave &source ) : m_source(source) {}
  69. ~CWaveDataVoice( void ) {}
  70. virtual CAudioSource &Source( void )
  71. {
  72. return m_source;
  73. }
  74. // this file is in memory, simply pass along the data request to the source
  75. virtual int ReadSourceData( void **pData, int64 sampleIndex, int sampleCount, char copyBuf[AUDIOSOURCE_COPYBUF_SIZE] )
  76. {
  77. return m_source.GetOutputData( pData, sampleIndex, sampleCount, copyBuf );
  78. }
  79. virtual bool IsReadyToMix()
  80. {
  81. return true;
  82. }
  83. void UpdateLoopPosition( int nLoopPosition )
  84. {
  85. // Should not be necessary in this implementation...
  86. Assert( false );
  87. }
  88. private:
  89. CAudioSourceWave &m_source; // pointer to source
  90. };
  91. private:
  92. CAudioSourceVoice( const CAudioSourceVoice & );
  93. // Which entity's voice this is for.
  94. int m_iChannel;
  95. // How many mixers are referencing us.
  96. int m_refCount;
  97. };
  98. // ----------------------------------------------------------------------------- //
  99. // Globals.
  100. // ----------------------------------------------------------------------------- //
  101. // The format we sample voice in.
  102. extern WAVEFORMATEX g_VoiceSampleFormat;
  103. class CVoiceSfx : public CSfxTable
  104. {
  105. public:
  106. virtual const char *getname( char *pBuf, size_t bufLen )
  107. {
  108. const char *pName = "?VoiceSfx";
  109. V_strncpy( pBuf, pName, bufLen );
  110. return pBuf;
  111. }
  112. };
  113. static CVoiceSfx g_CVoiceSfx[VOICE_NUM_CHANNELS];
  114. static float g_VoiceOverdriveDuration = 0;
  115. static bool g_bVoiceOverdriveOn = false;
  116. // When voice is on, all other sounds are decreased by this factor.
  117. static ConVar voice_overdrive( "voice_overdrive", "2" );
  118. static ConVar voice_overdrivefadetime( "voice_overdrivefadetime", "0.4" ); // How long it takes to fade in and out of the voice overdrive.
  119. // The sound engine uses this to lower all sound volumes.
  120. // All non-voice sounds are multiplied by this and divided by 256.
  121. int g_SND_VoiceOverdriveInt = 256;
  122. extern int Voice_SamplesPerSec();
  123. extern int Voice_AvgBytesPerSec();
  124. // ----------------------------------------------------------------------------- //
  125. // CAudioSourceVoice implementation.
  126. // ----------------------------------------------------------------------------- //
  127. CAudioSourceVoice::CAudioSourceVoice( CSfxTable *pSfx, int iChannel )
  128. : CAudioSourceWave( pSfx )
  129. {
  130. m_iChannel = iChannel;
  131. m_refCount = 0;
  132. WAVEFORMATEX tmp = g_VoiceSampleFormat;
  133. tmp.nSamplesPerSec = Voice_SamplesPerSec();
  134. tmp.nAvgBytesPerSec = Voice_AvgBytesPerSec();
  135. Init((char*)&tmp, sizeof(tmp));
  136. m_sampleCount = tmp.nSamplesPerSec;
  137. }
  138. CAudioSourceVoice::~CAudioSourceVoice()
  139. {
  140. Voice_OnAudioSourceShutdown( m_iChannel );
  141. }
  142. CAudioMixer *CAudioSourceVoice::CreateMixer( int initialStreamPosition, int skipInitialSamples, bool bUpdateDelayForChoreo, SoundError &soundError, struct hrtf_info_t* pHRTFVec )
  143. {
  144. soundError = SE_OK;
  145. CWaveDataVoice *pVoice = new CWaveDataVoice(*this);
  146. if(!pVoice)
  147. {
  148. Assert( false );
  149. soundError = SE_CANT_CREATE_MIXER;
  150. return NULL;
  151. }
  152. CAudioMixer *pMixer = CreateWaveMixer( pVoice, WAVE_FORMAT_PCM, 1, BYTES_PER_SAMPLE*8, initialStreamPosition, skipInitialSamples, bUpdateDelayForChoreo );
  153. if(!pMixer)
  154. {
  155. delete pVoice;
  156. soundError = SE_CANT_CREATE_MIXER;
  157. return NULL;
  158. }
  159. ReferenceAdd( pMixer );
  160. return pMixer;
  161. }
  162. int CAudioSourceVoice::GetOutputData( void **pData, int64 samplePosition, int sampleCount, char copyBuf[AUDIOSOURCE_COPYBUF_SIZE] )
  163. {
  164. int nSamplesGotten = Voice_GetOutputData(
  165. m_iChannel,
  166. copyBuf,
  167. AUDIOSOURCE_COPYBUF_SIZE,
  168. (int)samplePosition,
  169. sampleCount );
  170. // If there weren't enough bytes in the received data channel, pad it with zeros.
  171. if( nSamplesGotten < sampleCount )
  172. {
  173. if ( copyBuf != NULL )
  174. {
  175. memset( &copyBuf[nSamplesGotten], 0, (sampleCount - nSamplesGotten) * BYTES_PER_SAMPLE );
  176. }
  177. nSamplesGotten = sampleCount;
  178. }
  179. *pData = copyBuf;
  180. return nSamplesGotten;
  181. }
  182. int CAudioSourceVoice::SampleRate()
  183. {
  184. return Voice_SamplesPerSec();
  185. }
  186. int CAudioSourceVoice::SampleSize()
  187. {
  188. return BYTES_PER_SAMPLE;
  189. }
  190. int CAudioSourceVoice::SampleCount()
  191. {
  192. return Voice_SamplesPerSec();
  193. }
  194. void CAudioSourceVoice::ReferenceAdd(CAudioMixer *pMixer)
  195. {
  196. m_refCount++;
  197. }
  198. void CAudioSourceVoice::ReferenceRemove(CAudioMixer *pMixer)
  199. {
  200. m_refCount--;
  201. if ( m_refCount <= 0 )
  202. delete this;
  203. }
  204. bool CAudioSourceVoice::CanDelete()
  205. {
  206. return m_refCount == 0;
  207. }
  208. // ----------------------------------------------------------------------------- //
  209. // Interface implementation.
  210. // ----------------------------------------------------------------------------- //
  211. bool VoiceSE_Init()
  212. {
  213. if( !snd_initialized )
  214. return false;
  215. g_SND_VoiceOverdriveInt = 256;
  216. return true;
  217. }
  218. void VoiceSE_Term()
  219. {
  220. // Disable voice ducking.
  221. g_SND_VoiceOverdriveInt = 256;
  222. }
  223. void VoiceSE_Idle(float frametime)
  224. {
  225. g_SND_VoiceOverdriveInt = 256;
  226. if( g_bVoiceOverdriveOn )
  227. {
  228. g_VoiceOverdriveDuration = MIN( g_VoiceOverdriveDuration+frametime, voice_overdrivefadetime.GetFloat() );
  229. }
  230. else
  231. {
  232. if(g_VoiceOverdriveDuration == 0)
  233. return;
  234. g_VoiceOverdriveDuration = MAX(g_VoiceOverdriveDuration-frametime, 0);
  235. }
  236. float percent = g_VoiceOverdriveDuration / voice_overdrivefadetime.GetFloat();
  237. percent = (float)(-cos(percent * 3.1415926535) * 0.5 + 0.5); // Smooth it out..
  238. float voiceOverdrive = 1 + (voice_overdrive.GetFloat() - 1) * percent;
  239. g_SND_VoiceOverdriveInt = (int)(256 / voiceOverdrive);
  240. }
  241. int VoiceSE_StartChannel(
  242. int iChannel, //! Which channel to start.
  243. int iEntity,
  244. bool bProximity,
  245. int nViewEntityIndex )
  246. {
  247. Assert( iChannel >= 0 && iChannel < VOICE_NUM_CHANNELS );
  248. // Start the sound.
  249. CSfxTable *sfx = &g_CVoiceSfx[iChannel];
  250. sfx->pSource = NULL;
  251. Vector vOrigin(0,0,0);
  252. StartSoundParams_t params;
  253. params.staticsound = false;
  254. params.entchannel = (CHAN_VOICE_BASE+iChannel);
  255. params.pSfx = sfx;
  256. params.origin = vOrigin;
  257. params.fvol = 1.0f;
  258. params.flags = 0;
  259. params.pitch = PITCH_NORM;
  260. if ( bProximity == true )
  261. {
  262. params.bUpdatePositions = true;
  263. params.soundlevel = SNDLVL_TALKING;
  264. params.soundsource = iEntity;
  265. }
  266. else
  267. {
  268. params.soundlevel = SNDLVL_IDLE;
  269. params.soundsource = nViewEntityIndex;
  270. }
  271. return S_StartSound( params );
  272. }
  273. void VoiceSE_EndChannel(
  274. int iChannel, //! Which channel to stop.
  275. int iEntity
  276. )
  277. {
  278. Assert( iChannel >= 0 && iChannel < VOICE_NUM_CHANNELS );
  279. S_StopSound( iEntity, CHAN_VOICE_BASE+iChannel );
  280. // Start the sound.
  281. CSfxTable *sfx = &g_CVoiceSfx[iChannel];
  282. sfx->pSource = NULL;
  283. }
  284. void VoiceSE_StartOverdrive()
  285. {
  286. g_bVoiceOverdriveOn = true;
  287. }
  288. void VoiceSE_EndOverdrive()
  289. {
  290. g_bVoiceOverdriveOn = false;
  291. }
  292. void VoiceSE_InitMouth(int entnum)
  293. {
  294. }
  295. void VoiceSE_CloseMouth(int entnum)
  296. {
  297. }
  298. void VoiceSE_MoveMouth(int entnum, short *pSamples, int nSamples)
  299. {
  300. }
  301. CAudioSource* Voice_SetupAudioSource( int soundsource, int entchannel )
  302. {
  303. int iChannel = entchannel - CHAN_VOICE_BASE;
  304. if( iChannel >= 0 && iChannel < VOICE_NUM_CHANNELS )
  305. {
  306. CSfxTable *sfx = &g_CVoiceSfx[iChannel];
  307. return new CAudioSourceVoice( sfx, iChannel );
  308. }
  309. else
  310. return NULL;
  311. }