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.

392 lines
9.5 KiB

  1. //========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //
  7. //=============================================================================//
  8. #include "audio_pch.h"
  9. #include "snd_mp3_source.h"
  10. // memdbgon must be the last include file in a .cpp file!!!
  11. #include "tier0/memdbgon.h"
  12. CAudioSourceMP3::CAudioSourceMP3( CSfxTable *pSfx )
  13. {
  14. m_sampleRate = 44100;
  15. m_pSfx = pSfx;
  16. m_refCount = 0;
  17. m_dataStart = 0;
  18. char nameBuf[MAX_PATH];
  19. FileHandle_t file = g_pSndIO->open( pSfx->GetFileName( nameBuf, sizeof(nameBuf) ) );
  20. if ( (intp)file != -1 )
  21. {
  22. m_dataSize = g_pSndIO->size( file );
  23. g_pSndIO->close( file );
  24. }
  25. else
  26. {
  27. m_dataSize = 0;
  28. }
  29. m_nCachedDataSize = 0;
  30. m_bIsPlayOnce = false;
  31. m_bIsSentenceWord = false;
  32. }
  33. CAudioSourceMP3::CAudioSourceMP3( CSfxTable *pSfx, CAudioSourceCachedInfo *info )
  34. {
  35. m_sampleRate = 44100;
  36. m_pSfx = pSfx;
  37. m_refCount = 0;
  38. m_dataSize = info->DataSize();
  39. m_dataStart = info->DataStart();
  40. m_nCachedDataSize = 0;
  41. m_bIsPlayOnce = false;
  42. }
  43. CAudioSourceMP3::~CAudioSourceMP3()
  44. {
  45. }
  46. // mixer's references
  47. void CAudioSourceMP3::ReferenceAdd( CAudioMixer * )
  48. {
  49. m_refCount++;
  50. }
  51. void CAudioSourceMP3::ReferenceRemove( CAudioMixer * )
  52. {
  53. m_refCount--;
  54. if ( m_refCount == 0 && IsPlayOnce() )
  55. {
  56. SetPlayOnce( false ); // in case it gets used again
  57. CacheUnload();
  58. }
  59. }
  60. //-----------------------------------------------------------------------------
  61. // Purpose:
  62. // Output : Returns true on success, false on failure.
  63. //-----------------------------------------------------------------------------
  64. bool CAudioSourceMP3::IsAsyncLoad()
  65. {
  66. if ( !m_AudioCacheHandle.IsValid() )
  67. {
  68. m_AudioCacheHandle.Get( GetType(), m_pSfx->IsPrecachedSound(), m_pSfx, &m_nCachedDataSize );
  69. }
  70. // If there's a bit of "cached data" then we don't have to lazy/async load (we still async load the remaining data,
  71. // but we run from the cache initially)
  72. return ( m_nCachedDataSize > 0 ) ? false : true;
  73. }
  74. // check reference count, return true if nothing is referencing this
  75. bool CAudioSourceMP3::CanDelete( void )
  76. {
  77. return m_refCount > 0 ? false : true;
  78. }
  79. bool CAudioSourceMP3::GetStartupData()
  80. {
  81. char nameBuf[MAX_PATH];
  82. FileHandle_t file = g_pSndIO->open( m_pSfx->GetFileName( nameBuf, sizeof(nameBuf) ) );
  83. if ( !file )
  84. {
  85. return false;
  86. }
  87. m_dataSize = (int)g_pSndIO->size( file );
  88. g_pSndIO->close( file );
  89. return true;
  90. }
  91. //-----------------------------------------------------------------------------
  92. // Purpose:
  93. // Output : int
  94. //-----------------------------------------------------------------------------
  95. int CAudioSourceMP3::GetType()
  96. {
  97. return AUDIO_SOURCE_MP3;
  98. }
  99. void CAudioSourceMP3::GetCacheData( CAudioSourceCachedInfo *info )
  100. {
  101. info->SetSampleRate( m_sampleRate );
  102. info->SetDataStart( 0 );
  103. GetStartupData();
  104. // Data size gets computed in GetStartupData!!!
  105. info->SetDataSize( m_dataSize );
  106. }
  107. //-----------------------------------------------------------------------------
  108. // Purpose:
  109. // Output : char const
  110. //-----------------------------------------------------------------------------
  111. char const *CAudioSourceMP3::GetFileName( char *pOutBuf, size_t bufLen )
  112. {
  113. return m_pSfx ? m_pSfx->GetFileName(pOutBuf, bufLen) : "NULL m_pSfx";
  114. }
  115. //-----------------------------------------------------------------------------
  116. // Purpose:
  117. //-----------------------------------------------------------------------------
  118. void CAudioSourceMP3::CheckAudioSourceCache()
  119. {
  120. Assert( m_pSfx );
  121. if ( !m_pSfx->IsPrecachedSound() )
  122. {
  123. return;
  124. }
  125. // This will "re-cache" this if it's not in this level's cache already
  126. m_AudioCacheHandle.Get( GetType(), true, m_pSfx, &m_nCachedDataSize );
  127. }
  128. //-----------------------------------------------------------------------------
  129. // Purpose: NULL the wave data pointer (we haven't loaded yet)
  130. //-----------------------------------------------------------------------------
  131. CAudioSourceMP3Cache::CAudioSourceMP3Cache( CSfxTable *pSfx ) :
  132. CAudioSourceMP3( pSfx )
  133. {
  134. m_hCache = 0;
  135. }
  136. CAudioSourceMP3Cache::CAudioSourceMP3Cache( CSfxTable *pSfx, CAudioSourceCachedInfo *info ) :
  137. CAudioSourceMP3( pSfx, info )
  138. {
  139. m_hCache = 0;
  140. m_dataSize = info->DataSize();
  141. m_dataStart = info->DataStart();
  142. }
  143. //-----------------------------------------------------------------------------
  144. // Purpose: Free any wave data we've allocated
  145. //-----------------------------------------------------------------------------
  146. CAudioSourceMP3Cache::~CAudioSourceMP3Cache( void )
  147. {
  148. CacheUnload();
  149. }
  150. int CAudioSourceMP3Cache::GetCacheStatus( void )
  151. {
  152. bool bCacheValid;
  153. int loaded = wavedatacache->IsDataLoadCompleted( m_hCache, &bCacheValid ) ? AUDIO_IS_LOADED : AUDIO_NOT_LOADED;
  154. if ( !bCacheValid )
  155. {
  156. char nameBuf[MAX_PATH];
  157. wavedatacache->RestartDataLoad( &m_hCache, m_pSfx->GetFileName(nameBuf, sizeof(nameBuf)), m_dataSize, m_dataStart );
  158. }
  159. return loaded;
  160. }
  161. void CAudioSourceMP3Cache::CacheLoad( void )
  162. {
  163. // Commence lazy load?
  164. if ( m_hCache != 0 )
  165. {
  166. GetCacheStatus();
  167. return;
  168. }
  169. char nameBuf[MAX_PATH];
  170. m_hCache = wavedatacache->AsyncLoadCache( m_pSfx->GetFileName(nameBuf, sizeof(nameBuf)), m_dataSize, m_dataStart );
  171. }
  172. void CAudioSourceMP3Cache::CacheUnload( void )
  173. {
  174. if ( m_hCache != 0 )
  175. {
  176. wavedatacache->Unload( m_hCache );
  177. }
  178. }
  179. char *CAudioSourceMP3Cache::GetDataPointer( void )
  180. {
  181. char *pMP3Data = NULL;
  182. bool dummy = false;
  183. if ( m_hCache == 0 )
  184. {
  185. CacheLoad();
  186. }
  187. char nameBuf[MAX_PATH];
  188. wavedatacache->GetDataPointer(
  189. m_hCache,
  190. m_pSfx->GetFileName(nameBuf, sizeof(nameBuf)),
  191. m_dataSize,
  192. m_dataStart,
  193. (void **)&pMP3Data,
  194. 0,
  195. &dummy );
  196. return pMP3Data;
  197. }
  198. int CAudioSourceMP3Cache::GetOutputData( void **pData, int64 samplePosition, int sampleCount, char copyBuf[AUDIOSOURCE_COPYBUF_SIZE] )
  199. {
  200. // how many bytes are available ?
  201. int totalSampleCount = m_dataSize - samplePosition;
  202. // may be asking for a sample out of range, clip at zero
  203. if ( totalSampleCount < 0 )
  204. totalSampleCount = 0;
  205. // clip max output samples to max available
  206. if ( sampleCount > totalSampleCount )
  207. sampleCount = totalSampleCount;
  208. // if we are returning some samples, store the pointer
  209. if ( sampleCount )
  210. {
  211. // Starting past end of "preloaded" data, just use regular cache
  212. if ( samplePosition >= m_nCachedDataSize )
  213. {
  214. *pData = GetDataPointer();
  215. }
  216. else
  217. {
  218. // Start async loader if we haven't already done so
  219. CacheLoad();
  220. // Return less data if we are about to run out of uncached data
  221. if ( samplePosition + sampleCount >= m_nCachedDataSize )
  222. {
  223. sampleCount = m_nCachedDataSize - samplePosition;
  224. }
  225. // Point at preloaded/cached data from .cache file for now
  226. *pData = GetCachedDataPointer();
  227. }
  228. if ( *pData )
  229. {
  230. *pData = (char *)*pData + samplePosition;
  231. }
  232. else
  233. {
  234. // Out of data or file i/o problem
  235. sampleCount = 0;
  236. }
  237. }
  238. return sampleCount;
  239. }
  240. CAudioMixer *CAudioSourceMP3Cache::CreateMixer( int initialStreamPosition, int skipInitialSamples, bool bUpdateDelayForChoreo, SoundError &soundError, hrtf_info_t *pHRTFVector )
  241. {
  242. CAudioMixer *pMixer = CreateMP3Mixer( CreateWaveDataMemory(*this), &m_sampleRate );
  243. if ( pMixer )
  244. {
  245. ReferenceAdd( pMixer );
  246. soundError = SE_OK;
  247. }
  248. else
  249. {
  250. soundError = SE_CANT_CREATE_MIXER;
  251. }
  252. return pMixer;
  253. }
  254. CAudioSourceStreamMP3::CAudioSourceStreamMP3( CSfxTable *pSfx ) :
  255. CAudioSourceMP3( pSfx )
  256. {
  257. }
  258. CAudioSourceStreamMP3::CAudioSourceStreamMP3( CSfxTable *pSfx, CAudioSourceCachedInfo *info ) :
  259. CAudioSourceMP3( pSfx, info )
  260. {
  261. m_dataSize = info->DataSize();
  262. }
  263. //-----------------------------------------------------------------------------
  264. // Purpose:
  265. //-----------------------------------------------------------------------------
  266. void CAudioSourceStreamMP3::Prefetch()
  267. {
  268. char nameBuf[MAX_PATH];
  269. PrefetchDataStream( m_pSfx->GetFileName(nameBuf, sizeof(nameBuf)), 0, m_dataSize );
  270. }
  271. CAudioMixer *CAudioSourceStreamMP3::CreateMixer(int intialStreamPosition, int initialSkipSamples, bool bUpdateDelayForChoreo, SoundError &soundError, hrtf_info_t *pHRTFVector )
  272. {
  273. char nameBuf[MAX_PATH];
  274. // BUGBUG: Source constructs the IWaveData, mixer frees it, fix this?
  275. IWaveData *pWaveData = CreateWaveDataStream(*this, static_cast<IWaveStreamSource *>(this), m_pSfx->GetFileName(nameBuf, sizeof(nameBuf)), 0, m_dataSize, m_pSfx, 0, 0, soundError );
  276. if ( pWaveData )
  277. {
  278. CAudioMixer *pMixer = CreateMP3Mixer( pWaveData, &m_sampleRate );
  279. if ( pMixer )
  280. {
  281. ReferenceAdd( pMixer );
  282. soundError = SE_OK;
  283. return pMixer;
  284. }
  285. // no mixer but pWaveData was deleted in mixer's destructor
  286. // so no need to delete
  287. }
  288. soundError = SE_CANT_CREATE_MIXER;
  289. return NULL;
  290. }
  291. int CAudioSourceStreamMP3::GetOutputData( void **pData, int64 samplePosition, int sampleCount, char copyBuf[AUDIOSOURCE_COPYBUF_SIZE] )
  292. {
  293. return 0;
  294. }
  295. bool Audio_IsMP3( const char *pName )
  296. {
  297. int len = strlen(pName);
  298. if ( len > 4 )
  299. {
  300. if ( !Q_strnicmp( &pName[len - 4], ".mp3", 4 ) )
  301. {
  302. return true;
  303. }
  304. }
  305. return false;
  306. }
  307. CAudioSource *Audio_CreateStreamedMP3( CSfxTable *pSfx )
  308. {
  309. CAudioSourceStreamMP3 *pMP3 = NULL;
  310. CAudioSourceCachedInfo *info = audiosourcecache->GetInfo( CAudioSource::AUDIO_SOURCE_MP3, pSfx->IsPrecachedSound(), pSfx );
  311. if ( info && info->DataSize() != 0 )
  312. {
  313. pMP3 = new CAudioSourceStreamMP3( pSfx, info );
  314. }
  315. else
  316. {
  317. pMP3 = new CAudioSourceStreamMP3( pSfx );
  318. }
  319. return pMP3;
  320. }
  321. CAudioSource *Audio_CreateMemoryMP3( CSfxTable *pSfx )
  322. {
  323. CAudioSourceMP3Cache *pMP3 = NULL;
  324. CAudioSourceCachedInfo *info = audiosourcecache->GetInfo( CAudioSource::AUDIO_SOURCE_MP3, pSfx->IsPrecachedSound(), pSfx );
  325. if ( info )
  326. {
  327. pMP3 = new CAudioSourceMP3Cache( pSfx, info );
  328. }
  329. else
  330. {
  331. pMP3 = new CAudioSourceMP3Cache( pSfx );
  332. }
  333. return pMP3;
  334. }