diff options
-rw-r--r-- | Alc/ALc.c | 99 | ||||
-rw-r--r-- | Alc/ALu.c | 22 | ||||
-rw-r--r-- | Alc/helpers.c | 1 | ||||
-rw-r--r-- | OpenAL32/Include/alMain.h | 9 | ||||
-rw-r--r-- | OpenAL32/Include/alSource.h | 8 | ||||
-rw-r--r-- | OpenAL32/alSource.c | 21 |
6 files changed, 121 insertions, 39 deletions
@@ -1769,6 +1769,7 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList) ALCcontext *context; enum HrtfRequestMode hrtf_appreq = Hrtf_Default; enum HrtfRequestMode hrtf_userreq = Hrtf_Default; + ALsizei old_sends = device->NumAuxSends; enum DevFmtChannels oldChans; enum DevFmtType oldType; ALCuint oldFreq; @@ -2183,7 +2184,7 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList) { ALsizei pos; - ReadLock(&context->PropLock); + WriteLock(&context->PropLock); LockUIntMapRead(&context->EffectSlotMap); for(pos = 0;pos < context->EffectSlotMap.size;pos++) { @@ -2208,8 +2209,10 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList) for(pos = 0;pos < context->SourceMap.size;pos++) { ALsource *source = context->SourceMap.values[pos]; - ALuint s = device->NumAuxSends; - while(s < MAX_SENDS) + struct ALsourceProps *props; + ALsizei s; + + for(s = device->NumAuxSends;s < MAX_SENDS;s++) { if(source->Send[s].Slot) DecrementRef(&source->Send[s].Slot->ref); @@ -2219,14 +2222,32 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList) source->Send[s].HFReference = LOWPASSFREQREF; source->Send[s].GainLF = 1.0f; source->Send[s].LFReference = HIGHPASSFREQREF; - s++; } + source->NeedsUpdate = AL_TRUE; + + /* Clear any pre-existing source property structs, in case the + * number of auxiliary sends changed. Playing (or paused) sources + * will have updates specified. + */ + props = ATOMIC_EXCHANGE_SEQ(struct ALsourceProps*, &source->Update, NULL); + al_free(props); + + props = ATOMIC_EXCHANGE(struct ALsourceProps*, &source->FreeList, NULL, + almemory_order_relaxed); + while(props) + { + struct ALsourceProps *next = ATOMIC_LOAD(&props->next, almemory_order_relaxed); + al_free(props); + props = next; + } } + AllocateVoices(context, context->MaxVoices, old_sends); UnlockUIntMapRead(&context->SourceMap); UpdateListenerProps(context); - ReadUnlock(&context->PropLock); + UpdateAllSourceProps(context); + WriteUnlock(&context->PropLock); context = context->next; } @@ -2595,6 +2616,65 @@ ALCcontext *GetContextRef(void) } +void AllocateVoices(ALCcontext *context, ALsizei num_voices, ALsizei old_sends) +{ + ALCdevice *device = context->Device; + ALsizei num_sends = device->NumAuxSends; + struct ALsourceProps *props; + size_t sizeof_props; + ALvoice *voices; + ALsizei v = 0; + size_t size; + + if(num_voices == context->MaxVoices && num_sends == old_sends) + return; + + /* Allocate the voices, and the voices' stored source property set + * (including the dynamically-sized Send[] array) in one chunk. + */ + sizeof_props = RoundUp(offsetof(struct ALsourceProps, Send[num_sends]), 16); + size = sizeof(*voices) + sizeof_props; + + voices = al_calloc(16, size * num_voices); + props = (struct ALsourceProps*)(voices + num_voices); + + if(context->Voices) + { + ALsizei v_count = mini(context->VoiceCount, num_voices); + for(;v < v_count;v++) + { + ALsizei s_count = mini(old_sends, num_sends); + ALsizei i; + + /* Copy the old voice data and source property set to the new + * storage. + */ + voices[v] = context->Voices[v]; + *props = *(context->Voices[v].Props); + for(i = 0;i < s_count;i++) + props->Send[i] = context->Voices[v].Props->Send[i]; + + /* Set this voice's property set pointer and increment 'props' to + * the next property storage space. + */ + voices[v].Props = props; + props = (struct ALsourceProps*)((char*)props + sizeof_props); + } + } + /* Finish setting the voices' property set pointers. */ + for(;v < num_voices;v++) + { + voices[v].Props = props; + props = (struct ALsourceProps*)((char*)props + sizeof_props); + } + + al_free(context->Voices); + context->Voices = voices; + context->MaxVoices = num_voices; + context->VoiceCount = mini(context->VoiceCount, num_voices); +} + + /************************************************ * Standard ALC functions ************************************************/ @@ -3267,11 +3347,13 @@ ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCin InitRef(&ALContext->ref, 1); ALContext->Listener = (ALlistener*)ALContext->_listener_mem; + ALContext->Device = device; ATOMIC_INIT(&ALContext->ActiveAuxSlotList, NULL); + ALContext->Voices = NULL; + ALContext->MaxVoices = 0; ALContext->VoiceCount = 0; - ALContext->MaxVoices = 256; - ALContext->Voices = al_calloc(16, ALContext->MaxVoices * sizeof(ALContext->Voices[0])); + AllocateVoices(ALContext, 256, device->NumAuxSends); } if(!ALContext || !ALContext->Voices) { @@ -3312,8 +3394,7 @@ ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCin return NULL; } - ALContext->Device = device; - ALCdevice_IncRef(device); + ALCdevice_IncRef(ALContext->Device); InitContext(ALContext); if(ConfigValueFloat(al_string_get_cstr(device->DeviceName), NULL, "volume-adjust", &valf)) @@ -807,14 +807,6 @@ static void CalcAttnSourceParams(ALvoice *voice, const struct ALsourceProps *pro ALint NumSends; ALint i; - DryGainHF = 1.0f; - DryGainLF = 1.0f; - for(i = 0;i < MAX_SENDS;i++) - { - WetGainHF[i] = 1.0f; - WetGainLF[i] = 1.0f; - } - /* Get context/device properties */ DopplerFactor = Listener->Params.DopplerFactor; SpeedOfSound = Listener->Params.SpeedOfSound; @@ -989,8 +981,14 @@ static void CalcAttnSourceParams(ALvoice *voice, const struct ALsourceProps *pro /* Source Gain + Attenuation */ DryGain = SourceVolume * Attenuation; + DryGainHF = 1.0f; + DryGainLF = 1.0f; for(i = 0;i < NumSends;i++) + { WetGain[i] = SourceVolume * RoomAttenuation[i]; + WetGainHF[i] = 1.0f; + WetGainLF[i] = 1.0f; + } /* Distance-based air absorption */ if(AirAbsorptionFactor > 0.0f && ClampedDist > MinDist) @@ -1284,7 +1282,9 @@ static void CalcSourceParams(ALvoice *voice, ALCcontext *context, ALboolean forc if(props) { - voice->Props = *props; + memcpy(voice->Props, props, + offsetof(struct ALsourceProps, Send[context->Device->NumAuxSends]) + ); ATOMIC_REPLACE_HEAD(struct ALsourceProps*, &source->FreeList, props); } @@ -1296,9 +1296,9 @@ static void CalcSourceParams(ALvoice *voice, ALCcontext *context, ALboolean forc if((buffer=BufferListItem->buffer) != NULL) { if(buffer->FmtChannels == FmtMono) - CalcAttnSourceParams(voice, &voice->Props, buffer, context); + CalcAttnSourceParams(voice, voice->Props, buffer, context); else - CalcNonAttnSourceParams(voice, &voice->Props, buffer, context); + CalcNonAttnSourceParams(voice, voice->Props, buffer, context); break; } BufferListItem = BufferListItem->next; diff --git a/Alc/helpers.c b/Alc/helpers.c index eac3811d..1ce567b2 100644 --- a/Alc/helpers.c +++ b/Alc/helpers.c @@ -112,6 +112,7 @@ DEFINE_PROPERTYKEY(PKEY_AudioEndpoint_GUID, 0x1da5d803, 0xd492, 0x4edd, 0x8c, 0x extern inline ALuint NextPowerOf2(ALuint value); +extern inline size_t RoundUp(size_t value, size_t r); extern inline ALint fastf2i(ALfloat f); extern inline ALuint fastf2u(ALfloat f); diff --git a/OpenAL32/Include/alMain.h b/OpenAL32/Include/alMain.h index 2573c836..947a16ba 100644 --- a/OpenAL32/Include/alMain.h +++ b/OpenAL32/Include/alMain.h @@ -356,6 +356,13 @@ inline ALuint NextPowerOf2(ALuint value) return value+1; } +/** Round up a value to the next multiple. */ +inline size_t RoundUp(size_t value, size_t r) +{ + value += r-1; + return value - (value%r); +} + /* Fast float-to-int conversion. Assumes the FPU is already in round-to-zero * mode. */ inline ALint fastf2i(ALfloat f) @@ -813,6 +820,8 @@ ALCcontext *GetContextRef(void); void ALCcontext_IncRef(ALCcontext *context); void ALCcontext_DecRef(ALCcontext *context); +void AllocateVoices(ALCcontext *context, ALsizei num_voices, ALsizei old_sends); + void AppendAllDevicesList(const ALCchar *name); void AppendCaptureDeviceList(const ALCchar *name); diff --git a/OpenAL32/Include/alSource.h b/OpenAL32/Include/alSource.h index d45e5d9c..cc9dd763 100644 --- a/OpenAL32/Include/alSource.h +++ b/OpenAL32/Include/alSource.h @@ -23,6 +23,8 @@ typedef struct ALbufferlistitem { struct ALsourceProps { + ATOMIC(struct ALsourceProps*) next; + ATOMIC(ALfloat) Pitch; ATOMIC(ALfloat) Gain; ATOMIC(ALfloat) OuterGain; @@ -69,14 +71,12 @@ struct ALsourceProps { ATOMIC(ALfloat) HFReference; ATOMIC(ALfloat) GainLF; ATOMIC(ALfloat) LFReference; - } Send[MAX_SENDS]; - - ATOMIC(struct ALsourceProps*) next; + } Send[]; }; typedef struct ALvoice { - struct ALsourceProps Props; + struct ALsourceProps *Props; struct ALsource *Source; diff --git a/OpenAL32/alSource.c b/OpenAL32/alSource.c index 036b7542..56d2b415 100644 --- a/OpenAL32/alSource.c +++ b/OpenAL32/alSource.c @@ -2306,23 +2306,13 @@ AL_API ALvoid AL_APIENTRY alSourcePlayv(ALsizei n, const ALuint *sources) ALCdevice_Lock(context->Device); while(n > context->MaxVoices-context->VoiceCount) { - ALvoice *temp = NULL; - ALsizei newcount; - - newcount = context->MaxVoices << 1; - if(newcount > 0) - temp = al_malloc(16, newcount * sizeof(context->Voices[0])); - if(!temp) + ALsizei newcount = context->MaxVoices << 1; + if(context->MaxVoices >= newcount) { ALCdevice_Unlock(context->Device); SET_ERROR_AND_GOTO(context, AL_OUT_OF_MEMORY, done); } - memcpy(temp, context->Voices, context->MaxVoices * sizeof(temp[0])); - memset(&temp[context->MaxVoices], 0, (newcount-context->MaxVoices) * sizeof(temp[0])); - - al_free(context->Voices); - context->Voices = temp; - context->MaxVoices = newcount; + AllocateVoices(context, newcount, context->Device->NumAuxSends); } if(ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire) == DeferAll) @@ -2757,6 +2747,7 @@ static void InitSourceParams(ALsource *Source) Source->Direct.LFReference = HIGHPASSFREQREF; for(i = 0;i < MAX_SENDS;i++) { + Source->Send[i].Slot = NULL; Source->Send[i].Gain = 1.0f; Source->Send[i].GainHF = 1.0f; Source->Send[i].HFReference = LOWPASSFREQREF; @@ -2819,7 +2810,7 @@ static void DeinitSource(ALsource *source) BufferList = next; } - for(i = 0;i < MAX_SENDS;++i) + for(i = 0;i < MAX_SENDS;i++) { if(source->Send[i].Slot) DecrementRef(&source->Send[i].Slot->ref); @@ -2835,7 +2826,7 @@ static void UpdateSourceProps(ALsource *source, ALuint num_sends) /* Get an unused property container, or allocate a new one as needed. */ props = ATOMIC_LOAD(&source->FreeList, almemory_order_acquire); if(!props) - props = al_calloc(16, sizeof(*props)); + props = al_calloc(16, offsetof(struct ALsourceProps, Send[num_sends])); else { struct ALsourceProps *next; |