From 84d2d623b644880eb4d677d45e257ffb00f6244c Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Tue, 8 Dec 2009 14:18:07 -0800 Subject: [PATCH] Add a head-dampening option This simulates occlusion of the player's head for sounds coming from behind, when outputing to mono or stereo --- Alc/ALc.c | 9 +++++++++ Alc/ALu.c | 24 ++++++++++++++++++------ OpenAL32/Include/alMain.h | 5 +++++ alsoftrc.sample | 8 ++++++++ 4 files changed, 40 insertions(+), 6 deletions(-) diff --git a/Alc/ALc.c b/Alc/ALc.c index 383e2c47..3f4fb706 100644 --- a/Alc/ALc.c +++ b/Alc/ALc.c @@ -1711,6 +1711,15 @@ ALCAPI ALCdevice* ALCAPIENTRY alcOpenDevice(const ALCchar *deviceName) device->Bs2bLevel = GetConfigValueInt(NULL, "cf_level", 0); + if(aluChannelsFromFormat(device->Format) <= 2) + { + device->HeadDampen = GetConfigValueFloat(NULL, "head_dampen", DEFAULT_HEAD_DAMPEN); + device->HeadDampen = __min(device->HeadDampen, 1.0f); + device->HeadDampen = __max(device->HeadDampen, 0.0f); + } + else + device->HeadDampen = 0.0f; + // Find a playback device to open SuspendContext(NULL); for(i = 0;BackendList[i].Init;i++) diff --git a/Alc/ALu.c b/Alc/ALu.c index 8874cccc..c99ac881 100644 --- a/Alc/ALu.c +++ b/Alc/ALu.c @@ -685,17 +685,11 @@ static ALvoid CalcSourceParams(const ALCcontext *ALContext, ALsource *ALSource, ALfloat scale = (Angle-InnerAngle) / (OuterAngle-InnerAngle); ConeVolume = (1.0f+(ALSource->flOuterGain-1.0f)*scale); ConeHF = (1.0f+(OuterGainHF-1.0f)*scale); - DryMix *= ConeVolume; - if(ALSource->DryGainHFAuto) - DryGainHF *= ConeHF; } else if(Angle > OuterAngle) { ConeVolume = (1.0f+(ALSource->flOuterGain-1.0f)); ConeHF = (1.0f+(OuterGainHF-1.0f)); - DryMix *= ConeVolume; - if(ALSource->DryGainHFAuto) - DryGainHF *= ConeHF; } else { @@ -703,6 +697,24 @@ static ALvoid CalcSourceParams(const ALCcontext *ALContext, ALsource *ALSource, ConeHF = 1.0f; } + // Apply some high-frequency attenuation for sources behind the listener + // NOTE: This should be aluDotproduct({0,0,-1}, ListenerToSource), however + // that is equivalent to aluDotproduct({0,0,1}, SourceToListener), which is + // the same as SourceToListener[2] + Angle = aluAcos(SourceToListener[2]) * 180.0f/M_PI; + // Sources within the minimum distance attenuate less + if(OrigDist < MinDist) + Angle *= OrigDist/MinDist; + if(Angle > 90.0f) + { + ALfloat scale = (Angle-90.0f) / (180.1f-90.0f); // .1 to account for fp errors + ConeHF *= 1.0f - (ALContext->Device->HeadDampen*scale); + } + + DryMix *= ConeVolume; + if(ALSource->DryGainHFAuto) + DryGainHF *= ConeHF; + // Clamp to Min/Max Gain DryMix = __min(DryMix,MaxVolume); DryMix = __max(DryMix,MinVolume); diff --git a/OpenAL32/Include/alMain.h b/OpenAL32/Include/alMain.h index 324c18fa..cb290e0c 100644 --- a/OpenAL32/Include/alMain.h +++ b/OpenAL32/Include/alMain.h @@ -163,6 +163,8 @@ static __inline void al_print(const char *fname, unsigned int line, const char * #define LOWPASSFREQCUTOFF (5000) +#define DEFAULT_HEAD_DAMPEN (0.25f) + // Find the next power-of-2 for non-power-of-2 numbers. static __inline ALuint NextPowerOf2(ALuint value) @@ -269,6 +271,9 @@ struct ALCdevice_struct struct bs2b *Bs2b; ALCint Bs2bLevel; + // Simulated dampening from head occlusion + ALfloat HeadDampen; + // Dry path buffer mix float DryBuffer[BUFFERSIZE][OUTPUTCHANNELS]; diff --git a/alsoftrc.sample b/alsoftrc.sample index 8efae414..6f25d3eb 100644 --- a/alsoftrc.sample +++ b/alsoftrc.sample @@ -48,6 +48,14 @@ # stereo modes. #cf_level = 0 +## head_dampen: +# Sets the amount of dampening on sounds emanating from behind the listener. +# This is used to simulate the natural occlusion of the head, which is +# typically missing with mono and stereo output, and as such, only works on +# mono and stereo output modes. Valid values range from 0 to 1 (inclusive), +# and higher values provide a stronger effect. +#head_dampen = 0.25 + ## frequency: # Sets the output frequency. #frequency = 44100 -- 2.11.4.GIT