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.

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