]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - snd_mix.c
Add underwater sound filter
[xonotic/darkplaces.git] / snd_mix.c
index 736d6ea1964f54ab7d11485daafde3d5d498f039..499c16f487a40bb9336d9fcaf22de9d949f60008 100644 (file)
--- a/snd_mix.c
+++ b/snd_mix.c
@@ -309,6 +309,65 @@ static void S_ConvertPaintBuffer(portable_sampleframe_t *painted_ptr, void *rb_p
        }
 }
 
+/*
+===============================================================================
+
+UNDERWATER EFFECT
+
+===============================================================================
+*/
+
+static struct {
+       float   intensity;
+       float   alpha;
+       float   accum[SND_LISTENERS];
+} underwater = {0.f, 1.f, {0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f}};
+
+void S_SetUnderwaterIntensity(void)
+{
+       float host_frametime = cl.realframetime;
+       float target = cl.view_underwater ? 1.f : 0.f;
+
+       if (snd_waterfx.value < 0.f)
+               target *= 0.f;
+       else if (snd_waterfx.value > 2.f)
+               target *= 2.f;
+       else
+               target *= snd_waterfx.value;
+
+       if (underwater.intensity < target)
+       {
+               underwater.intensity += host_frametime * 4.f;
+               underwater.intensity = min(underwater.intensity, target);
+       }
+       else if (underwater.intensity > target)
+       {
+               underwater.intensity -= host_frametime * 4.f;
+               underwater.intensity = max(underwater.intensity, target);
+       }
+
+       underwater.alpha = exp(-underwater.intensity * log(12.f));
+}
+
+static void S_UnderwaterFilter(int endtime)
+{
+       int i;
+       int sl;
+       if (!underwater.intensity) {
+               if (endtime > 0) {
+                       for (sl = 0; sl < SND_LISTENERS; sl++) {
+                               underwater.accum[sl] = paintbuffer[endtime-1].sample[sl];
+                       }
+               }
+               return;
+       }
+       for (i = 0; i < endtime; i++) {
+               for (sl = 0; sl < SND_LISTENERS; sl++) {
+                       underwater.accum[sl] += underwater.alpha * (paintbuffer[i].sample[sl] - underwater.accum[sl]);
+                       paintbuffer[i].sample[sl] = underwater.accum[sl];
+               }
+       }
+}
 
 /*
 ===============================================================================
@@ -580,6 +639,9 @@ void S_MixToBuffer(void *stream, unsigned int bufferframes)
 
                S_SoftClipPaintBuffer(paintbuffer, totalmixframes, snd_renderbuffer->format.width, snd_renderbuffer->format.channels);
 
+               S_UnderwaterFilter(totalmixframes);
+
+
 #ifdef CONFIG_VIDEO_CAPTURE
                if (!snd_usethreadedmixing)
                        S_CaptureAVISound(paintbuffer, totalmixframes);