From 23bfb03d2a362f33e6234c0bda848241a8bd1e32 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sat, 16 Jul 2011 00:22:01 -0700 Subject: 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. --- Alc/hrtf.c | 137 +++++++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 107 insertions(+), 30 deletions(-) (limited to 'Alc/hrtf.c') 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); } } -- cgit v1.2.3