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,55 +159,114 @@ 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;
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;
}
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("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(!failed)
{
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 val;
val = fgetc(f);
val |= fgetc(f)<<8;
newdata.coeffs[i][j] = val;
ALshort coeff;
coeff = fgetc(f);
coeff |= fgetc(f)<<8;
newdata.coeffs[i][j] = coeff;
}
}
for(i = 0;i < HRIR_COUNT;i++)
{
ALubyte val;
val = fgetc(f);
newdata.delays[i] = val;
if(val > maxDelay)
ALubyte delay;
delay = fgetc(f);
newdata.delays[i] = delay;
if(delay > maxDelay)
{
ERR("Invalid delay at idx %zu: %u (max: %u), in %s\n", i, val, maxDelay, str);
ERR("Invalid delay[%d]: %d (%d)\n", i, delay, maxDelay);
failed = AL_TRUE;
}
}
if(feof(f))
{
ERR("Premature end of data while reading %s\n", str);
ERR("Premature end of data\n");
failed = AL_TRUE;
}
}
fclose(f);
f = NULL;
if(!failed)
Hrtf = newdata;
else
ERR("Failed to load %s\n", fname);
}
}