aboutsummaryrefslogtreecommitdiffstats
path: root/Alc/hrtf.c
diff options
context:
space:
mode:
authorChris Robinson <[email protected]>2011-07-16 00:22:01 -0700
committerChris Robinson <[email protected]>2011-07-16 00:22:01 -0700
commit23bfb03d2a362f33e6234c0bda848241a8bd1e32 (patch)
treecb148648a2ce6b8ce90324704ec5cec1d412db27 /Alc/hrtf.c
parent7381b1a69696c2e1dc2161e85f9488b4cdef1198 (diff)
Improve the external HRTF data file format
Although more parameters are read from the file, some must currently conform to specific values. In the future, these restrictions may be lifted.
Diffstat (limited to 'Alc/hrtf.c')
-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);
}
}