aboutsummaryrefslogtreecommitdiffstats
path: root/Alc
diff options
context:
space:
mode:
authorChris Robinson <[email protected]>2011-06-03 01:06:00 -0700
committerChris Robinson <[email protected]>2011-06-03 01:06:00 -0700
commit7ddfacb58f941b21da26b2749d3204307e3a0bbd (patch)
tree2cb41f7de025705f38a634781e6413c7c004829e /Alc
parentc7a80418d9291cad29dc293b95a5c328f4408b08 (diff)
Use a minimum phase HRTF data set
This reduces the coefficient size from 128 down to 32, with a set of delays
Diffstat (limited to 'Alc')
-rw-r--r--Alc/ALc.c2
-rw-r--r--Alc/ALu.c20
-rw-r--r--Alc/hrtf.c131
-rw-r--r--Alc/mixer.c72
4 files changed, 142 insertions, 83 deletions
diff --git a/Alc/ALc.c b/Alc/ALc.c
index b4e8510d..9c4dd977 100644
--- a/Alc/ALc.c
+++ b/Alc/ALc.c
@@ -496,6 +496,8 @@ static void alc_init(void)
ALTHUNK_INIT();
ReadALConfig();
+ InitHrtf();
+
tls_create(&LocalContext);
RTPrioLevel = GetConfigValueInt(NULL, "rt-prio", 0);
diff --git a/Alc/ALu.c b/Alc/ALu.c
index 934d5992..2c35498a 100644
--- a/Alc/ALu.c
+++ b/Alc/ALu.c
@@ -245,7 +245,9 @@ ALvoid CalcNonAttnSourceParams(ALsource *ALSource, const ALCcontext *ALContext)
if(c == lfe_chan)
{
/* Skip LFE */
- for(i = 0;i < HRTF_LENGTH;i++)
+ ALSource->Params.HrtfDelay[c][0] = 0;
+ ALSource->Params.HrtfDelay[c][1] = 0;
+ for(i = 0;i < HRIR_LENGTH;i++)
{
ALSource->Params.HrtfCoeffs[c][i][0] = 0.0f;
ALSource->Params.HrtfCoeffs[c][i][1] = 0.0f;
@@ -253,8 +255,11 @@ ALvoid CalcNonAttnSourceParams(ALsource *ALSource, const ALCcontext *ALContext)
continue;
}
- GetHrtfCoeffs(0.0, angles[c], &hrtf_left, &hrtf_right);
- for(i = 0;i < HRTF_LENGTH;i++)
+ GetHrtfCoeffs(0.0, angles[c] * (M_PI/180.0),
+ &hrtf_left, &hrtf_right,
+ &ALSource->Params.HrtfDelay[c][0],
+ &ALSource->Params.HrtfDelay[c][1]);
+ for(i = 0;i < HRIR_LENGTH;i++)
{
ALSource->Params.HrtfCoeffs[c][i][0] =
hrtf_left[i]*(1.0/32767.0)*DryGain*ListenerGain;
@@ -676,10 +681,11 @@ ALvoid CalcSourceParams(ALsource *ALSource, const ALCcontext *ALContext)
Position[2] *= invlen;
}
- GetHrtfCoeffs(asin(Position[1]) * (180.0/M_PI),
- atan2(Position[0], -Position[2]*ZScale) * (180.0/M_PI),
- &hrtf_left, &hrtf_right);
- for(i = 0;i < HRTF_LENGTH;i++)
+ GetHrtfCoeffs(asin(Position[1]), atan2(Position[0], -Position[2]*ZScale),
+ &hrtf_left, &hrtf_right,
+ &ALSource->Params.HrtfDelay[0][0],
+ &ALSource->Params.HrtfDelay[0][1]);
+ for(i = 0;i < HRIR_LENGTH;i++)
{
ALSource->Params.HrtfCoeffs[0][i][0] = hrtf_left[i]*(1.0/32767.0) * DryGain;
ALSource->Params.HrtfCoeffs[0][i][1] = hrtf_right[i]*(1.0/32767.0) * DryGain;
diff --git a/Alc/hrtf.c b/Alc/hrtf.c
index da461dcf..5cc0aeed 100644
--- a/Alc/hrtf.c
+++ b/Alc/hrtf.c
@@ -23,56 +23,99 @@
#include "AL/al.h"
#include "AL/alc.h"
#include "alMain.h"
+#include "alSource.h"
+#define HRIR_COUNT 828
-typedef struct {
- ALsizei num_angles;
- ALsizei max_angle;
- ALshort coeffs[][2][HRTF_LENGTH];
-} HrtfFilterCoeffs;
+static const ALubyte evCount = 19;
+static const ALushort evOffset[19] = { 0, 1, 13, 37, 73, 118, 174, 234, 306, 378, 450, 522, 594, 654, 710, 755, 791, 815, 827 };
+static const ALubyte azCount[19] = { 1, 12, 24, 36, 45, 56, 60, 72, 72, 72, 72, 72, 60, 56, 45, 36, 24, 12, 1 };
-#include "hrtf_tables.inc"
+static struct HRTF {
+ ALshort coeffs[HRIR_COUNT][HRIR_LENGTH];
+ ALubyte delays[HRIR_COUNT];
+} Hrtf;
-static void get_angle_coeffs(const HrtfFilterCoeffs *elev, ALfloat angle, const ALshort **left, const ALshort **right)
+static ALuint CalcEvIndex(ALdouble ev)
{
- if(angle < 0)
- {
- int idx = ((angle > -elev->max_angle) ?
- (int)(angle*(elev->num_angles-1)/-elev->max_angle + 0.5) :
- (elev->num_angles-1));
- *left = elev->coeffs[idx][1];
- *right = elev->coeffs[idx][0];
- }
- else
- {
- int idx = ((angle < elev->max_angle) ?
- (int)(angle*(elev->num_angles-1)/elev->max_angle + 0.5) :
- (elev->num_angles-1));
- *left = elev->coeffs[idx][0];
- *right = elev->coeffs[idx][1];
- }
+ ev = (M_PI/2.0 + ev) * (evCount-1) / M_PI;
+ return (ALuint)(ev+0.5);
+}
+
+static ALuint CalcAzIndex(ALint evidx, ALdouble az)
+{
+ az = (M_PI*2.0 + az) * azCount[evidx] / (M_PI*2.0);
+ return (ALuint)(az+0.5) % azCount[evidx];
}
-void GetHrtfCoeffs(ALfloat elevation, ALfloat angle, const ALshort **left, const ALshort **right)
+void GetHrtfCoeffs(ALfloat elevation, ALfloat angle, const ALshort **left, const ALshort **right, ALuint *ldelay, ALuint *rdelay)
{
- int idx;
-
- if(elevation > 90.f) elevation = 90.f - (elevation - 90.f);
- else if(elevation < -90.f) elevation = -90.f - (elevation - -90.f);
-
- idx = (int)(elevation/10.0 + 0.5);
- if(idx >= 9) return get_angle_coeffs(&Elev90, angle, left, right);
- if(idx >= 8) return get_angle_coeffs(&Elev80, angle, left, right);
- if(idx >= 7) return get_angle_coeffs(&Elev70, angle, left, right);
- if(idx >= 6) return get_angle_coeffs(&Elev60, angle, left, right);
- if(idx >= 5) return get_angle_coeffs(&Elev50, angle, left, right);
- if(idx >= 4) return get_angle_coeffs(&Elev40, angle, left, right);
- if(idx >= 3) return get_angle_coeffs(&Elev30, angle, left, right);
- if(idx >= 2) return get_angle_coeffs(&Elev20, angle, left, right);
- if(idx >= 1) return get_angle_coeffs(&Elev10, angle, left, right);
- if(idx >= 0) return get_angle_coeffs(&Elev0, angle, left, right);
- if(idx >= -1) return get_angle_coeffs(&Elev10n, angle, left, right);
- if(idx >= -2) return get_angle_coeffs(&Elev20n, angle, left, right);
- if(idx >= -3) return get_angle_coeffs(&Elev30n, angle, left, right);
- return get_angle_coeffs(&Elev40n, angle, left, right);
+ ALuint lidx, ridx;
+ ALuint evidx, azidx;
+
+ evidx = CalcEvIndex(elevation);
+ azidx = CalcAzIndex(evidx, angle);
+
+ lidx = evOffset[evidx] + azidx;
+ ridx = evOffset[evidx] + ((azCount[evidx]-azidx) % azCount[evidx]);
+
+ *ldelay = Hrtf.delays[lidx];
+ *rdelay = Hrtf.delays[ridx];
+
+ *left = Hrtf.coeffs[lidx];
+ *right = Hrtf.coeffs[ridx];
+}
+
+void InitHrtf(void)
+{
+ const char *str;
+ FILE *f = NULL;
+
+ str = GetConfigValue(NULL, "hrtf_tables", "");
+ if(str[0] != '\0')
+ f = fopen(str, "rb");
+ if(f != NULL)
+ {
+ const ALubyte maxDelay = SRC_HISTORY_LENGTH - HRIR_LENGTH;
+ struct HRTF newdata;
+ size_t i, j;
+ union {
+ ALfloat f;
+ ALubyte ub[4];
+ } val;
+
+ for(i = 0;i < HRIR_COUNT;i++)
+ {
+ for(j = 0;j < HRIR_LENGTH;j++)
+ {
+ val.ub[0] = fgetc(f);
+ val.ub[1] = fgetc(f);
+ val.ub[2] = fgetc(f);
+ val.ub[3] = fgetc(f);
+ if(val.f > 1.0f) newdata.coeffs[i][j] = 32767;
+ else if(val.f < -1.0f) newdata.coeffs[i][j] = -32768;
+ else newdata.coeffs[i][j] = (ALshort)(val.f*32767.0f);
+ }
+ }
+ val.ub[0] = fgetc(f);
+ val.ub[1] = fgetc(f);
+ val.ub[2] = fgetc(f);
+ val.ub[3] = fgetc(f);
+ /* skip maxHrtd */
+ for(i = 0;i < HRIR_COUNT;i++)
+ {
+ val.ub[0] = fgetc(f);
+ val.ub[1] = fgetc(f);
+ val.ub[2] = fgetc(f);
+ val.ub[3] = fgetc(f);
+ val.f *= 44100.0f;
+ if(val.f >= maxDelay) newdata.delays[i] = maxDelay;
+ else newdata.delays[i] = (ALubyte)val.f;
+ }
+ if(!feof(f))
+ Hrtf = newdata;
+
+ fclose(f);
+ f = NULL;
+ }
}
diff --git a/Alc/mixer.c b/Alc/mixer.c
index 33181890..9a746ff9 100644
--- a/Alc/mixer.c
+++ b/Alc/mixer.c
@@ -79,9 +79,6 @@ static void Mix_Hrtf_##T##_##sampler(ALsource *Source, ALCdevice *Device, \
const T *RESTRICT data = srcdata; \
ALfloat (*RESTRICT DryBuffer)[MAXCHANNELS]; \
ALfloat *RESTRICT ClickRemoval, *RESTRICT PendingClicks; \
- ALfloat (*RESTRICT HrtfCoeffs)[HRTF_LENGTH][2]; \
- ALfloat (*RESTRICT HrtfHistory)[HRTF_LENGTH]; \
- ALuint HrtfOffset; \
ALuint pos, frac; \
FILTER *DryFilter; \
ALuint BufferIdx; \
@@ -96,15 +93,17 @@ static void Mix_Hrtf_##T##_##sampler(ALsource *Source, ALCdevice *Device, \
PendingClicks = Device->PendingClicks; \
DryFilter = &Source->Params.iirFilter; \
\
- HrtfCoeffs = Source->Params.HrtfCoeffs; \
- HrtfHistory = Source->HrtfHistory; \
- HrtfOffset = Source->HrtfOffset + OutPos; \
- \
pos = 0; \
frac = *DataPosFrac; \
\
for(i = 0;i < NumChannels;i++) \
{ \
+ static const ALuint MaxDelay = SRC_HISTORY_LENGTH - HRIR_LENGTH; \
+ ALfloat (*RESTRICT Coeffs)[2] = Source->Params.HrtfCoeffs[i]; \
+ const ALuint *RESTRICT Delay = Source->Params.HrtfDelay[i]; \
+ ALfloat (*RESTRICT History)[2] = Source->HrtfHistory[i]; \
+ ALuint Offset = Source->HrtfOffset + OutPos; \
+ \
pos = 0; \
frac = *DataPosFrac; \
\
@@ -113,15 +112,18 @@ static void Mix_Hrtf_##T##_##sampler(ALsource *Source, ALCdevice *Device, \
value = sampler(data + pos*NumChannels + i, NumChannels, frac); \
value = lpFilter2PC(DryFilter, i, value); \
\
- HrtfHistory[i][HrtfOffset&HRTF_LENGTH_MASK] = value; \
- for(c = 0;c < HRTF_LENGTH;c++) \
+ History[Offset&SRC_HISTORY_MASK][0] = value; \
+ History[Offset&SRC_HISTORY_MASK][1] = value; \
+ \
+ History[(Offset-MaxDelay)&SRC_HISTORY_MASK][0] = \
+ History[(Offset-Delay[0])&SRC_HISTORY_MASK][0];\
+ History[(Offset-MaxDelay)&SRC_HISTORY_MASK][1] = \
+ History[(Offset-Delay[1])&SRC_HISTORY_MASK][1];\
+ for(c = 0;c < HRIR_LENGTH;c++) \
{ \
- ClickRemoval[FRONT_LEFT] -= \
- HrtfHistory[i][(HrtfOffset-c)&HRTF_LENGTH_MASK] * \
- HrtfCoeffs[i][c][0]; \
- ClickRemoval[FRONT_RIGHT] -= \
- HrtfHistory[i][(HrtfOffset-c)&HRTF_LENGTH_MASK] * \
- HrtfCoeffs[i][c][1]; \
+ const ALuint off = (Offset-MaxDelay-c)&SRC_HISTORY_MASK; \
+ ClickRemoval[FRONT_LEFT] -= History[off][0] * Coeffs[c][0]; \
+ ClickRemoval[FRONT_RIGHT] -= History[off][1] * Coeffs[c][1]; \
} \
} \
for(BufferIdx = 0;BufferIdx < BufferSize;BufferIdx++) \
@@ -129,17 +131,20 @@ static void Mix_Hrtf_##T##_##sampler(ALsource *Source, ALCdevice *Device, \
value = sampler(data + pos*NumChannels + i, NumChannels, frac); \
value = lpFilter2P(DryFilter, i, value); \
\
- HrtfHistory[i][HrtfOffset&HRTF_LENGTH_MASK] = value; \
- for(c = 0;c < HRTF_LENGTH;c++) \
+ History[Offset&SRC_HISTORY_MASK][0] = value; \
+ History[Offset&SRC_HISTORY_MASK][1] = value; \
+ \
+ History[(Offset-MaxDelay)&SRC_HISTORY_MASK][0] = \
+ History[(Offset-Delay[0])&SRC_HISTORY_MASK][0];\
+ History[(Offset-MaxDelay)&SRC_HISTORY_MASK][1] = \
+ History[(Offset-Delay[1])&SRC_HISTORY_MASK][1];\
+ for(c = 0;c < HRIR_LENGTH;c++) \
{ \
- DryBuffer[OutPos][FRONT_LEFT] += \
- HrtfHistory[i][(HrtfOffset-c)&HRTF_LENGTH_MASK] * \
- HrtfCoeffs[i][c][0]; \
- DryBuffer[OutPos][FRONT_RIGHT] += \
- HrtfHistory[i][(HrtfOffset-c)&HRTF_LENGTH_MASK] * \
- HrtfCoeffs[i][c][1]; \
+ const ALuint off = (Offset-MaxDelay-c)&SRC_HISTORY_MASK; \
+ DryBuffer[OutPos][FRONT_LEFT] += History[off][0] * Coeffs[c][0];\
+ DryBuffer[OutPos][FRONT_RIGHT] += History[off][1] * Coeffs[c][1];\
} \
- HrtfOffset++; \
+ Offset++; \
\
frac += increment; \
pos += frac>>FRACTIONBITS; \
@@ -151,15 +156,18 @@ static void Mix_Hrtf_##T##_##sampler(ALsource *Source, ALCdevice *Device, \
value = sampler(data + pos*NumChannels + i, NumChannels, frac); \
value = lpFilter2PC(DryFilter, i, value); \
\
- HrtfHistory[i][HrtfOffset&HRTF_LENGTH_MASK] = value; \
- for(c = 0;c < HRTF_LENGTH;c++) \
+ History[Offset&SRC_HISTORY_MASK][0] = value; \
+ History[Offset&SRC_HISTORY_MASK][1] = value; \
+ \
+ History[(Offset-MaxDelay)&SRC_HISTORY_MASK][0] = \
+ History[(Offset-Delay[0])&SRC_HISTORY_MASK][0];\
+ History[(Offset-MaxDelay)&SRC_HISTORY_MASK][1] = \
+ History[(Offset-Delay[1])&SRC_HISTORY_MASK][1];\
+ for(c = 0;c < HRIR_LENGTH;c++) \
{ \
- PendingClicks[FRONT_LEFT] += \
- HrtfHistory[i][(HrtfOffset-c)&HRTF_LENGTH_MASK] * \
- HrtfCoeffs[i][c][0]; \
- PendingClicks[FRONT_RIGHT] += \
- HrtfHistory[i][(HrtfOffset-c)&HRTF_LENGTH_MASK] * \
- HrtfCoeffs[i][c][1]; \
+ const ALuint off = (Offset-MaxDelay-c)&SRC_HISTORY_MASK; \
+ PendingClicks[FRONT_LEFT] += History[off][0] * Coeffs[c][0]; \
+ PendingClicks[FRONT_RIGHT] += History[off][1] * Coeffs[c][1]; \
} \
} \
OutPos -= BufferSize; \