X-Git-Url: http://git.xonotic.org/?p=xonotic%2Fdarkplaces.git;a=blobdiff_plain;f=snd_mix.c;h=b718bdcb242b97089c043e803c410766bf42c572;hp=fa0069aaafce4f1f755401dc0554ddbc9c335351;hb=HEAD;hpb=79752d8b393b5d7935c97919cf0963d5c760d5f1 diff --git a/snd_mix.c b/snd_mix.c index fa0069aa..d8ea1dbe 100644 --- a/snd_mix.c +++ b/snd_mix.c @@ -24,12 +24,13 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 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) +#ifdef CONFIG_VIDEO_CAPTURE +static portable_sampleframe_t paintbuffer_unswapped[PAINTBUFFER_SIZE]; + +static void S_CaptureAVISound(const portable_sampleframe_t *sampleframes, size_t length) { size_t i; unsigned int j; @@ -42,20 +43,23 @@ static void S_CaptureAVISound(const portable_sampleframe_t *paintbuffer, size_t { unsigned int j0 = snd_speakerlayout.listeners[j].channel_unswapped; for(i = 0; i < length; ++i) - paintbuffer_unswapped[i].sample[j0] = paintbuffer[i].sample[j]; + paintbuffer_unswapped[i].sample[j0] = sampleframes[i].sample[j]; } SCR_CaptureVideo_SoundFrame(paintbuffer_unswapped, length); } +#endif extern cvar_t snd_softclip; -static void S_SoftClipPaintBuffer(portable_sampleframe_t *painted_ptr, int nbframes, int width, int channels) +static void S_SoftClipPaintBuffer(portable_sampleframe_t *painted_ptr, int nbframes, int width, int nchannels) { 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 */ @@ -67,8 +71,7 @@ static void S_SoftClipPaintBuffer(portable_sampleframe_t *painted_ptr, int nbfra 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; - portable_sampleframe_t *p = painted_ptr; - if (channels == 8) // 7.1 surround + if (nchannels == 8) // 7.1 surround { for (i = 0;i < nbframes;i++, p++) { @@ -82,7 +85,7 @@ static void S_SoftClipPaintBuffer(portable_sampleframe_t *painted_ptr, int nbfra SOFTCLIP(p->sample[7]); } } - else if (channels == 6) // 5.1 surround + else if (nchannels == 6) // 5.1 surround { for (i = 0; i < nbframes; i++, p++) { @@ -94,7 +97,7 @@ static void S_SoftClipPaintBuffer(portable_sampleframe_t *painted_ptr, int nbfra SOFTCLIP(p->sample[5]); } } - else if (channels == 4) // 4.0 surround + else if (nchannels == 4) // 4.0 surround { for (i = 0; i < nbframes; i++, p++) { @@ -104,7 +107,7 @@ static void S_SoftClipPaintBuffer(portable_sampleframe_t *painted_ptr, int nbfra SOFTCLIP(p->sample[3]); } } - else if (channels == 2) // 2.0 stereo + else if (nchannels == 2) // 2.0 stereo { for (i = 0; i < nbframes; i++, p++) { @@ -112,7 +115,7 @@ static void S_SoftClipPaintBuffer(portable_sampleframe_t *painted_ptr, int nbfra SOFTCLIP(p->sample[1]); } } - else if (channels == 1) // 1.0 mono + else if (nchannels == 1) // 1.0 mono { for (i = 0; i < nbframes; i++, p++) { @@ -123,16 +126,73 @@ static void S_SoftClipPaintBuffer(portable_sampleframe_t *painted_ptr, int nbfra } } -static void S_ConvertPaintBuffer(portable_sampleframe_t *painted_ptr, void *rb_ptr, int nbframes, int width, int channels) +static void S_ConvertPaintBuffer(portable_sampleframe_t *painted_ptr, void *rb_ptr, int nbframes, int width, int nchannels) { - int i, val; + int i; + float val; + if (width == 4) // 32bit float + { + float *snd_out = (float*)rb_ptr; + if (nchannels == 8) // 7.1 surround + { + for (i = 0; i < nbframes; i++, painted_ptr++) + { + *snd_out++ = painted_ptr->sample[0]; + *snd_out++ = painted_ptr->sample[1]; + *snd_out++ = painted_ptr->sample[2]; + *snd_out++ = painted_ptr->sample[3]; + *snd_out++ = painted_ptr->sample[4]; + *snd_out++ = painted_ptr->sample[5]; + *snd_out++ = painted_ptr->sample[6]; + *snd_out++ = painted_ptr->sample[7]; + } + } + else if (nchannels == 6) // 5.1 surround + { + for (i = 0; i < nbframes; i++, painted_ptr++) + { + *snd_out++ = painted_ptr->sample[0]; + *snd_out++ = painted_ptr->sample[1]; + *snd_out++ = painted_ptr->sample[2]; + *snd_out++ = painted_ptr->sample[3]; + *snd_out++ = painted_ptr->sample[4]; + *snd_out++ = painted_ptr->sample[5]; + } + } + else if (nchannels == 4) // 4.0 surround + { + for (i = 0; i < nbframes; i++, painted_ptr++) + { + *snd_out++ = painted_ptr->sample[0]; + *snd_out++ = painted_ptr->sample[1]; + *snd_out++ = painted_ptr->sample[2]; + *snd_out++ = painted_ptr->sample[3]; + } + } + else if (nchannels == 2) // 2.0 stereo + { + for (i = 0; i < nbframes; i++, painted_ptr++) + { + *snd_out++ = painted_ptr->sample[0]; + *snd_out++ = painted_ptr->sample[1]; + } + } + else if (nchannels == 1) // 1.0 mono + { + for (i = 0; i < nbframes; i++, painted_ptr++) + { + *snd_out++ = painted_ptr->sample[0]; + } + } - // FIXME: add 24bit and 32bit float formats - // FIXME: optimize with SSE intrinsics? - if (width == 2) // 16bit + // noise is really really annoying + if (cls.timedemo) + memset(rb_ptr, 0, nbframes * nchannels * width); + } + else if (width == 2) // 16bit { short *snd_out = (short*)rb_ptr; - if (channels == 8) // 7.1 surround + if (nchannels == 8) // 7.1 surround { for (i = 0;i < nbframes;i++, painted_ptr++) { @@ -146,7 +206,7 @@ static void S_ConvertPaintBuffer(portable_sampleframe_t *painted_ptr, void *rb_p val = (int)(painted_ptr->sample[7] * 32768.0f);*snd_out++ = bound(-32768, val, 32767); } } - else if (channels == 6) // 5.1 surround + else if (nchannels == 6) // 5.1 surround { for (i = 0; i < nbframes; i++, painted_ptr++) { @@ -158,7 +218,7 @@ static void S_ConvertPaintBuffer(portable_sampleframe_t *painted_ptr, void *rb_p val = (int)(painted_ptr->sample[5] * 32768.0f);*snd_out++ = bound(-32768, val, 32767); } } - else if (channels == 4) // 4.0 surround + else if (nchannels == 4) // 4.0 surround { for (i = 0; i < nbframes; i++, painted_ptr++) { @@ -168,7 +228,7 @@ static void S_ConvertPaintBuffer(portable_sampleframe_t *painted_ptr, void *rb_p val = (int)(painted_ptr->sample[3] * 32768.0f);*snd_out++ = bound(-32768, val, 32767); } } - else if (channels == 2) // 2.0 stereo + else if (nchannels == 2) // 2.0 stereo { for (i = 0; i < nbframes; i++, painted_ptr++) { @@ -176,7 +236,7 @@ static void S_ConvertPaintBuffer(portable_sampleframe_t *painted_ptr, void *rb_p val = (int)(painted_ptr->sample[1] * 32768.0f);*snd_out++ = bound(-32768, val, 32767); } } - else if (channels == 1) // 1.0 mono + else if (nchannels == 1) // 1.0 mono { for (i = 0; i < nbframes; i++, painted_ptr++) { @@ -186,12 +246,12 @@ static void S_ConvertPaintBuffer(portable_sampleframe_t *painted_ptr, void *rb_p // noise is really really annoying if (cls.timedemo) - memset(rb_ptr, 0, nbframes * channels * width); + memset(rb_ptr, 0, nbframes * nchannels * width); } else // 8bit { unsigned char *snd_out = (unsigned char*)rb_ptr; - if (channels == 8) // 7.1 surround + if (nchannels == 8) // 7.1 surround { for (i = 0; i < nbframes; i++, painted_ptr++) { @@ -205,7 +265,7 @@ static void S_ConvertPaintBuffer(portable_sampleframe_t *painted_ptr, void *rb_p val = (int)(painted_ptr->sample[7] * 128.0f) + 128; *snd_out++ = bound(0, val, 255); } } - else if (channels == 6) // 5.1 surround + else if (nchannels == 6) // 5.1 surround { for (i = 0; i < nbframes; i++, painted_ptr++) { @@ -217,7 +277,7 @@ static void S_ConvertPaintBuffer(portable_sampleframe_t *painted_ptr, void *rb_p val = (int)(painted_ptr->sample[5] * 128.0f) + 128; *snd_out++ = bound(0, val, 255); } } - else if (channels == 4) // 4.0 surround + else if (nchannels == 4) // 4.0 surround { for (i = 0; i < nbframes; i++, painted_ptr++) { @@ -227,7 +287,7 @@ static void S_ConvertPaintBuffer(portable_sampleframe_t *painted_ptr, void *rb_p val = (int)(painted_ptr->sample[3] * 128.0f) + 128; *snd_out++ = bound(0, val, 255); } } - else if (channels == 2) // 2.0 stereo + else if (nchannels == 2) // 2.0 stereo { for (i = 0; i < nbframes; i++, painted_ptr++) { @@ -235,7 +295,7 @@ static void S_ConvertPaintBuffer(portable_sampleframe_t *painted_ptr, void *rb_p val = (int)(painted_ptr->sample[1] * 128.0f) + 128; *snd_out++ = bound(0, val, 255); } } - else if (channels == 1) // 1.0 mono + else if (nchannels == 1) // 1.0 mono { for (i = 0;i < nbframes;i++, painted_ptr++) { @@ -245,11 +305,71 @@ static void S_ConvertPaintBuffer(portable_sampleframe_t *painted_ptr, void *rb_p // noise is really really annoying if (cls.timedemo) - memset(rb_ptr, 128, nbframes * channels); + memset(rb_ptr, 128, nbframes * nchannels); } } + +/* +=============================================================================== + +UNDERWATER EFFECT + +Muffles the intensity of sounds when the player is underwater + +=============================================================================== +*/ + +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 target = cl.view_underwater ? bound(0.f, snd_waterfx.value, 2.f) : 0.f; + + if (underwater.intensity < target) + { + underwater.intensity += cl.realframetime * 4.f; + underwater.intensity = min(underwater.intensity, target); + } + else if (underwater.intensity > target) + { + underwater.intensity -= cl.realframetime * 4.f; + underwater.intensity = max(underwater.intensity, target); + } + + underwater.alpha = underwater.intensity ? exp(-underwater.intensity * log(12.f)) : 1.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]; + } +} + + + /* =============================================================================== @@ -287,8 +407,8 @@ void S_MixToBuffer(void *stream, unsigned int bufferframes) double posd; double speedd; float maxvol; - qboolean looping; - qboolean silent; + qbool looping; + qbool silent; // mix as many times as needed to fill the requested buffer while (bufferframes) @@ -301,7 +421,7 @@ void S_MixToBuffer(void *stream, unsigned int bufferframes) // paint in the channels. // channels with zero volumes still advance in time but don't paint. - ch = channels; + ch = channels; // cppcheck complains here but it is wrong, channels is a channel_t[MAX_CHANNELS] and not an int for (channelindex = 0;channelindex < (int)total_channels;channelindex++, ch++) { sfx = ch->sfx; @@ -360,7 +480,6 @@ void S_MixToBuffer(void *stream, unsigned int bufferframes) // do the actual paint now (may skip work if silent) paint = paintbuffer; - wantframes = totalmixframes; istartframe = 0; for (wantframes = totalmixframes;wantframes > 0;posd += count * speedd, wantframes -= count) { @@ -521,8 +640,13 @@ 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); +#endif S_ConvertPaintBuffer(paintbuffer, outbytes, totalmixframes, snd_renderbuffer->format.width, snd_renderbuffer->format.channels);