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.

590 lines
16 KiB

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