Team Fortress 2 Source Code as on 22/4/2020
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.

526 lines
14 KiB

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