diff options
author | Chris Robinson <[email protected]> | 2019-01-22 10:27:04 -0800 |
---|---|---|
committer | Chris Robinson <[email protected]> | 2019-01-22 10:27:04 -0800 |
commit | b4a2532ffc2540c12d21d17620ee39c6f9369c78 (patch) | |
tree | 3e725f2e40945e9e2dee22bd4a1f70578d3ee25f | |
parent | 1565d7e2764141f40b9f8b2713311ca3394271fd (diff) |
Partially allow loading of multi-field HRTFs
Only the first field actually gets used, but all the data is processed when
loading.
-rw-r--r-- | Alc/hrtf.cpp | 102 |
1 files changed, 62 insertions, 40 deletions
diff --git a/Alc/hrtf.cpp b/Alc/hrtf.cpp index b0865811..75e00448 100644 --- a/Alc/hrtf.cpp +++ b/Alc/hrtf.cpp @@ -28,6 +28,7 @@ #include <vector> #include <memory> #include <istream> +#include <numeric> #include <algorithm> #include "AL/al.h" @@ -798,7 +799,7 @@ HrtfEntry *LoadHrtf02(std::istream &data, const char *filename) irSize, MIN_IR_SIZE, MAX_IR_SIZE, MOD_IR_SIZE); failed = AL_TRUE; } - if(fdCount != 1) + if(fdCount < 1 || fdCount > MAX_FD_COUNT) { ERR("Multiple field-depths not supported: fdCount=%d (%d to %d)\n", fdCount, MIN_FD_COUNT, MAX_FD_COUNT); @@ -807,48 +808,49 @@ HrtfEntry *LoadHrtf02(std::istream &data, const char *filename) if(failed) return nullptr; - ALushort distance{}; - ALubyte evCount{}; + al::vector<ALushort> distance(fdCount); + al::vector<ALubyte> evCount(fdCount); al::vector<ALubyte> azCount; - for(ALsizei i{0};i < fdCount;i++) + for(ALsizei f{0};f < fdCount;f++) { - distance = GetLE_ALushort(data); - evCount = GetLE_ALubyte(data); + distance[f] = GetLE_ALushort(data); + evCount[f] = GetLE_ALubyte(data); if(!data || data.eof()) { ERR("Failed reading %s\n", filename); return nullptr; } - if(distance < MIN_FD_DISTANCE || distance > MAX_FD_DISTANCE) + if(distance[f] < MIN_FD_DISTANCE || distance[f] > MAX_FD_DISTANCE) { - ERR("Unsupported field distance: distance=%d (%dmm to %dmm)\n", - distance, MIN_FD_DISTANCE, MAX_FD_DISTANCE); + ERR("Unsupported field distance[%d]: distance=%d (%dmm to %dmm)\n", f, + distance[f], MIN_FD_DISTANCE, MAX_FD_DISTANCE); failed = AL_TRUE; } - if(evCount < MIN_EV_COUNT || evCount > MAX_EV_COUNT) + if(evCount[f] < MIN_EV_COUNT || evCount[f] > MAX_EV_COUNT) { - ERR("Unsupported elevation count: evCount=%d (%d to %d)\n", - evCount, MIN_EV_COUNT, MAX_EV_COUNT); + ERR("Unsupported elevation count: evCount[%d]=%d (%d to %d)\n", f, + evCount[f], MIN_EV_COUNT, MAX_EV_COUNT); failed = AL_TRUE; } if(failed) return nullptr; - azCount.resize(evCount); - data.read(reinterpret_cast<char*>(azCount.data()), evCount); - if(!data || data.eof() || data.gcount() < evCount) + size_t ebase{azCount.size()}; + azCount.resize(ebase + evCount[f]); + data.read(reinterpret_cast<char*>(azCount.data()+ebase), evCount[f]); + if(!data || data.eof() || data.gcount() < evCount[f]) { ERR("Failed reading %s\n", filename); return nullptr; } - for(ALsizei j{0};j < evCount;j++) + for(ALsizei e{0};e < evCount[f];e++) { - if(azCount[j] < MIN_AZ_COUNT || azCount[j] > MAX_AZ_COUNT) + if(azCount[ebase+e] < MIN_AZ_COUNT || azCount[ebase+e] > MAX_AZ_COUNT) { - ERR("Unsupported azimuth count: azCount[%d]=%d (%d to %d)\n", - j, azCount[j], MIN_AZ_COUNT, MAX_AZ_COUNT); + ERR("Unsupported azimuth count: azCount[%d][%d]=%d (%d to %d)\n", f, e, + azCount[ebase+e], MIN_AZ_COUNT, MAX_AZ_COUNT); failed = AL_TRUE; } } @@ -856,17 +858,33 @@ HrtfEntry *LoadHrtf02(std::istream &data, const char *filename) return nullptr; } - al::vector<ALushort> evOffset(evCount); + al::vector<ALushort> evOffset; + evOffset.resize(evCount[0]); + evOffset[0] = 0; ALushort irCount{azCount[0]}; - for(ALsizei i{1};i < evCount;++i) + for(ALsizei e{1};e < evCount[0];++e) { - evOffset[i] = evOffset[i-1] + azCount[i-1]; - irCount += azCount[i]; + evOffset[e] = evOffset[e-1] + azCount[e-1]; + irCount += azCount[e]; } - al::vector<std::array<ALfloat,2>> coeffs(irSize*irCount); - al::vector<std::array<ALubyte,2>> delays(irCount); + ALsizei irTotal{irCount}; + for(ALsizei f{1};f < fdCount;f++) + { + const ALsizei ebase{std::accumulate(evCount.begin(), evCount.begin()+f, 0)}; + evOffset.resize(ebase + evCount[f]); + + evOffset[ebase] = irTotal; + irTotal += azCount[ebase]; + for(ALsizei e{1};e < evCount[f];++e) + { + evOffset[ebase+e] = evOffset[ebase+e-1] + azCount[ebase+e-1]; + irTotal += azCount[ebase+e]; + } + } + al::vector<std::array<ALfloat,2>> coeffs(irSize*irTotal); + al::vector<std::array<ALubyte,2>> delays(irTotal); if(channelType == CHANTYPE_LEFTONLY) { if(sampleType == SAMPLETYPE_S16) @@ -886,7 +904,7 @@ HrtfEntry *LoadHrtf02(std::istream &data, const char *filename) ERR("Failed reading %s\n", filename); return nullptr; } - for(ALsizei i{0};i < irCount;++i) + for(ALsizei i{0};i < irTotal;++i) { if(delays[i][0] > MAX_HRIR_DELAY) { @@ -924,7 +942,7 @@ HrtfEntry *LoadHrtf02(std::istream &data, const char *filename) return nullptr; } - for(ALsizei i{0};i < irCount;++i) + for(ALsizei i{0};i < irTotal;++i) { if(delays[i][0] > MAX_HRIR_DELAY) { @@ -944,27 +962,31 @@ HrtfEntry *LoadHrtf02(std::istream &data, const char *filename) if(channelType == CHANTYPE_LEFTONLY) { /* Mirror the left ear responses to the right ear. */ - for(ALsizei i{0};i < evCount;i++) + ALsizei ebase{0}; + for(ALsizei f{0};f < fdCount;f++) { - ALushort evoffset = evOffset[i]; - ALubyte azcount = azCount[i]; - for(ALsizei j{0};j < azcount;j++) + for(ALsizei e{0};e < evCount[f];e++) { - ALsizei lidx = evoffset + j; - ALsizei ridx = evoffset + ((azcount-j) % azcount); + ALushort evoffset = evOffset[ebase+e]; + ALubyte azcount = azCount[ebase+e]; + for(ALsizei a{0};a < azcount;a++) + { + ALsizei lidx = evoffset + a; + ALsizei ridx = evoffset + ((azcount-a) % azcount); - for(ALsizei k{0};k < irSize;k++) - coeffs[ridx*irSize + k][1] = coeffs[lidx*irSize + k][0]; - delays[ridx][1] = delays[lidx][0]; + for(ALsizei k{0};k < irSize;k++) + coeffs[ridx*irSize + k][1] = coeffs[lidx*irSize + k][0]; + delays[ridx][1] = delays[lidx][0]; + } } + ebase += evCount[f]; } } return CreateHrtfStore(rate, irSize, - static_cast<ALfloat>(distance) / 1000.0f, evCount, irCount, azCount.data(), evOffset.data(), - &reinterpret_cast<ALfloat(&)[2]>(coeffs[0]), - &reinterpret_cast<ALubyte(&)[2]>(delays[0]), filename - ); + static_cast<ALfloat>(distance[0]) / 1000.0f, evCount[0], irCount, azCount.data(), + evOffset.data(), &reinterpret_cast<ALfloat(&)[2]>(coeffs[0]), + &reinterpret_cast<ALubyte(&)[2]>(delays[0]), filename); } |