diff options
author | Chris Robinson <[email protected]> | 2014-07-08 09:13:35 -0700 |
---|---|---|
committer | Chris Robinson <[email protected]> | 2014-07-11 00:03:13 -0700 |
commit | f4cdecebcf043758d51885fdb0f84497476b6d96 (patch) | |
tree | 52ad1f71d77ef03d65ad038427c280ec0dee1ecc /Alc | |
parent | c5af088b5ff1f7b5c51dbdcb7327d3f22c1de5df (diff) |
Add a source radius property that determines the directionality of a sound
At 0 distance from the listener, the sound is omni-directional. As the source
and listener become 'radius' units apart, the sound becomes more directional.
With HRTF, an omni-directional sound is handled using 0-delay, pass-through
filter coefficients, which is blended with the real delay and coefficients as
needed to become more directional.
Diffstat (limited to 'Alc')
-rw-r--r-- | Alc/ALu.c | 21 | ||||
-rw-r--r-- | Alc/hrtf.c | 88 | ||||
-rw-r--r-- | Alc/hrtf.h | 4 |
3 files changed, 70 insertions, 43 deletions
@@ -425,7 +425,7 @@ ALvoid CalcNonAttnSourceParams(ALactivesource *src, const ALCcontext *ALContext) /* Get the static HRIR coefficients and delays for this * channel. */ GetLerpedHrtfCoeffs(Device->Hrtf, - 0.0f, chans[c].angle, DryGain, + 0.0f, chans[c].angle, 1.0f, DryGain, src->Direct.Mix.Hrtf.Params[c].Coeffs, src->Direct.Mix.Hrtf.Params[c].Delay); } @@ -899,6 +899,8 @@ ALvoid CalcSourceParams(ALactivesource *src, const ALCcontext *ALContext) { /* Use a binaural HRTF algorithm for stereo headphone playback */ ALfloat delta, ev = 0.0f, az = 0.0f; + ALfloat radius = ALSource->Radius; + ALfloat dirfact = 1.0f; if(Distance > FLT_EPSILON) { @@ -914,6 +916,8 @@ ALvoid CalcSourceParams(ALactivesource *src, const ALCcontext *ALContext) ev = asinf(clampf(Position[1], -1.0f, 1.0f)); az = atan2f(Position[0], -Position[2]*ZScale); } + if(radius > Distance) + dirfact *= Distance / radius; /* Check to see if the HRIR is already moving. */ if(src->Direct.Moving) @@ -926,12 +930,10 @@ ALvoid CalcSourceParams(ALactivesource *src, const ALCcontext *ALContext) if(delta > 0.001f) { ALuint counter = GetMovingHrtfCoeffs(Device->Hrtf, - ev, az, DryGain, delta, - src->Direct.Counter, - src->Direct.Mix.Hrtf.Params[0].Coeffs, - src->Direct.Mix.Hrtf.Params[0].Delay, - src->Direct.Mix.Hrtf.Params[0].CoeffStep, - src->Direct.Mix.Hrtf.Params[0].DelayStep); + ev, az, dirfact, DryGain, delta, src->Direct.Counter, + src->Direct.Mix.Hrtf.Params[0].Coeffs, src->Direct.Mix.Hrtf.Params[0].Delay, + src->Direct.Mix.Hrtf.Params[0].CoeffStep, src->Direct.Mix.Hrtf.Params[0].DelayStep + ); src->Direct.Counter = counter; src->Direct.Mix.Hrtf.Gain = DryGain; src->Direct.Mix.Hrtf.Dir[0] = Position[0]; @@ -942,7 +944,7 @@ ALvoid CalcSourceParams(ALactivesource *src, const ALCcontext *ALContext) else { /* Get the initial (static) HRIR coefficients and delays. */ - GetLerpedHrtfCoeffs(Device->Hrtf, ev, az, DryGain, + GetLerpedHrtfCoeffs(Device->Hrtf, ev, az, dirfact, DryGain, src->Direct.Mix.Hrtf.Params[0].Coeffs, src->Direct.Mix.Hrtf.Params[0].Delay); src->Direct.Counter = 0; @@ -968,8 +970,9 @@ ALvoid CalcSourceParams(ALactivesource *src, const ALCcontext *ALContext) /* Normalize the length, and compute panned gains. */ if(Distance > FLT_EPSILON) { + ALfloat radius = ALSource->Radius; ALfloat Target[MaxChannels]; - ALfloat invlen = 1.0f/Distance; + ALfloat invlen = 1.0f/maxf(Distance, radius); Position[0] *= invlen; Position[1] *= invlen; Position[2] *= invlen; @@ -123,7 +123,7 @@ ALfloat CalcHrtfDelta(ALfloat oldGain, ALfloat newGain, const ALfloat olddir[3], * increase the apparent resolution of the HRIR data set. The coefficients * are also normalized and attenuated by the specified gain. */ -void GetLerpedHrtfCoeffs(const struct Hrtf *Hrtf, ALfloat elevation, ALfloat azimuth, ALfloat gain, ALfloat (*coeffs)[2], ALuint *delays) +void GetLerpedHrtfCoeffs(const struct Hrtf *Hrtf, ALfloat elevation, ALfloat azimuth, ALfloat dirfact, ALfloat gain, ALfloat (*coeffs)[2], ALuint *delays) { ALuint evidx[2], azidx[2]; ALuint lidx[4], ridx[4]; @@ -162,12 +162,12 @@ void GetLerpedHrtfCoeffs(const struct Hrtf *Hrtf, ALfloat elevation, ALfloat azi blend[3] = ( mu[1]) * ( mu[2]); /* Calculate the HRIR delays using linear interpolation. */ - delays[0] = fastf2u(Hrtf->delays[lidx[0]]*blend[0] + Hrtf->delays[lidx[1]]*blend[1] + - Hrtf->delays[lidx[2]]*blend[2] + Hrtf->delays[lidx[3]]*blend[3] + - 0.5f) << HRTFDELAY_BITS; - delays[1] = fastf2u(Hrtf->delays[ridx[0]]*blend[0] + Hrtf->delays[ridx[1]]*blend[1] + - Hrtf->delays[ridx[2]]*blend[2] + Hrtf->delays[ridx[3]]*blend[3] + - 0.5f) << HRTFDELAY_BITS; + delays[0] = fastf2u((Hrtf->delays[lidx[0]]*blend[0] + Hrtf->delays[lidx[1]]*blend[1] + + Hrtf->delays[lidx[2]]*blend[2] + Hrtf->delays[lidx[3]]*blend[3]) * + dirfact + 0.5f) << HRTFDELAY_BITS; + delays[1] = fastf2u((Hrtf->delays[ridx[0]]*blend[0] + Hrtf->delays[ridx[1]]*blend[1] + + Hrtf->delays[ridx[2]]*blend[2] + Hrtf->delays[ridx[3]]*blend[3]) * + dirfact + 0.5f) << HRTFDELAY_BITS; /* Calculate the sample offsets for the HRIR indices. */ lidx[0] *= Hrtf->irSize; @@ -185,17 +185,26 @@ void GetLerpedHrtfCoeffs(const struct Hrtf *Hrtf, ALfloat elevation, ALfloat azi */ if(gain > 0.0001f) { + ALfloat c; + gain *= 1.0f/32767.0f; - for(i = 0;i < Hrtf->irSize;i++) + + i = 0; + c = (Hrtf->coeffs[lidx[0]+i]*blend[0] + Hrtf->coeffs[lidx[1]+i]*blend[1] + + Hrtf->coeffs[lidx[2]+i]*blend[2] + Hrtf->coeffs[lidx[3]+i]*blend[3]); + coeffs[i][0] = lerp(1.0f, c, dirfact) * gain; + c = (Hrtf->coeffs[ridx[0]+i]*blend[0] + Hrtf->coeffs[ridx[1]+i]*blend[1] + + Hrtf->coeffs[ridx[2]+i]*blend[2] + Hrtf->coeffs[ridx[3]+i]*blend[3]); + coeffs[i][1] = lerp(1.0f, c, dirfact) * gain; + + for(i = 1;i < Hrtf->irSize;i++) { - coeffs[i][0] = (Hrtf->coeffs[lidx[0]+i]*blend[0] + - Hrtf->coeffs[lidx[1]+i]*blend[1] + - Hrtf->coeffs[lidx[2]+i]*blend[2] + - Hrtf->coeffs[lidx[3]+i]*blend[3]) * gain; - coeffs[i][1] = (Hrtf->coeffs[ridx[0]+i]*blend[0] + - Hrtf->coeffs[ridx[1]+i]*blend[1] + - Hrtf->coeffs[ridx[2]+i]*blend[2] + - Hrtf->coeffs[ridx[3]+i]*blend[3]) * gain; + c = (Hrtf->coeffs[lidx[0]+i]*blend[0] + Hrtf->coeffs[lidx[1]+i]*blend[1] + + Hrtf->coeffs[lidx[2]+i]*blend[2] + Hrtf->coeffs[lidx[3]+i]*blend[3]); + coeffs[i][0] = lerp(0.0f, c, dirfact) * gain; + c = (Hrtf->coeffs[ridx[0]+i]*blend[0] + Hrtf->coeffs[ridx[1]+i]*blend[1] + + Hrtf->coeffs[ridx[2]+i]*blend[2] + Hrtf->coeffs[ridx[3]+i]*blend[3]); + coeffs[i][1] = lerp(0.0f, c, dirfact) * gain; } } else @@ -215,7 +224,7 @@ void GetLerpedHrtfCoeffs(const struct Hrtf *Hrtf, ALfloat elevation, ALfloat azi * specified gain. Stepping resolution and count is determined using the * given delta factor between 0.0 and 1.0. */ -ALuint GetMovingHrtfCoeffs(const struct Hrtf *Hrtf, ALfloat elevation, ALfloat azimuth, ALfloat gain, ALfloat delta, ALint counter, ALfloat (*coeffs)[2], ALuint *delays, ALfloat (*coeffStep)[2], ALint *delayStep) +ALuint GetMovingHrtfCoeffs(const struct Hrtf *Hrtf, ALfloat elevation, ALfloat azimuth, ALfloat dirfact, ALfloat gain, ALfloat delta, ALint counter, ALfloat (*coeffs)[2], ALuint *delays, ALfloat (*coeffStep)[2], ALint *delayStep) { ALuint evidx[2], azidx[2]; ALuint lidx[4], ridx[4]; @@ -266,12 +275,12 @@ ALuint GetMovingHrtfCoeffs(const struct Hrtf *Hrtf, ALfloat elevation, ALfloat a left = (ALfloat)(delays[0] - (delayStep[0] * counter)); right = (ALfloat)(delays[1] - (delayStep[1] * counter)); - delays[0] = fastf2u(Hrtf->delays[lidx[0]]*blend[0] + Hrtf->delays[lidx[1]]*blend[1] + - Hrtf->delays[lidx[2]]*blend[2] + Hrtf->delays[lidx[3]]*blend[3] + - 0.5f) << HRTFDELAY_BITS; - delays[1] = fastf2u(Hrtf->delays[ridx[0]]*blend[0] + Hrtf->delays[ridx[1]]*blend[1] + - Hrtf->delays[ridx[2]]*blend[2] + Hrtf->delays[ridx[3]]*blend[3] + - 0.5f) << HRTFDELAY_BITS; + delays[0] = fastf2u((Hrtf->delays[lidx[0]]*blend[0] + Hrtf->delays[lidx[1]]*blend[1] + + Hrtf->delays[lidx[2]]*blend[2] + Hrtf->delays[lidx[3]]*blend[3]) * + dirfact + 0.5f) << HRTFDELAY_BITS; + delays[1] = fastf2u((Hrtf->delays[ridx[0]]*blend[0] + Hrtf->delays[ridx[1]]*blend[1] + + Hrtf->delays[ridx[2]]*blend[2] + Hrtf->delays[ridx[3]]*blend[3]) * + dirfact + 0.5f) << HRTFDELAY_BITS; delayStep[0] = fastf2i(step * (delays[0] - left)); delayStep[1] = fastf2i(step * (delays[1] - right)); @@ -294,20 +303,35 @@ ALuint GetMovingHrtfCoeffs(const struct Hrtf *Hrtf, ALfloat elevation, ALfloat a */ if(gain > 0.0001f) { + ALfloat c; + gain *= 1.0f/32767.0f; - for(i = 0;i < Hrtf->irSize;i++) + + i = 0; + left = coeffs[i][0] - (coeffStep[i][0] * counter); + right = coeffs[i][1] - (coeffStep[i][1] * counter); + + c = (Hrtf->coeffs[lidx[0]+i]*blend[0] + Hrtf->coeffs[lidx[1]+i]*blend[1] + + Hrtf->coeffs[lidx[2]+i]*blend[2] + Hrtf->coeffs[lidx[3]+i]*blend[3]); + coeffs[i][0] = lerp(0.0f, c, dirfact) * gain; + c = (Hrtf->coeffs[ridx[0]+i]*blend[0] + Hrtf->coeffs[ridx[1]+i]*blend[1] + + Hrtf->coeffs[ridx[2]+i]*blend[2] + Hrtf->coeffs[ridx[3]+i]*blend[3]); + coeffs[i][1] = lerp(0.0f, c, dirfact) * gain; + + coeffStep[i][0] = step * (coeffs[i][0] - left); + coeffStep[i][1] = step * (coeffs[i][1] - right); + + for(i = 1;i < Hrtf->irSize;i++) { left = coeffs[i][0] - (coeffStep[i][0] * counter); right = coeffs[i][1] - (coeffStep[i][1] * counter); - coeffs[i][0] = (Hrtf->coeffs[lidx[0]+i]*blend[0] + - Hrtf->coeffs[lidx[1]+i]*blend[1] + - Hrtf->coeffs[lidx[2]+i]*blend[2] + - Hrtf->coeffs[lidx[3]+i]*blend[3]) * gain; - coeffs[i][1] = (Hrtf->coeffs[ridx[0]+i]*blend[0] + - Hrtf->coeffs[ridx[1]+i]*blend[1] + - Hrtf->coeffs[ridx[2]+i]*blend[2] + - Hrtf->coeffs[ridx[3]+i]*blend[3]) * gain; + c = (Hrtf->coeffs[lidx[0]+i]*blend[0] + Hrtf->coeffs[lidx[1]+i]*blend[1] + + Hrtf->coeffs[lidx[2]+i]*blend[2] + Hrtf->coeffs[lidx[3]+i]*blend[3]); + coeffs[i][0] = lerp(1.0f, c, dirfact) * gain; + c = (Hrtf->coeffs[ridx[0]+i]*blend[0] + Hrtf->coeffs[ridx[1]+i]*blend[1] + + Hrtf->coeffs[ridx[2]+i]*blend[2] + Hrtf->coeffs[ridx[3]+i]*blend[3]); + coeffs[i][1] = lerp(1.0f, c, dirfact) * gain; coeffStep[i][0] = step * (coeffs[i][0] - left); coeffStep[i][1] = step * (coeffs[i][1] - right); @@ -22,7 +22,7 @@ void FreeHrtfs(void); ALuint GetHrtfIrSize(const struct Hrtf *Hrtf); ALfloat CalcHrtfDelta(ALfloat oldGain, ALfloat newGain, const ALfloat olddir[3], const ALfloat newdir[3]); -void GetLerpedHrtfCoeffs(const struct Hrtf *Hrtf, ALfloat elevation, ALfloat azimuth, ALfloat gain, ALfloat (*coeffs)[2], ALuint *delays); -ALuint GetMovingHrtfCoeffs(const struct Hrtf *Hrtf, ALfloat elevation, ALfloat azimuth, ALfloat gain, ALfloat delta, ALint counter, ALfloat (*coeffs)[2], ALuint *delays, ALfloat (*coeffStep)[2], ALint *delayStep); +void GetLerpedHrtfCoeffs(const struct Hrtf *Hrtf, ALfloat elevation, ALfloat azimuth, ALfloat dirfact, ALfloat gain, ALfloat (*coeffs)[2], ALuint *delays); +ALuint GetMovingHrtfCoeffs(const struct Hrtf *Hrtf, ALfloat elevation, ALfloat azimuth, ALfloat dirfact, ALfloat gain, ALfloat delta, ALint counter, ALfloat (*coeffs)[2], ALuint *delays, ALfloat (*coeffStep)[2], ALint *delayStep); #endif /* ALC_HRTF_H */ |