129 lines
4.1 KiB
C++
129 lines
4.1 KiB
C++
|
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
|
|||
|
//
|
|||
|
// Purpose: Sound code shared between server and client
|
|||
|
//
|
|||
|
//=============================================================================//
|
|||
|
|
|||
|
|
|||
|
#include <math.h>
|
|||
|
|
|||
|
#include "convar.h"
|
|||
|
#include "sound.h"
|
|||
|
|
|||
|
// NOTE: This has to be the last file included!
|
|||
|
#include "tier0/memdbgon.h"
|
|||
|
|
|||
|
|
|||
|
void DbReferenceChanged( IConVar *var, const char *pOldValue, float flOldValue );
|
|||
|
|
|||
|
ConVar snd_refdist( "snd_refdist", "36", FCVAR_CHEAT, "Reference distance for snd_refdb" );
|
|||
|
ConVar snd_refdb( "snd_refdb", "60", FCVAR_CHEAT, "Reference dB at snd_refdist", &DbReferenceChanged );
|
|||
|
float snd_refdb_dist_mult = pow( 10.0f, 60.0f / 20.0f );
|
|||
|
ConVar snd_foliage_db_loss( "snd_foliage_db_loss", "4", FCVAR_CHEAT, "foliage dB loss per 1200 units" );
|
|||
|
ConVar snd_gain( "snd_gain", "1", FCVAR_CHEAT );
|
|||
|
ConVar snd_gain_max( "snd_gain_max", "1", FCVAR_CHEAT );
|
|||
|
ConVar snd_gain_min( "snd_gain_min", "0.01", FCVAR_CHEAT );
|
|||
|
|
|||
|
// precomputed Db multipliers
|
|||
|
void DbReferenceChanged( IConVar *var, const char *pOldValue, float flOldValue )
|
|||
|
{
|
|||
|
snd_refdb_dist_mult = pow( 10.0f, snd_refdb.GetFloat() / 20.0f );
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
// calculate gain based on atmospheric attenuation.
|
|||
|
// as gain excedes threshold, round off (compress) towards 1.0 using spline
|
|||
|
#define SND_GAIN_COMP_EXP_MAX 2.5f // Increasing SND_GAIN_COMP_EXP_MAX fits compression curve more closely
|
|||
|
// to original gain curve as it approaches 1.0.
|
|||
|
#define SND_GAIN_COMP_EXP_MIN 0.8f
|
|||
|
//#define SND_GAIN_COMP_EXP_MIN 1.8f
|
|||
|
|
|||
|
|
|||
|
#define SND_GAIN_COMP_THRESH 0.5f // gain value above which gain curve is rounded to approach 1.0
|
|||
|
|
|||
|
#define SND_DB_MAX 140.0f // max db of any sound source
|
|||
|
#define SND_DB_MED 90.0f // db at which compression curve changes
|
|||
|
|
|||
|
#define SNDLVL_TO_DIST_MULT( sndlvl ) ( sndlvl ? ((snd_refdb_dist_mult / FastPow10( (float)sndlvl / 20 )) / snd_refdist.GetFloat()) : 0 )
|
|||
|
#define DIST_MULT_TO_SNDLVL( dist_mult ) (soundlevel_t)(int)( dist_mult ? ( 20 * log10( (float)(snd_refdb_dist_mult / (dist_mult * snd_refdist.GetFloat()) )) ) : 0 )
|
|||
|
|
|||
|
|
|||
|
|
|||
|
float SND_GetGainFromMult( float gain, float dist_mult, vec_t dist )
|
|||
|
{
|
|||
|
// test additional attenuation
|
|||
|
// at 30c, 14.7psi, 60% humidity, 1000Hz == 0.22dB / 100ft.
|
|||
|
// dense foliage is roughly 2dB / 100ft
|
|||
|
|
|||
|
float additional_dB_loss = snd_foliage_db_loss.GetFloat() * (dist / 1200);
|
|||
|
float additional_dist_mult = FastPow10( additional_dB_loss / 20);
|
|||
|
|
|||
|
float relative_dist = dist * dist_mult * additional_dist_mult;
|
|||
|
|
|||
|
// hard code clamp gain to 10x normal (assumes volume and external clipping)
|
|||
|
|
|||
|
if (relative_dist > 0.1)
|
|||
|
{
|
|||
|
gain *= (1/relative_dist);
|
|||
|
}
|
|||
|
else
|
|||
|
gain *= 10.0;
|
|||
|
|
|||
|
// if gain passess threshold, compress gain curve such that gain smoothly approaches 1.0
|
|||
|
|
|||
|
if ( gain > SND_GAIN_COMP_THRESH )
|
|||
|
{
|
|||
|
float snd_gain_comp_power = SND_GAIN_COMP_EXP_MAX;
|
|||
|
soundlevel_t sndlvl = DIST_MULT_TO_SNDLVL( dist_mult );
|
|||
|
float Y;
|
|||
|
|
|||
|
// decrease compression curve fit for higher sndlvl values
|
|||
|
|
|||
|
if ( sndlvl > SND_DB_MED )
|
|||
|
{
|
|||
|
// snd_gain_power varies from max to min as sndlvl varies from 90 to 140
|
|||
|
|
|||
|
snd_gain_comp_power = RemapVal ((float)sndlvl, SND_DB_MED, SND_DB_MAX, SND_GAIN_COMP_EXP_MAX, SND_GAIN_COMP_EXP_MIN);
|
|||
|
}
|
|||
|
|
|||
|
// calculate crossover point
|
|||
|
|
|||
|
Y = -1.0 / ( FastPow(SND_GAIN_COMP_THRESH, snd_gain_comp_power) * (SND_GAIN_COMP_THRESH - 1) );
|
|||
|
|
|||
|
// calculate compressed gain
|
|||
|
|
|||
|
gain = 1.0 - 1.0 / (Y * FastPow( gain, snd_gain_comp_power ) );
|
|||
|
|
|||
|
gain = gain * snd_gain_max.GetFloat();
|
|||
|
}
|
|||
|
|
|||
|
if ( gain < snd_gain_min.GetFloat() )
|
|||
|
{
|
|||
|
// sounds less than snd_gain_min fall off to 0 in distance it took them to fall to snd_gain_min
|
|||
|
|
|||
|
gain = snd_gain_min.GetFloat() * (2.0 - relative_dist * snd_gain_min.GetFloat());
|
|||
|
|
|||
|
if (gain <= 0.0)
|
|||
|
gain = 0.001; // don't propagate 0 gain
|
|||
|
}
|
|||
|
|
|||
|
return gain;
|
|||
|
}
|
|||
|
|
|||
|
float S_GetGainFromSoundLevel( soundlevel_t soundlevel, vec_t dist )
|
|||
|
{
|
|||
|
|
|||
|
// this effecively means that gain is effecting falloff,
|
|||
|
// which it shouldn't do and should be removed
|
|||
|
// FIX ME: Morasky
|
|||
|
float gain = snd_gain.GetFloat();
|
|||
|
|
|||
|
float dist_mult = SNDLVL_TO_DIST_MULT( soundlevel );
|
|||
|
if ( dist_mult )
|
|||
|
{
|
|||
|
gain = SND_GetGainFromMult( gain, dist_mult, dist );
|
|||
|
}
|
|||
|
|
|||
|
return gain;
|
|||
|
}
|