Dynamically allocate the ALsource Send[] array

This commit is contained in:
Chris Robinson
2017-02-21 16:31:59 -08:00
parent 29994aa2de
commit 864d5387dd
5 changed files with 94 additions and 69 deletions
+58 -44
View File
@@ -1766,15 +1766,17 @@ static inline void UpdateClockBase(ALCdevice *device)
*/
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 HrtfRequestMode hrtf_appreq = Hrtf_Default;
const ALsizei old_sends = device->NumAuxSends;
ALsizei new_sends = device->NumAuxSends;
enum DevFmtChannels oldChans;
enum DevFmtType oldType;
ALboolean update_failed;
ALCsizei hrtf_id = -1;
ALCcontext *context;
ALCuint oldFreq;
FPUCtl oldMode;
ALCsizei hrtf_id = -1;
size_t size;
// Check for attributes
@@ -1800,10 +1802,10 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
numMono = device->NumMonoSources;
numStereo = device->NumStereoSources;
numSends = device->NumAuxSends;
schans = device->FmtChans;
stype = device->FmtType;
freq = device->Frequency;
numSends = old_sends;
#define TRACE_ATTR(a, v) TRACE("Loopback %s = %d\n", #a, v)
while(attrList[attrIdx])
@@ -1880,9 +1882,6 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
return ALC_INVALID_VALUE;
}
ConfigValueUInt(NULL, NULL, "sends", &numSends);
numSends = minu(MAX_SENDS, numSends);
if((device->Flags&DEVICE_RUNNING))
V0(device->Backend,stop)();
device->Flags &= ~DEVICE_RUNNING;
@@ -1894,7 +1893,9 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
device->FmtType = stype;
device->NumMonoSources = numMono;
device->NumStereoSources = numStereo;
device->NumAuxSends = numSends;
ConfigValueUInt(NULL, NULL, "sends", &numSends);
new_sends = clampi(numSends, 1, MAX_SENDS);
}
else if(attrList && attrList[0])
{
@@ -1907,10 +1908,12 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
V0(device->Backend,stop)();
device->Flags &= ~DEVICE_RUNNING;
UpdateClockBase(device);
freq = device->Frequency;
numMono = device->NumMonoSources;
numStereo = device->NumStereoSources;
numSends = device->NumAuxSends;
numSends = old_sends;
#define TRACE_ATTR(a, v) TRACE("%s = %d\n", #a, v)
while(attrList[attrIdx])
@@ -1962,11 +1965,6 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
ConfigValueUInt(al_string_get_cstr(device->DeviceName), NULL, "frequency", &freq);
freq = maxu(freq, MIN_OUTPUT_RATE);
ConfigValueUInt(al_string_get_cstr(device->DeviceName), NULL, "sends", &numSends);
numSends = minu(MAX_SENDS, numSends);
UpdateClockBase(device);
device->UpdateSize = (ALuint64)device->UpdateSize * freq /
device->Frequency;
/* SSE and Neon do best with the update size being a multiple of 4 */
@@ -1976,7 +1974,9 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
device->Frequency = freq;
device->NumMonoSources = numMono;
device->NumStereoSources = numStereo;
device->NumAuxSends = numSends;
ConfigValueUInt(al_string_get_cstr(device->DeviceName), NULL, "sends", &numSends);
new_sends = clampi(numSends, 1, MAX_SENDS);
}
if((device->Flags&DEVICE_RUNNING))
@@ -2148,6 +2148,11 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
device->FOAOut.NumChannels = device->Dry.NumChannels;
}
/* Need to delay returning failure until replacement Send arrays have been
* allocated with the appropriate size.
*/
device->NumAuxSends = new_sends;
update_failed = AL_FALSE;
SetMixerFPUMode(&oldMode);
if(device->DefaultSlot)
{
@@ -2157,11 +2162,9 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
state->OutBuffer = device->Dry.Buffer;
state->OutChannels = device->Dry.NumChannels;
if(V(state,deviceUpdate)(device) == AL_FALSE)
{
RestoreFPUMode(&oldMode);
return ALC_INVALID_DEVICE;
}
UpdateEffectSlotProps(slot);
update_failed = AL_TRUE;
else
UpdateEffectSlotProps(slot);
}
context = ATOMIC_LOAD_SEQ(&device->ContextList);
@@ -2179,14 +2182,9 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
state->OutBuffer = device->Dry.Buffer;
state->OutChannels = device->Dry.NumChannels;
if(V(state,deviceUpdate)(device) == AL_FALSE)
{
UnlockUIntMapRead(&context->EffectSlotMap);
ReadUnlock(&context->PropLock);
RestoreFPUMode(&oldMode);
return ALC_INVALID_DEVICE;
}
UpdateEffectSlotProps(slot);
update_failed = AL_TRUE;
else
UpdateEffectSlotProps(slot);
}
UnlockUIntMapRead(&context->EffectSlotMap);
@@ -2195,25 +2193,39 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
{
ALsource *source = context->SourceMap.values[pos];
struct ALsourceProps *props;
ALsizei s;
for(s = device->NumAuxSends;s < MAX_SENDS;s++)
if(old_sends != device->NumAuxSends)
{
if(source->Send[s].Slot)
DecrementRef(&source->Send[s].Slot->ref);
source->Send[s].Slot = NULL;
source->Send[s].Gain = 1.0f;
source->Send[s].GainHF = 1.0f;
source->Send[s].HFReference = LOWPASSFREQREF;
source->Send[s].GainLF = 1.0f;
source->Send[s].LFReference = HIGHPASSFREQREF;
ALvoid *sends = al_calloc(16, device->NumAuxSends*sizeof(source->Send[0]));
ALsizei s;
memcpy(sends, source->Send,
mini(device->NumAuxSends, old_sends)*sizeof(source->Send[0])
);
for(s = device->NumAuxSends;s < old_sends;s++)
{
if(source->Send[s].Slot)
DecrementRef(&source->Send[s].Slot->ref);
source->Send[s].Slot = NULL;
}
al_free(source->Send);
source->Send = sends;
for(s = old_sends;s < device->NumAuxSends;s++)
{
source->Send[s].Slot = NULL;
source->Send[s].Gain = 1.0f;
source->Send[s].GainHF = 1.0f;
source->Send[s].HFReference = LOWPASSFREQREF;
source->Send[s].GainLF = 1.0f;
source->Send[s].LFReference = HIGHPASSFREQREF;
}
}
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.
* will have updates respecified in UpdateAllSourceProps.
*/
props = ATOMIC_EXCHANGE_SEQ(struct ALsourceProps*, &source->Update, NULL);
al_free(props);
@@ -2237,6 +2249,8 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
context = context->next;
}
RestoreFPUMode(&oldMode);
if(update_failed)
return ALC_INVALID_DEVICE;
if(!(device->Flags&DEVICE_PAUSED))
{
@@ -3720,8 +3734,8 @@ ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName)
ConfigValueUInt(deviceName, NULL, "slots", &device->AuxiliaryEffectSlotMax);
if(device->AuxiliaryEffectSlotMax == 0) device->AuxiliaryEffectSlotMax = 4;
ConfigValueUInt(deviceName, NULL, "sends", &device->NumAuxSends);
if(device->NumAuxSends > MAX_SENDS) device->NumAuxSends = MAX_SENDS;
ConfigValueInt(deviceName, NULL, "sends", &device->NumAuxSends);
device->NumAuxSends = clampi(device->NumAuxSends, 0, MAX_SENDS);
device->NumStereoSources = 1;
device->NumMonoSources = device->SourcesMax - device->NumStereoSources;
@@ -4126,8 +4140,8 @@ ALC_API ALCdevice* ALC_APIENTRY alcLoopbackOpenDeviceSOFT(const ALCchar *deviceN
ConfigValueUInt(NULL, NULL, "slots", &device->AuxiliaryEffectSlotMax);
if(device->AuxiliaryEffectSlotMax == 0) device->AuxiliaryEffectSlotMax = 4;
ConfigValueUInt(NULL, NULL, "sends", &device->NumAuxSends);
if(device->NumAuxSends > MAX_SENDS) device->NumAuxSends = MAX_SENDS;
ConfigValueInt(NULL, NULL, "sends", &device->NumAuxSends);
device->NumAuxSends = clampi(device->NumAuxSends, 0, MAX_SENDS);
device->NumStereoSources = 1;
device->NumMonoSources = device->SourcesMax - device->NumStereoSources;
+1 -1
View File
@@ -381,7 +381,7 @@ void MixSource(ALvoice *voice, ALsource *Source, ALCdevice *Device, ALsizei Samp
ALsizei Counter;
ALsizei IrSize;
ALsizei chan, j;
ALuint send;
ALsizei send;
/* Get source info */
State = AL_PLAYING; /* Only called while playing. */
+1 -1
View File
@@ -648,7 +648,7 @@ struct ALCdevice_struct
ALCuint NumMonoSources;
ALCuint NumStereoSources;
ALuint NumAuxSends;
ALsizei NumAuxSends;
// Map of Buffers for this device
UIntMap BufferMap;
+1 -1
View File
@@ -161,7 +161,7 @@ typedef struct ALsource {
ALfloat HFReference;
ALfloat GainLF;
ALfloat LFReference;
} Send[MAX_SENDS];
} *Send;
/**
* Last user-specified offset, and the offset type (bytes, samples, or
+33 -22
View File
@@ -48,9 +48,9 @@ extern inline struct ALsource *LookupSource(ALCcontext *context, ALuint id);
extern inline struct ALsource *RemoveSource(ALCcontext *context, ALuint id);
extern inline ALboolean IsPlayingOrPaused(const ALsource *source);
static void InitSourceParams(ALsource *Source);
static void DeinitSource(ALsource *source);
static void UpdateSourceProps(ALsource *source, ALuint num_sends);
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 ALint64 GetSourceSampleOffset(ALsource *Source, ALCdevice *device, ALuint64 *clocktime);
static ALdouble GetSourceSecOffset(ALsource *Source, ALCdevice *device, ALuint64 *clocktime);
static ALdouble GetSourceOffset(ALsource *Source, ALenum name, ALCdevice *device);
@@ -816,7 +816,7 @@ static ALboolean SetSourceiv(ALsource *Source, ALCcontext *Context, SourceProp p
case AL_AUXILIARY_SEND_FILTER:
LockEffectSlotsRead(Context);
LockFiltersRead(device);
if(!((ALuint)values[1] < device->NumAuxSends &&
if(!((ALuint)values[1] < (ALuint)device->NumAuxSends &&
(values[0] == 0 || (slot=LookupEffectSlot(Context, values[0])) != NULL) &&
(values[2] == 0 || (filter=LookupFilter(device, values[2])) != NULL)))
{
@@ -1539,6 +1539,7 @@ static ALboolean GetSourcei64v(ALsource *Source, ALCcontext *Context, SourceProp
AL_API ALvoid AL_APIENTRY alGenSources(ALsizei n, ALuint *sources)
{
ALCdevice *device;
ALCcontext *context;
ALsizei cur = 0;
ALenum err;
@@ -1548,6 +1549,7 @@ AL_API ALvoid AL_APIENTRY alGenSources(ALsizei n, ALuint *sources)
if(!(n >= 0))
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
device = context->Device;
for(cur = 0;cur < n;cur++)
{
ALsource *source = al_calloc(16, sizeof(ALsource));
@@ -1556,7 +1558,7 @@ AL_API ALvoid AL_APIENTRY alGenSources(ALsizei n, ALuint *sources)
alDeleteSources(cur, sources);
SET_ERROR_AND_GOTO(context, AL_OUT_OF_MEMORY, done);
}
InitSourceParams(source);
InitSourceParams(source, device->NumAuxSends);
err = NewThunkEntry(&source->id);
if(err == AL_NO_ERROR)
@@ -1581,6 +1583,7 @@ done:
AL_API ALvoid AL_APIENTRY alDeleteSources(ALsizei n, const ALuint *sources)
{
ALCdevice *device;
ALCcontext *context;
ALsource *Source;
ALsizei i;
@@ -1598,6 +1601,7 @@ AL_API ALvoid AL_APIENTRY alDeleteSources(ALsizei n, const ALuint *sources)
if(LookupSource(context, sources[i]) == NULL)
SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
}
device = context->Device;
for(i = 0;i < n;i++)
{
ALvoice *voice;
@@ -1606,12 +1610,12 @@ AL_API ALvoid AL_APIENTRY alDeleteSources(ALsizei n, const ALuint *sources)
continue;
FreeThunkEntry(Source->id);
ALCdevice_Lock(context->Device);
ALCdevice_Lock(device);
voice = GetSourceVoice(Source, context);
if(voice) voice->Source = NULL;
ALCdevice_Unlock(context->Device);
ALCdevice_Unlock(device);
DeinitSource(Source);
DeinitSource(Source, device->NumAuxSends);
memset(Source, 0, sizeof(*Source));
al_free(Source);
@@ -2692,9 +2696,9 @@ done:
}
static void InitSourceParams(ALsource *Source)
static void InitSourceParams(ALsource *Source, ALsizei num_sends)
{
ALuint i;
ALsizei i;
RWLockInit(&Source->queue_lock);
@@ -2745,7 +2749,8 @@ static void InitSourceParams(ALsource *Source)
Source->Direct.HFReference = LOWPASSFREQREF;
Source->Direct.GainLF = 1.0f;
Source->Direct.LFReference = HIGHPASSFREQREF;
for(i = 0;i < MAX_SENDS;i++)
Source->Send = al_calloc(16, num_sends*sizeof(Source->Send[0]));
for(i = 0;i < num_sends;i++)
{
Source->Send[i].Slot = NULL;
Source->Send[i].Gain = 1.0f;
@@ -2775,12 +2780,12 @@ static void InitSourceParams(ALsource *Source)
ATOMIC_INIT(&Source->FreeList, NULL);
}
static void DeinitSource(ALsource *source)
static void DeinitSource(ALsource *source, ALsizei num_sends)
{
ALbufferlistitem *BufferList;
struct ALsourceProps *props;
size_t count = 0;
size_t i;
ALsizei i;
props = ATOMIC_LOAD_SEQ(&source->Update);
if(props) al_free(props);
@@ -2810,18 +2815,23 @@ static void DeinitSource(ALsource *source)
BufferList = next;
}
for(i = 0;i < MAX_SENDS;i++)
if(source->Send)
{
if(source->Send[i].Slot)
DecrementRef(&source->Send[i].Slot->ref);
source->Send[i].Slot = NULL;
for(i = 0;i < num_sends;i++)
{
if(source->Send[i].Slot)
DecrementRef(&source->Send[i].Slot->ref);
source->Send[i].Slot = NULL;
}
al_free(source->Send);
source->Send = NULL;
}
}
static void UpdateSourceProps(ALsource *source, ALuint num_sends)
static void UpdateSourceProps(ALsource *source, ALsizei num_sends)
{
struct ALsourceProps *props;
size_t i;
ALsizei i;
/* Get an unused property container, or allocate a new one as needed. */
props = ATOMIC_LOAD(&source->FreeList, almemory_order_acquire);
@@ -2856,7 +2866,7 @@ static void UpdateSourceProps(ALsource *source, ALuint num_sends)
ATOMIC_STORE(&props->Direction[i], source->Direction[i], almemory_order_relaxed);
for(i = 0;i < 2;i++)
{
size_t j;
ALsizei j;
for(j = 0;j < 3;j++)
ATOMIC_STORE(&props->Orientation[i][j], source->Orientation[i][j],
almemory_order_relaxed);
@@ -2910,7 +2920,7 @@ static void UpdateSourceProps(ALsource *source, ALuint num_sends)
void UpdateAllSourceProps(ALCcontext *context)
{
ALuint num_sends = context->Device->NumAuxSends;
ALsizei num_sends = context->Device->NumAuxSends;
ALsizei pos;
for(pos = 0;pos < context->VoiceCount;pos++)
@@ -3390,13 +3400,14 @@ static ALboolean GetSampleOffset(ALsource *Source, ALuint *offset, ALuint *frac)
*/
ALvoid ReleaseALSources(ALCcontext *Context)
{
ALCdevice *device = Context->Device;
ALsizei pos;
for(pos = 0;pos < Context->SourceMap.size;pos++)
{
ALsource *temp = Context->SourceMap.values[pos];
Context->SourceMap.values[pos] = NULL;
DeinitSource(temp);
DeinitSource(temp, device->NumAuxSends);
FreeThunkEntry(temp->id);
memset(temp, 0, sizeof(*temp));