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.

555 lines
16 KiB

  1. //========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $Workfile: $
  6. // $Date: $
  7. //
  8. //-----------------------------------------------------------------------------
  9. // $Log: $
  10. //
  11. // $NoKeywords: $
  12. //=============================================================================//
  13. #ifndef SND_AUDIO_SOURCE_H
  14. #define SND_AUDIO_SOURCE_H
  15. #pragma once
  16. #if !defined( _GAMECONSOLE )
  17. #define MP3_SUPPORT 1
  18. #endif
  19. #define AUDIOSOURCE_COPYBUF_SIZE 4096
  20. struct channel_t;
  21. class CSentence;
  22. class CSfxTable;
  23. class CAudioSource;
  24. class IAudioDevice;
  25. class CUtlBuffer;
  26. #include "tier0/vprof.h"
  27. #include "utlhandletable.h"
  28. //-----------------------------------------------------------------------------
  29. // Purpose: This is an instance of an audio source.
  30. // Mixers are attached to channels and reference an audio source.
  31. // Mixers are specific to the sample format and source format.
  32. // Mixers are never re-used, so they can track instance data like
  33. // sample position, fractional sample, stream cache, faders, etc.
  34. //-----------------------------------------------------------------------------
  35. abstract_class CAudioMixer
  36. {
  37. public:
  38. virtual ~CAudioMixer( void ) {}
  39. // return number of samples mixed
  40. virtual int MixDataToDevice( channel_t *pChannel, int sampleCount, int outputRate, int outputOffset ) = 0;
  41. virtual int SkipSamples( channel_t *pChannel, int sampleCount, int outputRate, int outputOffset ) = 0;
  42. virtual bool ShouldContinueMixing( void ) = 0;
  43. virtual CAudioSource *GetSource( void ) = 0;
  44. // get the current position (next sample to be mixed)
  45. virtual int GetSamplePosition( void ) = 0;
  46. // Allow the mixer to modulate pitch and volume.
  47. // returns a floating point modulator
  48. virtual float ModifyPitch( float pitch ) = 0;
  49. virtual float GetVolumeScale( void ) = 0;
  50. // NOTE: Playback is optimized for linear streaming. These calls will usually cost performance
  51. // It is currently optimal to call them before any playback starts, but some audio sources may not
  52. // guarantee this. Also, some mixers may choose to ignore these calls for internal reasons (none do currently).
  53. virtual bool IsSetSampleStartSupported() const = 0;
  54. // Move the current position to newPosition
  55. // BUGBUG: THIS CALL DOES NOT SUPPORT MOVING BACKWARD, ONLY FORWARD!!!
  56. virtual void SetSampleStart( int newPosition ) = 0;
  57. // End playback at newEndPosition
  58. virtual void SetSampleEnd( int newEndPosition ) = 0;
  59. // How many samples to skip before commencing actual data reading ( to allow sub-frametime sound
  60. // offsets and avoid synchronizing sounds to various 100 msec clock intervals throughout the
  61. // engine and game code)
  62. virtual void SetStartupDelaySamples( int delaySamples ) = 0;
  63. virtual int GetMixSampleSize() = 0;
  64. // Certain async loaded sounds lazilly load into memory in the background, use this to determine
  65. // if the sound is ready for mixing
  66. virtual bool IsReadyToMix() = 0;
  67. // NOTE: The "saved" position can be different than the "sample" position
  68. // NOTE: Allows mixer to save file offsets, loop info, etc
  69. virtual int GetPositionForSave() = 0;
  70. virtual void SetPositionFromSaved( int savedPosition ) = 0;
  71. };
  72. inline int CalcSampleSize( int bitsPerSample, int channels )
  73. {
  74. return (bitsPerSample >> 3) * channels;
  75. }
  76. #include "UtlCachedFileData.h"
  77. class CSentence;
  78. class CSfxTable;
  79. class CAudioSourceCachedInfo : public IBaseCacheInfo
  80. {
  81. public:
  82. CAudioSourceCachedInfo();
  83. CAudioSourceCachedInfo( const CAudioSourceCachedInfo& src );
  84. virtual ~CAudioSourceCachedInfo();
  85. CAudioSourceCachedInfo& operator =( const CAudioSourceCachedInfo& src );
  86. void Clear();
  87. void RemoveData();
  88. virtual void Save( CUtlBuffer& buf );
  89. virtual void Restore( CUtlBuffer& buf );
  90. virtual void Rebuild( char const *filename );
  91. // A hack, but will work okay
  92. static int s_CurrentType;
  93. static CSfxTable *s_pSfx;
  94. static bool s_bIsPrecacheSound;
  95. inline int Type() const
  96. {
  97. return info.m_Type;
  98. }
  99. void SetType( int type )
  100. {
  101. info.m_Type = type;
  102. }
  103. inline int Bits() const
  104. {
  105. return info.m_bits;
  106. }
  107. void SetBits( int bits )
  108. {
  109. info.m_bits = bits;
  110. }
  111. inline int Channels() const
  112. {
  113. return info.m_channels;
  114. }
  115. void SetChannels( int channels )
  116. {
  117. info.m_channels = channels;
  118. }
  119. inline int SampleSize() const
  120. {
  121. return info.m_sampleSize;
  122. }
  123. void SetSampleSize( int size )
  124. {
  125. info.m_sampleSize = size;
  126. }
  127. inline int Format() const
  128. {
  129. return info.m_format;
  130. }
  131. void SetFormat( int format )
  132. {
  133. info.m_format = format;
  134. }
  135. inline int SampleRate() const
  136. {
  137. return info.m_rate;
  138. }
  139. void SetSampleRate( int rate )
  140. {
  141. info.m_rate = rate;
  142. }
  143. inline int CachedDataSize() const
  144. {
  145. return (int)m_usCachedDataSize;
  146. }
  147. void SetCachedDataSize( int size )
  148. {
  149. m_usCachedDataSize = (unsigned short)size;
  150. }
  151. inline const byte *CachedData() const
  152. {
  153. return m_pCachedData;
  154. }
  155. void SetCachedData( const byte *data )
  156. {
  157. m_pCachedData = ( byte * )data;
  158. flags.m_bCachedData = ( data != NULL ) ? true : false;
  159. }
  160. inline int HeaderSize() const
  161. {
  162. return (int)m_usHeaderSize;
  163. }
  164. void SetHeaderSize( int size )
  165. {
  166. m_usHeaderSize = (unsigned short)size;
  167. }
  168. inline const byte *HeaderData() const
  169. {
  170. return m_pHeader;
  171. }
  172. void SetHeaderData( const byte *data )
  173. {
  174. m_pHeader = ( byte * )data;
  175. flags.m_bHeader = ( data != NULL ) ? true : false;
  176. }
  177. inline int LoopStart() const
  178. {
  179. return m_loopStart;
  180. }
  181. void SetLoopStart( int start )
  182. {
  183. m_loopStart = start;
  184. }
  185. inline int SampleCount() const
  186. {
  187. return m_sampleCount;
  188. }
  189. void SetSampleCount( int count )
  190. {
  191. m_sampleCount = count;
  192. }
  193. inline int DataStart() const
  194. {
  195. return m_dataStart;
  196. }
  197. void SetDataStart( int start )
  198. {
  199. m_dataStart = start;
  200. }
  201. inline int DataSize() const
  202. {
  203. return m_dataSize;
  204. }
  205. void SetDataSize( int size )
  206. {
  207. m_dataSize = size;
  208. }
  209. inline CSentence *Sentence() const
  210. {
  211. return m_pSentence;
  212. }
  213. void SetSentence( CSentence *sentence )
  214. {
  215. m_pSentence = sentence;
  216. flags.m_bSentence = ( sentence != NULL ) ? true : false;
  217. }
  218. private:
  219. union
  220. {
  221. unsigned int infolong;
  222. struct
  223. {
  224. unsigned int m_Type : 2; // 0 1 2 or 3
  225. unsigned int m_bits : 5; // 0 to 31
  226. unsigned int m_channels : 2; // 1 or 2
  227. unsigned int m_sampleSize : 3; // 1 2 or 4
  228. unsigned int m_format : 2; // 1 == PCM, 2 == ADPCM
  229. unsigned int m_rate : 17; // 0 to 64 K
  230. } info;
  231. };
  232. union
  233. {
  234. byte flagsbyte;
  235. struct
  236. {
  237. bool m_bSentence : 1;
  238. bool m_bCachedData : 1;
  239. bool m_bHeader : 1;
  240. } flags;
  241. };
  242. int m_loopStart;
  243. int m_sampleCount;
  244. int m_dataStart; // offset of wave data chunk
  245. int m_dataSize; // size of wave data chunk
  246. unsigned short m_usCachedDataSize;
  247. unsigned short m_usHeaderSize;
  248. CSentence *m_pSentence;
  249. byte *m_pCachedData;
  250. byte *m_pHeader;
  251. };
  252. class IAudioSourceCache
  253. {
  254. public:
  255. virtual bool Init( unsigned int memSize ) = 0;
  256. virtual void Shutdown() = 0;
  257. virtual void LevelInit( char const *mapname ) = 0;
  258. virtual void LevelShutdown() = 0;
  259. virtual CAudioSourceCachedInfo *GetInfo( int audiosourcetype, bool soundisprecached, CSfxTable *sfx ) = 0;
  260. virtual CAudioSourceCachedInfo *GetInfoByName( const char *soundName ) = 0;
  261. virtual void RebuildCacheEntry( int audiosourcetype, bool soundisprecached, CSfxTable *sfx ) = 0;
  262. };
  263. extern IAudioSourceCache *audiosourcecache;
  264. typedef UtlHandle_t WaveCacheHandle_t;
  265. enum
  266. {
  267. // purposely 0
  268. INVALID_WAVECACHE_HANDLE = (UtlHandle_t)0
  269. };
  270. typedef int StreamHandle_t;
  271. enum
  272. {
  273. INVALID_STREAM_HANDLE = (StreamHandle_t)~0
  274. };
  275. typedef int BufferHandle_t;
  276. enum
  277. {
  278. INVALID_BUFFER_HANDLE = (BufferHandle_t)~0
  279. };
  280. typedef unsigned int streamFlags_t;
  281. enum
  282. {
  283. STREAMED_FROMDVD = 0x00000001, // stream buffers are compliant to dvd sectors
  284. STREAMED_SINGLEPLAY = 0x00000002, // non recurring data, buffers don't need to persist and can be recycled
  285. STREAMED_QUEUEDLOAD = 0x00000004, // hint the streamer to load using the queued loader system
  286. STREAMED_TRANSIENT = 0x00000008, // hint the streamer to pool memory buffers according to dynamic nature
  287. };
  288. enum SoundError
  289. {
  290. SE_NO_STREAM_BUFFER = -1000,
  291. SE_FILE_NOT_FOUND,
  292. SE_CANT_GET_NAME,
  293. SE_SKIPPED,
  294. SE_NO_SOURCE_SETUP,
  295. SE_CANT_CREATE_MIXER,
  296. // Avoid 0 on purpose, to avoid ambiguity on the meaning
  297. SE_OK = 1,
  298. };
  299. abstract_class IAsyncWavDataCache
  300. {
  301. public:
  302. virtual bool Init( unsigned int memSize ) = 0;
  303. virtual void Shutdown() = 0;
  304. // implementation that treats file as monolithic
  305. virtual WaveCacheHandle_t AsyncLoadCache( char const *filename, int datasize, int startpos, bool bIsPrefetch = false ) = 0;
  306. virtual void PrefetchCache( char const *filename, int datasize, int startpos ) = 0;
  307. virtual bool CopyDataIntoMemory( char const *filename, int datasize, int startpos, void *buffer, int bufsize, int copystartpos, int bytestocopy, bool *pbPostProcessed ) = 0;
  308. virtual bool CopyDataIntoMemory( WaveCacheHandle_t& handle, char const *filename, int datasize, int startpos, void *buffer, int bufsize, int copystartpos, int bytestocopy, bool *pbPostProcessed ) = 0;
  309. virtual bool IsDataLoadCompleted( WaveCacheHandle_t handle, bool *pIsValid, bool *pIsMissing = NULL ) = 0;
  310. virtual void RestartDataLoad( WaveCacheHandle_t *pHandle, const char *pFilename, int dataSize, int startpos ) = 0;
  311. virtual bool GetDataPointer( WaveCacheHandle_t& handle, char const *filename, int datasize, int startpos, void **pData, int copystartpos, bool *pbPostProcessed ) = 0;
  312. virtual void SetPostProcessed( WaveCacheHandle_t handle, bool proc ) = 0;
  313. virtual void Unload( WaveCacheHandle_t handle ) = 0;
  314. // alternate multi-buffer streaming implementation
  315. virtual StreamHandle_t OpenStreamedLoad( char const *pFileName, int dataSize, int dataStart, int startPos, int loopPos, int bufferSize, int numBuffers, streamFlags_t flags, SoundError &soundError ) = 0;
  316. virtual void CloseStreamedLoad( StreamHandle_t hStream ) = 0;
  317. virtual int CopyStreamedDataIntoMemory( StreamHandle_t hStream, void *pBuffer, int buffSize, int copyStartPos, int bytesToCopy ) = 0;
  318. virtual bool IsStreamedDataReady( StreamHandle_t hStream ) = 0;
  319. virtual void MarkBufferDiscarded( BufferHandle_t hBuffer ) = 0;
  320. virtual void *GetStreamedDataPointer( StreamHandle_t hStream, bool bSync ) = 0;
  321. virtual bool IsDataLoadInProgress( WaveCacheHandle_t handle ) = 0;
  322. virtual void Flush( bool bTearDownStaticPool = false ) = 0;
  323. // This can get called by some implementation when a more accurate loop position has been found later in the process.
  324. // For example, the initial loop can be the position in bytes in decompressed samples.
  325. // But later, while the sound is being decompressed, a more accurate loop can be set based on the position in the compressed samples.
  326. virtual void UpdateLoopPosition( StreamHandle_t hStream, int nLoopPosition ) = 0;
  327. };
  328. extern IAsyncWavDataCache *wavedatacache;
  329. struct CAudioSourceCachedInfoHandle_t
  330. {
  331. CAudioSourceCachedInfoHandle_t() :
  332. info( NULL ),
  333. m_FlushCount( 0 )
  334. {
  335. }
  336. CAudioSourceCachedInfo *info;
  337. unsigned int m_FlushCount;
  338. inline CAudioSourceCachedInfo *Get( int audiosourcetype, bool soundisprecached, CSfxTable *sfx, int *pcacheddatasize )
  339. {
  340. VPROF("CAudioSourceCachedInfoHandle_t::Get");
  341. if ( m_FlushCount != s_nCurrentFlushCount )
  342. {
  343. // Reacquire
  344. info = audiosourcecache->GetInfo( audiosourcetype, soundisprecached, sfx );
  345. if ( pcacheddatasize && info )
  346. {
  347. *pcacheddatasize = info->CachedDataSize();
  348. }
  349. // Tag as current
  350. m_FlushCount = s_nCurrentFlushCount;
  351. }
  352. return info;
  353. }
  354. inline bool IsValid()
  355. {
  356. return !!( m_FlushCount == s_nCurrentFlushCount );
  357. }
  358. inline CAudioSourceCachedInfo *FastGet()
  359. {
  360. VPROF("CAudioSourceCachedInfoHandle_t::FastGet");
  361. if ( m_FlushCount != s_nCurrentFlushCount )
  362. {
  363. return NULL;
  364. }
  365. return info;
  366. }
  367. static void InvalidateCache();
  368. static unsigned int s_nCurrentFlushCount;
  369. };
  370. //-----------------------------------------------------------------------------
  371. // Purpose: A source is an abstraction for a stream, cached file, or procedural
  372. // source of audio.
  373. //-----------------------------------------------------------------------------
  374. abstract_class CAudioSource
  375. {
  376. public:
  377. enum
  378. {
  379. AUDIO_SOURCE_UNK = 0,
  380. AUDIO_SOURCE_WAV,
  381. AUDIO_SOURCE_MP3,
  382. AUDIO_SOURCE_VOICE,
  383. AUDIO_SOURCE_MAXTYPE,
  384. };
  385. enum
  386. {
  387. AUDIO_NOT_LOADED = 0,
  388. AUDIO_IS_LOADED,
  389. AUDIO_LOADING,
  390. AUDIO_ERROR_LOADING,
  391. };
  392. virtual ~CAudioSource( void ) {}
  393. // Create an instance (mixer) of this audio source
  394. virtual CAudioMixer *CreateMixer( int initialStreamPosition, int skipInitialSamples, bool bUpdateDelayForChoreo, SoundError &soundError, struct hrtf_info_t *pHRTFPos ) = 0;
  395. // Serialization for caching
  396. virtual int GetType( void ) = 0;
  397. virtual void GetCacheData( CAudioSourceCachedInfo *info ) = 0;
  398. // Provide samples for the mixer. You can point pData at your own data, or if you prefer to copy the data,
  399. // you can copy it into copyBuf and set pData to copyBuf.
  400. virtual int GetOutputData( void **pData, int64 samplePosition, int sampleCount, char copyBuf[AUDIOSOURCE_COPYBUF_SIZE] ) = 0;
  401. virtual int SampleRate( void ) = 0;
  402. // Returns true if the source is a voice source.
  403. // This affects the voice_overdrive behavior (all sounds get quieter when
  404. // someone is speaking).
  405. virtual bool IsVoiceSource() = 0;
  406. // Returns true if this sound comes from player voice chat
  407. virtual bool IsPlayerVoice() {return true;}
  408. // Sample size is in bytes. It will not be accurate for compressed audio. This is a best estimate.
  409. // The compressed audio mixers understand this, but in general do not assume that SampleSize() * SampleCount() = filesize
  410. // or even that SampleSize() is 100% accurate due to compression.
  411. virtual int SampleSize( void ) = 0;
  412. // Total number of samples in this source. NOTE: Some sources are infinite (mic input), they should return
  413. // a count equal to one second of audio at their current rate.
  414. virtual int SampleCount( void ) = 0;
  415. virtual int Format( void ) = 0;
  416. virtual int DataSize( void ) = 0;
  417. virtual bool IsLooped( void ) = 0;
  418. virtual bool IsStereoWav( void ) = 0;
  419. virtual bool IsStreaming( void ) = 0;
  420. virtual int GetCacheStatus( void ) = 0;
  421. int IsCached( void ) { return GetCacheStatus() == AUDIO_IS_LOADED ? true : false; }
  422. virtual void CacheLoad( void ) = 0;
  423. virtual void CacheUnload( void ) = 0;
  424. virtual CSentence *GetSentence( void ) = 0;
  425. virtual int GetQuality( void ) = 0;
  426. // these are used to find good splice/loop points.
  427. // If not implementing these, simply return sample
  428. virtual int ZeroCrossingBefore( int sample ) = 0;
  429. virtual int ZeroCrossingAfter( int sample ) = 0;
  430. // mixer's references
  431. virtual void ReferenceAdd( CAudioMixer *pMixer ) = 0;
  432. virtual void ReferenceRemove( CAudioMixer *pMixer ) = 0;
  433. // check reference count, return true if nothing is referencing this
  434. virtual bool CanDelete( void ) = 0;
  435. virtual void Prefetch() = 0;
  436. virtual bool IsAsyncLoad() = 0;
  437. // Make sure our data is rebuilt into the per-level cache
  438. virtual void CheckAudioSourceCache() = 0;
  439. virtual char const *GetFileName(char *pBuf, size_t bufLen) = 0;
  440. virtual void SetPlayOnce( bool ) = 0;
  441. virtual bool IsPlayOnce() = 0;
  442. // Used to identify a word that is part of a sentence mixing operation
  443. virtual void SetSentenceWord( bool bIsWord ) = 0;
  444. virtual bool IsSentenceWord() = 0;
  445. virtual int SampleToStreamPosition( int samplePosition ) = 0;
  446. virtual int StreamToSamplePosition( int streamPosition ) = 0;
  447. };
  448. // Fast method for determining duration of .wav/.mp3, exposed to server as well
  449. extern float AudioSource_GetSoundDuration( char const *pName );
  450. // uses wave file cached in memory already
  451. extern float AudioSource_GetSoundDuration( CSfxTable *pSfx );
  452. #endif // SND_AUDIO_SOURCE_H