aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Alc/hrtf.c137
1 files changed, 107 insertions, 30 deletions
diff --git a/Alc/hrtf.c b/Alc/hrtf.c
index cc383163..4d833d1d 100644
--- a/Alc/hrtf.c
+++ b/Alc/hrtf.c
@@ -25,11 +25,29 @@
#include "alMain.h"
#include "alSource.h"
+/* External HRTF file format (LE byte order):
+ *
+ * ALchar magic[8] = "MinPHR00";
+ * ALuint sampleRate;
+ *
+ * ALushort hrirCount; // Required value: 828
+ * ALushort hrirSize; // Required value: 32
+ * ALubyte evCount; // Required value: 19
+ *
+ * ALushort evOffset[evCount]; // Required values:
+ * { 0, 1, 13, 37, 73, 118, 174, 234, 306, 378, 450, 522, 594, 654, 710, 755, 791, 815, 827 }
+ *
+ * ALushort coefficients[hrirCount][hrirSize];
+ * ALubyte delays[hrirCount]; // Element values must not exceed 127
+ */
+
+static const ALchar magicMarker[8] = "MinPHR00";
+
#define HRIR_COUNT 828
+#define ELEV_COUNT 19
-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 };
+static const ALushort evOffset[ELEV_COUNT] = { 0, 1, 13, 37, 73, 118, 174, 234, 306, 378, 450, 522, 594, 654, 710, 755, 791, 815, 827 };
+static const ALubyte azCount[ELEV_COUNT] = { 1, 12, 24, 36, 45, 56, 60, 72, 72, 72, 72, 72, 60, 56, 45, 36, 24, 12, 1 };
static struct Hrtf {
ALuint sampleRate;
@@ -41,13 +59,13 @@ static struct Hrtf {
};
// Calculate the elevation indices given the polar elevation in radians.
-// This will return two indices between 0 and (evCount - 1) and an
+// This will return two indices between 0 and (ELEV_COUNT-1) and an
// interpolation factor between 0.0 and 1.0.
static void CalcEvIndices(ALfloat ev, ALuint *evidx, ALfloat *evmu)
{
- ev = (M_PI/2.0f + ev) * (evCount-1) / M_PI;
+ ev = (M_PI/2.0f + ev) * (ELEV_COUNT-1) / M_PI;
evidx[0] = (ALuint)ev;
- evidx[1] = __min(evidx[0] + 1, evCount - 1);
+ evidx[1] = __min(evidx[0] + 1, ELEV_COUNT-1);
*evmu = ev - evidx[0];
}
@@ -141,49 +159,106 @@ ALCboolean IsHrtfCompatible(ALCdevice *device)
void InitHrtf(void)
{
- const char *str;
+ const char *fname;
FILE *f = NULL;
- str = GetConfigValue(NULL, "hrtf_tables", "");
- if(str[0] != '\0')
+ fname = GetConfigValue(NULL, "hrtf_tables", "");
+ if(fname[0] != '\0')
{
- f = fopen(str, "rb");
+ f = fopen(fname, "rb");
if(f == NULL)
- ERR("Could not open %s\n", str);
+ ERR("Could not open %s\n", fname);
}
if(f != NULL)
{
- const ALubyte maxDelay = SRC_HISTORY_LENGTH;
+ const ALubyte maxDelay = SRC_HISTORY_LENGTH-1;
ALboolean failed = AL_FALSE;
struct Hrtf newdata;
- size_t i, j;
+ ALchar magic[9];
+ ALsizei i, j;
+
+ if(fread(magic, 1, sizeof(magicMarker), f) != sizeof(magicMarker))
+ {
+ ERR("Failed to read magic marker\n");
+ failed = AL_TRUE;
+ }
+ else if(memcmp(magic, magicMarker, sizeof(magicMarker)) != 0)
+ {
+ magic[8] = 0;
+ ERR("Invalid magic marker: \"%s\"\n", magic);
+ failed = AL_TRUE;
+ }
- newdata.sampleRate = 44100;
- for(i = 0;i < HRIR_COUNT;i++)
+ if(!failed)
{
- for(j = 0;j < HRIR_LENGTH;j++)
+ ALushort hrirCount, hrirSize;
+ ALubyte evCount;
+
+ newdata.sampleRate = fgetc(f);
+ newdata.sampleRate |= fgetc(f)<<8;
+ newdata.sampleRate |= fgetc(f)<<16;
+ newdata.sampleRate |= fgetc(f)<<24;
+
+ hrirCount = fgetc(f);
+ hrirCount |= fgetc(f)<<8;
+
+ hrirSize = fgetc(f);
+ hrirSize |= fgetc(f)<<8;
+
+ evCount = fgetc(f);
+
+ if(hrirCount != HRIR_COUNT || hrirSize != HRIR_LENGTH || evCount != ELEV_COUNT)
{
- ALshort val;
- val = fgetc(f);
- val |= fgetc(f)<<8;
- newdata.coeffs[i][j] = val;
+ ERR("Unsupported value: hrirCount=%d (%d), hrirSize=%d (%d), evCount=%d (%d)\n",
+ hrirCount, HRIR_COUNT, hrirSize, HRIR_LENGTH, evCount, ELEV_COUNT);
+ failed = AL_TRUE;
}
}
- for(i = 0;i < HRIR_COUNT;i++)
+
+ if(!failed)
{
- ALubyte val;
- val = fgetc(f);
- newdata.delays[i] = val;
- if(val > maxDelay)
+ for(i = 0;i < HRIR_COUNT;i++)
{
- ERR("Invalid delay at idx %zu: %u (max: %u), in %s\n", i, val, maxDelay, str);
- failed = AL_TRUE;
+ ALushort offset;
+ offset = fgetc(f);
+ offset |= fgetc(f)<<8;
+ if(offset != evOffset[i])
+ {
+ ERR("Unsupported evOffset[%d] value: %d (%d)\n", i, offset, evOffset[i]);
+ failed = AL_TRUE;
+ }
}
}
- if(feof(f))
+
+ if(!failed)
{
- ERR("Premature end of data while reading %s\n", str);
- failed = AL_TRUE;
+ for(i = 0;i < HRIR_COUNT;i++)
+ {
+ for(j = 0;j < HRIR_LENGTH;j++)
+ {
+ ALshort coeff;
+ coeff = fgetc(f);
+ coeff |= fgetc(f)<<8;
+ newdata.coeffs[i][j] = coeff;
+ }
+ }
+ for(i = 0;i < HRIR_COUNT;i++)
+ {
+ ALubyte delay;
+ delay = fgetc(f);
+ newdata.delays[i] = delay;
+ if(delay > maxDelay)
+ {
+ ERR("Invalid delay[%d]: %d (%d)\n", i, delay, maxDelay);
+ failed = AL_TRUE;
+ }
+ }
+
+ if(feof(f))
+ {
+ ERR("Premature end of data\n");
+ failed = AL_TRUE;
+ }
}
fclose(f);
@@ -191,5 +266,7 @@ void InitHrtf(void)
if(!failed)
Hrtf = newdata;
+ else
+ ERR("Failed to load %s\n", fname);
}
}