diff options
-rw-r--r-- | Alc/ALc.c | 11 | ||||
-rw-r--r-- | Alc/hrtf.c | 49 | ||||
-rw-r--r-- | Alc/hrtf.h | 5 | ||||
-rw-r--r-- | Alc/panning.c | 32 | ||||
-rw-r--r-- | OpenAL32/Include/alMain.h | 2 |
5 files changed, 90 insertions, 9 deletions
@@ -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; @@ -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; @@ -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; |