From 14bc7baeb79f537cde9574934bee290908c43fb8 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Mon, 17 Apr 2017 21:16:01 -0700 Subject: Store the source prop updates with the mixer voice Also move its declaration and rename it for consistency. --- Alc/ALc.c | 57 +++++++++++++++++++++++-------------- Alc/ALu.c | 43 ++++++++++++++++++++++------ OpenAL32/Include/alSource.h | 57 ------------------------------------- OpenAL32/Include/alu.h | 61 ++++++++++++++++++++++++++++++++++++++-- OpenAL32/alSource.c | 68 +++++++++++++++++---------------------------- 5 files changed, 154 insertions(+), 132 deletions(-) diff --git a/Alc/ALc.c b/Alc/ALc.c index 7c6956ad..a352cacd 100644 --- a/Alc/ALc.c +++ b/Alc/ALc.c @@ -2232,7 +2232,6 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList) for(pos = 0;pos < context->SourceMap.size;pos++) { ALsource *source = context->SourceMap.values[pos]; - struct ALsourceProps *props; if(old_sends != device->NumAuxSends) { @@ -2262,26 +2261,28 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList) } ATOMIC_FLAG_CLEAR(&source->PropsClean, almemory_order_release); + } + AllocateVoices(context, context->MaxVoices, old_sends); + for(pos = 0;pos < context->VoiceCount;pos++) + { + ALvoice *voice = context->Voices[pos]; + struct ALvoiceProps *props; - /* Clear any pre-existing source property structs, in case the - * number of auxiliary sends changed. Playing (or paused) sources - * will have updates respecified in UpdateAllSourceProps. + /* Clear any pre-existing voice property structs, in case the + * number of auxiliary sends changed. Active sources will have + * updates respecified in UpdateAllSourceProps. */ - props = ATOMIC_EXCHANGE_PTR_SEQ(&source->Update, NULL); + props = ATOMIC_EXCHANGE_PTR(&voice->Update, NULL, almemory_order_relaxed); al_free(props); - props = ATOMIC_EXCHANGE_PTR(&source->FreeList, NULL, almemory_order_relaxed); + props = ATOMIC_EXCHANGE_PTR(&voice->FreeList, NULL, almemory_order_relaxed); while(props) { - struct ALsourceProps *next = ATOMIC_LOAD(&props->next, almemory_order_relaxed); + struct ALvoiceProps *next = ATOMIC_LOAD(&props->next, almemory_order_relaxed); al_free(props); props = next; } - } - AllocateVoices(context, context->MaxVoices, old_sends); - for(pos = 0;pos < context->VoiceCount;pos++) - { - ALvoice *voice = context->Voices[pos]; + if(ATOMIC_LOAD(&voice->Source, almemory_order_acquire) == NULL) continue; @@ -2527,6 +2528,7 @@ static void FreeContext(ALCcontext *context) struct ALeffectslotArray *auxslots; struct ALlistenerProps *lprops; size_t count; + ALsizei i; TRACE("%p\n", context); @@ -2549,6 +2551,8 @@ static void FreeContext(ALCcontext *context) } ResetUIntMap(&context->EffectSlotMap); + for(i = 0;i < context->VoiceCount;i++) + DeinitVoice(context->Voices[i]); al_free(context->Voices); context->Voices = NULL; context->VoiceCount = 0; @@ -2706,7 +2710,7 @@ void AllocateVoices(ALCcontext *context, ALsizei num_voices, ALsizei old_sends) { ALCdevice *device = context->Device; ALsizei num_sends = device->NumAuxSends; - struct ALsourceProps *props; + struct ALvoiceProps *props; size_t sizeof_props; size_t sizeof_voice; ALvoice **voices; @@ -2721,7 +2725,7 @@ void AllocateVoices(ALCcontext *context, ALsizei num_voices, ALsizei old_sends) * property set (including the dynamically-sized Send[] array) in one * chunk. */ - sizeof_props = RoundUp(offsetof(struct ALsourceProps, Send[num_sends]), 16); + sizeof_props = RoundUp(offsetof(struct ALvoiceProps, Send[num_sends]), 16); sizeof_voice = RoundUp(offsetof(ALvoice, Send[num_sends]), 16); size = sizeof(ALvoice*) + sizeof_voice + sizeof_props; @@ -2730,7 +2734,7 @@ void AllocateVoices(ALCcontext *context, ALsizei num_voices, ALsizei old_sends) * paired together. */ voice = (ALvoice*)((char*)voices + RoundUp(num_voices*sizeof(ALvoice*), 16)); - props = (struct ALsourceProps*)((char*)voice + sizeof_voice); + props = (struct ALvoiceProps*)((char*)voice + sizeof_voice); if(context->Voices) { @@ -2738,17 +2742,18 @@ void AllocateVoices(ALCcontext *context, ALsizei num_voices, ALsizei old_sends) for(;v < v_count;v++) { ALsizei s_count = mini(old_sends, num_sends); + ALvoice *old_voice = context->Voices[v]; ALsizei i; /* Copy the old voice data and source property set to the new * storage. */ - *voice = *(context->Voices[v]); + *voice = *old_voice; for(i = 0;i < s_count;i++) - voice->Send[i] = context->Voices[v]->Send[i]; - *props = *(context->Voices[v]->Props); + voice->Send[i] = old_voice->Send[i]; + *props = *(old_voice->Props); for(i = 0;i < s_count;i++) - props->Send[i] = context->Voices[v]->Props->Send[i]; + props->Send[i] = old_voice->Props->Send[i]; /* Set this voice's property set pointer and voice reference. */ voice->Props = props; @@ -2756,17 +2761,27 @@ void AllocateVoices(ALCcontext *context, ALsizei num_voices, ALsizei old_sends) /* Increment pointers to the next storage space. */ voice = (ALvoice*)((char*)props + sizeof_props); - props = (struct ALsourceProps*)((char*)voice + sizeof_voice); + props = (struct ALvoiceProps*)((char*)voice + sizeof_voice); } + /* Deinit any left over voices that weren't copied over to the new + * array. NOTE: If this does anything, v equals num_voices and + * num_voices is less than VoiceCount, so the following loop won't do + * anything. + */ + for(;v < context->VoiceCount;v++) + DeinitVoice(context->Voices[v]); } /* Finish setting the voices' property set pointers and references. */ for(;v < num_voices;v++) { + ATOMIC_INIT(&voice->Update, NULL); + ATOMIC_INIT(&voice->FreeList, NULL); + voice->Props = props; voices[v] = voice; voice = (ALvoice*)((char*)props + sizeof_props); - props = (struct ALsourceProps*)((char*)voice + sizeof_voice); + props = (struct ALvoiceProps*)((char*)voice + sizeof_voice); } al_free(context->Voices); diff --git a/Alc/ALu.c b/Alc/ALu.c index 89689fba..4a4709b0 100644 --- a/Alc/ALu.c +++ b/Alc/ALu.c @@ -100,6 +100,31 @@ const aluMatrixf IdentityMatrixf = {{ }}; +void DeinitVoice(ALvoice *voice) +{ + struct ALvoiceProps *props; + size_t count = 0; + + props = ATOMIC_EXCHANGE_PTR_SEQ(&voice->Update, NULL); + if(props) al_free(props); + + props = ATOMIC_EXCHANGE_PTR(&voice->FreeList, NULL, almemory_order_relaxed); + while(props) + { + struct ALvoiceProps *next; + next = ATOMIC_LOAD(&props->next, almemory_order_relaxed); + al_free(props); + props = next; + ++count; + } + /* This is excessively spammy if it traces every voice destruction, so just + * warn if it was unexpectedly large. + */ + if(count > 3) + WARN("Freed "SZFMT" voice property objects\n", count); +} + + static inline HrtfDirectMixerFunc SelectHrtfMixer(void) { #ifdef HAVE_NEON @@ -324,7 +349,7 @@ static ALboolean CalcEffectSlotParams(ALeffectslot *slot, ALCdevice *device) } -static void CalcNonAttnSourceParams(ALvoice *voice, const struct ALsourceProps *props, const ALbuffer *ALBuffer, const ALCcontext *ALContext) +static void CalcNonAttnSourceParams(ALvoice *voice, const struct ALvoiceProps *props, const ALbuffer *ALBuffer, const ALCcontext *ALContext) { static const struct ChanMap MonoMap[1] = { { FrontCenter, 0.0f, 0.0f } @@ -749,7 +774,7 @@ static void CalcNonAttnSourceParams(ALvoice *voice, const struct ALsourceProps * } } -static void CalcAttnSourceParams(ALvoice *voice, const struct ALsourceProps *props, const ALbuffer *ALBuffer, const ALCcontext *ALContext) +static void CalcAttnSourceParams(ALvoice *voice, const struct ALvoiceProps *props, const ALbuffer *ALBuffer, const ALCcontext *ALContext) { const ALCdevice *Device = ALContext->Device; const ALlistener *Listener = ALContext->Listener; @@ -1247,24 +1272,24 @@ static void CalcAttnSourceParams(ALvoice *voice, const struct ALsourceProps *pro } } -static void CalcSourceParams(ALvoice *voice, ALsource *source, ALCcontext *context, ALboolean force) +static void CalcSourceParams(ALvoice *voice, ALCcontext *context, ALboolean force) { const ALbufferlistitem *BufferListItem; - struct ALsourceProps *props; + struct ALvoiceProps *props; - props = ATOMIC_EXCHANGE_PTR(&source->Update, NULL, almemory_order_acq_rel); + props = ATOMIC_EXCHANGE_PTR(&voice->Update, NULL, almemory_order_acq_rel); if(!props && !force) return; if(props) { memcpy(voice->Props, props, - offsetof(struct ALsourceProps, Send[context->Device->NumAuxSends]) + offsetof(struct ALvoiceProps, Send[context->Device->NumAuxSends]) ); - ATOMIC_REPLACE_HEAD(struct ALsourceProps*, &source->FreeList, props); + ATOMIC_REPLACE_HEAD(struct ALvoiceProps*, &voice->FreeList, props); } - BufferListItem = ATOMIC_LOAD(&source->queue, almemory_order_relaxed); + BufferListItem = ATOMIC_LOAD(&voice->current_buffer, almemory_order_relaxed); while(BufferListItem != NULL) { const ALbuffer *buffer; @@ -1299,7 +1324,7 @@ static void UpdateContextSources(ALCcontext *ctx, const struct ALeffectslotArray for(;voice != voice_end;++voice) { source = ATOMIC_LOAD(&(*voice)->Source, almemory_order_acquire); - if(source) CalcSourceParams(*voice, source, ctx, force); + if(source) CalcSourceParams(*voice, ctx, force); } } IncrementRef(&ctx->UpdateCount); diff --git a/OpenAL32/Include/alSource.h b/OpenAL32/Include/alSource.h index 5b1e2547..265a8f47 100644 --- a/OpenAL32/Include/alSource.h +++ b/OpenAL32/Include/alSource.h @@ -15,7 +15,6 @@ extern "C" { struct ALbuffer; struct ALsource; -struct ALsourceProps; typedef struct ALbufferlistitem { @@ -24,59 +23,6 @@ typedef struct ALbufferlistitem { } ALbufferlistitem; -struct ALsourceProps { - ATOMIC(struct ALsourceProps*) next; - - ALfloat Pitch; - ALfloat Gain; - ALfloat OuterGain; - ALfloat MinGain; - ALfloat MaxGain; - ALfloat InnerAngle; - ALfloat OuterAngle; - ALfloat RefDistance; - ALfloat MaxDistance; - ALfloat RollOffFactor; - ALfloat Position[3]; - ALfloat Velocity[3]; - ALfloat Direction[3]; - ALfloat Orientation[2][3]; - ALboolean HeadRelative; - enum DistanceModel DistanceModel; - ALboolean DirectChannels; - - ALboolean DryGainHFAuto; - ALboolean WetGainAuto; - ALboolean WetGainHFAuto; - ALfloat OuterGainHF; - - ALfloat AirAbsorptionFactor; - ALfloat RoomRolloffFactor; - ALfloat DopplerFactor; - - ALfloat StereoPan[2]; - - ALfloat Radius; - - /** Direct filter and auxiliary send info. */ - struct { - ALfloat Gain; - ALfloat GainHF; - ALfloat HFReference; - ALfloat GainLF; - ALfloat LFReference; - } Direct; - struct { - struct ALeffectslot *Slot; - ALfloat Gain; - ALfloat GainHF; - ALfloat HFReference; - ALfloat GainLF; - ALfloat LFReference; - } Send[]; -}; - - typedef struct ALsource { /** Source properties. */ ALfloat Pitch; @@ -151,9 +97,6 @@ typedef struct ALsource { ATOMIC_FLAG PropsClean; - ATOMIC(struct ALsourceProps*) Update; - ATOMIC(struct ALsourceProps*) FreeList; - /** Self ID */ ALuint id; } ALsource; diff --git a/OpenAL32/Include/alu.h b/OpenAL32/Include/alu.h index 6c3f3499..a2ba4fae 100644 --- a/OpenAL32/Include/alu.h +++ b/OpenAL32/Include/alu.h @@ -35,7 +35,6 @@ extern "C" { #endif struct ALsource; -struct ALsourceProps; struct ALbufferlistitem; struct ALvoice; struct ALeffectslot; @@ -153,13 +152,69 @@ typedef struct SendParams { } Gains; } SendParams; + +struct ALvoiceProps { + ATOMIC(struct ALvoiceProps*) next; + + ALfloat Pitch; + ALfloat Gain; + ALfloat OuterGain; + ALfloat MinGain; + ALfloat MaxGain; + ALfloat InnerAngle; + ALfloat OuterAngle; + ALfloat RefDistance; + ALfloat MaxDistance; + ALfloat RollOffFactor; + ALfloat Position[3]; + ALfloat Velocity[3]; + ALfloat Direction[3]; + ALfloat Orientation[2][3]; + ALboolean HeadRelative; + enum DistanceModel DistanceModel; + ALboolean DirectChannels; + + ALboolean DryGainHFAuto; + ALboolean WetGainAuto; + ALboolean WetGainHFAuto; + ALfloat OuterGainHF; + + ALfloat AirAbsorptionFactor; + ALfloat RoomRolloffFactor; + ALfloat DopplerFactor; + + ALfloat StereoPan[2]; + + ALfloat Radius; + + /** Direct filter and auxiliary send info. */ + struct { + ALfloat Gain; + ALfloat GainHF; + ALfloat HFReference; + ALfloat GainLF; + ALfloat LFReference; + } Direct; + struct { + struct ALeffectslot *Slot; + ALfloat Gain; + ALfloat GainHF; + ALfloat HFReference; + ALfloat GainLF; + ALfloat LFReference; + } Send[]; +}; + /* If not 'moving', gain targets are used directly without fading. */ #define VOICE_IS_MOVING (1<<0) #define VOICE_IS_HRTF (1<<1) #define VOICE_HAS_NFC (1<<2) typedef struct ALvoice { - struct ALsourceProps *Props; + struct ALvoiceProps *Props; + + ATOMIC(struct ALvoiceProps*) Update; + ATOMIC(struct ALvoiceProps*) FreeList; ATOMIC(struct ALsource*) Source; ATOMIC(bool) Playing; @@ -209,6 +264,8 @@ typedef struct ALvoice { } Send[]; } ALvoice; +void DeinitVoice(ALvoice *voice); + typedef const ALfloat* (*ResamplerFunc)(const InterpState *state, const ALfloat *restrict src, ALsizei frac, ALint increment, diff --git a/OpenAL32/alSource.c b/OpenAL32/alSource.c index 040078df..dcf9821e 100644 --- a/OpenAL32/alSource.c +++ b/OpenAL32/alSource.c @@ -49,7 +49,7 @@ extern inline struct ALsource *RemoveSource(ALCcontext *context, ALuint id); static void InitSourceParams(ALsource *Source, ALsizei num_sends); static void DeinitSource(ALsource *source, ALsizei num_sends); -static void UpdateSourceProps(ALsource *source, ALsizei num_sends); +static void UpdateSourceProps(ALsource *source, ALvoice *voice, ALsizei num_sends); static ALint64 GetSourceSampleOffset(ALsource *Source, ALCcontext *context, ALuint64 *clocktime); static ALdouble GetSourceSecOffset(ALsource *Source, ALCcontext *context, ALuint64 *clocktime); static ALdouble GetSourceOffset(ALsource *Source, ALenum name, ALCcontext *context); @@ -430,8 +430,10 @@ static ALint Int64ValsByProp(ALenum prop) } while(0) #define DO_UPDATEPROPS() do { \ - if(SourceShouldUpdate(Source, Context)) \ - UpdateSourceProps(Source, device->NumAuxSends); \ + ALvoice *voice; \ + if(SourceShouldUpdate(Source, Context) && \ + (voice=GetSourceVoice(Source, Context)) != NULL) \ + UpdateSourceProps(Source, voice, device->NumAuxSends); \ else \ ATOMIC_FLAG_CLEAR(&Source->PropsClean, almemory_order_release); \ } while(0) @@ -896,16 +898,20 @@ static ALboolean SetSourceiv(ALsource *Source, ALCcontext *Context, SourceProp p if(slot != Source->Send[values[1]].Slot && IsPlayingOrPaused(Source)) { + ALvoice *voice; /* Add refcount on the new slot, and release the previous slot */ if(slot) IncrementRef(&slot->ref); if(Source->Send[values[1]].Slot) DecrementRef(&Source->Send[values[1]].Slot->ref); Source->Send[values[1]].Slot = slot; - /* We must force an update if the auxiliary slot changed on a - * playing source, in case the slot is about to be deleted. + /* We must force an update if the auxiliary slot changed on an + * active source, in case the slot is about to be deleted. */ - UpdateSourceProps(Source, device->NumAuxSends); + if((voice=GetSourceVoice(Source, Context)) != NULL) + UpdateSourceProps(Source, voice, device->NumAuxSends); + else + ATOMIC_FLAG_CLEAR(&Source->PropsClean, almemory_order_release); } else { @@ -2450,9 +2456,6 @@ AL_API ALvoid AL_APIENTRY alSourcePlayv(ALsizei n, const ALuint *sources) break; } - ATOMIC_FLAG_TEST_AND_SET(&source->PropsClean, almemory_order_acquire); - UpdateSourceProps(source, device->NumAuxSends); - /* Make sure this source isn't already active, and if not, look for an * unused voice to put it in. */ @@ -2468,7 +2471,9 @@ AL_API ALvoid AL_APIENTRY alSourcePlayv(ALsizei n, const ALuint *sources) if(voice == NULL) voice = context->Voices[context->VoiceCount++]; ATOMIC_STORE(&voice->Playing, false, almemory_order_release); - ATOMIC_THREAD_FENCE(almemory_order_acquire); + + ATOMIC_FLAG_TEST_AND_SET(&source->PropsClean, almemory_order_acquire); + UpdateSourceProps(source, voice, device->NumAuxSends); /* A source that's not playing or paused has any offset applied when it * starts playing. @@ -2973,36 +2978,13 @@ static void InitSourceParams(ALsource *Source, ALsizei num_sends) * ignore the test. */ ATOMIC_FLAG_TEST_AND_SET(&Source->PropsClean, almemory_order_relaxed); - - ATOMIC_INIT(&Source->Update, NULL); - ATOMIC_INIT(&Source->FreeList, NULL); } static void DeinitSource(ALsource *source, ALsizei num_sends) { ALbufferlistitem *BufferList; - struct ALsourceProps *props; - size_t count = 0; ALsizei i; - props = ATOMIC_LOAD_SEQ(&source->Update); - if(props) al_free(props); - - props = ATOMIC_LOAD(&source->FreeList, almemory_order_relaxed); - while(props) - { - struct ALsourceProps *next; - next = ATOMIC_LOAD(&props->next, almemory_order_relaxed); - al_free(props); - props = next; - ++count; - } - /* This is excessively spammy if it traces every source destruction, so - * just warn if it was unexpectedly large. - */ - if(count > 3) - WARN("Freed "SZFMT" Source property objects\n", count); - BufferList = ATOMIC_EXCHANGE_PTR_SEQ(&source->queue, NULL); while(BufferList != NULL) { @@ -3026,21 +3008,21 @@ static void DeinitSource(ALsource *source, ALsizei num_sends) } } -static void UpdateSourceProps(ALsource *source, ALsizei num_sends) +static void UpdateSourceProps(ALsource *source, ALvoice *voice, ALsizei num_sends) { - struct ALsourceProps *props; + struct ALvoiceProps *props; ALsizei i; /* Get an unused property container, or allocate a new one as needed. */ - props = ATOMIC_LOAD(&source->FreeList, almemory_order_acquire); + props = ATOMIC_LOAD(&voice->FreeList, almemory_order_acquire); if(!props) - props = al_calloc(16, offsetof(struct ALsourceProps, Send[num_sends])); + props = al_calloc(16, offsetof(struct ALvoiceProps, Send[num_sends])); else { - struct ALsourceProps *next; + struct ALvoiceProps *next; do { next = ATOMIC_LOAD(&props->next, almemory_order_relaxed); - } while(ATOMIC_COMPARE_EXCHANGE_PTR_WEAK(&source->FreeList, &props, next, + } while(ATOMIC_COMPARE_EXCHANGE_PTR_WEAK(&voice->FreeList, &props, next, almemory_order_acq_rel, almemory_order_acquire) == 0); } @@ -3102,13 +3084,13 @@ static void UpdateSourceProps(ALsource *source, ALsizei num_sends) } /* Set the new container for updating internal parameters. */ - props = ATOMIC_EXCHANGE_PTR(&source->Update, props, almemory_order_acq_rel); + props = ATOMIC_EXCHANGE_PTR(&voice->Update, props, almemory_order_acq_rel); if(props) { /* If there was an unused update container, put it back in the * freelist. */ - ATOMIC_REPLACE_HEAD(struct ALsourceProps*, &source->FreeList, props); + ATOMIC_REPLACE_HEAD(struct ALvoiceProps*, &voice->FreeList, props); } } @@ -3121,8 +3103,8 @@ void UpdateAllSourceProps(ALCcontext *context) { ALvoice *voice = context->Voices[pos]; ALsource *source = ATOMIC_LOAD(&voice->Source, almemory_order_acquire); - if(source != NULL && !ATOMIC_FLAG_TEST_AND_SET(&source->PropsClean, almemory_order_acq_rel)) - UpdateSourceProps(source, num_sends); + if(source && !ATOMIC_FLAG_TEST_AND_SET(&source->PropsClean, almemory_order_acq_rel)) + UpdateSourceProps(source, voice, num_sends); } } -- cgit v1.2.3