diff options
author | Chris Robinson <[email protected]> | 2011-07-16 00:22:01 -0700 |
---|---|---|
committer | Chris Robinson <[email protected]> | 2011-07-16 00:22:01 -0700 |
commit | 23bfb03d2a362f33e6234c0bda848241a8bd1e32 (patch) | |
tree | cb148648a2ce6b8ce90324704ec5cec1d412db27 /Alc/hrtf.c | |
parent | 7381b1a69696c2e1dc2161e85f9488b4cdef1198 (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.c | 137 |
1 files changed, 107 insertions, 30 deletions
@@ -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); } } |