| 289 | } |
| 290 | |
| 291 | void BuildBFormatHrtf(const HrtfEntry *Hrtf, DirectHrtfState *state, |
| 292 | const al::span<const AngularPoint> AmbiPoints, const ALfloat (*AmbiMatrix)[MAX_AMBI_CHANNELS], |
| 293 | const ALfloat *AmbiOrderHFGain) |
| 294 | { |
| 295 | using double2 = std::array<double,2>; |
| 296 | struct ImpulseResponse { |
| 297 | alignas(16) std::array<double2,HRIR_LENGTH> hrir; |
| 298 | ALuint ldelay, rdelay; |
| 299 | }; |
| 300 | |
| 301 | static const int OrderFromChan[MAX_AMBI_CHANNELS]{ |
| 302 | 0, 1,1,1, 2,2,2,2,2, 3,3,3,3,3,3,3, |
| 303 | }; |
| 304 | /* Set this to true for dual-band HRTF processing. May require better |
| 305 | * calculation of the new IR length to deal with the head and tail |
| 306 | * generated by the HF scaling. |
| 307 | */ |
| 308 | static constexpr bool DualBand{true}; |
| 309 | |
| 310 | ALuint min_delay{HRTF_HISTORY_LENGTH}; |
| 311 | ALuint max_delay{0}; |
| 312 | al::vector<ImpulseResponse> impres; impres.reserve(AmbiPoints.size()); |
| 313 | auto calc_res = [Hrtf,&max_delay,&min_delay](const AngularPoint &pt) -> ImpulseResponse |
| 314 | { |
| 315 | ImpulseResponse res; |
| 316 | |
| 317 | auto &field = Hrtf->field[0]; |
| 318 | |
| 319 | /* Calculate the elevation indices. */ |
| 320 | const auto elev0 = CalcEvIndex(field.evCount, pt.Elev.value); |
| 321 | const ALsizei elev1_idx{mini(elev0.idx+1, field.evCount-1)}; |
| 322 | const ALsizei ir0offset{Hrtf->elev[elev0.idx].irOffset}; |
| 323 | const ALsizei ir1offset{Hrtf->elev[elev1_idx].irOffset}; |
| 324 | |
| 325 | /* Calculate azimuth indices. */ |
| 326 | const auto az0 = CalcAzIndex(Hrtf->elev[elev0.idx].azCount, pt.Azim.value); |
| 327 | const auto az1 = CalcAzIndex(Hrtf->elev[elev1_idx].azCount, pt.Azim.value); |
| 328 | |
| 329 | /* Calculate the HRIR indices to blend. */ |
| 330 | const ALuint idx[4]{ |
| 331 | static_cast<ALuint>(ir0offset + az0.idx), |
| 332 | static_cast<ALuint>(ir0offset + ((az0.idx+1) % Hrtf->elev[elev0.idx].azCount)), |
| 333 | static_cast<ALuint>(ir1offset + az1.idx), |
| 334 | static_cast<ALuint>(ir1offset + ((az1.idx+1) % Hrtf->elev[elev1_idx].azCount))}; |
| 335 | |
| 336 | /* Calculate bilinear blending weights. */ |
| 337 | const ALfloat blend[4]{ |
| 338 | (1.0f-elev0.blend) * (1.0f-az0.blend), |
| 339 | (1.0f-elev0.blend) * ( az0.blend), |
| 340 | ( elev0.blend) * (1.0f-az1.blend), |
| 341 | ( elev0.blend) * ( az1.blend)}; |
| 342 | |
| 343 | /* Calculate the blended HRIR delays. */ |
| 344 | res.ldelay = fastf2u( |
| 345 | Hrtf->delays[idx[0]][0]*blend[0] + Hrtf->delays[idx[1]][0]*blend[1] + |
| 346 | Hrtf->delays[idx[2]][0]*blend[2] + Hrtf->delays[idx[3]][0]*blend[3]); |
| 347 | res.rdelay = fastf2u( |
| 348 | Hrtf->delays[idx[0]][1]*blend[0] + Hrtf->delays[idx[1]][1]*blend[1] + |
no test coverage detected