aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--alc/alu.cpp6
-rw-r--r--alc/panning.cpp4
-rw-r--r--core/hrtf.cpp111
-rw-r--r--core/hrtf.h20
4 files changed, 72 insertions, 69 deletions
diff --git a/alc/alu.cpp b/alc/alu.cpp
index a9bb5298..d0b8fbd5 100644
--- a/alc/alu.cpp
+++ b/alc/alu.cpp
@@ -1047,7 +1047,7 @@ void CalcPanningAndFilters(Voice *voice, const float xpos, const float ypos, con
if(voice->mFmtChannels == FmtMono)
{
- GetHrtfCoeffs(Device->mHrtf.get(), src_ev, src_az, Distance*NfcScale, Spread,
+ Device->mHrtf->getCoeffs(src_ev, src_az, Distance*NfcScale, Spread,
voice->mChans[0].mDryParams.Hrtf.Target.Coeffs,
voice->mChans[0].mDryParams.Hrtf.Target.Delay);
voice->mChans[0].mDryParams.Hrtf.Target.Gain = DryGain.Base;
@@ -1084,7 +1084,7 @@ void CalcPanningAndFilters(Voice *voice, const float xpos, const float ypos, con
if(az < -pi_v<float>) az += pi_v<float>*2.0f;
else if(az > pi_v<float>) az -= pi_v<float>*2.0f;
- GetHrtfCoeffs(Device->mHrtf.get(), ev, az, Distance*NfcScale, 0.0f,
+ Device->mHrtf->getCoeffs(ev, az, Distance*NfcScale, 0.0f,
voice->mChans[c].mDryParams.Hrtf.Target.Coeffs,
voice->mChans[c].mDryParams.Hrtf.Target.Delay);
voice->mChans[c].mDryParams.Hrtf.Target.Gain = DryGain.Base;
@@ -1119,7 +1119,7 @@ void CalcPanningAndFilters(Voice *voice, const float xpos, const float ypos, con
/* Get the HRIR coefficients and delays for this channel
* position.
*/
- GetHrtfCoeffs(Device->mHrtf.get(), chans[c].elevation, chans[c].angle,
+ Device->mHrtf->getCoeffs(chans[c].elevation, chans[c].angle,
std::numeric_limits<float>::infinity(), spread,
voice->mChans[c].mDryParams.Hrtf.Target.Coeffs,
voice->mChans[c].mDryParams.Hrtf.Target.Delay);
diff --git a/alc/panning.cpp b/alc/panning.cpp
index 80418b39..b3bd3d3b 100644
--- a/alc/panning.cpp
+++ b/alc/panning.cpp
@@ -913,7 +913,7 @@ void InitHrtfPanning(ALCdevice *device)
AmbiOrderHFGain);
device->mHrtfState = std::move(hrtfstate);
- InitNearFieldCtrl(device, Hrtf->field[0].distance, ambi_order, true);
+ InitNearFieldCtrl(device, Hrtf->mField[0].distance, ambi_order, true);
}
void InitUhjPanning(ALCdevice *device)
@@ -1075,7 +1075,7 @@ void aluInitRenderer(ALCdevice *device, int hrtf_id, al::optional<StereoEncoding
old_hrtf = nullptr;
HrtfStore *hrtf{device->mHrtf.get()};
- device->mIrSize = hrtf->irSize;
+ device->mIrSize = hrtf->mIrSize;
if(auto hrtfsizeopt = device->configValue<uint>(nullptr, "hrtf-size"))
{
if(*hrtfsizeopt > 0 && *hrtfsizeopt < device->mIrSize)
diff --git a/core/hrtf.cpp b/core/hrtf.cpp
index 076d62d5..3d252e5a 100644
--- a/core/hrtf.cpp
+++ b/core/hrtf.cpp
@@ -205,36 +205,38 @@ IdxBlend CalcAzIndex(uint azcount, float az)
/* Calculates static HRIR coefficients and delays for the given polar elevation
* and azimuth in radians. The coefficients are normalized.
*/
-void GetHrtfCoeffs(const HrtfStore *Hrtf, float elevation, float azimuth, float distance,
- float spread, HrirArray &coeffs, const al::span<uint,2> delays)
+void HrtfStore::getCoeffs(float elevation, float azimuth, float distance, float spread,
+ HrirArray &coeffs, const al::span<uint,2> delays)
{
const float dirfact{1.0f - (al::numbers::inv_pi_v<float>/2.0f * spread)};
- const auto *field = Hrtf->field;
- const auto *field_end = field + Hrtf->fdCount-1;
+ al::span<const Field> fields{mField, mFieldCount-1};
size_t ebase{0};
- while(distance < field->distance && field != field_end)
+ auto match_field = [&ebase,distance](const Field &field) noexcept -> bool
{
- ebase += field->evCount;
- ++field;
- }
+ if(distance >= field.distance)
+ return true;
+ ebase += field.evCount;
+ return false;
+ };
+ auto field = std::find_if(fields.begin(), fields.end(), match_field);
/* Calculate the elevation indices. */
const auto elev0 = CalcEvIndex(field->evCount, elevation);
const size_t elev1_idx{minu(elev0.idx+1, field->evCount-1)};
- const size_t ir0offset{Hrtf->elev[ebase + elev0.idx].irOffset};
- const size_t ir1offset{Hrtf->elev[ebase + elev1_idx].irOffset};
+ const size_t ir0offset{mElev[ebase + elev0.idx].irOffset};
+ const size_t ir1offset{mElev[ebase + elev1_idx].irOffset};
/* Calculate azimuth indices. */
- const auto az0 = CalcAzIndex(Hrtf->elev[ebase + elev0.idx].azCount, azimuth);
- const auto az1 = CalcAzIndex(Hrtf->elev[ebase + elev1_idx].azCount, azimuth);
+ const auto az0 = CalcAzIndex(mElev[ebase + elev0.idx].azCount, azimuth);
+ const auto az1 = CalcAzIndex(mElev[ebase + elev1_idx].azCount, azimuth);
/* Calculate the HRIR indices to blend. */
const size_t idx[4]{
ir0offset + az0.idx,
- ir0offset + ((az0.idx+1) % Hrtf->elev[ebase + elev0.idx].azCount),
+ ir0offset + ((az0.idx+1) % mElev[ebase + elev0.idx].azCount),
ir1offset + az1.idx,
- ir1offset + ((az1.idx+1) % Hrtf->elev[ebase + elev1_idx].azCount)
+ ir1offset + ((az1.idx+1) % mElev[ebase + elev1_idx].azCount)
};
/* Calculate bilinear blending weights, attenuated according to the
@@ -248,11 +250,11 @@ void GetHrtfCoeffs(const HrtfStore *Hrtf, float elevation, float azimuth, float
};
/* Calculate the blended HRIR delays. */
- float 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]};
+ float d{mDelays[idx[0]][0]*blend[0] + mDelays[idx[1]][0]*blend[1] + mDelays[idx[2]][0]*blend[2]
+ + mDelays[idx[3]][0]*blend[3]};
delays[0] = fastf2u(d * float{1.0f/HrirDelayFracOne});
- 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];
+ d = mDelays[idx[0]][1]*blend[0] + mDelays[idx[1]][1]*blend[1] + mDelays[idx[2]][1]*blend[2]
+ + mDelays[idx[3]][1]*blend[3];
delays[1] = fastf2u(d * float{1.0f/HrirDelayFracOne});
/* Calculate the blended HRIR coefficients. */
@@ -262,7 +264,7 @@ void GetHrtfCoeffs(const HrtfStore *Hrtf, float elevation, float azimuth, float
std::fill_n(coeffout+2, size_t{HrirLength-1}*2, 0.0f);
for(size_t c{0};c < 4;c++)
{
- const float *srccoeffs{al::assume_aligned<16>(Hrtf->coeffs[idx[c]][0].data())};
+ const float *srccoeffs{al::assume_aligned<16>(mCoeffs[idx[c]][0].data())};
const float mult{blend[c]};
auto blend_coeffs = [mult](const float src, const float coeff) noexcept -> float
{ return src*mult + coeff; };
@@ -284,7 +286,7 @@ void DirectHrtfState::build(const HrtfStore *Hrtf, const uint irSize, const bool
uint ldelay, rdelay;
};
- const double xover_norm{double{XOverFreq} / Hrtf->sampleRate};
+ const double xover_norm{double{XOverFreq} / Hrtf->mSampleRate};
mChannels[0].mSplitter.init(static_cast<float>(xover_norm));
for(size_t i{0};i < mChannels.size();++i)
{
@@ -297,26 +299,26 @@ void DirectHrtfState::build(const HrtfStore *Hrtf, const uint irSize, const bool
al::vector<ImpulseResponse> impres; impres.reserve(AmbiPoints.size());
auto calc_res = [Hrtf,&max_delay,&min_delay](const AngularPoint &pt) -> ImpulseResponse
{
- auto &field = Hrtf->field[0];
+ auto &field = Hrtf->mField[0];
const auto elev0 = CalcEvIndex(field.evCount, pt.Elev.value);
const size_t elev1_idx{minu(elev0.idx+1, field.evCount-1)};
- const size_t ir0offset{Hrtf->elev[elev0.idx].irOffset};
- const size_t ir1offset{Hrtf->elev[elev1_idx].irOffset};
+ const size_t ir0offset{Hrtf->mElev[elev0.idx].irOffset};
+ const size_t ir1offset{Hrtf->mElev[elev1_idx].irOffset};
- const auto az0 = CalcAzIndex(Hrtf->elev[elev0.idx].azCount, pt.Azim.value);
- const auto az1 = CalcAzIndex(Hrtf->elev[elev1_idx].azCount, pt.Azim.value);
+ const auto az0 = CalcAzIndex(Hrtf->mElev[elev0.idx].azCount, pt.Azim.value);
+ const auto az1 = CalcAzIndex(Hrtf->mElev[elev1_idx].azCount, pt.Azim.value);
const size_t idx[4]{
ir0offset + az0.idx,
- ir0offset + ((az0.idx+1) % Hrtf->elev[elev0.idx].azCount),
+ ir0offset + ((az0.idx+1) % Hrtf->mElev[elev0.idx].azCount),
ir1offset + az1.idx,
- ir1offset + ((az1.idx+1) % Hrtf->elev[elev1_idx].azCount)
+ ir1offset + ((az1.idx+1) % Hrtf->mElev[elev1_idx].azCount)
};
/* The largest blend factor serves as the closest HRIR. */
const size_t irOffset{idx[(elev0.blend >= 0.5f)*2 + (az1.blend >= 0.5f)]};
- ImpulseResponse res{Hrtf->coeffs[irOffset],
- Hrtf->delays[irOffset][0], Hrtf->delays[irOffset][1]};
+ ImpulseResponse res{Hrtf->mCoeffs[irOffset],
+ Hrtf->mDelays[irOffset][0], Hrtf->mDelays[irOffset][1]};
min_delay = minu(min_delay, minu(res.ldelay, res.rdelay));
max_delay = maxu(max_delay, maxu(res.ldelay, res.rdelay));
@@ -380,12 +382,12 @@ std::unique_ptr<HrtfStore> CreateHrtfStore(uint rate, ushort irSize,
const size_t irCount{size_t{elevs.back().azCount} + elevs.back().irOffset};
size_t total{sizeof(HrtfStore)};
total = RoundUp(total, alignof(HrtfStore::Field)); /* Align for field infos */
- total += sizeof(std::declval<HrtfStore&>().field[0])*fields.size();
+ total += sizeof(std::declval<HrtfStore&>().mField[0])*fields.size();
total = RoundUp(total, alignof(HrtfStore::Elevation)); /* Align for elevation infos */
- total += sizeof(std::declval<HrtfStore&>().elev[0])*elevs.size();
+ total += sizeof(std::declval<HrtfStore&>().mElev[0])*elevs.size();
total = RoundUp(total, 16); /* Align for coefficients using SIMD */
- total += sizeof(std::declval<HrtfStore&>().coeffs[0])*irCount;
- total += sizeof(std::declval<HrtfStore&>().delays[0])*irCount;
+ total += sizeof(std::declval<HrtfStore&>().mCoeffs[0])*irCount;
+ total += sizeof(std::declval<HrtfStore&>().mDelays[0])*irCount;
void *ptr{al_calloc(16, total)};
std::unique_ptr<HrtfStore> Hrtf{al::construct_at(static_cast<HrtfStore*>(ptr))};
@@ -394,9 +396,9 @@ std::unique_ptr<HrtfStore> CreateHrtfStore(uint rate, ushort irSize,
else
{
InitRef(Hrtf->mRef, 1u);
- Hrtf->sampleRate = rate;
- Hrtf->irSize = irSize;
- Hrtf->fdCount = static_cast<uint>(fields.size());
+ Hrtf->mSampleRate = rate;
+ Hrtf->mIrSize = irSize;
+ Hrtf->mFieldCount = static_cast<uint>(fields.size());
/* Set up pointers to storage following the main HRTF struct. */
char *base = reinterpret_cast<char*>(Hrtf.get());
@@ -427,10 +429,10 @@ std::unique_ptr<HrtfStore> CreateHrtfStore(uint rate, ushort irSize,
std::uninitialized_copy_n(delays, irCount, delays_);
/* Finally, assign the storage pointers. */
- Hrtf->field = field_;
- Hrtf->elev = elev_;
- Hrtf->coeffs = coeffs_;
- Hrtf->delays = delays_;
+ Hrtf->mField = field_;
+ Hrtf->mElev = elev_;
+ Hrtf->mCoeffs = coeffs_;
+ Hrtf->mDelays = delays_;
}
return Hrtf;
@@ -1292,7 +1294,7 @@ HrtfStorePtr GetLoadedHrtf(const std::string &name, const uint devrate)
while(handle != LoadedHrtfs.end() && handle->mFilename == fname)
{
HrtfStore *hrtf{handle->mEntry.get()};
- if(hrtf && hrtf->sampleRate == devrate)
+ if(hrtf && hrtf->mSampleRate == devrate)
{
hrtf->add_ref();
return HrtfStorePtr{hrtf};
@@ -1361,24 +1363,25 @@ HrtfStorePtr GetLoadedHrtf(const std::string &name, const uint devrate)
return nullptr;
}
- if(hrtf->sampleRate != devrate)
+ if(hrtf->mSampleRate != devrate)
{
- TRACE("Resampling HRTF %s (%uhz -> %uhz)\n", name.c_str(), hrtf->sampleRate, devrate);
+ TRACE("Resampling HRTF %s (%uhz -> %uhz)\n", name.c_str(), hrtf->mSampleRate, devrate);
/* Calculate the last elevation's index and get the total IR count. */
- const size_t lastEv{std::accumulate(hrtf->field, hrtf->field+hrtf->fdCount, size_t{0},
+ auto fields = al::as_span(hrtf->mField, hrtf->mFieldCount);
+ const size_t lastEv{std::accumulate(fields.begin(), fields.end(), size_t{0},
[](const size_t curval, const HrtfStore::Field &field) noexcept -> size_t
{ return curval + field.evCount; }
) - 1};
- const size_t irCount{size_t{hrtf->elev[lastEv].irOffset} + hrtf->elev[lastEv].azCount};
+ const size_t irCount{size_t{hrtf->mElev[lastEv].irOffset} + hrtf->mElev[lastEv].azCount};
/* Resample all the IRs. */
std::array<std::array<double,HrirLength>,2> inout;
PPhaseResampler rs;
- rs.init(hrtf->sampleRate, devrate);
+ rs.init(hrtf->mSampleRate, devrate);
for(size_t i{0};i < irCount;++i)
{
- HrirArray &coeffs = const_cast<HrirArray&>(hrtf->coeffs[i]);
+ HrirArray &coeffs = const_cast<HrirArray&>(hrtf->mCoeffs[i]);
for(size_t j{0};j < 2;++j)
{
std::transform(coeffs.cbegin(), coeffs.cend(), inout[0].begin(),
@@ -1393,12 +1396,12 @@ HrtfStorePtr GetLoadedHrtf(const std::string &name, const uint devrate)
/* Scale the delays for the new sample rate. */
float max_delay{0.0f};
auto new_delays = al::vector<float2>(irCount);
- const float rate_scale{static_cast<float>(devrate)/static_cast<float>(hrtf->sampleRate)};
+ const float rate_scale{static_cast<float>(devrate)/static_cast<float>(hrtf->mSampleRate)};
for(size_t i{0};i < irCount;++i)
{
for(size_t j{0};j < 2;++j)
{
- const float new_delay{std::round(hrtf->delays[i][j] * rate_scale) /
+ const float new_delay{std::round(hrtf->mDelays[i][j] * rate_scale) /
float{HrirDelayFracOne}};
max_delay = maxf(max_delay, new_delay);
new_delays[i][j] = new_delay;
@@ -1418,7 +1421,7 @@ HrtfStorePtr GetLoadedHrtf(const std::string &name, const uint devrate)
for(size_t i{0};i < irCount;++i)
{
- ubyte2 &delays = const_cast<ubyte2&>(hrtf->delays[i]);
+ ubyte2 &delays = const_cast<ubyte2&>(hrtf->mDelays[i]);
for(size_t j{0};j < 2;++j)
delays[j] = static_cast<ubyte>(float2int(new_delays[i][j]*delay_scale + 0.5f));
}
@@ -1426,13 +1429,13 @@ HrtfStorePtr GetLoadedHrtf(const std::string &name, const uint devrate)
/* Scale the IR size for the new sample rate and update the stored
* sample rate.
*/
- const float newIrSize{std::round(static_cast<float>(hrtf->irSize) * rate_scale)};
- hrtf->irSize = static_cast<uint>(minf(HrirLength, newIrSize));
- hrtf->sampleRate = devrate;
+ const float newIrSize{std::round(static_cast<float>(hrtf->mIrSize) * rate_scale)};
+ hrtf->mIrSize = static_cast<uint>(minf(HrirLength, newIrSize));
+ hrtf->mSampleRate = devrate;
}
TRACE("Loaded HRTF %s for sample rate %uhz, %u-sample filter\n", name.c_str(),
- hrtf->sampleRate, hrtf->irSize);
+ hrtf->mSampleRate, hrtf->mIrSize);
handle = LoadedHrtfs.emplace(handle, fname, std::move(hrtf));
return HrtfStorePtr{handle->mEntry.get()};
diff --git a/core/hrtf.h b/core/hrtf.h
index 0c8d2a49..64bd4f5c 100644
--- a/core/hrtf.h
+++ b/core/hrtf.h
@@ -20,8 +20,8 @@
struct HrtfStore {
RefCount mRef;
- uint sampleRate;
- uint irSize;
+ uint mSampleRate;
+ uint mIrSize;
struct Field {
float distance;
@@ -30,16 +30,19 @@ struct HrtfStore {
/* NOTE: Fields are stored *backwards*. field[0] is the farthest field, and
* field[fdCount-1] is the nearest.
*/
- uint fdCount;
- const Field *field;
+ uint mFieldCount;
+ const Field *mField;
struct Elevation {
ushort azCount;
ushort irOffset;
};
- Elevation *elev;
- const HrirArray *coeffs;
- const ubyte2 *delays;
+ Elevation *mElev;
+ const HrirArray *mCoeffs;
+ const ubyte2 *mDelays;
+
+ void getCoeffs(float elevation, float azimuth, float distance, float spread, HrirArray &coeffs,
+ const al::span<uint,2> delays);
void add_ref();
void dec_ref();
@@ -84,7 +87,4 @@ struct DirectHrtfState {
al::vector<std::string> EnumerateHrtf(al::optional<std::string> pathopt);
HrtfStorePtr GetLoadedHrtf(const std::string &name, const uint devrate);
-void GetHrtfCoeffs(const HrtfStore *Hrtf, float elevation, float azimuth, float distance,
- float spread, HrirArray &coeffs, const al::span<uint,2> delays);
-
#endif /* CORE_HRTF_H */