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.

605 lines
17 KiB

  1. //===== Copyright � 1996-2005, Valve Corporation, All rights reserved. ======//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //
  7. //===========================================================================//
  8. #include <stdio.h>
  9. #include <string.h>
  10. #include <stdlib.h>
  11. #include <windows.h>
  12. #include "tier2/riff.h"
  13. #include "snd_wave_source.h"
  14. #include "snd_wave_mixer_private.h"
  15. #include "snd_audio_source.h"
  16. #include <mmsystem.h> // wave format
  17. #include <mmreg.h> // adpcm format
  18. #include "hlfaceposer.h"
  19. #include "FileSystem.h"
  20. #include "utlbuffer.h"
  21. #include "phonemeconverter.h"
  22. //-----------------------------------------------------------------------------
  23. // Purpose: Implements the RIFF i/o interface on stdio
  24. //-----------------------------------------------------------------------------
  25. class StdIOReadBinary : public IFileReadBinary
  26. {
  27. public:
  28. FileHandle_t open( const char *pFileName )
  29. {
  30. return filesystem->Open( pFileName, "rb" );
  31. }
  32. int read( void *pOutput, int size, FileHandle_t file )
  33. {
  34. if ( !file )
  35. return 0;
  36. return filesystem->Read( pOutput, size, file );
  37. }
  38. void seek( FileHandle_t file, int pos )
  39. {
  40. if ( !file )
  41. return;
  42. filesystem->Seek( file, pos, FILESYSTEM_SEEK_HEAD );
  43. }
  44. unsigned int tell( FileHandle_t file )
  45. {
  46. if ( !file )
  47. return 0;
  48. return filesystem->Tell( file );
  49. }
  50. unsigned int size( FileHandle_t file )
  51. {
  52. if ( !file )
  53. return 0;
  54. return filesystem->Size( file );
  55. }
  56. void close( FileHandle_t file )
  57. {
  58. if ( !file )
  59. return;
  60. filesystem->Close( file );
  61. }
  62. };
  63. static StdIOReadBinary io;
  64. #define RIFF_WAVE MAKEID('W','A','V','E')
  65. #define WAVE_FMT MAKEID('f','m','t',' ')
  66. #define WAVE_DATA MAKEID('d','a','t','a')
  67. #define WAVE_FACT MAKEID('f','a','c','t')
  68. #define WAVE_CUE MAKEID('c','u','e',' ')
  69. void ChunkError( unsigned int id )
  70. {
  71. }
  72. //-----------------------------------------------------------------------------
  73. // Purpose: Init to empty wave
  74. //-----------------------------------------------------------------------------
  75. CAudioSourceWave::CAudioSourceWave( void )
  76. {
  77. m_format = 0;
  78. m_pHeader = NULL;
  79. // no looping
  80. m_loopStart = -1;
  81. m_sampleSize = 1;
  82. m_sampleCount = 0;
  83. }
  84. CAudioSourceWave::~CAudioSourceWave( void )
  85. {
  86. // for non-standard waves, we store a copy of the header in RAM
  87. delete[] m_pHeader;
  88. // m_pWords points into m_pWordBuffer, no need to delete
  89. }
  90. //-----------------------------------------------------------------------------
  91. // Purpose: Init the wave data.
  92. // Input : *pHeaderBuffer - the RIFF fmt chunk
  93. // headerSize - size of that chunk
  94. //-----------------------------------------------------------------------------
  95. void CAudioSourceWave::Init( const char *pHeaderBuffer, int headerSize )
  96. {
  97. const WAVEFORMATEX *pHeader = (const WAVEFORMATEX *)pHeaderBuffer;
  98. // copy the relevant header data
  99. m_format = pHeader->wFormatTag;
  100. m_bits = pHeader->wBitsPerSample;
  101. m_rate = pHeader->nSamplesPerSec;
  102. m_channels = pHeader->nChannels;
  103. m_sampleSize = (m_bits * m_channels) / 8;
  104. // this can never be zero -- other functions divide by this.
  105. // This should never happen, but avoid crashing
  106. if ( m_sampleSize <= 0 )
  107. m_sampleSize = 1;
  108. // For non-standard waves (like ADPCM) store the header, it has some useful data
  109. if ( m_format != WAVE_FORMAT_PCM )
  110. {
  111. m_pHeader = new char[headerSize];
  112. memcpy( m_pHeader, pHeader, headerSize );
  113. if ( m_format == WAVE_FORMAT_ADPCM )
  114. {
  115. // treat ADPCM sources as a file of bytes. They are decoded by the mixer
  116. m_sampleSize = 1;
  117. }
  118. }
  119. }
  120. //-----------------------------------------------------------------------------
  121. // Purpose:
  122. // Output : float
  123. //-----------------------------------------------------------------------------
  124. float CAudioSourceWave::TrueSampleSize( void )
  125. {
  126. if ( m_format == WAVE_FORMAT_ADPCM )
  127. {
  128. return 0.5f;
  129. }
  130. return (float)m_sampleSize;
  131. }
  132. //-----------------------------------------------------------------------------
  133. // Purpose: Total number of samples in this source
  134. // Output : int
  135. //-----------------------------------------------------------------------------
  136. int CAudioSourceWave::SampleCount( void )
  137. {
  138. if ( m_format == WAVE_FORMAT_ADPCM )
  139. {
  140. ADPCMWAVEFORMAT *pFormat = (ADPCMWAVEFORMAT *)m_pHeader;
  141. int blockSize = ((pFormat->wSamplesPerBlock - 2) * pFormat->wfx.nChannels ) / 2;
  142. blockSize += 7 * pFormat->wfx.nChannels;
  143. int blockCount = m_sampleCount / blockSize;
  144. int blockRem = m_sampleCount % blockSize;
  145. // total samples in complete blocks
  146. int sampleCount = blockCount * pFormat->wSamplesPerBlock;
  147. // add remaining in a short block
  148. if ( blockRem )
  149. {
  150. sampleCount += pFormat->wSamplesPerBlock - (((blockSize - blockRem) * 2) / m_channels);
  151. }
  152. return sampleCount;
  153. }
  154. return m_sampleCount;
  155. }
  156. //-----------------------------------------------------------------------------
  157. // Purpose: Do any sample conversion
  158. // For 8 bit PCM, convert to signed because the mixing routine assumes this
  159. // Input : *pData - pointer to sample data
  160. // sampleCount - number of samples
  161. //-----------------------------------------------------------------------------
  162. void CAudioSourceWave::ConvertSamples( char *pData, int sampleCount )
  163. {
  164. if ( m_format == WAVE_FORMAT_PCM )
  165. {
  166. if ( m_bits == 8 )
  167. {
  168. for ( int i = 0; i < sampleCount; i++ )
  169. {
  170. for ( int j = 0; j < m_channels; j++ )
  171. {
  172. *pData = (unsigned char)((int)((unsigned)*pData) - 128);
  173. pData++;
  174. }
  175. }
  176. }
  177. }
  178. }
  179. //-----------------------------------------------------------------------------
  180. // Purpose:
  181. // Input : &walk -
  182. //-----------------------------------------------------------------------------
  183. void CAudioSourceWave::ParseSentence( IterateRIFF &walk )
  184. {
  185. CUtlBuffer buf( 0, 0, CUtlBuffer::TEXT_BUFFER );
  186. buf.EnsureCapacity( walk.ChunkSize() );
  187. walk.ChunkRead( buf.Base() );
  188. buf.SeekPut( CUtlBuffer::SEEK_HEAD, walk.ChunkSize() );
  189. m_Sentence.InitFromDataChunk( buf.Base(), buf.TellPut() );
  190. }
  191. //-----------------------------------------------------------------------------
  192. // Purpose: Parse base chunks
  193. // Input : &walk - riff file to parse
  194. // : chunkName - name of the chunk to parse
  195. //-----------------------------------------------------------------------------
  196. // UNDONE: Move parsing loop here and drop each chunk into a virtual function
  197. // instead of this being virtual.
  198. void CAudioSourceWave::ParseChunk( IterateRIFF &walk, int chunkName )
  199. {
  200. switch( chunkName )
  201. {
  202. case WAVE_CUE:
  203. {
  204. m_loopStart = ParseCueChunk( walk );
  205. }
  206. break;
  207. case WAVE_VALVEDATA:
  208. {
  209. ParseSentence( walk );
  210. }
  211. break;
  212. // unknown/don't care
  213. default:
  214. {
  215. ChunkError( walk.ChunkName() );
  216. }
  217. break;
  218. }
  219. }
  220. //-----------------------------------------------------------------------------
  221. // Purpose:
  222. // Output : CSentence
  223. //-----------------------------------------------------------------------------
  224. CSentence *CAudioSourceWave::GetSentence( void )
  225. {
  226. return &m_Sentence;
  227. }
  228. //-----------------------------------------------------------------------------
  229. // Purpose: Bastardized construction routine. This is just to avoid complex
  230. // constructor functions so code can be shared more easily by sub-classes
  231. // Input : *pFormatBuffer - RIFF header
  232. // formatSize - header size
  233. // &walk - RIFF file
  234. //-----------------------------------------------------------------------------
  235. void CAudioSourceWave::Setup( const char *pFormatBuffer, int formatSize, IterateRIFF &walk )
  236. {
  237. Init( pFormatBuffer, formatSize );
  238. while ( walk.ChunkAvailable() )
  239. {
  240. ParseChunk( walk, walk.ChunkName() );
  241. walk.ChunkNext();
  242. }
  243. }
  244. //-----------------------------------------------------------------------------
  245. // Purpose: Wave file that is completely in memory
  246. // UNDONE: Implement Lock/Unlock and caching
  247. //-----------------------------------------------------------------------------
  248. class CAudioSourceMemWave : public CAudioSourceWave
  249. {
  250. public:
  251. CAudioSourceMemWave( void );
  252. ~CAudioSourceMemWave( void );
  253. // Create an instance (mixer) of this audio source
  254. virtual CAudioMixer *CreateMixer( void );
  255. virtual void ParseChunk( IterateRIFF &walk, int chunkName );
  256. void ParseDataChunk( IterateRIFF &walk );
  257. virtual int GetOutputData( void **pData, int samplePosition, int sampleCount, bool forward = true );
  258. virtual float GetRunningLength( void ) { return CAudioSourceWave::GetRunningLength(); };
  259. virtual int GetNumChannels();
  260. private:
  261. char *m_pData; // wave data
  262. };
  263. //-----------------------------------------------------------------------------
  264. // Purpose: Iterator for wave data (this is to abstract streaming/buffering)
  265. //-----------------------------------------------------------------------------
  266. class CWaveDataMemory : public CWaveData
  267. {
  268. public:
  269. CWaveDataMemory( CAudioSourceWave &source ) : m_source(source) {}
  270. ~CWaveDataMemory( void ) {}
  271. CAudioSourceWave &Source( void ) { return m_source; }
  272. // this file is in memory, simply pass along the data request to the source
  273. virtual int ReadSourceData( void **pData, int sampleIndex, int sampleCount, bool forward /*= true*/ )
  274. {
  275. return m_source.GetOutputData( pData, sampleIndex, sampleCount, forward );
  276. }
  277. private:
  278. CAudioSourceWave &m_source; // pointer to source
  279. };
  280. //-----------------------------------------------------------------------------
  281. // Purpose: NULL the wave data pointer (we haven't loaded yet)
  282. //-----------------------------------------------------------------------------
  283. CAudioSourceMemWave::CAudioSourceMemWave( void )
  284. {
  285. m_pData = NULL;
  286. }
  287. //-----------------------------------------------------------------------------
  288. // Purpose: Free any wave data we've allocated
  289. //-----------------------------------------------------------------------------
  290. CAudioSourceMemWave::~CAudioSourceMemWave( void )
  291. {
  292. delete[] m_pData;
  293. }
  294. //-----------------------------------------------------------------------------
  295. // Purpose: Creates a mixer and initializes it with an appropriate mixer
  296. //-----------------------------------------------------------------------------
  297. CAudioMixer *CAudioSourceMemWave::CreateMixer( void )
  298. {
  299. return CreateWaveMixer( new CWaveDataMemory(*this), m_format, m_channels, m_bits );
  300. }
  301. //-----------------------------------------------------------------------------
  302. // Purpose: parse chunks with unique processing to in-memory waves
  303. // Input : &walk - RIFF file
  304. //-----------------------------------------------------------------------------
  305. void CAudioSourceMemWave::ParseChunk( IterateRIFF &walk, int chunkName )
  306. {
  307. switch( chunkName )
  308. {
  309. // this is the audio data
  310. case WAVE_DATA:
  311. {
  312. ParseDataChunk( walk );
  313. }
  314. return;
  315. }
  316. CAudioSourceWave::ParseChunk( walk, chunkName );
  317. }
  318. //-----------------------------------------------------------------------------
  319. // Purpose: reads the actual sample data and parses it
  320. // Input : &walk - RIFF file
  321. //-----------------------------------------------------------------------------
  322. void CAudioSourceMemWave::ParseDataChunk( IterateRIFF &walk )
  323. {
  324. int size = walk.ChunkSize();
  325. // create a buffer for the samples
  326. m_pData = new char[size];
  327. // load them into memory
  328. walk.ChunkRead( m_pData );
  329. if ( m_format == WAVE_FORMAT_PCM )
  330. {
  331. // number of samples loaded
  332. m_sampleCount = size / m_sampleSize;
  333. // some samples need to be converted
  334. ConvertSamples( m_pData, m_sampleCount );
  335. }
  336. else if ( m_format == WAVE_FORMAT_ADPCM )
  337. {
  338. // The ADPCM mixers treat the wave source as a flat file of bytes.
  339. m_sampleSize = 1;
  340. // Since each "sample" is a byte (this is a flat file), the number of samples is the file size
  341. m_sampleCount = size;
  342. // file says 4, output is 16
  343. m_bits = 16;
  344. }
  345. }
  346. int CAudioSourceMemWave::GetNumChannels()
  347. {
  348. return m_channels;
  349. }
  350. //-----------------------------------------------------------------------------
  351. // Purpose: parses loop information from a cue chunk
  352. // Input : &walk - RIFF iterator
  353. // Output : int loop start position
  354. //-----------------------------------------------------------------------------
  355. int CAudioSourceWave::ParseCueChunk( IterateRIFF &walk )
  356. {
  357. // Cue chunk as specified by RIFF format
  358. // see $/research/jay/sound/riffnew.htm
  359. struct
  360. {
  361. unsigned int dwName;
  362. unsigned int dwPosition;
  363. unsigned int fccChunk;
  364. unsigned int dwChunkStart;
  365. unsigned int dwBlockStart;
  366. unsigned int dwSampleOffset;
  367. } cue_chunk;
  368. int cueCount;
  369. // assume that the cue chunk stored in the wave is the start of the loop
  370. // assume only one cue chunk, UNDONE: Test this assumption here?
  371. cueCount = walk.ChunkReadInt();
  372. walk.ChunkReadPartial( &cue_chunk, sizeof(cue_chunk) );
  373. return cue_chunk.dwSampleOffset;
  374. }
  375. //-----------------------------------------------------------------------------
  376. // Purpose: get the wave header
  377. //-----------------------------------------------------------------------------
  378. void *CAudioSourceWave::GetHeader( void )
  379. {
  380. return m_pHeader;
  381. }
  382. //-----------------------------------------------------------------------------
  383. // Purpose: wrap the position wrt looping
  384. // Input : samplePosition - absolute position
  385. // Output : int - looped position
  386. //-----------------------------------------------------------------------------
  387. int CAudioSourceWave::ConvertLoopedPosition( int samplePosition )
  388. {
  389. // if the wave is looping and we're past the end of the sample
  390. // convert to a position within the loop
  391. // At the end of the loop, we return a short buffer, and subsequent call
  392. // will loop back and get the rest of the buffer
  393. if ( m_loopStart >= 0 )
  394. {
  395. if ( samplePosition >= m_sampleCount )
  396. {
  397. // size of loop
  398. int loopSize = m_sampleCount - m_loopStart;
  399. // subtract off starting bit of the wave
  400. samplePosition -= m_loopStart;
  401. if ( loopSize )
  402. {
  403. // "real" position in memory (mod off extra loops)
  404. samplePosition = m_loopStart + (samplePosition % loopSize);
  405. }
  406. // ERROR? if no loopSize
  407. }
  408. }
  409. return samplePosition;
  410. }
  411. bool CAudioSourceWave::IsStereoWav( void )
  412. {
  413. return (m_channels == 2) ? true : false;
  414. }
  415. //-----------------------------------------------------------------------------
  416. // Purpose:
  417. // Input : **pData - output pointer to samples
  418. // samplePosition - position (in samples not bytes)
  419. // sampleCount - number of samples (not bytes)
  420. // Output : int - number of samples available
  421. //-----------------------------------------------------------------------------
  422. int CAudioSourceMemWave::GetOutputData( void **pData, int samplePosition, int sampleCount, bool forward /*= true*/ )
  423. {
  424. // handle position looping
  425. samplePosition = ConvertLoopedPosition( samplePosition );
  426. // how many samples are available (linearly not counting looping)
  427. int availableSampleCount = m_sampleCount - samplePosition;
  428. if ( !forward )
  429. {
  430. if ( samplePosition >= m_sampleCount )
  431. {
  432. availableSampleCount = 0;
  433. }
  434. else
  435. {
  436. availableSampleCount = samplePosition;
  437. }
  438. }
  439. // may be asking for a sample out of range, clip at zero
  440. if ( availableSampleCount < 0 )
  441. availableSampleCount = 0;
  442. // clip max output samples to max available
  443. if ( sampleCount > availableSampleCount )
  444. sampleCount = availableSampleCount;
  445. // byte offset in sample database
  446. samplePosition *= m_sampleSize;
  447. // if we are returning some samples, store the pointer
  448. if ( sampleCount )
  449. {
  450. *pData = m_pData + samplePosition;
  451. }
  452. return sampleCount;
  453. }
  454. //-----------------------------------------------------------------------------
  455. // Purpose: Create a wave audio source (streaming or in memory)
  456. // Input : *pName - file name
  457. // streaming - if true, don't load, stream each instance
  458. // Output : CAudioSource * - a new source
  459. //-----------------------------------------------------------------------------
  460. // UNDONE : Pool these and check for duplicates?
  461. CAudioSource *CreateWave( const char *pName )
  462. {
  463. char formatBuffer[1024];
  464. InFileRIFF riff( pName, io );
  465. // UNDONE: Don't use printf to handle errors
  466. if ( riff.RIFFName() != RIFF_WAVE )
  467. {
  468. printf("Bad RIFF file type %s\n", pName );
  469. return NULL;
  470. }
  471. // set up the iterator for the whole file (root RIFF is a chunk)
  472. IterateRIFF walk( riff, riff.RIFFSize() );
  473. int format = 0;
  474. int formatSize = 0;
  475. // This chunk must be first as it contains the wave's format
  476. // break out when we've parsed it
  477. while ( walk.ChunkAvailable() && format == 0 )
  478. {
  479. switch( walk.ChunkName() )
  480. {
  481. case WAVE_FMT:
  482. {
  483. if ( walk.ChunkSize() <= 1024 )
  484. {
  485. walk.ChunkRead( formatBuffer );
  486. formatSize = walk.ChunkSize();
  487. format = ((WAVEFORMATEX *)formatBuffer)->wFormatTag;
  488. }
  489. }
  490. break;
  491. default:
  492. {
  493. ChunkError( walk.ChunkName() );
  494. }
  495. break;
  496. }
  497. walk.ChunkNext();
  498. }
  499. // Not really a WAVE file or no format chunk, bail
  500. if ( !format )
  501. return NULL;
  502. CAudioSourceWave *pWave;
  503. // create the source from this file
  504. pWave = new CAudioSourceMemWave();
  505. // init the wave source
  506. pWave->Setup( formatBuffer, formatSize, walk );
  507. return pWave;
  508. }
  509. //-----------------------------------------------------------------------------
  510. // Purpose: Wrapper for CreateWave()
  511. //-----------------------------------------------------------------------------
  512. CAudioSource *Audio_CreateMemoryWave( const char *pName )
  513. {
  514. return CreateWave( pName );
  515. }