aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Alc/ALc.c57
-rw-r--r--Alc/ALu.c43
-rw-r--r--OpenAL32/Include/alSource.h57
-rw-r--r--OpenAL32/Include/alu.h61
-rw-r--r--OpenAL32/alSource.c68
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);
}
}