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.

108 lines
3.4 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: Sound code shared between server and client
  4. //
  5. //=============================================================================//
  6. #include <math.h>
  7. #include "convar.h"
  8. #include "sound.h"
  9. ConVar snd_refdist( "snd_refdist", "36", FCVAR_CHEAT);
  10. ConVar snd_refdb( "snd_refdb", "60", FCVAR_CHEAT );
  11. ConVar snd_foliage_db_loss( "snd_foliage_db_loss", "4", FCVAR_CHEAT );
  12. ConVar snd_gain( "snd_gain", "1", FCVAR_CHEAT );
  13. ConVar snd_gain_max( "snd_gain_max", "1", FCVAR_CHEAT );
  14. ConVar snd_gain_min( "snd_gain_min", "0.01", FCVAR_CHEAT );
  15. // calculate gain based on atmospheric attenuation.
  16. // as gain excedes threshold, round off (compress) towards 1.0 using spline
  17. #define SND_GAIN_COMP_EXP_MAX 2.5f // Increasing SND_GAIN_COMP_EXP_MAX fits compression curve more closely
  18. // to original gain curve as it approaches 1.0.
  19. #define SND_GAIN_COMP_EXP_MIN 0.8f
  20. #define SND_GAIN_COMP_THRESH 0.5f // gain value above which gain curve is rounded to approach 1.0
  21. #define SND_DB_MAX 140.0f // max db of any sound source
  22. #define SND_DB_MED 90.0f // db at which compression curve changes
  23. #define SNDLVL_TO_DIST_MULT( sndlvl ) ( sndlvl ? ((pow( 10.0f, snd_refdb.GetFloat() / 20 ) / pow( 10.0f, (float)sndlvl / 20 )) / snd_refdist.GetFloat()) : 0 )
  24. #define DIST_MULT_TO_SNDLVL( dist_mult ) (soundlevel_t)(int)( dist_mult ? ( 20 * log10( pow( 10.0f, snd_refdb.GetFloat() / 20 ) / (dist_mult * snd_refdist.GetFloat()) ) ) : 0 )
  25. float SND_GetGainFromMult( float gain, float dist_mult, vec_t dist )
  26. {
  27. // test additional attenuation
  28. // at 30c, 14.7psi, 60% humidity, 1000Hz == 0.22dB / 100ft.
  29. // dense foliage is roughly 2dB / 100ft
  30. float additional_dB_loss = snd_foliage_db_loss.GetFloat() * (dist / 1200);
  31. float additional_dist_mult = pow( 10.0f, additional_dB_loss / 20);
  32. float relative_dist = dist * dist_mult * additional_dist_mult;
  33. // hard code clamp gain to 10x normal (assumes volume and external clipping)
  34. if (relative_dist > 0.1)
  35. {
  36. gain *= (1/relative_dist);
  37. }
  38. else
  39. gain *= 10.0;
  40. // if gain passess threshold, compress gain curve such that gain smoothly approaches 1.0
  41. if ( gain > SND_GAIN_COMP_THRESH )
  42. {
  43. float snd_gain_comp_power = SND_GAIN_COMP_EXP_MAX;
  44. soundlevel_t sndlvl = DIST_MULT_TO_SNDLVL( dist_mult );
  45. float Y;
  46. // decrease compression curve fit for higher sndlvl values
  47. if ( sndlvl > SND_DB_MED )
  48. {
  49. // snd_gain_power varies from max to min as sndlvl varies from 90 to 140
  50. snd_gain_comp_power = RemapVal ((float)sndlvl, SND_DB_MED, SND_DB_MAX, SND_GAIN_COMP_EXP_MAX, SND_GAIN_COMP_EXP_MIN);
  51. }
  52. // calculate crossover point
  53. Y = -1.0 / ( pow(SND_GAIN_COMP_THRESH, snd_gain_comp_power) * (SND_GAIN_COMP_THRESH - 1) );
  54. // calculate compressed gain
  55. gain = 1.0 - 1.0 / (Y * pow( gain, snd_gain_comp_power ) );
  56. gain = gain * snd_gain_max.GetFloat();
  57. }
  58. if ( gain < snd_gain_min.GetFloat() )
  59. {
  60. // sounds less than snd_gain_min fall off to 0 in distance it took them to fall to snd_gain_min
  61. gain = snd_gain_min.GetFloat() * (2.0 - relative_dist * snd_gain_min.GetFloat());
  62. if (gain <= 0.0)
  63. gain = 0.001; // don't propagate 0 gain
  64. }
  65. return gain;
  66. }
  67. float S_GetGainFromSoundLevel( soundlevel_t soundlevel, vec_t dist )
  68. {
  69. float gain = snd_gain.GetFloat();
  70. float dist_mult = SNDLVL_TO_DIST_MULT( soundlevel );
  71. if ( dist_mult )
  72. {
  73. gain = SND_GetGainFromMult( gain, dist_mult, dist );
  74. }
  75. return gain;
  76. }