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.

602 lines
17 KiB

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