aboutsummaryrefslogtreecommitdiffstats
path: root/Alc
diff options
context:
space:
mode:
authorChris Robinson <[email protected]>2017-04-05 12:27:30 -0700
committerChris Robinson <[email protected]>2017-04-05 12:27:30 -0700
commit2eaa10fc213dd60b197129da17b431b3d7e9f1d5 (patch)
tree21795210b08e9d29b5afff3fcfe557e58b079f05 /Alc
parentf76dea0c0321ebcc0f5a8838f1826309463cd2c1 (diff)
Load HRTF files as needed
Currently only applies to external files, rather than embedded datasets. Also, HRTFs aren't unloaded after being loaded, until library shutdown.
Diffstat (limited to 'Alc')
-rw-r--r--Alc/ALc.c40
-rw-r--r--Alc/hrtf.c140
-rw-r--r--Alc/hrtf.h9
-rw-r--r--Alc/panning.c8
4 files changed, 96 insertions, 101 deletions
diff --git a/Alc/ALc.c b/Alc/ALc.c
index d154e240..ed2c5e8e 100644
--- a/Alc/ALc.c
+++ b/Alc/ALc.c
@@ -2049,6 +2049,7 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
if(hrtf_userreq == Hrtf_Enable || (hrtf_userreq != Hrtf_Disable && hrtf_appreq == Hrtf_Enable))
{
+ const struct Hrtf *hrtf = NULL;
if(VECTOR_SIZE(device->HrtfList) == 0)
{
VECTOR_DEINIT(device->HrtfList);
@@ -2056,9 +2057,14 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
}
if(VECTOR_SIZE(device->HrtfList) > 0)
{
- const struct Hrtf *hrtf = VECTOR_ELEM(device->HrtfList, 0).hrtf->handle;
if(hrtf_id >= 0 && (size_t)hrtf_id < VECTOR_SIZE(device->HrtfList))
- hrtf = VECTOR_ELEM(device->HrtfList, hrtf_id).hrtf->handle;
+ hrtf = GetLoadedHrtf(VECTOR_ELEM(device->HrtfList, hrtf_id).hrtf);
+ else
+ hrtf = GetLoadedHrtf(VECTOR_ELEM(device->HrtfList, 0).hrtf);
+ }
+
+ if(hrtf)
+ {
device->FmtChans = DevFmtStereo;
device->Frequency = hrtf->sampleRate;
device->Flags |= DEVICE_CHANNELS_REQUEST | DEVICE_FREQUENCY_REQUEST;
@@ -2071,36 +2077,6 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
}
}
}
- else if(hrtf_appreq == Hrtf_Enable)
- {
- size_t i = VECTOR_SIZE(device->HrtfList);
- /* Loopback device. We don't need to match to a specific HRTF entry
- * here. If the requested ID matches, we'll pick that later, if not,
- * we'll try to auto-select one anyway. Just make sure one exists
- * that'll work.
- */
- if(device->FmtChans == DevFmtStereo)
- {
- if(VECTOR_SIZE(device->HrtfList) == 0)
- {
- VECTOR_DEINIT(device->HrtfList);
- device->HrtfList = EnumerateHrtf(device->DeviceName);
- }
- for(i = 0;i < VECTOR_SIZE(device->HrtfList);i++)
- {
- const struct Hrtf *hrtf = VECTOR_ELEM(device->HrtfList, i).hrtf->handle;
- if(hrtf->sampleRate == device->Frequency)
- break;
- }
- }
- if(i == VECTOR_SIZE(device->HrtfList))
- {
- ERR("Requested format not HRTF compatible: %s, %uhz\n",
- DevFmtChannelsString(device->FmtChans), device->Frequency);
- hrtf_appreq = Hrtf_Disable;
- device->HrtfStatus = ALC_HRTF_UNSUPPORTED_FORMAT_SOFT;
- }
- }
oldFreq = device->Frequency;
oldChans = device->FmtChans;
diff --git a/Alc/hrtf.c b/Alc/hrtf.c
index f0ec9a98..4394cf56 100644
--- a/Alc/hrtf.c
+++ b/Alc/hrtf.c
@@ -46,6 +46,12 @@
#define MIN_AZ_COUNT (1)
#define MAX_AZ_COUNT (128)
+struct HrtfEntry {
+ struct HrtfEntry *next;
+ struct Hrtf *handle;
+ char filename[];
+};
+
static const ALchar magicMarker00[8] = "MinPHR00";
static const ALchar magicMarker01[8] = "MinPHR01";
@@ -240,7 +246,7 @@ ALsizei BuildBFormatHrtf(const struct Hrtf *Hrtf, DirectHrtfState *state, ALsize
static struct Hrtf *CreateHrtfStore(ALuint rate, ALsizei irSize, ALsizei evCount, ALsizei irCount,
const ALubyte *azCount, const ALushort *evOffset,
const ALshort *coeffs, const ALubyte *delays,
- const_al_string filename)
+ const char *filename)
{
struct Hrtf *Hrtf;
size_t total;
@@ -255,7 +261,7 @@ static struct Hrtf *CreateHrtfStore(ALuint rate, ALsizei irSize, ALsizei evCount
Hrtf = al_calloc(16, total);
if(Hrtf == NULL)
- ERR("Out of memory allocating storage for %s.\n", alstr_get_cstr(filename));
+ ERR("Out of memory allocating storage for %s.\n", filename);
else
{
uintptr_t offset = sizeof(struct Hrtf);
@@ -298,7 +304,7 @@ static struct Hrtf *CreateHrtfStore(ALuint rate, ALsizei irSize, ALsizei evCount
return Hrtf;
}
-static struct Hrtf *LoadHrtf00(const ALubyte *data, size_t datalen, const_al_string filename)
+static struct Hrtf *LoadHrtf00(const ALubyte *data, size_t datalen, const char *filename)
{
const ALubyte maxDelay = HRTF_HISTORY_LENGTH-1;
struct Hrtf *Hrtf = NULL;
@@ -314,8 +320,7 @@ static struct Hrtf *LoadHrtf00(const ALubyte *data, size_t datalen, const_al_str
if(datalen < 9)
{
- ERR("Unexpected end of %s data (req %d, rem "SZFMT")\n",
- alstr_get_cstr(filename), 9, datalen);
+ ERR("Unexpected end of %s data (req %d, rem "SZFMT")\n", filename, 9, datalen);
return NULL;
}
@@ -353,8 +358,7 @@ static struct Hrtf *LoadHrtf00(const ALubyte *data, size_t datalen, const_al_str
if(datalen < evCount*2)
{
- ERR("Unexpected end of %s data (req %d, rem "SZFMT")\n",
- alstr_get_cstr(filename), evCount*2, datalen);
+ ERR("Unexpected end of %s data (req %d, rem "SZFMT")\n", filename, evCount*2, datalen);
return NULL;
}
@@ -423,7 +427,7 @@ static struct Hrtf *LoadHrtf00(const ALubyte *data, size_t datalen, const_al_str
if(datalen < reqsize)
{
ERR("Unexpected end of %s data (req "SZFMT", rem "SZFMT")\n",
- alstr_get_cstr(filename), reqsize, datalen);
+ filename, reqsize, datalen);
failed = AL_TRUE;
}
}
@@ -463,7 +467,7 @@ static struct Hrtf *LoadHrtf00(const ALubyte *data, size_t datalen, const_al_str
return Hrtf;
}
-static struct Hrtf *LoadHrtf01(const ALubyte *data, size_t datalen, const_al_string filename)
+static struct Hrtf *LoadHrtf01(const ALubyte *data, size_t datalen, const char *filename)
{
const ALubyte maxDelay = HRTF_HISTORY_LENGTH-1;
struct Hrtf *Hrtf = NULL;
@@ -478,8 +482,7 @@ static struct Hrtf *LoadHrtf01(const ALubyte *data, size_t datalen, const_al_str
if(datalen < 6)
{
- ERR("Unexpected end of %s data (req %d, rem "SZFMT"\n",
- alstr_get_cstr(filename), 6, datalen);
+ ERR("Unexpected end of %s data (req %d, rem "SZFMT"\n", filename, 6, datalen);
return NULL;
}
@@ -512,8 +515,7 @@ static struct Hrtf *LoadHrtf01(const ALubyte *data, size_t datalen, const_al_str
if(datalen < evCount)
{
- ERR("Unexpected end of %s data (req %d, rem "SZFMT"\n",
- alstr_get_cstr(filename), evCount, datalen);
+ ERR("Unexpected end of %s data (req %d, rem "SZFMT"\n", filename, evCount, datalen);
return NULL;
}
@@ -565,7 +567,7 @@ static struct Hrtf *LoadHrtf01(const ALubyte *data, size_t datalen, const_al_str
if(datalen < reqsize)
{
ERR("Unexpected end of %s data (req "SZFMT", rem "SZFMT"\n",
- alstr_get_cstr(filename), reqsize, datalen);
+ filename, reqsize, datalen);
failed = AL_TRUE;
}
}
@@ -610,9 +612,7 @@ static void AddFileEntry(vector_EnumeratedHrtf *list, const_al_string filename)
{
EnumeratedHrtf entry = { AL_STRING_INIT_STATIC(), NULL };
struct HrtfEntry *loaded_entry;
- struct Hrtf *hrtf = NULL;
const EnumeratedHrtf *iter;
- struct FileMapping fmap;
const char *name;
const char *ext;
int i;
@@ -639,51 +639,14 @@ static void AddFileEntry(vector_EnumeratedHrtf *list, const_al_string filename)
loaded_entry = loaded_entry->next;
}
- TRACE("Loading %s...\n", alstr_get_cstr(filename));
- fmap = MapFileToMem(alstr_get_cstr(filename));
- if(fmap.ptr == NULL)
- {
- ERR("Could not open %s\n", alstr_get_cstr(filename));
- return;
- }
-
- if(fmap.len < sizeof(magicMarker01))
- ERR("%s data is too short ("SZFMT" bytes)\n", alstr_get_cstr(filename), fmap.len);
- else if(memcmp(fmap.ptr, magicMarker01, sizeof(magicMarker01)) == 0)
- {
- TRACE("Detected data set format v1\n");
- hrtf = LoadHrtf01((const ALubyte*)fmap.ptr+sizeof(magicMarker01),
- fmap.len-sizeof(magicMarker01), filename
- );
- }
- else if(memcmp(fmap.ptr, magicMarker00, sizeof(magicMarker00)) == 0)
- {
- TRACE("Detected data set format v0\n");
- hrtf = LoadHrtf00((const ALubyte*)fmap.ptr+sizeof(magicMarker00),
- fmap.len-sizeof(magicMarker00), filename
- );
- }
- else
- ERR("Invalid header in %s: \"%.8s\"\n", alstr_get_cstr(filename), (const char*)fmap.ptr);
- UnmapFileMem(&fmap);
-
- if(!hrtf)
- {
- ERR("Failed to load %s\n", alstr_get_cstr(filename));
- return;
- }
-
loaded_entry = al_calloc(DEF_ALIGN,
offsetof(struct HrtfEntry, filename[alstr_length(filename)+1])
);
loaded_entry->next = LoadedHrtfs;
- loaded_entry->handle = hrtf;
+ loaded_entry->handle = NULL;
strcpy(loaded_entry->filename, alstr_get_cstr(filename));
LoadedHrtfs = loaded_entry;
- TRACE("Loaded HRTF support for format: %s %uhz\n",
- DevFmtChannelsString(DevFmtStereo), hrtf->sampleRate);
-
skip_load:
/* TODO: Get a human-readable name from the HRTF data (possibly coming in a
* format update). */
@@ -762,19 +725,19 @@ static void AddBuiltInEntry(vector_EnumeratedHrtf *list, const ALubyte *data, si
if(memcmp(data, magicMarker01, sizeof(magicMarker01)) == 0)
{
TRACE("Detected data set format v1\n");
- hrtf = LoadHrtf01(data+sizeof(magicMarker01),
- datalen-sizeof(magicMarker01), filename
+ hrtf = LoadHrtf01((const ALubyte*)data+sizeof(magicMarker01),
+ datalen-sizeof(magicMarker01), alstr_get_cstr(filename)
);
}
else if(memcmp(data, magicMarker00, sizeof(magicMarker00)) == 0)
{
TRACE("Detected data set format v0\n");
- hrtf = LoadHrtf00(data+sizeof(magicMarker00),
- datalen-sizeof(magicMarker00), filename
+ hrtf = LoadHrtf00((const ALubyte*)data+sizeof(magicMarker00),
+ datalen-sizeof(magicMarker00), alstr_get_cstr(filename)
);
}
else
- ERR("Invalid header in %s: \"%.8s\"\n", alstr_get_cstr(filename), data);
+ ERR("Invalid header in %s: \"%.8s\"\n", alstr_get_cstr(filename), (const char*)data);
if(!hrtf)
{
@@ -1032,6 +995,65 @@ void FreeHrtfList(vector_EnumeratedHrtf *list)
#undef CLEAR_ENTRY
}
+struct Hrtf *GetLoadedHrtf(struct HrtfEntry *entry)
+{
+ static ATOMIC_FLAG LoadLock = ATOMIC_FLAG_INIT;
+ struct Hrtf *hrtf = NULL;
+ struct FileMapping fmap;
+
+ while(ATOMIC_FLAG_TEST_AND_SET(&LoadLock, almemory_order_seq_cst))
+ althrd_yield();
+
+ if(entry->handle)
+ {
+ hrtf = entry->handle;
+ goto done;
+ }
+
+ TRACE("Loading %s...\n", entry->filename);
+ fmap = MapFileToMem(entry->filename);
+ if(fmap.ptr == NULL)
+ {
+ ERR("Could not open %s\n", entry->filename);
+ goto done;
+ }
+
+ if(fmap.len < sizeof(magicMarker01))
+ ERR("%s data is too short ("SZFMT" bytes)\n", entry->filename, fmap.len);
+ else if(memcmp(fmap.ptr, magicMarker01, sizeof(magicMarker01)) == 0)
+ {
+ TRACE("Detected data set format v1\n");
+ hrtf = LoadHrtf01((const ALubyte*)fmap.ptr+sizeof(magicMarker01),
+ fmap.len-sizeof(magicMarker01), entry->filename
+ );
+ }
+ else if(memcmp(fmap.ptr, magicMarker00, sizeof(magicMarker00)) == 0)
+ {
+ TRACE("Detected data set format v0\n");
+ hrtf = LoadHrtf00((const ALubyte*)fmap.ptr+sizeof(magicMarker00),
+ fmap.len-sizeof(magicMarker00), entry->filename
+ );
+ }
+ else
+ ERR("Invalid header in %s: \"%.8s\"\n", entry->filename, (const char*)fmap.ptr);
+ UnmapFileMem(&fmap);
+
+ if(!hrtf)
+ {
+ ERR("Failed to load %s\n", entry->filename);
+ goto done;
+ }
+
+ TRACE("Loaded HRTF support for format: %s %uhz\n",
+ DevFmtChannelsString(DevFmtStereo), hrtf->sampleRate);
+
+ entry->handle = hrtf;
+
+done:
+ ATOMIC_FLAG_CLEAR(&LoadLock, almemory_order_seq_cst);
+ return hrtf;
+}
+
void FreeHrtfs(void)
{
diff --git a/Alc/hrtf.h b/Alc/hrtf.h
index 009bddea..4e25dde3 100644
--- a/Alc/hrtf.h
+++ b/Alc/hrtf.h
@@ -18,6 +18,8 @@
#define HRTF_AMBI_MAX_CHANNELS 16
+struct HrtfEntry;
+
struct Hrtf {
ALuint sampleRate;
ALsizei irSize;
@@ -29,17 +31,12 @@ struct Hrtf {
const ALubyte *delays;
};
-struct HrtfEntry {
- struct HrtfEntry *next;
- struct Hrtf *handle;
- char filename[];
-};
-
void FreeHrtfs(void);
vector_EnumeratedHrtf EnumerateHrtf(const_al_string devname);
void FreeHrtfList(vector_EnumeratedHrtf *list);
+struct Hrtf *GetLoadedHrtf(struct HrtfEntry *entry);
void GetHrtfCoeffs(const struct Hrtf *Hrtf, ALfloat elevation, ALfloat azimuth, ALfloat spread, ALfloat (*coeffs)[2], ALsizei *delays);
diff --git a/Alc/panning.c b/Alc/panning.c
index aa8175d4..bd550b32 100644
--- a/Alc/panning.c
+++ b/Alc/panning.c
@@ -1151,8 +1151,8 @@ void aluInitRenderer(ALCdevice *device, ALint hrtf_id, enum HrtfRequestMode hrtf
if(hrtf_id >= 0 && (size_t)hrtf_id < VECTOR_SIZE(device->HrtfList))
{
const EnumeratedHrtf *entry = &VECTOR_ELEM(device->HrtfList, hrtf_id);
- const struct Hrtf *hrtf = entry->hrtf->handle;
- if(hrtf->sampleRate == device->Frequency)
+ const struct Hrtf *hrtf = GetLoadedHrtf(entry->hrtf);
+ if(hrtf && hrtf->sampleRate == device->Frequency)
{
device->HrtfHandle = hrtf;
alstr_copy(&device->HrtfName, entry->name);
@@ -1162,8 +1162,8 @@ void aluInitRenderer(ALCdevice *device, ALint hrtf_id, enum HrtfRequestMode hrtf
for(i = 0;!device->HrtfHandle && i < VECTOR_SIZE(device->HrtfList);i++)
{
const EnumeratedHrtf *entry = &VECTOR_ELEM(device->HrtfList, i);
- const struct Hrtf *hrtf = entry->hrtf->handle;
- if(hrtf->sampleRate == device->Frequency)
+ const struct Hrtf *hrtf = GetLoadedHrtf(entry->hrtf);
+ if(hrtf && hrtf->sampleRate == device->Frequency)
{
device->HrtfHandle = hrtf;
alstr_copy(&device->HrtfName, entry->name);