From 7ded42cb94d555b33891f59ec7fc86b710318ebb Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 8 Dec 2019 19:17:58 -0800 Subject: Load SOFA HRIRs in a background thread --- utils/makemhr/loadsofa.cpp | 142 +++++++++++++++++++++++++-------------------- 1 file changed, 79 insertions(+), 63 deletions(-) (limited to 'utils/makemhr') diff --git a/utils/makemhr/loadsofa.cpp b/utils/makemhr/loadsofa.cpp index 00dbf8f9..e2f2e232 100644 --- a/utils/makemhr/loadsofa.cpp +++ b/utils/makemhr/loadsofa.cpp @@ -25,9 +25,11 @@ #include #include +#include #include #include #include +#include #include #include #include @@ -486,79 +488,93 @@ static void CalcHrirMagnitude(const uint points, const uint n, std::vectormChannelType == CT_STEREO) ? 2u : 1u}; - hData->mHrirsBase.resize(channels * hData->mIrCount * hData->mIrSize); - double *hrirs = hData->mHrirsBase.data(); - - /* Temporary buffers used to calculate the IR's onset and frequency - * magnitudes. - */ - auto upsampled = std::vector(10 * hData->mIrPoints); - auto htemp = std::vector(hData->mFftSize); - auto hrir = std::vector(hData->mFftSize); + std::atomic loaded_count{0u}; - for(uint si{0u};si < sofaHrtf->M;si++) + auto load_proc = [sofaHrtf,hData,&loaded_count]() -> bool { - printf("\rLoading HRIRs... %d of %d", si+1, sofaHrtf->M); - fflush(stdout); + const uint channels{(hData->mChannelType == CT_STEREO) ? 2u : 1u}; + hData->mHrirsBase.resize(channels * hData->mIrCount * hData->mIrSize); + double *hrirs = hData->mHrirsBase.data(); - float aer[3]{ - sofaHrtf->SourcePosition.values[3*si], - sofaHrtf->SourcePosition.values[3*si + 1], - sofaHrtf->SourcePosition.values[3*si + 2] - }; - mysofa_c2s(aer); + /* Temporary buffers used to calculate the IR's onset and frequency + * magnitudes. + */ + auto upsampled = std::vector(10 * hData->mIrPoints); + auto htemp = std::vector(hData->mFftSize); + auto hrir = std::vector(hData->mFftSize); - if(std::abs(aer[1]) >= 89.999f) - aer[0] = 0.0f; - else - aer[0] = std::fmod(360.0f - aer[0], 360.0f); + for(uint si{0u};si < sofaHrtf->M;++si) + { + loaded_count.fetch_add(1u); - auto field = std::find_if(hData->mFds.cbegin(), hData->mFds.cend(), - [&aer](const HrirFdT &fld) -> bool - { - double delta = aer[2] - fld.mDistance; - return (std::abs(delta) < 0.001); - }); - if(field == hData->mFds.cend()) - continue; + float aer[3]{ + sofaHrtf->SourcePosition.values[3*si], + sofaHrtf->SourcePosition.values[3*si + 1], + sofaHrtf->SourcePosition.values[3*si + 2] + }; + mysofa_c2s(aer); - double ef{(90.0+aer[1]) / 180.0 * (field->mEvCount-1)}; - auto ei = static_cast(std::round(ef)); - ef = (ef-ei) * 180.0 / (field->mEvCount-1); - if(std::abs(ef) >= 0.1) continue; + if(std::abs(aer[1]) >= 89.999f) + aer[0] = 0.0f; + else + aer[0] = std::fmod(360.0f - aer[0], 360.0f); - double af{aer[0] / 360.0 * field->mEvs[ei].mAzCount}; - auto ai = static_cast(std::round(af)); - af = (af-ai) * 360.0 / field->mEvs[ei].mAzCount; - ai %= field->mEvs[ei].mAzCount; - if(std::abs(af) >= 0.1) continue; + auto field = std::find_if(hData->mFds.cbegin(), hData->mFds.cend(), + [&aer](const HrirFdT &fld) -> bool + { + double delta = aer[2] - fld.mDistance; + return (std::abs(delta) < 0.001); + }); + if(field == hData->mFds.cend()) + continue; + + double ef{(90.0+aer[1]) / 180.0 * (field->mEvCount-1)}; + auto ei = static_cast(std::round(ef)); + ef = (ef-ei) * 180.0 / (field->mEvCount-1); + if(std::abs(ef) >= 0.1) continue; + + double af{aer[0] / 360.0 * field->mEvs[ei].mAzCount}; + auto ai = static_cast(std::round(af)); + af = (af-ai) * 360.0 / field->mEvs[ei].mAzCount; + ai %= field->mEvs[ei].mAzCount; + if(std::abs(af) >= 0.1) continue; + + HrirAzT *azd = &field->mEvs[ei].mAzs[ai]; + if(azd->mIrs[0] != nullptr) + { + fprintf(stderr, "\nMultiple measurements near [ a=%f, e=%f, r=%f ].\n", + aer[0], aer[1], aer[2]); + return false; + } - HrirAzT *azd = &field->mEvs[ei].mAzs[ai]; - if(azd->mIrs[0] != nullptr) - { - fprintf(stderr, "Multiple measurements near [ a=%f, e=%f, r=%f ].\n", - aer[0], aer[1], aer[2]); - return false; - } + for(uint ti{0u};ti < channels;++ti) + { + std::copy_n(&sofaHrtf->DataIR.values[(si*sofaHrtf->R + ti)*sofaHrtf->N], + hData->mIrPoints, hrir.begin()); + azd->mIrs[ti] = &hrirs[hData->mIrSize * (hData->mIrCount*ti + azd->mIndex)]; + azd->mDelays[ti] = CalcHrirOnset(hData->mIrRate, hData->mIrPoints, upsampled, + hrir.data()); + CalcHrirMagnitude(hData->mIrPoints, hData->mFftSize, htemp, hrir.data(), + azd->mIrs[ti]); + } - for(uint ti{0u};ti < channels;++ti) - { - std::copy_n(&sofaHrtf->DataIR.values[(si*sofaHrtf->R + ti)*sofaHrtf->N], - hData->mIrPoints, hrir.begin()); - azd->mIrs[ti] = &hrirs[hData->mIrSize * (hData->mIrCount*ti + azd->mIndex)]; - azd->mDelays[ti] = CalcHrirOnset(hData->mIrRate, hData->mIrPoints, upsampled, - hrir.data()); - CalcHrirMagnitude(hData->mIrPoints, hData->mFftSize, htemp, hrir.data(), - azd->mIrs[ti]); + /* TODO: Since some SOFA files contain minimum phase HRIRs, + * it would be beneficial to check for per-measurement delays + * (when available) to reconstruct the HRTDs. + */ } - - // TODO: Since some SOFA files contain minimum phase HRIRs, - // it would be beneficial to check for per-measurement delays - // (when available) to reconstruct the HRTDs. - } - printf("\n"); - return true; + return true; + }; + + std::future_status load_status{}; + auto load_future = std::async(std::launch::async, load_proc); + do { + load_status = load_future.wait_for(std::chrono::milliseconds{50}); + printf("\rLoading HRIRs... %u of %u", loaded_count.load(), sofaHrtf->M); + fflush(stdout); + } while(load_status != std::future_status::ready); + fputc('\n', stdout); + return load_future.get(); } struct MySofaHrtfDeleter { -- cgit v1.2.3