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.

624 lines
13 KiB

  1. //========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //
  7. //=============================================================================//
  8. #include "cbase.h"
  9. #if !defined(_STATIC_LINKED) || defined(SOUNDEMITTERSYSTEM_DLL)
  10. #include "SoundEmitterSystem/isoundemittersystembase.h"
  11. #include "tier2/interval.h"
  12. #include "soundchars.h"
  13. #include "keyvalues.h"
  14. // memdbgon must be the last include file in a .cpp file!!!
  15. #include "tier0/memdbgon.h"
  16. struct SoundChannels
  17. {
  18. int channel;
  19. const char *name;
  20. };
  21. // NOTE: This will need to be updated if channel names are added/removed
  22. static SoundChannels g_pChannelNames[] =
  23. {
  24. { CHAN_AUTO, "CHAN_AUTO" },
  25. { CHAN_WEAPON, "CHAN_WEAPON" },
  26. { CHAN_VOICE, "CHAN_VOICE" },
  27. { CHAN_ITEM, "CHAN_ITEM" },
  28. { CHAN_BODY, "CHAN_BODY" },
  29. { CHAN_STREAM, "CHAN_STREAM" },
  30. { CHAN_STATIC, "CHAN_STATIC" },
  31. };
  32. struct VolumeLevel
  33. {
  34. float volume;
  35. const char *name;
  36. };
  37. static VolumeLevel g_pVolumeLevels[] =
  38. {
  39. { VOL_NORM, "VOL_NORM" },
  40. };
  41. struct PitchLookup
  42. {
  43. float pitch;
  44. const char *name;
  45. };
  46. static PitchLookup g_pPitchLookup[] =
  47. {
  48. { PITCH_NORM, "PITCH_NORM" },
  49. { PITCH_LOW, "PITCH_LOW" },
  50. { PITCH_HIGH, "PITCH_HIGH" },
  51. };
  52. //-----------------------------------------------------------------------------
  53. // Purpose:
  54. //-----------------------------------------------------------------------------
  55. struct SoundLevelLookup
  56. {
  57. soundlevel_t level;
  58. char const *name;
  59. };
  60. // NOTE: Needs to reflect the soundlevel_t enum defined in soundflags.h
  61. static SoundLevelLookup g_pSoundLevels[] =
  62. {
  63. { SNDLVL_NONE, "SNDLVL_NONE" },
  64. { SNDLVL_20dB, "SNDLVL_20dB" },
  65. { SNDLVL_25dB, "SNDLVL_25dB" },
  66. { SNDLVL_30dB, "SNDLVL_30dB" },
  67. { SNDLVL_35dB, "SNDLVL_35dB" },
  68. { SNDLVL_40dB, "SNDLVL_40dB" },
  69. { SNDLVL_45dB, "SNDLVL_45dB" },
  70. { SNDLVL_50dB, "SNDLVL_50dB" },
  71. { SNDLVL_55dB, "SNDLVL_55dB" },
  72. { SNDLVL_IDLE, "SNDLVL_IDLE" },
  73. { SNDLVL_TALKING, "SNDLVL_TALKING" },
  74. { SNDLVL_60dB, "SNDLVL_60dB" },
  75. { SNDLVL_65dB, "SNDLVL_65dB" },
  76. { SNDLVL_STATIC, "SNDLVL_STATIC" },
  77. { SNDLVL_70dB, "SNDLVL_70dB" },
  78. { SNDLVL_NORM, "SNDLVL_NORM" },
  79. { SNDLVL_75dB, "SNDLVL_75dB" },
  80. { SNDLVL_80dB, "SNDLVL_80dB" },
  81. { SNDLVL_85dB, "SNDLVL_85dB" },
  82. { SNDLVL_90dB, "SNDLVL_90dB" },
  83. { SNDLVL_95dB, "SNDLVL_95dB" },
  84. { SNDLVL_100dB, "SNDLVL_100dB" },
  85. { SNDLVL_105dB, "SNDLVL_105dB" },
  86. { SNDLVL_110dB, "SNDLVL_110dB" },
  87. { SNDLVL_120dB, "SNDLVL_120dB" },
  88. { SNDLVL_130dB, "SNDLVL_130dB" },
  89. { SNDLVL_GUNFIRE, "SNDLVL_GUNFIRE" },
  90. { SNDLVL_140dB, "SNDLVL_140dB" },
  91. { SNDLVL_150dB, "SNDLVL_150dB" },
  92. { SNDLVL_180dB, "SNDLVL_180dB" },
  93. };
  94. static const char *_SoundLevelToString( soundlevel_t level )
  95. {
  96. int c = ARRAYSIZE( g_pSoundLevels );
  97. int i;
  98. for ( i = 0 ; i < c; i++ )
  99. {
  100. SoundLevelLookup *entry = &g_pSoundLevels[ i ];
  101. if ( entry->level == level )
  102. return entry->name;
  103. }
  104. static char sz[ 32 ];
  105. Q_snprintf( sz, sizeof( sz ), "%i", (int)level );
  106. return sz;
  107. }
  108. static const char *_ChannelToString( int channel )
  109. {
  110. int c = ARRAYSIZE( g_pChannelNames );
  111. int i;
  112. for ( i = 0 ; i < c; i++ )
  113. {
  114. SoundChannels *entry = &g_pChannelNames[ i ];
  115. if ( entry->channel == channel )
  116. return entry->name;
  117. }
  118. static char sz[ 32 ];
  119. Q_snprintf( sz, sizeof( sz ), "%i", (int)channel );
  120. return sz;
  121. }
  122. static const char *_VolumeToString( float volume )
  123. {
  124. int c = ARRAYSIZE( g_pVolumeLevels );
  125. int i;
  126. for ( i = 0 ; i < c; i++ )
  127. {
  128. VolumeLevel *entry = &g_pVolumeLevels[ i ];
  129. if ( entry->volume == volume )
  130. return entry->name;
  131. }
  132. static char sz[ 32 ];
  133. Q_snprintf( sz, sizeof( sz ), "%.3f", volume );
  134. return sz;
  135. }
  136. static const char *_PitchToString( float pitch )
  137. {
  138. int c = ARRAYSIZE( g_pPitchLookup );
  139. int i;
  140. for ( i = 0 ; i < c; i++ )
  141. {
  142. PitchLookup *entry = &g_pPitchLookup[ i ];
  143. if ( entry->pitch == pitch )
  144. return entry->name;
  145. }
  146. static char sz[ 32 ];
  147. Q_snprintf( sz, sizeof( sz ), "%.3f", pitch );
  148. return sz;
  149. }
  150. #define SNDLVL_PREFIX "SNDLVL_"
  151. soundlevel_t TextToSoundLevel( const char *key )
  152. {
  153. if ( !key )
  154. {
  155. Assert( 0 );
  156. return SNDLVL_NORM;
  157. }
  158. int c = ARRAYSIZE( g_pSoundLevels );
  159. int i;
  160. for ( i = 0 ; i < c; i++ )
  161. {
  162. SoundLevelLookup *entry = &g_pSoundLevels[ i ];
  163. if ( !Q_strcasecmp( key, entry->name ) )
  164. return entry->level;
  165. }
  166. if ( StringHasPrefix( key, SNDLVL_PREFIX ) )
  167. {
  168. char const *val = key + V_strlen( SNDLVL_PREFIX );
  169. int sndlvl = atoi( val );
  170. if ( sndlvl > 0 && sndlvl <= 180 )
  171. {
  172. return ( soundlevel_t )sndlvl;
  173. }
  174. }
  175. DevMsg( "CSoundEmitterSystem: Unknown sound level %s\n", key );
  176. return SNDLVL_NORM;
  177. }
  178. //-----------------------------------------------------------------------------
  179. // Purpose: Convert "chan_xxx" into integer value for channel
  180. // Input : *name -
  181. // Output : static int
  182. //-----------------------------------------------------------------------------
  183. int TextToChannel( const char *name )
  184. {
  185. if ( !name )
  186. {
  187. Assert( 0 );
  188. // CHAN_AUTO
  189. return CHAN_AUTO;
  190. }
  191. if ( Q_strncasecmp( name, "chan_", strlen( "chan_" ) ) )
  192. {
  193. return atoi( name );
  194. }
  195. int c = ARRAYSIZE( g_pChannelNames );
  196. int i;
  197. for ( i = 0; i < c; i++ )
  198. {
  199. if ( !Q_strcasecmp( name, g_pChannelNames[ i ].name ) )
  200. {
  201. return g_pChannelNames[ i ].channel;
  202. }
  203. }
  204. // At this point, it starts with chan_ but is not recognized
  205. // atoi would return 0, so just do chan auto
  206. DevMsg( "CSoundEmitterSystem: Warning, unknown channel type in sounds.txt (%s)\n", name );
  207. return CHAN_AUTO;
  208. }
  209. const char *SoundLevelToString( soundlevel_t level )
  210. {
  211. int c = ARRAYSIZE( g_pSoundLevels );
  212. int i;
  213. for ( i = 0 ; i < c; i++ )
  214. {
  215. SoundLevelLookup *entry = &g_pSoundLevels[ i ];
  216. if ( entry->level == level )
  217. return entry->name;
  218. }
  219. static char sz[ 32 ];
  220. Q_snprintf( sz, sizeof( sz ), "%i", (int)level );
  221. return sz;
  222. }
  223. const char *ChannelToString( int channel )
  224. {
  225. int c = ARRAYSIZE( g_pChannelNames );
  226. int i;
  227. for ( i = 0 ; i < c; i++ )
  228. {
  229. SoundChannels *entry = &g_pChannelNames[ i ];
  230. if ( entry->channel == channel )
  231. return entry->name;
  232. }
  233. static char sz[ 32 ];
  234. Q_snprintf( sz, sizeof( sz ), "%i", (int)channel );
  235. return sz;
  236. }
  237. const char *VolumeToString( float volume )
  238. {
  239. int c = ARRAYSIZE( g_pVolumeLevels );
  240. int i;
  241. for ( i = 0 ; i < c; i++ )
  242. {
  243. VolumeLevel *entry = &g_pVolumeLevels[ i ];
  244. if ( entry->volume == volume )
  245. return entry->name;
  246. }
  247. static char sz[ 32 ];
  248. Q_snprintf( sz, sizeof( sz ), "%.3f", volume );
  249. return sz;
  250. }
  251. const char *PitchToString( float pitch )
  252. {
  253. int c = ARRAYSIZE( g_pPitchLookup );
  254. int i;
  255. for ( i = 0 ; i < c; i++ )
  256. {
  257. PitchLookup *entry = &g_pPitchLookup[ i ];
  258. if ( entry->pitch == pitch )
  259. return entry->name;
  260. }
  261. static char sz[ 32 ];
  262. Q_snprintf( sz, sizeof( sz ), "%.3f", pitch );
  263. return sz;
  264. }
  265. CSoundParametersInternal::CSoundParametersInternal()
  266. {
  267. m_pConvertedNames = m_pSoundNames = NULL;
  268. m_nConvertedNames = m_nSoundNames = 0;
  269. channel = CHAN_AUTO; // 0
  270. volume.start = VOL_NORM; // 1.0f
  271. volume.range = 0.0f;
  272. pitch.start = PITCH_NORM; // 100
  273. pitch.range = 0;
  274. soundlevel.start = SNDLVL_NORM; // 75dB
  275. soundlevel.range = 0;
  276. delay_msec = 0;
  277. play_to_owner_only = false;
  278. had_missing_wave_files = false;
  279. uses_gender_token = false;
  280. m_bHasCached = false;
  281. m_bHRTFBilinear = false;
  282. m_bHRTFFollowEntity = false;
  283. m_nSoundEntryVersion = 1;
  284. m_pOperatorsKV = NULL;
  285. // TERROR:
  286. m_pGameData = NULL;
  287. }
  288. CSoundParametersInternal::CSoundParametersInternal( const CSoundParametersInternal& src )
  289. {
  290. m_pSoundNames = NULL;
  291. m_pConvertedNames = NULL;
  292. m_pOperatorsKV = NULL;
  293. // TERROR:
  294. m_pGameData = NULL;
  295. CopyFrom( src );
  296. }
  297. CSoundParametersInternal::~CSoundParametersInternal()
  298. {
  299. if ( m_nSoundNames > 1 )
  300. free(m_pSoundNames );
  301. if ( m_nConvertedNames > 1 )
  302. free( m_pConvertedNames);
  303. if ( m_pOperatorsKV )
  304. {
  305. m_pOperatorsKV->deleteThis();
  306. m_pOperatorsKV = NULL;
  307. }
  308. m_pConvertedNames = NULL;
  309. m_pSoundNames = NULL;
  310. m_nSoundNames = 0;
  311. m_nConvertedNames = 0;
  312. }
  313. void CSoundParametersInternal::SetOperatorsKV( KeyValues *src )
  314. {
  315. if ( m_pOperatorsKV )
  316. {
  317. m_pOperatorsKV->deleteThis();
  318. }
  319. m_pOperatorsKV = NULL;
  320. m_pOperatorsKV = new KeyValues( "Operators" );
  321. src->CopySubkeys( m_pOperatorsKV );
  322. }
  323. void CSoundParametersInternal::CopyFrom( const CSoundParametersInternal& src )
  324. {
  325. if ( m_nSoundNames > 1 )
  326. free(m_pSoundNames);
  327. if ( m_nConvertedNames > 1 )
  328. free(m_pConvertedNames);
  329. channel = src.channel;
  330. volume = src.volume;
  331. pitch = src.pitch;
  332. soundlevel = src.soundlevel;
  333. delay_msec = src.delay_msec;
  334. play_to_owner_only = src.play_to_owner_only;
  335. m_bHRTFBilinear = src.m_bHRTFBilinear;
  336. m_bHRTFFollowEntity = src.m_bHRTFFollowEntity;
  337. m_nSoundNames = src.m_nSoundNames;
  338. if ( m_nSoundNames )
  339. {
  340. if ( m_nSoundNames > 1 )
  341. {
  342. m_pSoundNames = (SoundFile*)malloc( sizeof(SoundFile)*m_nSoundNames);
  343. memcpy( m_pSoundNames, src.m_pSoundNames, m_nSoundNames * sizeof(SoundFile) );
  344. }
  345. else
  346. {
  347. m_pSoundNames = src.m_pSoundNames;
  348. }
  349. }
  350. else
  351. {
  352. m_pSoundNames = NULL;
  353. }
  354. m_nConvertedNames = src.m_nConvertedNames;
  355. if ( m_nConvertedNames )
  356. {
  357. if ( m_nConvertedNames > 1 )
  358. {
  359. m_pConvertedNames = (SoundFile*)malloc( sizeof(SoundFile)*m_nConvertedNames);
  360. memcpy( m_pConvertedNames, src.m_pConvertedNames, m_nConvertedNames * sizeof(SoundFile) );
  361. }
  362. else
  363. {
  364. m_pConvertedNames = src.m_pConvertedNames;
  365. }
  366. }
  367. else
  368. {
  369. m_pConvertedNames = NULL;
  370. }
  371. if ( src.m_pOperatorsKV )
  372. {
  373. SetOperatorsKV( src.m_pOperatorsKV );
  374. }
  375. had_missing_wave_files = src.had_missing_wave_files;
  376. uses_gender_token = src.uses_gender_token;
  377. }
  378. #define CompareInterval( i1, i2 ) ( memcmp( &(i1), &(i2), sizeof(i1) ) == 0 )
  379. bool CSoundParametersInternal::operator == ( const CSoundParametersInternal& other ) const
  380. {
  381. if ( this == &other )
  382. return true;
  383. if ( channel != other.channel )
  384. return false;
  385. if ( !CompareInterval( volume, other.volume ) )
  386. return false;
  387. if ( !CompareInterval( pitch, other.pitch ) )
  388. return false;
  389. if ( !CompareInterval( soundlevel, other.soundlevel ) )
  390. return false;
  391. if ( delay_msec != other.delay_msec )
  392. return false;
  393. if ( play_to_owner_only != other.play_to_owner_only )
  394. return false;
  395. if (m_bHRTFBilinear != other.m_bHRTFBilinear)
  396. return false;
  397. if ( m_bHRTFFollowEntity != other.m_bHRTFFollowEntity )
  398. return false;
  399. if ( m_nSoundNames != other.m_nSoundNames )
  400. return false;
  401. // Compare items
  402. int c = m_nSoundNames;
  403. for ( int i = 0; i < c; i++ )
  404. {
  405. if ( GetSoundNames()[ i ].symbol != other.GetSoundNames()[ i ].symbol )
  406. return false;
  407. }
  408. return true;
  409. }
  410. float16 ZERO_FLOAT16;
  411. const char *CSoundParametersInternal::VolumeToString( void ) const
  412. {
  413. if ( volume.range == ZERO_FLOAT16 )
  414. {
  415. return _VolumeToString( volume.start );
  416. }
  417. static char sz[ 64 ];
  418. Q_snprintf( sz, sizeof( sz ), "%.3f, %.3f", (float)volume.start, (float)volume.start + (float)volume.range );
  419. return sz;
  420. }
  421. const char *CSoundParametersInternal::ChannelToString( void ) const
  422. {
  423. return _ChannelToString( channel );
  424. }
  425. const char *CSoundParametersInternal::SoundLevelToString( void ) const
  426. {
  427. if ( soundlevel.range == 0 )
  428. {
  429. return _SoundLevelToString( (soundlevel_t)(int)soundlevel.start );
  430. }
  431. static char sz[ 64 ];
  432. Q_snprintf( sz, sizeof( sz ), "%i, %i", (soundlevel_t)(int)soundlevel.start, (soundlevel_t)(int)(soundlevel.start + soundlevel.range ) );
  433. return sz;
  434. }
  435. const char *CSoundParametersInternal::PitchToString( void ) const
  436. {
  437. if ( pitch.range == 0 )
  438. {
  439. return _PitchToString( (int)pitch.start );
  440. }
  441. static char sz[ 64 ];
  442. Q_snprintf( sz, sizeof( sz ), "%i, %i", (int)pitch.start, (int)(pitch.start + pitch.range ) );
  443. return sz;
  444. }
  445. void CSoundParametersInternal::VolumeFromString( const char *sz )
  446. {
  447. if ( !Q_strcasecmp( sz, "VOL_NORM" ) )
  448. {
  449. volume.start = VOL_NORM;
  450. volume.range = 0.0f;
  451. }
  452. else
  453. {
  454. volume.FromInterval( ReadInterval( sz ) );
  455. }
  456. }
  457. void CSoundParametersInternal::ChannelFromString( const char *sz )
  458. {
  459. channel = TextToChannel( sz );
  460. }
  461. void CSoundParametersInternal::PitchFromString( const char *sz )
  462. {
  463. if ( !Q_strcasecmp( sz, "PITCH_NORM" ) )
  464. {
  465. pitch.start = PITCH_NORM;
  466. pitch.range = 0;
  467. }
  468. else if ( !Q_strcasecmp( sz, "PITCH_LOW" ) )
  469. {
  470. pitch.start = PITCH_LOW;
  471. pitch.range = 0;
  472. }
  473. else if ( !Q_strcasecmp( sz, "PITCH_HIGH" ) )
  474. {
  475. pitch.start = PITCH_HIGH;
  476. pitch.range = 0;
  477. }
  478. else
  479. {
  480. pitch.FromInterval( ReadInterval( sz ) );
  481. }
  482. }
  483. void CSoundParametersInternal::SoundLevelFromString( const char *sz )
  484. {
  485. if ( !Q_strncasecmp( sz, "SNDLVL_", strlen( "SNDLVL_" ) ) )
  486. {
  487. soundlevel.start = TextToSoundLevel( sz );
  488. soundlevel.range = 0;
  489. }
  490. else
  491. {
  492. soundlevel.FromInterval( ReadInterval( sz ) );
  493. }
  494. }
  495. void CSoundParametersInternal::AddToTail( SoundFile **pDest, uint16 *pDestCount, const SoundFile &source )
  496. {
  497. (*pDestCount)++;
  498. if ( *pDestCount == 1 )
  499. {
  500. // NOTE: when there's only one soundfile in the list, we store it
  501. // packed into the pointer itself, the four bytes for the pointer is just used to store the sound file!
  502. COMPILE_TIME_ASSERT( sizeof(SoundFile) <= sizeof(SoundFile *) );
  503. *((SoundFile *)(pDest)) = source;
  504. }
  505. else
  506. {
  507. SoundFile temp;
  508. if ( *pDestCount == 2 )
  509. {
  510. // Copying from a list of one soundfile. Save off the struct
  511. // packed into the pointer field.
  512. temp = *((SoundFile *)(pDest));
  513. *pDest = NULL;
  514. }
  515. *pDest = (SoundFile *)realloc( *pDest, (*pDestCount) * sizeof(SoundFile) );
  516. (*pDest)[ *pDestCount - 1 ] = source;
  517. if ( *pDestCount == 2 )
  518. {
  519. (*pDest)[0] = temp;
  520. }
  521. }
  522. }
  523. #endif // !_STATIC_LINKED || SOUNDEMITTERSYSTEM_DLL