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.
This commit is contained in:
Chris Robinson 2011-07-16 00:22:01 -07:00
parent 7381b1a696
commit 23bfb03d2a

View File

@ -25,11 +25,29 @@
#include "alMain.h"
#include "alSource.h"
#define HRIR_COUNT 828
/* 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 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 ALchar magicMarker[8] = "MinPHR00";
#define HRIR_COUNT 828
#define ELEV_COUNT 19
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;
newdata.sampleRate = 44100;
for(i = 0;i < HRIR_COUNT;i++)
if(fread(magic, 1, sizeof(magicMarker), f) != sizeof(magicMarker))
{
for(j = 0;j < HRIR_LENGTH;j++)
{
ALshort val;
val = fgetc(f);
val |= fgetc(f)<<8;
newdata.coeffs[i][j] = val;
}
ERR("Failed to read magic marker\n");
failed = AL_TRUE;
}
for(i = 0;i < HRIR_COUNT;i++)
else if(memcmp(magic, magicMarker, sizeof(magicMarker)) != 0)
{
ALubyte val;
val = fgetc(f);
newdata.delays[i] = val;
if(val > maxDelay)
magic[8] = 0;
ERR("Invalid magic marker: \"%s\"\n", magic);
failed = AL_TRUE;
}
if(!failed)
{
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)
{
ERR("Invalid delay at idx %zu: %u (max: %u), in %s\n", i, val, maxDelay, str);
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;
}
}
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++)
{
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(!failed)
{
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);
}
}