diff options
author | Chris Robinson <[email protected]> | 2019-12-08 16:46:11 -0800 |
---|---|---|
committer | Chris Robinson <[email protected]> | 2019-12-08 16:46:11 -0800 |
commit | a280373dc1d596b720c33556e8cbbf30276fe388 (patch) | |
tree | add8c2d100f40f8ad23fe4522a9264f0b64bd133 | |
parent | 8cb0e0a58b97d989bcc82aeac37f0336bea0402a (diff) |
Improve blended IR delay precision for the B-Format decoder
-rw-r--r-- | alc/hrtf.cpp | 21 |
1 files changed, 13 insertions, 8 deletions
diff --git a/alc/hrtf.cpp b/alc/hrtf.cpp index 8e01b3bf..6405c1e8 100644 --- a/alc/hrtf.cpp +++ b/alc/hrtf.cpp @@ -92,6 +92,7 @@ struct LoadedHrtf { #define HRIR_DELAY_FRACBITS 2 #define HRIR_DELAY_FRACONE (1<<HRIR_DELAY_FRACBITS) +#define HRIR_DELAY_FRACHALF (HRIR_DELAY_FRACONE>>1) static_assert(MAX_HRIR_DELAY*HRIR_DELAY_FRACONE < 256, "MAX_HRIR_DELAY or DELAY_FRAC too large"); @@ -304,7 +305,7 @@ void BuildBFormatHrtf(const HrtfStore *Hrtf, DirectHrtfState *state, */ static constexpr bool DualBand{true}; - ALuint min_delay{HRTF_HISTORY_LENGTH}; + ALuint min_delay{HRTF_HISTORY_LENGTH*HRIR_DELAY_FRACONE}; ALuint max_delay{0}; al::vector<ImpulseResponse> impres; impres.reserve(AmbiPoints.size()); auto calc_res = [Hrtf,&max_delay,&min_delay](const AngularPoint &pt) -> ImpulseResponse @@ -337,13 +338,13 @@ void BuildBFormatHrtf(const HrtfStore *Hrtf, DirectHrtfState *state, ( elev0.blend) * (1.0-az1.blend), ( elev0.blend) * ( az1.blend)}; - /* Calculate the blended HRIR delays. */ + /* Calculate the blended HRIR delays (in fixed-point). */ double d{Hrtf->delays[idx[0]][0]*blend[0] + Hrtf->delays[idx[1]][0]*blend[1] + Hrtf->delays[idx[2]][0]*blend[2] + Hrtf->delays[idx[3]][0]*blend[3]}; - res.ldelay = fastf2u(static_cast<float>(d) * float{1.0f/HRIR_DELAY_FRACONE}); + res.ldelay = fastf2u(static_cast<float>(d)); d = Hrtf->delays[idx[0]][1]*blend[0] + Hrtf->delays[idx[1]][1]*blend[1] + Hrtf->delays[idx[2]][1]*blend[2] + Hrtf->delays[idx[3]][1]*blend[3]; - res.rdelay = fastf2u(static_cast<float>(d) * float{1.0f/HRIR_DELAY_FRACONE}); + res.rdelay = fastf2u(static_cast<float>(d)); /* Calculate the blended HRIR coefficients. */ double *coeffout{al::assume_aligned<16>(&res.hrir[0][0])}; @@ -363,6 +364,8 @@ void BuildBFormatHrtf(const HrtfStore *Hrtf, DirectHrtfState *state, return res; }; std::transform(AmbiPoints.begin(), AmbiPoints.end(), std::back_inserter(impres), calc_res); + auto hrir_delay_round = [](const ALuint d) noexcept -> ALuint + { return (d+HRIR_DELAY_FRACHALF) >> HRIR_DELAY_FRACBITS; }; /* For dual-band processing, add a 16-sample delay to compensate for the HF * scale on the minimum-phase response. @@ -376,8 +379,8 @@ void BuildBFormatHrtf(const HrtfStore *Hrtf, DirectHrtfState *state, for(size_t c{0u};c < AmbiPoints.size();++c) { const al::span<const double2,HRIR_LENGTH> hrir{impres[c].hrir}; - const ALuint ldelay{impres[c].ldelay - min_delay + base_delay}; - const ALuint rdelay{impres[c].rdelay - min_delay + base_delay}; + const ALuint ldelay{hrir_delay_round(impres[c].ldelay-min_delay) + base_delay}; + const ALuint rdelay{hrir_delay_round(impres[c].rdelay-min_delay) + base_delay}; if /*constexpr*/(!DualBand) { @@ -463,18 +466,20 @@ void BuildBFormatHrtf(const HrtfStore *Hrtf, DirectHrtfState *state, } tmpres.clear(); + max_delay -= min_delay; ALuint max_length{HRIR_LENGTH}; /* Increase the IR size by double the base delay with dual-band processing * to account for the head and tail from the HF response scale. */ const ALuint irsize{minu(Hrtf->irSize + base_delay*2, max_length)}; - max_length = minu(max_delay-min_delay + irsize, max_length); + max_length = minu(hrir_delay_round(max_delay) + irsize, max_length); /* Round up to the next IR size multiple. */ max_length += MOD_IR_SIZE-1; max_length -= max_length%MOD_IR_SIZE; - TRACE("Skipped delay: %u, max delay: %u, new FIR length: %u\n", min_delay, max_delay-min_delay, + TRACE("Skipped delay: %.2f, max delay: %.2f, new FIR length: %u\n", + min_delay/double{HRIR_DELAY_FRACONE}, max_delay/double{HRIR_DELAY_FRACONE}, max_length); state->IrSize = max_length; } |