X-Git-Url: https://git.xonotic.org/?a=blobdiff_plain;ds=sidebyside;f=snd_main.c;h=e76bc8047e78207f5d91e01c787b072fa23fc1a1;hb=badaa9e2623b5a0b1a32808c77fe9a08970c9e16;hp=d0a1011c4cf1f64ffd7b25c94e60f99efb2d42bb;hpb=6d2396afcbd2468777f372c680af9a3b679d44a0;p=xonotic%2Fdarkplaces.git diff --git a/snd_main.c b/snd_main.c index d0a1011c..e76bc804 100644 --- a/snd_main.c +++ b/snd_main.c @@ -165,6 +165,8 @@ cvar_t volume = {CVAR_SAVE, "volume", "0.7", "volume of sound effects"}; cvar_t snd_initialized = { CVAR_READONLY, "snd_initialized", "0", "indicates the sound subsystem is active"}; cvar_t snd_staticvolume = {CVAR_SAVE, "snd_staticvolume", "1", "volume of ambient sound effects (such as swampy sounds at the start of e1m2)"}; cvar_t snd_soundradius = {CVAR_SAVE, "snd_soundradius", "1200", "radius of weapon sounds and other standard sound effects (monster idle noises are half this radius and flickering light noises are one third of this radius)"}; +cvar_t snd_attenuation_exponent = {CVAR_SAVE, "snd_attenuation_exponent", "1", "Exponent of (1-radius) in sound attenuation formula"}; +cvar_t snd_attenuation_decibel = {CVAR_SAVE, "snd_attenuation_decibel", "0", "Decibel sound attenuation per sound radius distance"}; cvar_t snd_spatialization_min_radius = {CVAR_SAVE, "snd_spatialization_min_radius", "10000", "use minimum spatialization above to this radius"}; cvar_t snd_spatialization_max_radius = {CVAR_SAVE, "snd_spatialization_max_radius", "100", "use maximum spatialization below this radius"}; cvar_t snd_spatialization_min = {CVAR_SAVE, "snd_spatialization_min", "0.70", "minimum spatializazion of sounds"}; @@ -183,6 +185,9 @@ cvar_t snd_swapstereo = {CVAR_SAVE, "snd_swapstereo", "0", "swaps left/right spe extern cvar_t v_flipped; cvar_t snd_channellayout = {0, "snd_channellayout", "0", "channel layout. Can be 0 (auto - snd_restart needed), 1 (standard layout), or 2 (ALSA layout)"}; cvar_t snd_mutewhenidle = {CVAR_SAVE, "snd_mutewhenidle", "1", "whether to disable sound output when game window is inactive"}; +cvar_t snd_maxchannelvolume = {CVAR_SAVE, "snd_maxchannelvolume", "10", "maximum volume of a single sound"}; +cvar_t snd_softclip = {CVAR_SAVE, "snd_softclip", "0", "Use soft-clipping. Soft-clipping can make the sound more smooth if very high volume levels are used. Enable this option if the dynamic range of the loudspeakers is very low. WARNING: This feature creates distortion and should be considered a last resort."}; +//cvar_t snd_softclip = {CVAR_SAVE, "snd_softclip", "0", "Use soft-clipping (when set to 2, use it even if output is floating point). Soft-clipping can make the sound more smooth if very high volume levels are used. Enable this option if the dynamic range of the loudspeakers is very low. WARNING: This feature creates distortion and should be considered a last resort."}; cvar_t snd_entchannel0volume = {CVAR_SAVE, "snd_entchannel0volume", "1", "volume multiplier of the auto-allocate entity channel of regular entities (DEPRECATED)"}; cvar_t snd_entchannel1volume = {CVAR_SAVE, "snd_entchannel1volume", "1", "volume multiplier of the 1st entity channel of regular entities (DEPRECATED)"}; cvar_t snd_entchannel2volume = {CVAR_SAVE, "snd_entchannel2volume", "1", "volume multiplier of the 2nd entity channel of regular entities (DEPRECATED)"}; @@ -241,6 +246,10 @@ static cvar_t snd_channels = {CVAR_SAVE, "snd_channels", "2", "number of channel static cvar_t snd_startloopingsounds = {0, "snd_startloopingsounds", "1", "whether to start sounds that would loop (you want this to be 1); existing sounds are not affected"}; static cvar_t snd_startnonloopingsounds = {0, "snd_startnonloopingsounds", "1", "whether to start sounds that would not loop (you want this to be 1); existing sounds are not affected"}; +// randomization +static cvar_t snd_identicalsoundrandomization_time = {0, "snd_identicalsoundrandomization_time", "0.1", "how much seconds to randomly skip (positive) or delay (negative) sounds when multiple identical sounds are started on the same frame"}; +static cvar_t snd_identicalsoundrandomization_tics = {0, "snd_identicalsoundrandomization_tics", "0", "if nonzero, how many tics to limit sound randomization as defined by snd_identicalsoundrandomization_time"}; + // Ambient sounds static sfx_t* ambient_sfxs [2] = { NULL, NULL }; static const char* ambient_names [2] = { "sound/ambience/water1.wav", "sound/ambience/wind2.wav" }; @@ -833,6 +842,9 @@ void S_Init(void) Cvar_RegisterVariable(&snd_channel6volume); Cvar_RegisterVariable(&snd_channel7volume); + Cvar_RegisterVariable(&snd_attenuation_exponent); + Cvar_RegisterVariable(&snd_attenuation_decibel); + Cvar_RegisterVariable(&snd_spatialization_min_radius); Cvar_RegisterVariable(&snd_spatialization_max_radius); Cvar_RegisterVariable(&snd_spatialization_min); @@ -847,10 +859,15 @@ void S_Init(void) Cvar_RegisterVariable(&snd_width); Cvar_RegisterVariable(&snd_channels); Cvar_RegisterVariable(&snd_mutewhenidle); + Cvar_RegisterVariable(&snd_maxchannelvolume); + Cvar_RegisterVariable(&snd_softclip); Cvar_RegisterVariable(&snd_startloopingsounds); Cvar_RegisterVariable(&snd_startnonloopingsounds); + Cvar_RegisterVariable(&snd_identicalsoundrandomization_time); + Cvar_RegisterVariable(&snd_identicalsoundrandomization_tics); + // COMMANDLINEOPTION: Sound: -nosound disables sound (including CD audio) if (COM_CheckParm("-nosound")) { @@ -1397,8 +1414,11 @@ void SND_Spatialize_WithSfx(channel_t *ch, qboolean isstatic, sfx_t *sfx) if (!(ch->flags & CHANNELFLAG_FULLVOLUME)) mastervol *= volume.value; - // clamp HERE to allow to go at most 10dB past mastervolume (before clamping), when mastervolume < -10dB (so relative volumes don't get too messy) - mastervol = bound(0.0f, mastervol, 10.0f); + if(snd_maxchannelvolume.value > 0) + { + // clamp HERE to allow to go at most 10dB past mastervolume (before clamping), when mastervolume < -10dB (so relative volumes don't get too messy) + mastervol = bound(0.0f, mastervol, 10.0f * snd_maxchannelvolume.value); + } // always apply "master" mastervol *= mastervolume.value; @@ -1410,13 +1430,21 @@ void SND_Spatialize_WithSfx(channel_t *ch, qboolean isstatic, sfx_t *sfx) // Replaygain support // Con_DPrintf("Setting volume on ReplayGain-enabled track... %f -> ", fvol); mastervol *= sfx->volume_mult; - if(mastervol * sfx->volume_peak > 1.0f) - mastervol = 1.0f / sfx->volume_peak; + if(snd_maxchannelvolume.value > 0) + { + if(mastervol * sfx->volume_peak > snd_maxchannelvolume.value) + mastervol = snd_maxchannelvolume.value / sfx->volume_peak; + } // Con_DPrintf("%f\n", fvol); } - // clamp HERE to keep relative volumes of the channels correct - mastervol = bound(0.0f, mastervol, 1.0f); + if(snd_maxchannelvolume.value > 0) + { + // clamp HERE to keep relative volumes of the channels correct + mastervol = min(mastervol, snd_maxchannelvolume.value); + } + + mastervol = max(0.0f, mastervol); ch->mixspeed = mixspeed; @@ -1443,7 +1471,14 @@ void SND_Spatialize_WithSfx(channel_t *ch, qboolean isstatic, sfx_t *sfx) // calculate stereo seperation and distance attenuation VectorSubtract(listener_origin, ch->origin, source_vec); dist = VectorLength(source_vec); - intensity = mastervol * (1.0f - dist * ch->distfade); + f = dist * ch->distfade; + + f = + ((snd_attenuation_exponent.value == 0) ? 1.0 : pow(1.0 - min(1.0, f), snd_attenuation_exponent.value)) + * + ((snd_attenuation_decibel.value == 0) ? 1.0 : pow(0.1, 0.1 * snd_attenuation_decibel.value * f)); + + intensity = mastervol * f; if (intensity > 0) { qboolean occluded = false; @@ -1677,8 +1712,18 @@ int S_StartSound_StartPosition_Flags (int entnum, int entchannel, sfx_t *sfx, ve continue; if (check->sfx == sfx && check->position == 0 && check->basespeed == fspeed) { + // calculate max offset + float maxtime = snd_identicalsoundrandomization_time.value; + float maxtics = snd_identicalsoundrandomization_tics.value; + float maxticsdelta = ((cls.state == ca_connected) ? (maxtics * (cl.mtime[0] - cl.mtime[1])) : 0); + float maxdelta = 0; + if(maxticsdelta == 0 || fabs(maxticsdelta) > fabs(maxtime)) + maxdelta = maxtime; + else + maxdelta = fabs(maxticsdelta) * ((maxtime > 0) ? 1 : -1); + // use negative pos offset to delay this sound effect - startpos = lhrandom(0, -0.1 * sfx->format.speed); + startpos = lhrandom(0, maxdelta * sfx->format.speed); break; } } @@ -1689,14 +1734,9 @@ int S_StartSound_StartPosition_Flags (int entnum, int entchannel, sfx_t *sfx, ve return (target_chan - channels); } -int S_StartSound_StartPosition (int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float fvol, float attenuation, float startposition) -{ - return S_StartSound_StartPosition_Flags(entnum, entchannel, sfx, origin, fvol, attenuation, startposition, CHANNELFLAG_NONE, 1.0f); -} - int S_StartSound (int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float fvol, float attenuation) { - return S_StartSound_StartPosition(entnum, entchannel, sfx, origin, fvol, attenuation, 0); + return S_StartSound_StartPosition_Flags(entnum, entchannel, sfx, origin, fvol, attenuation, 0, CHANNELFLAG_NONE, 1.0f); } void S_StopChannel (unsigned int channel_ind, qboolean lockmutex, qboolean freesfx)