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.

241 lines
6.0 KiB

  1. //===== Copyright 2005-2009, Valve Corporation, All rights reserved. ======//
  2. //
  3. // Purpose: Helper methods + classes for sound
  4. //
  5. //===========================================================================//
  6. #include "tier2/soundutils.h"
  7. #include "tier2/riff.h"
  8. #include "tier2/tier2.h"
  9. #include "filesystem.h"
  10. #ifdef IS_WINDOWS_PC
  11. #include <windows.h> // WAVEFORMATEX, WAVEFORMAT and ADPCM WAVEFORMAT!!!
  12. #include <mmreg.h>
  13. #else
  14. #ifdef _X360
  15. #include "xbox/xbox_win32stubs.h" // WAVEFORMATEX, WAVEFORMAT and ADPCM WAVEFORMAT!!!
  16. #endif
  17. #endif
  18. // NOTE: This has to be the last file included!
  19. #include "tier0/memdbgon.h"
  20. //-----------------------------------------------------------------------------
  21. // RIFF reader/writers that use the file system
  22. //-----------------------------------------------------------------------------
  23. class CFSIOReadBinary : public IFileReadBinary
  24. {
  25. public:
  26. // inherited from IFileReadBinary
  27. virtual FileHandle_t open( const char *pFileName );
  28. virtual int read( void *pOutput, int size, FileHandle_t file );
  29. virtual void seek( FileHandle_t file, int pos );
  30. virtual unsigned int tell( FileHandle_t file );
  31. virtual unsigned int size( FileHandle_t file );
  32. virtual void close( FileHandle_t file );
  33. };
  34. class CFSIOWriteBinary : public IFileWriteBinary
  35. {
  36. public:
  37. virtual FileHandle_t create( const char *pFileName );
  38. virtual int write( void *pData, int size, FileHandle_t file );
  39. virtual void close( FileHandle_t file );
  40. virtual void seek( FileHandle_t file, int pos );
  41. virtual unsigned int tell( FileHandle_t file );
  42. };
  43. //-----------------------------------------------------------------------------
  44. // Singletons
  45. //-----------------------------------------------------------------------------
  46. static CFSIOReadBinary s_FSIoIn;
  47. static CFSIOWriteBinary s_FSIoOut;
  48. IFileReadBinary *g_pFSIOReadBinary = &s_FSIoIn;
  49. IFileWriteBinary *g_pFSIOWriteBinary = &s_FSIoOut;
  50. //-----------------------------------------------------------------------------
  51. // RIFF reader that use the file system
  52. //-----------------------------------------------------------------------------
  53. FileHandle_t CFSIOReadBinary::open( const char *pFileName )
  54. {
  55. return g_pFullFileSystem->Open( pFileName, "rb" );
  56. }
  57. int CFSIOReadBinary::read( void *pOutput, int size, FileHandle_t file )
  58. {
  59. if ( !file )
  60. return 0;
  61. return g_pFullFileSystem->Read( pOutput, size, file );
  62. }
  63. void CFSIOReadBinary::seek( FileHandle_t file, int pos )
  64. {
  65. if ( !file )
  66. return;
  67. g_pFullFileSystem->Seek( file, pos, FILESYSTEM_SEEK_HEAD );
  68. }
  69. unsigned int CFSIOReadBinary::tell( FileHandle_t file )
  70. {
  71. if ( !file )
  72. return 0;
  73. return g_pFullFileSystem->Tell( file );
  74. }
  75. unsigned int CFSIOReadBinary::size( FileHandle_t file )
  76. {
  77. if ( !file )
  78. return 0;
  79. return g_pFullFileSystem->Size( file );
  80. }
  81. void CFSIOReadBinary::close( FileHandle_t file )
  82. {
  83. if ( !file )
  84. return;
  85. g_pFullFileSystem->Close( file );
  86. }
  87. //-----------------------------------------------------------------------------
  88. // RIFF writer that use the file system
  89. //-----------------------------------------------------------------------------
  90. FileHandle_t CFSIOWriteBinary::create( const char *pFileName )
  91. {
  92. g_pFullFileSystem->SetFileWritable( pFileName, true );
  93. return g_pFullFileSystem->Open( pFileName, "wb" );
  94. }
  95. int CFSIOWriteBinary::write( void *pData, int size, FileHandle_t file )
  96. {
  97. return g_pFullFileSystem->Write( pData, size, file );
  98. }
  99. void CFSIOWriteBinary::close( FileHandle_t file )
  100. {
  101. g_pFullFileSystem->Close( file );
  102. }
  103. void CFSIOWriteBinary::seek( FileHandle_t file, int pos )
  104. {
  105. g_pFullFileSystem->Seek( file, pos, FILESYSTEM_SEEK_HEAD );
  106. }
  107. unsigned int CFSIOWriteBinary::tell( FileHandle_t file )
  108. {
  109. return g_pFullFileSystem->Tell( file );
  110. }
  111. #ifndef POSIX
  112. //-----------------------------------------------------------------------------
  113. // Returns the duration of a wav file
  114. //-----------------------------------------------------------------------------
  115. float GetWavSoundDuration( const char *pWavFile )
  116. {
  117. InFileRIFF riff( pWavFile, *g_pFSIOReadBinary );
  118. // UNDONE: Don't use printf to handle errors
  119. if ( riff.RIFFName() != RIFF_WAVE )
  120. return 0.0f;
  121. int nDataSize = 0;
  122. // set up the iterator for the whole file (root RIFF is a chunk)
  123. IterateRIFF walk( riff, riff.RIFFSize() );
  124. // This chunk must be first as it contains the wave's format
  125. // break out when we've parsed it
  126. char pFormatBuffer[ 1024 ];
  127. int nFormatSize;
  128. bool bFound = false;
  129. for ( ; walk.ChunkAvailable( ); walk.ChunkNext() )
  130. {
  131. switch ( walk.ChunkName() )
  132. {
  133. case WAVE_FMT:
  134. bFound = true;
  135. if ( walk.ChunkSize() > sizeof(pFormatBuffer) )
  136. {
  137. Warning( "oops, format tag too big!!!" );
  138. return 0.0f;
  139. }
  140. nFormatSize = walk.ChunkSize();
  141. walk.ChunkRead( pFormatBuffer );
  142. break;
  143. case WAVE_DATA:
  144. nDataSize += walk.ChunkSize();
  145. break;
  146. }
  147. }
  148. if ( !bFound )
  149. return 0.0f;
  150. const WAVEFORMATEX *pHeader = (const WAVEFORMATEX *)pFormatBuffer;
  151. int format = pHeader->wFormatTag;
  152. int nBits = pHeader->wBitsPerSample;
  153. int nRate = pHeader->nSamplesPerSec;
  154. int nChannels = pHeader->nChannels;
  155. int nSampleSize = ( nBits * nChannels ) / 8;
  156. // this can never be zero -- other functions divide by this.
  157. // This should never happen, but avoid crashing
  158. if ( nSampleSize <= 0 )
  159. {
  160. nSampleSize = 1;
  161. }
  162. int nSampleCount = 0;
  163. float flTrueSampleSize = nSampleSize;
  164. if ( format == WAVE_FORMAT_ADPCM )
  165. {
  166. nSampleSize = 1;
  167. ADPCMWAVEFORMAT *pFormat = (ADPCMWAVEFORMAT *)pFormatBuffer;
  168. int blockSize = ((pFormat->wSamplesPerBlock - 2) * pFormat->wfx.nChannels ) / 2;
  169. blockSize += 7 * pFormat->wfx.nChannels;
  170. int blockCount = nSampleCount / blockSize;
  171. int blockRem = nSampleCount % blockSize;
  172. // total samples in complete blocks
  173. nSampleCount = blockCount * pFormat->wSamplesPerBlock;
  174. // add remaining in a short block
  175. if ( blockRem )
  176. {
  177. nSampleCount += pFormat->wSamplesPerBlock - (((blockSize - blockRem) * 2) / nChannels);
  178. }
  179. flTrueSampleSize = 0.5f;
  180. }
  181. else
  182. {
  183. nSampleCount = nDataSize / nSampleSize;
  184. }
  185. float flDuration = (float)nSampleCount / (float)nRate;
  186. return flDuration;
  187. }
  188. #endif