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:
parent
7381b1a696
commit
23bfb03d2a
141
Alc/hrtf.c
141
Alc/hrtf.c
@ -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);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user