From d6ebf5d1b6450c53b6ad781d31f54f2e608729ca Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Mon, 24 Nov 2014 01:53:45 -0800 Subject: [PATCH] Make CalcHrtfDelta more generic --- Alc/ALu.c | 43 +++++++++++++++++++++++++++++++++++++++---- Alc/hrtf.c | 35 +---------------------------------- Alc/hrtf.h | 1 - 3 files changed, 40 insertions(+), 39 deletions(-) diff --git a/Alc/ALu.c b/Alc/ALu.c index 85948084..51148b9d 100644 --- a/Alc/ALu.c +++ b/Alc/ALu.c @@ -137,6 +137,42 @@ static inline ALvoid aluMatrixVector(ALfloat *vector, ALfloat w, ALfloat (*restr } +/* Calculates the fade time from the changes in gain and listener to source + * angle between updates. The result is a the time, in seconds, for the + * transition to complete. + */ +static ALfloat CalcFadeTime(ALfloat oldGain, ALfloat newGain, const ALfloat olddir[3], const ALfloat newdir[3]) +{ + ALfloat gainChange, angleChange, change; + + /* Calculate the normalized dB gain change. */ + newGain = maxf(newGain, 0.0001f); + oldGain = maxf(oldGain, 0.0001f); + gainChange = fabsf(log10f(newGain / oldGain) / log10f(0.0001f)); + + /* Calculate the angle change only when there is enough gain to notice it. */ + angleChange = 0.0f; + if(gainChange > 0.0001f || newGain > 0.0001f) + { + /* No angle change when the directions are equal or degenerate (when + * both have zero length). + */ + if(newdir[0] != olddir[0] || newdir[1] != olddir[1] || newdir[2] != olddir[2]) + { + ALfloat dotp = aluDotproduct(olddir, newdir); + angleChange = acosf(clampf(dotp, -1.0f, 1.0f)) / F_PI; + } + } + + /* Use the largest of the two changes, and apply a significance shaping + * function to it. The result is then scaled to cover a 15ms transition + * range. + */ + change = maxf(angleChange * 25.0f, gainChange) * 2.0f; + return minf(change, 1.0f) * 0.015f; +} + + static void UpdateDryStepping(DirectParams *params, ALuint num_chans) { ALuint i, j; @@ -997,12 +1033,11 @@ ALvoid CalcSourceParams(ALvoice *voice, const ALsource *ALSource, const ALCconte /* Check to see if the HRIR is already moving. */ if(voice->Direct.Moving) { - /* Calculate the normalized HRTF transition factor (delta). */ - delta = CalcHrtfDelta(voice->Direct.LastGain, DryGain, - voice->Direct.LastDir, Position); + delta = CalcFadeTime(voice->Direct.LastGain, DryGain, + voice->Direct.LastDir, Position); /* If the delta is large enough, get the moving HRIR target * coefficients, target delays, steppping values, and counter. */ - if(delta > 0.001f) + if(delta > 0.000015f) { ALuint counter = GetMovingHrtfCoeffs(Device->Hrtf, ev, az, dirfact, DryGain, delta, voice->Direct.Counter, diff --git a/Alc/hrtf.c b/Alc/hrtf.c index 8561902e..54e16cc7 100644 --- a/Alc/hrtf.c +++ b/Alc/hrtf.c @@ -88,39 +88,6 @@ static void CalcAzIndices(ALuint azcount, ALfloat az, ALuint *azidx, ALfloat *az *azmu = az - floorf(az); } -/* Calculates the normalized HRTF transition factor (delta) from the changes - * in gain and listener to source angle between updates. The result is a - * normalized delta factor that can be used to calculate moving HRIR stepping - * values. - */ -ALfloat CalcHrtfDelta(ALfloat oldGain, ALfloat newGain, const ALfloat olddir[3], const ALfloat newdir[3]) -{ - ALfloat gainChange, angleChange, change; - - // Calculate the normalized dB gain change. - newGain = maxf(newGain, 0.0001f); - oldGain = maxf(oldGain, 0.0001f); - gainChange = fabsf(log10f(newGain / oldGain) / log10f(0.0001f)); - - // Calculate the angle change only when there is enough gain to notice it. - angleChange = 0.0f; - if(gainChange > 0.0001f || newGain > 0.0001f) - { - // No angle change when the directions are equal or degenerate (when - // both have zero length). - if(newdir[0] != olddir[0] || newdir[1] != olddir[1] || newdir[2] != olddir[2]) - { - ALfloat dotp = olddir[0]*newdir[0] + olddir[1]*newdir[1] + olddir[2]*newdir[2]; - angleChange = acosf(clampf(dotp, -1.0f, 1.0f)) / F_PI; - } - } - - // Use the largest of the two changes for the delta factor, and apply a - // significance shaping function to it. - change = maxf(angleChange * 25.0f, gainChange) * 2.0f; - return minf(change, 1.0f); -} - /* Calculates static HRIR coefficients and delays for the given polar * elevation and azimuth in radians. Linear interpolation is used to * increase the apparent resolution of the HRIR data set. The coefficients @@ -246,7 +213,7 @@ ALuint GetMovingHrtfCoeffs(const struct Hrtf *Hrtf, ALfloat elevation, ALfloat a } // Calculate the stepping parameters. - steps = maxf(floorf(delta*(Hrtf->sampleRate*0.015f) + 0.5f), 1.0f); + steps = maxf(floorf(delta*Hrtf->sampleRate + 0.5f), 1.0f); delta = 1.0f / steps; /* Calculate 4 blending weights for 2D bilinear interpolation. */ diff --git a/Alc/hrtf.h b/Alc/hrtf.h index 938bf552..3eaa4e28 100644 --- a/Alc/hrtf.h +++ b/Alc/hrtf.h @@ -21,7 +21,6 @@ ALCboolean FindHrtfFormat(enum DevFmtChannels *chans, ALCuint *srate); 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 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); -- 2.11.4.GIT