Make ALsourceProps' Send array dynamically sized
ALsourceProps' Send[] array is placed at the end of the struct, and given an indeterminate size. Extra space is allocated at the end of each struct given the number of auxiliary sends set for the device.
This commit is contained in:
parent
69dd570961
commit
5a50c46c22
99
Alc/ALc.c
99
Alc/ALc.c
@ -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))
|
||||
|
22
Alc/ALu.c
22
Alc/ALu.c
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user