aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Alc/ALc.c11
-rw-r--r--Alc/hrtf.c49
-rw-r--r--Alc/hrtf.h5
-rw-r--r--Alc/panning.c32
-rw-r--r--OpenAL32/Include/alMain.h2
5 files changed, 90 insertions, 9 deletions
diff --git a/Alc/ALc.c b/Alc/ALc.c
index ed2c5e8e..0cc36cad 100644
--- a/Alc/ALc.c
+++ b/Alc/ALc.c
@@ -2049,7 +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;
+ struct Hrtf *hrtf = NULL;
if(VECTOR_SIZE(device->HrtfList) == 0)
{
VECTOR_DEINIT(device->HrtfList);
@@ -2068,6 +2068,9 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
device->FmtChans = DevFmtStereo;
device->Frequency = hrtf->sampleRate;
device->Flags |= DEVICE_CHANNELS_REQUEST | DEVICE_FREQUENCY_REQUEST;
+ if(device->HrtfHandle)
+ Hrtf_DecRef(device->HrtfHandle);
+ device->HrtfHandle = hrtf;
}
else
{
@@ -2338,6 +2341,9 @@ static ALCvoid FreeDevice(ALCdevice *device)
AL_STRING_DEINIT(device->HrtfName);
FreeHrtfList(&device->HrtfList);
+ if(device->HrtfHandle)
+ Hrtf_DecRef(device->HrtfHandle);
+ device->HrtfHandle = NULL;
al_free(device->Hrtf);
device->Hrtf = NULL;
@@ -3755,6 +3761,7 @@ ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName)
device->Bs2b = NULL;
device->Uhj_Encoder = NULL;
device->Hrtf = NULL;
+ device->HrtfHandle = NULL;
VECTOR_INIT(device->HrtfList);
AL_STRING_INIT(device->HrtfName);
device->Render_Mode = NormalRender;
@@ -4062,6 +4069,7 @@ ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *deviceName,
device->Type = Capture;
device->Hrtf = NULL;
+ device->HrtfHandle = NULL;
VECTOR_INIT(device->HrtfList);
AL_STRING_INIT(device->HrtfName);
@@ -4272,6 +4280,7 @@ ALC_API ALCdevice* ALC_APIENTRY alcLoopbackOpenDeviceSOFT(const ALCchar *deviceN
device->Flags = 0;
device->Hrtf = NULL;
+ device->HrtfHandle = NULL;
VECTOR_INIT(device->HrtfList);
AL_STRING_INIT(device->HrtfName);
device->Bs2b = NULL;
diff --git a/Alc/hrtf.c b/Alc/hrtf.c
index 35be4dc3..32a6357e 100644
--- a/Alc/hrtf.c
+++ b/Alc/hrtf.c
@@ -59,6 +59,7 @@ static const ALchar magicMarker01[8] = "MinPHR01";
* directional sounds. */
static const ALfloat PassthruCoeff = 0.707106781187f/*sqrt(0.5)*/;
+static ATOMIC_FLAG LoadedHrtfLock = ATOMIC_FLAG_INIT;
static struct HrtfEntry *LoadedHrtfs = NULL;
@@ -272,6 +273,7 @@ static struct Hrtf *CreateHrtfStore(ALuint rate, ALsizei irSize, ALsizei evCount
ALfloat *_coeffs;
ALsizei i;
+ InitRef(&Hrtf->ref, 0);
Hrtf->sampleRate = rate;
Hrtf->irSize = irSize;
Hrtf->evCount = evCount;
@@ -973,7 +975,6 @@ void FreeHrtfList(vector_EnumeratedHrtf *list)
struct Hrtf *GetLoadedHrtf(struct HrtfEntry *entry)
{
- static ATOMIC_FLAG LoadLock = ATOMIC_FLAG_INIT;
struct Hrtf *hrtf = NULL;
struct FileMapping fmap;
const ALubyte *rdata;
@@ -982,12 +983,13 @@ struct Hrtf *GetLoadedHrtf(struct HrtfEntry *entry)
size_t rsize;
char ch;
- while(ATOMIC_FLAG_TEST_AND_SET(&LoadLock, almemory_order_seq_cst))
+ while(ATOMIC_FLAG_TEST_AND_SET(&LoadedHrtfLock, almemory_order_seq_cst))
althrd_yield();
if(entry->handle)
{
hrtf = entry->handle;
+ Hrtf_IncRef(hrtf);
goto done;
}
@@ -1047,18 +1049,55 @@ struct Hrtf *GetLoadedHrtf(struct HrtfEntry *entry)
ERR("Failed to load %s\n", name);
goto done;
}
+ entry->handle = hrtf;
+ Hrtf_IncRef(hrtf);
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);
+ ATOMIC_FLAG_CLEAR(&LoadedHrtfLock, almemory_order_seq_cst);
return hrtf;
}
+void Hrtf_IncRef(struct Hrtf *hrtf)
+{
+ uint ref = IncrementRef(&hrtf->ref);
+ TRACEREF("%p increasing refcount to %u\n", hrtf, ref);
+}
+
+void Hrtf_DecRef(struct Hrtf *hrtf)
+{
+ struct HrtfEntry *Hrtf;
+ uint ref = DecrementRef(&hrtf->ref);
+ TRACEREF("%p decreasing refcount to %u\n", hrtf, ref);
+ if(ref == 0)
+ {
+ while(ATOMIC_FLAG_TEST_AND_SET(&LoadedHrtfLock, almemory_order_seq_cst))
+ althrd_yield();
+
+ Hrtf = LoadedHrtfs;
+ while(Hrtf != NULL)
+ {
+ /* Need to double-check that it's still unused, as another device
+ * could've reacquired this HRTF after its reference went to 0 and
+ * before the lock was taken.
+ */
+ if(hrtf == Hrtf->handle && ReadRef(&hrtf->ref) == 0)
+ {
+ al_free(Hrtf->handle);
+ Hrtf->handle = NULL;
+ TRACE("Unloaded unused HRTF %s\n", Hrtf->filename);
+ }
+ Hrtf = Hrtf->next;
+ }
+
+ ATOMIC_FLAG_CLEAR(&LoadedHrtfLock, almemory_order_seq_cst);
+ }
+}
+
+
void FreeHrtfs(void)
{
struct HrtfEntry *Hrtf = LoadedHrtfs;
diff --git a/Alc/hrtf.h b/Alc/hrtf.h
index 4e25dde3..3ec3e19e 100644
--- a/Alc/hrtf.h
+++ b/Alc/hrtf.h
@@ -6,6 +6,7 @@
#include "alMain.h"
#include "alstring.h"
+#include "atomic.h"
#define HRTFDELAY_BITS (20)
@@ -21,6 +22,8 @@
struct HrtfEntry;
struct Hrtf {
+ RefCount ref;
+
ALuint sampleRate;
ALsizei irSize;
ALubyte evCount;
@@ -37,6 +40,8 @@ void FreeHrtfs(void);
vector_EnumeratedHrtf EnumerateHrtf(const_al_string devname);
void FreeHrtfList(vector_EnumeratedHrtf *list);
struct Hrtf *GetLoadedHrtf(struct HrtfEntry *entry);
+void Hrtf_IncRef(struct Hrtf *hrtf);
+void Hrtf_DecRef(struct Hrtf *hrtf);
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 bd550b32..8a8840fb 100644
--- a/Alc/panning.c
+++ b/Alc/panning.c
@@ -997,6 +997,8 @@ static void InitUhjPanning(ALCdevice *device)
void aluInitRenderer(ALCdevice *device, ALint hrtf_id, enum HrtfRequestMode hrtf_appreq, enum HrtfRequestMode hrtf_userreq)
{
+ /* Hold the HRTF the device last used, in case it's used again. */
+ struct Hrtf *old_hrtf = device->HrtfHandle;
const char *mode;
bool headphones;
int bs2blevel;
@@ -1028,6 +1030,9 @@ void aluInitRenderer(ALCdevice *device, ALint hrtf_id, enum HrtfRequestMode hrtf
const char *devname, *layout = NULL;
AmbDecConf conf, *pconf = NULL;
+ if(old_hrtf)
+ Hrtf_DecRef(old_hrtf);
+ old_hrtf = NULL;
if(hrtf_appreq == Hrtf_Enable)
device->HrtfStatus = ALC_HRTF_UNSUPPORTED_FORMAT_SOFT;
@@ -1151,29 +1156,49 @@ 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 = GetLoadedHrtf(entry->hrtf);
+ struct Hrtf *hrtf = GetLoadedHrtf(entry->hrtf);
if(hrtf && hrtf->sampleRate == device->Frequency)
{
device->HrtfHandle = hrtf;
alstr_copy(&device->HrtfName, entry->name);
}
+ else if(hrtf)
+ Hrtf_DecRef(hrtf);
+ }
+
+ /* Reuse the old HRTF if its compatible and any desired HRTF isn't
+ * compatible.
+ */
+ if(!device->HrtfHandle && old_hrtf)
+ {
+ if(old_hrtf->sampleRate == device->Frequency)
+ {
+ device->HrtfHandle = old_hrtf;
+ old_hrtf = NULL;
+ }
}
for(i = 0;!device->HrtfHandle && i < VECTOR_SIZE(device->HrtfList);i++)
{
const EnumeratedHrtf *entry = &VECTOR_ELEM(device->HrtfList, i);
- const struct Hrtf *hrtf = GetLoadedHrtf(entry->hrtf);
+ struct Hrtf *hrtf = GetLoadedHrtf(entry->hrtf);
if(hrtf && hrtf->sampleRate == device->Frequency)
{
device->HrtfHandle = hrtf;
alstr_copy(&device->HrtfName, entry->name);
}
+ else if(hrtf)
+ Hrtf_DecRef(hrtf);
}
if(device->HrtfHandle)
{
bool hoa_mode;
+ if(old_hrtf)
+ Hrtf_DecRef(old_hrtf);
+ old_hrtf = NULL;
+
device->Render_Mode = HrtfRender;
if(ConfigValueStr(alstr_get_cstr(device->DeviceName), NULL, "hrtf-mode", &mode))
{
@@ -1211,6 +1236,9 @@ void aluInitRenderer(ALCdevice *device, ALint hrtf_id, enum HrtfRequestMode hrtf
device->HrtfStatus = ALC_HRTF_UNSUPPORTED_FORMAT_SOFT;
no_hrtf:
+ if(old_hrtf)
+ Hrtf_DecRef(old_hrtf);
+ old_hrtf = NULL;
TRACE("HRTF disabled\n");
device->Render_Mode = StereoPair;
diff --git a/OpenAL32/Include/alMain.h b/OpenAL32/Include/alMain.h
index 4807e07d..7add9310 100644
--- a/OpenAL32/Include/alMain.h
+++ b/OpenAL32/Include/alMain.h
@@ -702,7 +702,7 @@ struct ALCdevice_struct
/* HRTF state and info */
DirectHrtfState *Hrtf;
al_string HrtfName;
- const struct Hrtf *HrtfHandle;
+ struct Hrtf *HrtfHandle;
vector_EnumeratedHrtf HrtfList;
ALCenum HrtfStatus;