aboutsummaryrefslogtreecommitdiffstats
path: root/alc/hrtf.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'alc/hrtf.cpp')
-rw-r--r--alc/hrtf.cpp105
1 files changed, 13 insertions, 92 deletions
diff --git a/alc/hrtf.cpp b/alc/hrtf.cpp
index f1e1a86b..05803865 100644
--- a/alc/hrtf.cpp
+++ b/alc/hrtf.cpp
@@ -289,13 +289,7 @@ void DirectHrtfState::build(const HrtfStore *Hrtf, const al::span<const AngularP
ALuint ldelay, rdelay;
};
- /* Set this to true for dual-band HRTF processing. May require better
- * calculation of the new IR length to deal with the head and tail
- * generated by the HF scaling.
- */
- constexpr bool DualBand{false};
const double xover_norm{400.0 / Hrtf->sampleRate};
-
for(size_t i{0};i < mChannels.size();++i)
{
const size_t order{AmbiIndex::OrderFromChannel[i]};
@@ -303,8 +297,7 @@ void DirectHrtfState::build(const HrtfStore *Hrtf, const al::span<const AngularP
mChannels[i].mHfScale = AmbiOrderHFGain[order];
}
- ALuint min_delay{HRTF_HISTORY_LENGTH*HRIR_DELAY_FRACONE};
- ALuint max_delay{0};
+ ALuint min_delay{HRTF_HISTORY_LENGTH*HRIR_DELAY_FRACONE}, max_delay{0};
al::vector<ImpulseResponse> impres; impres.reserve(AmbiPoints.size());
auto calc_res = [Hrtf,&max_delay,&min_delay](const AngularPoint &pt) -> ImpulseResponse
{
@@ -345,93 +338,25 @@ void DirectHrtfState::build(const HrtfStore *Hrtf, const al::span<const AngularP
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.
- */
- constexpr ALuint base_delay{DualBand ? 16 : 0};
- BandSplitterR<double> splitter{xover_norm};
-
auto tmpres = al::vector<std::array<double2,HRIR_LENGTH>>(mChannels.size());
- auto tmpflt = al::vector<std::array<double,HRIR_LENGTH*4>>(3);
- const al::span<double,HRIR_LENGTH*4> tempir{tmpflt[2]};
for(size_t c{0u};c < AmbiPoints.size();++c)
{
const HrirArray &hrir{impres[c].hrir};
- 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)
- {
- for(size_t i{0u};i < mChannels.size();++i)
- {
- const double mult{AmbiMatrix[c][i]};
- const size_t numirs{HRIR_LENGTH - maxz(ldelay, rdelay)};
- size_t lidx{ldelay}, ridx{rdelay};
- for(size_t j{0};j < numirs;++j)
- {
- tmpres[i][lidx++][0] += hrir[j][0] * mult;
- tmpres[i][ridx++][1] += hrir[j][1] * mult;
- }
- }
- continue;
- }
-
- /* For dual-band processing, the HRIR needs to be split into low and
- * high frequency responses. The band-splitter alone creates frequency-
- * dependent phase-shifts, which is not ideal. To counteract it,
- * combine it with a backwards phase-shift.
- */
-
- /* Load the (left) HRIR backwards, into a temp buffer with padding. */
- std::fill(tempir.begin(), tempir.end(), 0.0);
- std::transform(hrir.crbegin(), hrir.crend(), tempir.begin(),
- [](const float2 &ir) noexcept -> double { return ir[0]; });
-
- /* Apply the all-pass on the reversed signal and reverse the resulting
- * sample array. This produces the forward response with a backwards
- * phase-shift (+n degrees becomes -n degrees).
- */
- splitter.applyAllpass(tempir);
- std::reverse(tempir.begin(), tempir.end());
-
- /* Now apply the band-splitter. This applies the normal phase-shift,
- * which cancels out with the backwards phase-shift to get the original
- * phase on the split signal.
- */
- splitter.clear();
- splitter.process(tempir, tmpflt[0].data(), tmpflt[1].data());
-
- /* Apply left ear response with delay and HF scale. */
- for(size_t i{0u};i < mChannels.size();++i)
- {
- const double mult{AmbiMatrix[c][i]};
- const double hfgain{AmbiOrderHFGain[AmbiIndex::OrderFromChannel[i]]};
- size_t j{tmpflt[0].size()-HRIR_LENGTH - ldelay};
- for(size_t lidx{0};lidx < HRIR_LENGTH;++lidx,++j)
- tmpres[i][lidx][0] += (tmpflt[0][j]*hfgain + tmpflt[1][j]) * mult;
- }
-
- /* Now run the same process on the right HRIR. */
- std::fill(tempir.begin(), tempir.end(), 0.0);
- std::transform(hrir.crbegin(), hrir.crend(), tempir.begin(),
- [](const float2 &ir) noexcept -> double { return ir[1]; });
-
- splitter.applyAllpass(tempir);
- std::reverse(tempir.begin(), tempir.end());
-
- splitter.clear();
- splitter.process(tempir, tmpflt[0].data(), tmpflt[1].data());
+ const ALuint ldelay{hrir_delay_round(impres[c].ldelay - min_delay)};
+ const ALuint rdelay{hrir_delay_round(impres[c].rdelay - min_delay)};
for(size_t i{0u};i < mChannels.size();++i)
{
const double mult{AmbiMatrix[c][i]};
- const double hfgain{AmbiOrderHFGain[AmbiIndex::OrderFromChannel[i]]};
- size_t j{tmpflt[0].size()-HRIR_LENGTH - rdelay};
- for(size_t ridx{0};ridx < HRIR_LENGTH;++ridx,++j)
- tmpres[i][ridx][1] += (tmpflt[0][j]*hfgain + tmpflt[1][j]) * mult;
+ const size_t numirs{HRIR_LENGTH - maxz(ldelay, rdelay)};
+ size_t lidx{ldelay}, ridx{rdelay};
+ for(size_t j{0};j < numirs;++j)
+ {
+ tmpres[i][lidx++][0] += hrir[j][0] * mult;
+ tmpres[i][ridx++][1] += hrir[j][1] * mult;
+ }
}
}
- tmpflt.clear();
impres.clear();
for(size_t i{0u};i < mChannels.size();++i)
@@ -443,14 +368,10 @@ void DirectHrtfState::build(const HrtfStore *Hrtf, const al::span<const AngularP
}
tmpres.clear();
- max_delay -= min_delay;
- /* 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, HRIR_LENGTH)};
- const ALuint max_length{minu(hrir_delay_round(max_delay) + irsize, HRIR_LENGTH)};
+ max_delay = hrir_delay_round(max_delay - min_delay);
+ const ALuint max_length{minu(max_delay + Hrtf->irSize, HRIR_LENGTH)};
- TRACE("Skipped delay: %.2f, max delay: %.2f, new FIR length: %u\n",
+ TRACE("Skipped delay: %.2f, new max delay: %.2f, FIR length: %u\n",
min_delay/double{HRIR_DELAY_FRACONE}, max_delay/double{HRIR_DELAY_FRACONE},
max_length);
mIrSize = max_length;