X-Git-Url: http://git.xonotic.org/?a=blobdiff_plain;f=snd_mix.c;h=4f3310bfcf1a83b3ef3eaad472b70fa7e850ceae;hb=1003437071042f3dd3d7c6a7880d73b66a77c1f6;hp=eab51a6474002d58d98266edb9609ead2907a4fb;hpb=12849b354eaba65efdaad7277863f6b0f036bb38;p=xonotic%2Fdarkplaces.git diff --git a/snd_mix.c b/snd_mix.c index eab51a64..4f3310bf 100644 --- a/snd_mix.c +++ b/snd_mix.c @@ -21,13 +21,13 @@ 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]; extern speakerlayout_t snd_speakerlayout; // for querying the listeners -extern void SCR_CaptureVideo_SoundFrame(const portable_sampleframe_t *paintbuffer, size_t length); static void S_CaptureAVISound(const portable_sampleframe_t *paintbuffer, size_t length) { size_t i; @@ -47,9 +47,86 @@ 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) + { + portable_sampleframe_t *p = painted_ptr; + +#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 / (0.4f * snd_renderbuffer->format.speed))); +#define SOFTCLIP(x) if(fabs(x)>maxvol) maxvol=fabs(x); (x) /= maxvol; + + 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 @@ -209,7 +286,7 @@ void S_MixToBuffer(void *stream, unsigned int bufferframes) float sample[3]; double posd; double speedd; - float sum; + float maxvol; qboolean looping; qboolean silent; @@ -246,10 +323,31 @@ void S_MixToBuffer(void *stream, unsigned int bufferframes) vol[i] = ch->volume[i]; // check total volume level, because we can skip some code on silent sounds but other code must still run (position updates mainly) - sum = 0; + maxvol = 0; for (i = 0;i < SND_LISTENERS;i++) - sum += vol[i]*vol[i]; - silent = sum < (1.0f / (65536.0f * 65536.0f)); // so silent it has zero effect + if(vol[i] > maxvol) + maxvol = vol[i]; + switch(snd_renderbuffer->format.width) + { + case 1: // 8bpp + silent = maxvol < (1.0f / (256.0f)); + // so silent it has zero effect + break; + case 2: // 16bpp + silent = maxvol < (1.0f / (65536.0f)); + // so silent it has zero effect + break; + default: // floating point + silent = maxvol < 1.0e-13f; + // 130 dB is difference between hearing + // threshold and a jackhammer from + // working distance. + // therefore, anyone who turns up + // volume so much they notice this + // cutoff, likely already has their + // ear-drums blown out anyway. + break; + } // when doing prologic mixing, some channels invert one side if (ch->prologic_invert == -1) @@ -421,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);