Small cleanup for BuildBFormatHrtf

This commit is contained in:
Chris Robinson
2018-12-21 18:17:59 -08:00
parent 3553ce1f67
commit 5e4378f30a
+39 -35
View File
@@ -277,6 +277,13 @@ void GetHrtfCoeffs(const struct Hrtf *Hrtf, ALfloat elevation, ALfloat azimuth,
void BuildBFormatHrtf(const struct Hrtf *Hrtf, DirectHrtfState *state, const ALsizei NumChannels, const AngularPoint *AmbiPoints, const ALfloat (*RESTRICT AmbiMatrix)[MAX_AMBI_COEFFS], const ALsizei AmbiCount, const ALfloat *RESTRICT AmbiOrderHFGain)
{
static constexpr int OrderFromChan[MAX_AMBI_COEFFS]{
0, 1,1,1, 2,2,2,2,2, 3,3,3,3,3,3,3,
};
ASSUME(NumChannels > 0);
ASSUME(AmbiCount > 0);
/* Set this to 2 for dual-band HRTF processing. May require a higher quality
* band-splitter, or better calculation of the new IR length to deal with the
* tail generated by the filter.
@@ -285,92 +292,89 @@ void BuildBFormatHrtf(const struct Hrtf *Hrtf, DirectHrtfState *state, const ALs
ALsizei min_delay{HRTF_HISTORY_LENGTH};
ALsizei max_delay{0};
al::vector<ALsizei> idx(AmbiCount);
for(ALsizei c{0};c < AmbiCount;c++)
auto calc_idxs = [Hrtf,&max_delay,&min_delay](const AngularPoint &pt) noexcept -> ALsizei
{
/* Calculate elevation index. */
const auto evidx = clampi(
static_cast<ALsizei>((90.0f+AmbiPoints[c].Elev)*(Hrtf->evCount-1)/180.0f + 0.5f),
static_cast<ALsizei>((90.0f+pt.Elev)*(Hrtf->evCount-1)/180.0f + 0.5f),
0, Hrtf->evCount-1);
const ALsizei azcount{Hrtf->azCount[evidx]};
const ALsizei evoffset{Hrtf->evOffset[evidx]};
/* Calculate azimuth index for this elevation. */
const auto azidx = static_cast<ALsizei>(
(360.0f+AmbiPoints[c].Azim)*azcount/360.0f + 0.5f) % azcount;
const auto azidx = static_cast<ALsizei>((360.0f+pt.Azim)*azcount/360.0f + 0.5f) % azcount;
/* Calculate indices for left and right channels. */
idx[c] = evoffset + azidx;
/* Calculate the index for the impulse response. */
ALsizei idx{evoffset + azidx};
min_delay = mini(min_delay, mini(Hrtf->delays[idx[c]][0], Hrtf->delays[idx[c]][1]));
max_delay = maxi(max_delay, maxi(Hrtf->delays[idx[c]][0], Hrtf->delays[idx[c]][1]));
}
min_delay = mini(min_delay, mini(Hrtf->delays[idx][0], Hrtf->delays[idx][1]));
max_delay = maxi(max_delay, maxi(Hrtf->delays[idx][0], Hrtf->delays[idx][1]));
return idx;
};
std::transform(AmbiPoints, AmbiPoints+AmbiCount, idx.begin(), calc_idxs);
al::vector<std::array<std::array<ALdouble,2>,HRIR_LENGTH>> tmpres(NumChannels);
ALfloat temps[3][HRIR_LENGTH]{};
BandSplitter splitter;
splitter.init(400.0f / (ALfloat)Hrtf->sampleRate);
for(ALsizei c{0};c < AmbiCount;++c)
{
const ALfloat (*fir)[2] = &Hrtf->coeffs[idx[c] * Hrtf->irSize];
ALsizei ldelay = Hrtf->delays[idx[c]][0] - min_delay;
ALsizei rdelay = Hrtf->delays[idx[c]][1] - min_delay;
const ALfloat (*fir)[2]{&Hrtf->coeffs[idx[c] * Hrtf->irSize]};
ALsizei ldelay{Hrtf->delays[idx[c]][0] - min_delay};
ALsizei rdelay{Hrtf->delays[idx[c]][1] - min_delay};
if(NUM_BANDS == 1)
{
for(ALsizei i{0};i < NumChannels;++i)
{
ALdouble mult = (ALdouble)AmbiOrderHFGain[(ALsizei)sqrt(i)] * AmbiMatrix[c][i];
ALsizei lidx = ldelay, ridx = rdelay;
ALsizei j = 0;
while(lidx < HRIR_LENGTH && ridx < HRIR_LENGTH && j < Hrtf->irSize)
const ALdouble mult{(ALdouble)AmbiOrderHFGain[OrderFromChan[i]] * AmbiMatrix[c][i]};
const ALsizei numirs{mini(Hrtf->irSize, HRIR_LENGTH-maxi(ldelay, rdelay))};
ALsizei lidx{ldelay}, ridx{rdelay};
for(ALsizei j{0};j < numirs;++j)
{
tmpres[i][lidx++][0] += fir[j][0] * mult;
tmpres[i][ridx++][1] += fir[j][1] * mult;
j++;
}
}
}
else
{
ALfloat temps[3][HRIR_LENGTH]{};
/* Band-split left HRIR into low and high frequency responses. */
splitter.clear();
for(ALsizei i{0};i < Hrtf->irSize;++i)
temps[2][i] = fir[i][0];
std::transform(fir, fir+Hrtf->irSize, std::begin(temps[2]),
[](const ALfloat (&ir)[2]) noexcept { return ir[0]; });
splitter.process(temps[0], temps[1], temps[2], HRIR_LENGTH);
/* Apply left ear response with delay. */
for(ALsizei i{0};i < NumChannels;++i)
{
ALdouble hfgain = AmbiOrderHFGain[(ALsizei)sqrt(i)];
const ALdouble hfgain{AmbiOrderHFGain[OrderFromChan[i]]};
for(ALsizei b{0};b < NUM_BANDS;++b)
{
ALdouble mult = AmbiMatrix[c][i] * ((b==0) ? hfgain : 1.0);
ALsizei lidx = ldelay;
ALsizei j = 0;
while(lidx < HRIR_LENGTH)
tmpres[i][lidx++][0] += temps[b][j++] * mult;
const ALdouble mult{AmbiMatrix[c][i] * ((b==0) ? hfgain : 1.0)};
for(ALsizei lidx{ldelay},j{0};lidx < HRIR_LENGTH;++lidx,++j)
tmpres[i][lidx][0] += temps[b][j] * mult;
}
}
/* Band-split right HRIR into low and high frequency responses. */
splitter.clear();
for(ALsizei i{0};i < Hrtf->irSize;++i)
temps[2][i] = fir[i][1];
std::transform(fir, fir+Hrtf->irSize, std::begin(temps[2]),
[](const ALfloat (&ir)[2]) noexcept { return ir[1]; });
splitter.process(temps[0], temps[1], temps[2], HRIR_LENGTH);
/* Apply right ear response with delay. */
for(ALsizei i{0};i < NumChannels;++i)
{
ALdouble hfgain = AmbiOrderHFGain[(ALsizei)sqrt(i)];
const ALdouble hfgain{AmbiOrderHFGain[OrderFromChan[i]]};
for(ALsizei b{0};b < NUM_BANDS;++b)
{
ALdouble mult = AmbiMatrix[c][i] * ((b==0) ? hfgain : 1.0);
ALsizei ridx = rdelay;
ALsizei j = 0;
while(ridx < HRIR_LENGTH)
tmpres[i][ridx++][1] += temps[b][j++] * mult;
const ALdouble mult{AmbiMatrix[c][i] * ((b==0) ? hfgain : 1.0)};
for(ALsizei ridx{rdelay},j{0};ridx < HRIR_LENGTH;++ridx,++j)
tmpres[i][ridx][1] += temps[b][j] * mult;
}
}
}