From 664d8bd04bf64f58df4b829edd9bd07d22cd4b32 Mon Sep 17 00:00:00 2001 From: divverent Date: Fri, 14 Oct 2011 18:48:59 +0000 Subject: [PATCH] snd_maxchannelvolume and snd_softclip git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@11415 d7cf8633-e32d-0410-b094-e92efae38249 ::stable-branch::merge=ba3466519160011c7d9487be0fa33ca86de26e92 --- snd_main.c | 28 +++++++++++++++---- snd_mix.c | 81 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 102 insertions(+), 7 deletions(-) diff --git a/snd_main.c b/snd_main.c index c937615b..e76bc804 100644 --- a/snd_main.c +++ b/snd_main.c @@ -185,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)"}; @@ -856,6 +859,8 @@ 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); @@ -1409,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; @@ -1422,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; diff --git a/snd_mix.c b/snd_mix.c index 35add4ef..3495d86d 100644 --- a/snd_mix.c +++ b/snd_mix.c @@ -21,6 +21,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "quakedef.h" #include "snd_main.h" +extern cvar_t snd_softclip; static portable_sampleframe_t paintbuffer[PAINTBUFFER_SIZE]; static portable_sampleframe_t paintbuffer_unswapped[PAINTBUFFER_SIZE]; @@ -47,9 +48,85 @@ static void S_CaptureAVISound(const portable_sampleframe_t *paintbuffer, size_t SCR_CaptureVideo_SoundFrame(paintbuffer_unswapped, length); } -static void S_ConvertPaintBuffer(const portable_sampleframe_t *painted_ptr, void *rb_ptr, int nbframes, int width, int channels) +extern cvar_t snd_softclip; + +static void S_SoftClipPaintBuffer(portable_sampleframe_t *painted_ptr, int nbframes, int width, int channels) +{ + int i; + + if((snd_softclip.integer == 1 && width <= 2) || snd_softclip.integer > 1) + { +#if 0 +/* Soft clipping, the sound of a dream, thanks to Jon Wattes + post to Musicdsp.org */ +#define SOFTCLIP(x) (x) = sin(bound(-M_PI/2, (x), M_PI/2)) * 0.25 +#endif + + // let's do a simple limiter instead, seems to sound better + static float maxvol = 0; + maxvol = max(1.0f, maxvol * (1.0f - nbframes / snd_renderbuffer->format.speed)); +#define SOFTCLIP(x) if((x)>maxvol) maxvol=(x); (x) /= maxvol; + + portable_sampleframe_t *p = painted_ptr; + if (channels == 8) // 7.1 surround + { + for (i = 0;i < nbframes;i++, p++) + { + SOFTCLIP(p->sample[0]); + SOFTCLIP(p->sample[1]); + SOFTCLIP(p->sample[2]); + SOFTCLIP(p->sample[3]); + SOFTCLIP(p->sample[4]); + SOFTCLIP(p->sample[5]); + SOFTCLIP(p->sample[6]); + SOFTCLIP(p->sample[7]); + } + } + else if (channels == 6) // 5.1 surround + { + for (i = 0; i < nbframes; i++, p++) + { + SOFTCLIP(p->sample[0]); + SOFTCLIP(p->sample[1]); + SOFTCLIP(p->sample[2]); + SOFTCLIP(p->sample[3]); + SOFTCLIP(p->sample[4]); + SOFTCLIP(p->sample[5]); + } + } + else if (channels == 4) // 4.0 surround + { + for (i = 0; i < nbframes; i++, p++) + { + SOFTCLIP(p->sample[0]); + SOFTCLIP(p->sample[1]); + SOFTCLIP(p->sample[2]); + SOFTCLIP(p->sample[3]); + } + } + else if (channels == 2) // 2.0 stereo + { + for (i = 0; i < nbframes; i++, p++) + { + SOFTCLIP(p->sample[0]); + SOFTCLIP(p->sample[1]); + } + } + else if (channels == 1) // 1.0 mono + { + for (i = 0; i < nbframes; i++, p++) + { + SOFTCLIP(p->sample[0]); + } + } +#undef SOFTCLIP + } +} + +static void S_ConvertPaintBuffer(portable_sampleframe_t *painted_ptr, void *rb_ptr, int nbframes, int width, int channels) { int i, val; + // FIXME: add 24bit and 32bit float formats // FIXME: optimize with SSE intrinsics? if (width == 2) // 16bit @@ -442,6 +519,8 @@ void S_MixToBuffer(void *stream, unsigned int bufferframes) S_StopChannel(ch - channels, false, false); } + S_SoftClipPaintBuffer(paintbuffer, totalmixframes, snd_renderbuffer->format.width, snd_renderbuffer->format.channels); + if (!snd_usethreadedmixing) S_CaptureAVISound(paintbuffer, totalmixframes); -- 2.39.2