aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Robinson <[email protected]>2023-12-31 04:46:35 -0800
committerChris Robinson <[email protected]>2023-12-31 05:08:59 -0800
commitba4f633a9e778b3d94f2e21d124cad2baf05a6b4 (patch)
tree10fac75873d2020560d44279bc436b009a80f469
parentcde39d4acf9d8267c8483991515b5f646336cc40 (diff)
Implement our own cache for MYSOFA_EASY objects
This is to both fix the potential issue of libmysofa calling free() on memory we allocated with calloc (which can be an issue if it linked to a different C runtime), and work around the code checker thinking the MYSOFA_EASY object leaks when mysofa_close and mysofa_cache_store are taking ownership of it.
-rw-r--r--utils/makemhr/loaddef.cpp53
1 files changed, 39 insertions, 14 deletions
diff --git a/utils/makemhr/loaddef.cpp b/utils/makemhr/loaddef.cpp
index 05bcfd2e..f01e93fc 100644
--- a/utils/makemhr/loaddef.cpp
+++ b/utils/makemhr/loaddef.cpp
@@ -34,6 +34,8 @@
#include <limits>
#include <memory>
#include <optional>
+#include <string>
+#include <string_view>
#include <vector>
#include "albit.h"
@@ -1073,15 +1075,39 @@ static int LoadWaveSource(std::istream &istream, SourceRefT *src, const uint hri
}
+namespace {
+
+struct SofaEasyDeleter {
+ void operator()(gsl::owner<MYSOFA_EASY*> sofa)
+ {
+ if(sofa->neighborhood) mysofa_neighborhood_free(sofa->neighborhood);
+ if(sofa->lookup) mysofa_lookup_free(sofa->lookup);
+ if(sofa->hrtf) mysofa_free(sofa->hrtf);
+ delete sofa;
+ }
+};
+using SofaEasyPtr = std::unique_ptr<MYSOFA_EASY,SofaEasyDeleter>;
+
+struct SofaCacheEntry {
+ std::string mName;
+ uint mSampleRate{};
+ SofaEasyPtr mSofa;
+};
+std::vector<SofaCacheEntry> gSofaCache;
+
+} // namespace
// Load a Spatially Oriented Format for Accoustics (SOFA) file.
static MYSOFA_EASY* LoadSofaFile(SourceRefT *src, const uint hrirRate, const uint n)
{
- MYSOFA_EASY *sofa{mysofa_cache_lookup(src->mPath.data(), static_cast<float>(hrirRate))};
- if(sofa) return sofa;
-
- sofa = static_cast<MYSOFA_EASY*>(calloc(1, sizeof(*sofa)));
- if(sofa == nullptr)
+ const std::string_view srcname{src->mPath.data()};
+ auto iter = std::find_if(gSofaCache.begin(), gSofaCache.end(),
+ [srcname,hrirRate](SofaCacheEntry &entry) -> bool
+ { return entry.mName == srcname && entry.mSampleRate == hrirRate; });
+ if(iter != gSofaCache.end()) return iter->mSofa.get();
+
+ SofaEasyPtr sofa{new(std::nothrow) MYSOFA_EASY{}};
+ if(!sofa)
{
fprintf(stderr, "\nError: Out of memory.\n");
return nullptr;
@@ -1093,23 +1119,22 @@ static MYSOFA_EASY* LoadSofaFile(SourceRefT *src, const uint hrirRate, const uin
sofa->hrtf = mysofa_load(src->mPath.data(), &err);
if(!sofa->hrtf)
{
- mysofa_close(sofa);
- fprintf(stderr, "\nError: Could not load source file '%s'.\n", src->mPath.data());
+ fprintf(stderr, "\nError: Could not load source file '%s' (error: %d).\n",
+ src->mPath.data(), err);
return nullptr;
}
/* NOTE: Some valid SOFA files are failing this check. */
err = mysofa_check(sofa->hrtf);
if(err != MYSOFA_OK)
- fprintf(stderr, "\nWarning: Supposedly malformed source file '%s'.\n", src->mPath.data());
+ fprintf(stderr, "\nWarning: Supposedly malformed source file '%s' (error: %d).\n",
+ src->mPath.data(), err);
if((src->mOffset + n) > sofa->hrtf->N)
{
- mysofa_close(sofa);
fprintf(stderr, "\nError: Not enough samples in SOFA file '%s'.\n", src->mPath.data());
return nullptr;
}
if(src->mChannel >= sofa->hrtf->R)
{
- mysofa_close(sofa);
fprintf(stderr, "\nError: Missing source receiver in SOFA file '%s'.\n",src->mPath.data());
return nullptr;
}
@@ -1117,11 +1142,11 @@ static MYSOFA_EASY* LoadSofaFile(SourceRefT *src, const uint hrirRate, const uin
sofa->lookup = mysofa_lookup_init(sofa->hrtf);
if(sofa->lookup == nullptr)
{
- mysofa_close(sofa);
fprintf(stderr, "\nError: Out of memory.\n");
return nullptr;
}
- return mysofa_cache_store(sofa, src->mPath.data(), static_cast<float>(hrirRate));
+ gSofaCache.emplace_back(SofaCacheEntry{std::string{srcname}, hrirRate, std::move(sofa)});
+ return gSofaCache.back().mSofa.get();
}
// Copies the HRIR data from a particular SOFA measurement.
@@ -2027,12 +2052,12 @@ static int ProcessSources(TokenReaderT *tr, HrirDataT *hData, const uint outRate
}
if(!TrLoad(tr))
{
- mysofa_cache_release_all();
+ gSofaCache.clear();
return 1;
}
TrError(tr, "Errant data at end of source list.\n");
- mysofa_cache_release_all();
+ gSofaCache.clear();
return 0;
}