mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-07-13 23:54:35 +00:00
Revert "Updated SDL, Bullet and OpenAL soft libs"
This reverts commit 370161cfb1.
This commit is contained in:
parent
160dc00c07
commit
e7ee94428e
1102 changed files with 62741 additions and 204988 deletions
|
|
@ -145,8 +145,8 @@ typedef struct ALeffectslot {
|
|||
* * Channel 3 is OpenAL -Z * sqrt(3)
|
||||
* Consequently, effects that only want to work with mono input can use
|
||||
* channel 0 by itself. Effects that want multichannel can process the
|
||||
* ambisonics signal and make a B-Format source pan for first-order device
|
||||
* output (FOAOut).
|
||||
* ambisonics signal and make a B-Format pan (ComputeFirstOrderGains) for
|
||||
* first-order device output (FOAOut).
|
||||
*/
|
||||
alignas(16) ALfloat WetBuffer[MAX_EFFECT_CHANNELS][BUFFERSIZE];
|
||||
} ALeffectslot;
|
||||
|
|
@ -160,14 +160,12 @@ ALvoid ReleaseALAuxiliaryEffectSlots(ALCcontext *Context);
|
|||
|
||||
EffectStateFactory *NullStateFactory_getFactory(void);
|
||||
EffectStateFactory *ReverbStateFactory_getFactory(void);
|
||||
EffectStateFactory *AutowahStateFactory_getFactory(void);
|
||||
EffectStateFactory *ChorusStateFactory_getFactory(void);
|
||||
EffectStateFactory *CompressorStateFactory_getFactory(void);
|
||||
EffectStateFactory *DistortionStateFactory_getFactory(void);
|
||||
EffectStateFactory *EchoStateFactory_getFactory(void);
|
||||
EffectStateFactory *EqualizerStateFactory_getFactory(void);
|
||||
EffectStateFactory *FlangerStateFactory_getFactory(void);
|
||||
EffectStateFactory *FshifterStateFactory_getFactory(void);
|
||||
EffectStateFactory *ModulatorStateFactory_getFactory(void);
|
||||
EffectStateFactory *PshifterStateFactory_getFactory(void);
|
||||
|
||||
|
|
|
|||
|
|
@ -12,14 +12,12 @@ struct ALeffect;
|
|||
enum {
|
||||
EAXREVERB_EFFECT = 0,
|
||||
REVERB_EFFECT,
|
||||
AUTOWAH_EFFECT,
|
||||
CHORUS_EFFECT,
|
||||
COMPRESSOR_EFFECT,
|
||||
DISTORTION_EFFECT,
|
||||
ECHO_EFFECT,
|
||||
EQUALIZER_EFFECT,
|
||||
FLANGER_EFFECT,
|
||||
FSHIFTER_EFFECT,
|
||||
MODULATOR_EFFECT,
|
||||
PSHIFTER_EFFECT,
|
||||
DEDICATED_EFFECT,
|
||||
|
|
@ -35,7 +33,7 @@ struct EffectList {
|
|||
int type;
|
||||
ALenum val;
|
||||
};
|
||||
#define EFFECTLIST_SIZE 14
|
||||
#define EFFECTLIST_SIZE 12
|
||||
extern const struct EffectList EffectList[EFFECTLIST_SIZE];
|
||||
|
||||
|
||||
|
|
@ -61,14 +59,12 @@ const struct ALeffectVtable T##_vtable = { \
|
|||
|
||||
extern const struct ALeffectVtable ALeaxreverb_vtable;
|
||||
extern const struct ALeffectVtable ALreverb_vtable;
|
||||
extern const struct ALeffectVtable ALautowah_vtable;
|
||||
extern const struct ALeffectVtable ALchorus_vtable;
|
||||
extern const struct ALeffectVtable ALcompressor_vtable;
|
||||
extern const struct ALeffectVtable ALdistortion_vtable;
|
||||
extern const struct ALeffectVtable ALecho_vtable;
|
||||
extern const struct ALeffectVtable ALequalizer_vtable;
|
||||
extern const struct ALeffectVtable ALflanger_vtable;
|
||||
extern const struct ALeffectVtable ALfshifter_vtable;
|
||||
extern const struct ALeffectVtable ALmodulator_vtable;
|
||||
extern const struct ALeffectVtable ALnull_vtable;
|
||||
extern const struct ALeffectVtable ALpshifter_vtable;
|
||||
|
|
@ -105,13 +101,6 @@ typedef union ALeffectProps {
|
|||
ALfloat LFReference;
|
||||
} Reverb;
|
||||
|
||||
struct {
|
||||
ALfloat AttackTime;
|
||||
ALfloat ReleaseTime;
|
||||
ALfloat Resonance;
|
||||
ALfloat PeakGain;
|
||||
} Autowah;
|
||||
|
||||
struct {
|
||||
ALint Waveform;
|
||||
ALint Phase;
|
||||
|
|
@ -156,12 +145,6 @@ typedef union ALeffectProps {
|
|||
ALfloat HighGain;
|
||||
} Equalizer;
|
||||
|
||||
struct {
|
||||
ALfloat Frequency;
|
||||
ALint LeftDirection;
|
||||
ALint RightDirection;
|
||||
} Fshifter;
|
||||
|
||||
struct {
|
||||
ALfloat Frequency;
|
||||
ALfloat HighPassCutoff;
|
||||
|
|
|
|||
|
|
@ -115,25 +115,15 @@ typedef ALuint64SOFT ALuint64;
|
|||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef I64
|
||||
#if defined(_MSC_VER)
|
||||
#define I64(x) ((ALint64)(x##i64))
|
||||
#elif SIZEOF_LONG == 8
|
||||
#define I64(x) ((ALint64)(x##l))
|
||||
#elif SIZEOF_LONG_LONG == 8
|
||||
#define I64(x) ((ALint64)(x##ll))
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Define a CTZ64 macro (count trailing zeros, for 64-bit integers). The result
|
||||
* is *UNDEFINED* if the value is 0.
|
||||
*/
|
||||
#ifdef __GNUC__
|
||||
|
||||
#if SIZEOF_LONG == 8
|
||||
#define CTZ64 __builtin_ctzl
|
||||
#define CTZ64(x) __builtin_ctzl(x)
|
||||
#else
|
||||
#define CTZ64 __builtin_ctzll
|
||||
#define CTZ64(x) __builtin_ctzll(x)
|
||||
#endif
|
||||
|
||||
#elif defined(HAVE_BITSCANFORWARD64_INTRINSIC)
|
||||
|
|
@ -144,7 +134,7 @@ inline int msvc64_ctz64(ALuint64 v)
|
|||
_BitScanForward64(&idx, v);
|
||||
return (int)idx;
|
||||
}
|
||||
#define CTZ64 msvc64_ctz64
|
||||
#define CTZ64(x) msvc64_ctz64(x)
|
||||
|
||||
#elif defined(HAVE_BITSCANFORWARD_INTRINSIC)
|
||||
|
||||
|
|
@ -158,7 +148,7 @@ inline int msvc_ctz64(ALuint64 v)
|
|||
}
|
||||
return (int)idx;
|
||||
}
|
||||
#define CTZ64 msvc_ctz64
|
||||
#define CTZ64(x) msvc_ctz64(x)
|
||||
|
||||
#else
|
||||
|
||||
|
|
@ -181,18 +171,14 @@ inline int fallback_ctz64(ALuint64 value)
|
|||
{
|
||||
return fallback_popcnt64(~value & (value - 1));
|
||||
}
|
||||
#define CTZ64 fallback_ctz64
|
||||
#define CTZ64(x) fallback_ctz64(x)
|
||||
#endif
|
||||
|
||||
#if defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__)
|
||||
#define IS_LITTLE_ENDIAN (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
|
||||
#else
|
||||
static const union {
|
||||
ALuint u;
|
||||
ALubyte b[sizeof(ALuint)];
|
||||
} EndianTest = { 1 };
|
||||
#define IS_LITTLE_ENDIAN (EndianTest.b[0] == 1)
|
||||
#endif
|
||||
|
||||
#define COUNTOF(x) (sizeof(x) / sizeof(0[x]))
|
||||
|
||||
|
|
@ -263,7 +249,7 @@ inline ALint fastf2i(ALfloat f)
|
|||
#ifdef __SSE_MATH__
|
||||
__asm__("cvtss2si %1, %0" : "=r"(i) : "x"(f));
|
||||
#else
|
||||
__asm__ __volatile__("fistpl %0" : "=m"(i) : "t"(f) : "st");
|
||||
__asm__("flds %1\n fistps %0" : "=m"(i) : "m"(f));
|
||||
#endif
|
||||
return i;
|
||||
|
||||
|
|
@ -285,85 +271,8 @@ inline ALint fastf2i(ALfloat f)
|
|||
/* Converts float-to-int using standard behavior (truncation). */
|
||||
inline int float2int(float f)
|
||||
{
|
||||
#if ((defined(__GNUC__) || defined(__clang__)) && (defined(__i386__) || defined(__x86_64__)) && \
|
||||
!defined(__SSE_MATH__)) || (defined(_MSC_VER) && defined(_M_IX86_FP) && _M_IX86_FP == 0)
|
||||
ALint sign, shift, mant;
|
||||
union {
|
||||
ALfloat f;
|
||||
ALint i;
|
||||
} conv;
|
||||
|
||||
conv.f = f;
|
||||
sign = (conv.i>>31) | 1;
|
||||
shift = ((conv.i>>23)&0xff) - (127+23);
|
||||
|
||||
/* Over/underflow */
|
||||
if(UNLIKELY(shift >= 31 || shift < -23))
|
||||
return 0;
|
||||
|
||||
mant = (conv.i&0x7fffff) | 0x800000;
|
||||
if(LIKELY(shift < 0))
|
||||
return (mant >> -shift) * sign;
|
||||
return (mant << shift) * sign;
|
||||
|
||||
#else
|
||||
|
||||
/* TODO: Make a more efficient method for x87. */
|
||||
return (ALint)f;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Rounds a float to the nearest integral value, according to the current
|
||||
* rounding mode. This is essentially an inlined version of rintf, although
|
||||
* makes fewer promises (e.g. -0 or -0.25 rounded to 0 may result in +0).
|
||||
*/
|
||||
inline float fast_roundf(float f)
|
||||
{
|
||||
#if (defined(__GNUC__) || defined(__clang__)) && (defined(__i386__) || defined(__x86_64__)) && \
|
||||
!defined(__SSE_MATH__)
|
||||
|
||||
float out;
|
||||
__asm__ __volatile__("frndint" : "=t"(out) : "0"(f));
|
||||
return out;
|
||||
|
||||
#else
|
||||
|
||||
/* Integral limit, where sub-integral precision is not available for
|
||||
* floats.
|
||||
*/
|
||||
static const float ilim[2] = {
|
||||
8388608.0f /* 0x1.0p+23 */,
|
||||
-8388608.0f /* -0x1.0p+23 */
|
||||
};
|
||||
ALuint sign, expo;
|
||||
union {
|
||||
ALfloat f;
|
||||
ALuint i;
|
||||
} conv;
|
||||
|
||||
conv.f = f;
|
||||
sign = (conv.i>>31)&0x01;
|
||||
expo = (conv.i>>23)&0xff;
|
||||
|
||||
if(UNLIKELY(expo >= 150/*+23*/))
|
||||
{
|
||||
/* An exponent (base-2) of 23 or higher is incapable of sub-integral
|
||||
* precision, so it's already an integral value. We don't need to worry
|
||||
* about infinity or NaN here.
|
||||
*/
|
||||
return f;
|
||||
}
|
||||
/* Adding the integral limit to the value (with a matching sign) forces a
|
||||
* result that has no sub-integral precision, and is consequently forced to
|
||||
* round to an integral value. Removing the integral limit then restores
|
||||
* the initial value rounded to the integral. The compiler should not
|
||||
* optimize this out because of non-associative rules on floating-point
|
||||
* math (as long as you don't use -fassociative-math,
|
||||
* -funsafe-math-optimizations, -ffast-math, or -Ofast, in which case this
|
||||
* may break).
|
||||
*/
|
||||
f += ilim[sign];
|
||||
return f - ilim[sign];
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -582,7 +491,7 @@ typedef struct DistanceComp {
|
|||
*/
|
||||
#define BUFFERSIZE 2048
|
||||
|
||||
typedef struct MixParams {
|
||||
typedef struct DryMixParams {
|
||||
AmbiConfig Ambi;
|
||||
/* Number of coefficients in each Ambi.Coeffs to mix together (4 for first-
|
||||
* order, 9 for second-order, etc). If the count is 0, Ambi.Map is used
|
||||
|
|
@ -592,7 +501,17 @@ typedef struct MixParams {
|
|||
|
||||
ALfloat (*Buffer)[BUFFERSIZE];
|
||||
ALsizei NumChannels;
|
||||
} MixParams;
|
||||
ALsizei NumChannelsPerOrder[MAX_AMBI_ORDER+1];
|
||||
} DryMixParams;
|
||||
|
||||
typedef struct BFMixParams {
|
||||
AmbiConfig Ambi;
|
||||
/* Will only be 4 or 0. */
|
||||
ALsizei CoeffCount;
|
||||
|
||||
ALfloat (*Buffer)[BUFFERSIZE];
|
||||
ALsizei NumChannels;
|
||||
} BFMixParams;
|
||||
|
||||
typedef struct RealMixParams {
|
||||
enum Channel ChannelName[MAX_OUTPUT_CHANNELS];
|
||||
|
|
@ -622,8 +541,6 @@ struct ALCdevice_struct {
|
|||
enum AmbiLayout AmbiLayout;
|
||||
enum AmbiNorm AmbiScale;
|
||||
|
||||
ALCenum LimiterState;
|
||||
|
||||
al_string DeviceName;
|
||||
|
||||
ATOMIC(ALCenum) LastError;
|
||||
|
|
@ -678,17 +595,15 @@ struct ALCdevice_struct {
|
|||
|
||||
ALuint64 ClockBase;
|
||||
ALuint SamplesDone;
|
||||
ALuint FixedLatency;
|
||||
|
||||
/* Temp storage used for mixer processing. */
|
||||
alignas(16) ALfloat TempBuffer[4][BUFFERSIZE];
|
||||
|
||||
/* The "dry" path corresponds to the main output. */
|
||||
MixParams Dry;
|
||||
ALsizei NumChannelsPerOrder[MAX_AMBI_ORDER+1];
|
||||
DryMixParams Dry;
|
||||
|
||||
/* First-order ambisonics output, to be upsampled to the dry buffer if different. */
|
||||
MixParams FOAOut;
|
||||
BFMixParams FOAOut;
|
||||
|
||||
/* "Real" output, which will be written to the device buffer. May alias the
|
||||
* dry buffer.
|
||||
|
|
@ -753,35 +668,21 @@ struct ALCdevice_struct {
|
|||
|
||||
|
||||
enum {
|
||||
/* End event thread processing. */
|
||||
EventType_KillThread = 0,
|
||||
|
||||
/* User event types. */
|
||||
EventType_SourceStateChange = 1<<0,
|
||||
EventType_BufferCompleted = 1<<1,
|
||||
EventType_Error = 1<<2,
|
||||
EventType_Performance = 1<<3,
|
||||
EventType_Deprecated = 1<<4,
|
||||
EventType_Disconnected = 1<<5,
|
||||
|
||||
/* Internal events. */
|
||||
EventType_ReleaseEffectState = 65536,
|
||||
};
|
||||
|
||||
typedef struct AsyncEvent {
|
||||
unsigned int EnumType;
|
||||
union {
|
||||
char dummy;
|
||||
struct {
|
||||
ALenum type;
|
||||
ALuint id;
|
||||
ALuint param;
|
||||
ALchar msg[1008];
|
||||
} user;
|
||||
struct ALeffectState *EffectState;
|
||||
} u;
|
||||
ALenum Type;
|
||||
ALuint ObjectId;
|
||||
ALuint Param;
|
||||
ALchar Message[1008];
|
||||
} AsyncEvent;
|
||||
#define ASYNC_EVENT(t) { t, { 0 } }
|
||||
|
||||
struct ALCcontext_struct {
|
||||
RefCount ref;
|
||||
|
|
@ -834,6 +735,7 @@ struct ALCcontext_struct {
|
|||
|
||||
ATOMIC(struct ALeffectslotArray*) ActiveAuxSlots;
|
||||
|
||||
almtx_t EventThrdLock;
|
||||
althrd_t EventThread;
|
||||
alsem_t EventSem;
|
||||
struct ll_ringbuffer *AsyncEvents;
|
||||
|
|
@ -863,6 +765,9 @@ void ALCcontext_ProcessUpdates(ALCcontext *context);
|
|||
|
||||
void AllocateVoices(ALCcontext *context, ALsizei num_voices, ALsizei old_sends);
|
||||
|
||||
void AppendAllDevicesList(const ALCchar *name);
|
||||
void AppendCaptureDeviceList(const ALCchar *name);
|
||||
|
||||
|
||||
extern ALint RTPrioLevel;
|
||||
void SetRTPriority(void);
|
||||
|
|
@ -908,9 +813,6 @@ inline void UnlockEffectSlotList(ALCcontext *context)
|
|||
{ almtx_unlock(&context->EffectSlotLock); }
|
||||
|
||||
|
||||
int EventThread(void *arg);
|
||||
|
||||
|
||||
vector_al_string SearchDataFiles(const char *match, const char *subdir);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ extern enum Resampler ResamplerDefault;
|
|||
typedef struct BsincState {
|
||||
ALfloat sf; /* Scale interpolation factor. */
|
||||
ALsizei m; /* Coefficient count. */
|
||||
ALsizei l; /* Left coefficient offset. */
|
||||
ALint l; /* Left coefficient offset. */
|
||||
/* Filter coefficients, followed by the scale, phase, and scale-phase
|
||||
* delta coefficients. Starting at phase index 0, each subsequent phase
|
||||
* index follows contiguously.
|
||||
|
|
@ -430,35 +430,14 @@ void aluInitEffectPanning(struct ALeffectslot *slot);
|
|||
|
||||
void aluSelectPostProcess(ALCdevice *device);
|
||||
|
||||
/**
|
||||
* Calculates ambisonic encoder coefficients using the X, Y, and Z direction
|
||||
* components, which must represent a normalized (unit length) vector, and the
|
||||
* spread is the angular width of the sound (0...tau).
|
||||
*
|
||||
* NOTE: The components use ambisonic coordinates. As a result:
|
||||
*
|
||||
* Ambisonic Y = OpenAL -X
|
||||
* Ambisonic Z = OpenAL Y
|
||||
* Ambisonic X = OpenAL -Z
|
||||
*
|
||||
* The components are ordered such that OpenAL's X, Y, and Z are the first,
|
||||
* second, and third parameters respectively -- simply negate X and Z.
|
||||
*/
|
||||
void CalcAmbiCoeffs(const ALfloat y, const ALfloat z, const ALfloat x, const ALfloat spread,
|
||||
ALfloat coeffs[MAX_AMBI_COEFFS]);
|
||||
|
||||
/**
|
||||
* CalcDirectionCoeffs
|
||||
*
|
||||
* Calculates ambisonic coefficients based on an OpenAL direction vector. The
|
||||
* vector must be normalized (unit length), and the spread is the angular width
|
||||
* of the sound (0...tau).
|
||||
* Calculates ambisonic coefficients based on a direction vector. The vector
|
||||
* must be normalized (unit length), and the spread is the angular width of the
|
||||
* sound (0...tau).
|
||||
*/
|
||||
inline void CalcDirectionCoeffs(const ALfloat dir[3], ALfloat spread, ALfloat coeffs[MAX_AMBI_COEFFS])
|
||||
{
|
||||
/* Convert from OpenAL coords to Ambisonics. */
|
||||
CalcAmbiCoeffs(-dir[0], dir[1], -dir[2], spread, coeffs);
|
||||
}
|
||||
void CalcDirectionCoeffs(const ALfloat dir[3], ALfloat spread, ALfloat coeffs[MAX_AMBI_COEFFS]);
|
||||
|
||||
/**
|
||||
* CalcAngleCoeffs
|
||||
|
|
@ -469,40 +448,34 @@ inline void CalcDirectionCoeffs(const ALfloat dir[3], ALfloat spread, ALfloat co
|
|||
*/
|
||||
inline void CalcAngleCoeffs(ALfloat azimuth, ALfloat elevation, ALfloat spread, ALfloat coeffs[MAX_AMBI_COEFFS])
|
||||
{
|
||||
ALfloat x = -sinf(azimuth) * cosf(elevation);
|
||||
ALfloat y = sinf(elevation);
|
||||
ALfloat z = cosf(azimuth) * cosf(elevation);
|
||||
|
||||
CalcAmbiCoeffs(x, y, z, spread, coeffs);
|
||||
ALfloat dir[3] = {
|
||||
sinf(azimuth) * cosf(elevation),
|
||||
sinf(elevation),
|
||||
-cosf(azimuth) * cosf(elevation)
|
||||
};
|
||||
CalcDirectionCoeffs(dir, spread, coeffs);
|
||||
}
|
||||
|
||||
/**
|
||||
* ScaleAzimuthFront
|
||||
* CalcAnglePairwiseCoeffs
|
||||
*
|
||||
* Scales the given azimuth toward the side (+/- pi/2 radians) for positions in
|
||||
* front.
|
||||
* Calculates ambisonic coefficients based on azimuth and elevation. The
|
||||
* azimuth and elevation parameters are in radians, going right and up
|
||||
* respectively. This pairwise variant warps the result such that +30 azimuth
|
||||
* is full right, and -30 azimuth is full left.
|
||||
*/
|
||||
inline float ScaleAzimuthFront(float azimuth, float scale)
|
||||
{
|
||||
ALfloat sign = copysignf(1.0f, azimuth);
|
||||
if(!(fabsf(azimuth) > F_PI_2))
|
||||
return minf(fabsf(azimuth) * scale, F_PI_2) * sign;
|
||||
return azimuth;
|
||||
}
|
||||
void CalcAnglePairwiseCoeffs(ALfloat azimuth, ALfloat elevation, ALfloat spread, ALfloat coeffs[MAX_AMBI_COEFFS]);
|
||||
|
||||
|
||||
void ComputePanningGainsMC(const ChannelConfig *chancoeffs, ALsizei numchans, ALsizei numcoeffs, const ALfloat*restrict coeffs, ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]);
|
||||
void ComputePanningGainsBF(const BFChannelConfig *chanmap, ALsizei numchans, const ALfloat*restrict coeffs, ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]);
|
||||
|
||||
void ComputePanningGainsMC(const ChannelConfig *chancoeffs, ALsizei numchans, ALsizei numcoeffs, const ALfloat coeffs[MAX_AMBI_COEFFS], ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]);
|
||||
void ComputePanningGainsBF(const BFChannelConfig *chanmap, ALsizei numchans, const ALfloat coeffs[MAX_AMBI_COEFFS], ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]);
|
||||
/**
|
||||
* ComputePanGains
|
||||
* ComputeDryPanGains
|
||||
*
|
||||
* Computes panning gains using the given channel decoder coefficients and the
|
||||
* pre-calculated direction or angle coefficients. For B-Format sources, the
|
||||
* coeffs are a 'slice' of a transform matrix for the input channel, used to
|
||||
* scale and orient the sound samples.
|
||||
* pre-calculated direction or angle coefficients.
|
||||
*/
|
||||
inline void ComputePanGains(const MixParams *dry, const ALfloat*restrict coeffs, ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS])
|
||||
inline void ComputeDryPanGains(const DryMixParams *dry, const ALfloat coeffs[MAX_AMBI_COEFFS], ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS])
|
||||
{
|
||||
if(dry->CoeffCount > 0)
|
||||
ComputePanningGainsMC(dry->Ambi.Coeffs, dry->NumChannels, dry->CoeffCount,
|
||||
|
|
@ -511,6 +484,23 @@ inline void ComputePanGains(const MixParams *dry, const ALfloat*restrict coeffs,
|
|||
ComputePanningGainsBF(dry->Ambi.Map, dry->NumChannels, coeffs, ingain, gains);
|
||||
}
|
||||
|
||||
void ComputeFirstOrderGainsMC(const ChannelConfig *chancoeffs, ALsizei numchans, const ALfloat mtx[4], ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]);
|
||||
void ComputeFirstOrderGainsBF(const BFChannelConfig *chanmap, ALsizei numchans, const ALfloat mtx[4], ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]);
|
||||
/**
|
||||
* ComputeFirstOrderGains
|
||||
*
|
||||
* Sets channel gains for a first-order ambisonics input channel. The matrix is
|
||||
* a 1x4 'slice' of a transform matrix for the input channel, used to scale and
|
||||
* orient the sound samples.
|
||||
*/
|
||||
inline void ComputeFirstOrderGains(const BFMixParams *foa, const ALfloat mtx[4], ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS])
|
||||
{
|
||||
if(foa->CoeffCount > 0)
|
||||
ComputeFirstOrderGainsMC(foa->Ambi.Coeffs, foa->NumChannels, mtx, ingain, gains);
|
||||
else
|
||||
ComputeFirstOrderGainsBF(foa->Ambi.Map, foa->NumChannels, mtx, ingain, gains);
|
||||
}
|
||||
|
||||
|
||||
ALboolean MixSource(struct ALvoice *voice, ALuint SourceID, ALCcontext *Context, ALsizei SamplesToDo);
|
||||
|
||||
|
|
|
|||
|
|
@ -48,14 +48,12 @@ static const struct {
|
|||
{ AL_EFFECT_NULL, NullStateFactory_getFactory },
|
||||
{ AL_EFFECT_EAXREVERB, ReverbStateFactory_getFactory },
|
||||
{ AL_EFFECT_REVERB, ReverbStateFactory_getFactory },
|
||||
{ AL_EFFECT_AUTOWAH, AutowahStateFactory_getFactory },
|
||||
{ AL_EFFECT_CHORUS, ChorusStateFactory_getFactory },
|
||||
{ AL_EFFECT_COMPRESSOR, CompressorStateFactory_getFactory },
|
||||
{ AL_EFFECT_DISTORTION, DistortionStateFactory_getFactory },
|
||||
{ AL_EFFECT_ECHO, EchoStateFactory_getFactory },
|
||||
{ AL_EFFECT_EQUALIZER, EqualizerStateFactory_getFactory },
|
||||
{ AL_EFFECT_FLANGER, FlangerStateFactory_getFactory },
|
||||
{ AL_EFFECT_FREQUENCY_SHIFTER, FshifterStateFactory_getFactory },
|
||||
{ AL_EFFECT_RING_MODULATOR, ModulatorStateFactory_getFactory },
|
||||
{ AL_EFFECT_PITCH_SHIFTER, PshifterStateFactory_getFactory},
|
||||
{ AL_EFFECT_DEDICATED_DIALOGUE, DedicatedStateFactory_getFactory },
|
||||
|
|
@ -122,6 +120,12 @@ AL_API ALvoid AL_APIENTRY alGenAuxiliaryEffectSlots(ALsizei n, ALuint *effectslo
|
|||
|
||||
LockEffectSlotList(context);
|
||||
device = context->Device;
|
||||
if(device->AuxiliaryEffectSlotMax - VECTOR_SIZE(context->EffectSlotList) < (ALuint)n)
|
||||
{
|
||||
UnlockEffectSlotList(context);
|
||||
SETERR_GOTO(context, AL_OUT_OF_MEMORY, done, "Exceeding %u auxiliary effect slot limit",
|
||||
device->AuxiliaryEffectSlotMax);
|
||||
}
|
||||
for(cur = 0;cur < n;cur++)
|
||||
{
|
||||
ALeffectslotPtr *iter = VECTOR_BEGIN(context->EffectSlotList);
|
||||
|
|
@ -136,13 +140,6 @@ AL_API ALvoid AL_APIENTRY alGenAuxiliaryEffectSlots(ALsizei n, ALuint *effectslo
|
|||
}
|
||||
if(iter == end)
|
||||
{
|
||||
if(device->AuxiliaryEffectSlotMax == VECTOR_SIZE(context->EffectSlotList))
|
||||
{
|
||||
UnlockEffectSlotList(context);
|
||||
alDeleteAuxiliaryEffectSlots(cur, effectslots);
|
||||
SETERR_GOTO(context, AL_OUT_OF_MEMORY, done,
|
||||
"Exceeding %u auxiliary effect slot limit", device->AuxiliaryEffectSlotMax);
|
||||
}
|
||||
VECTOR_PUSH_BACK(context->EffectSlotList, NULL);
|
||||
iter = &VECTOR_BACK(context->EffectSlotList);
|
||||
}
|
||||
|
|
@ -753,9 +750,6 @@ void UpdateEffectSlotProps(ALeffectslot *slot, ALCcontext *context)
|
|||
/* If there was an unused update container, put it back in the
|
||||
* freelist.
|
||||
*/
|
||||
if(props->State)
|
||||
ALeffectState_DecRef(props->State);
|
||||
props->State = NULL;
|
||||
ATOMIC_REPLACE_HEAD(struct ALeffectslotProps*, &context->FreeEffectslotProps, props);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -38,14 +38,12 @@ extern inline ALboolean IsReverbEffect(ALenum type);
|
|||
const struct EffectList EffectList[EFFECTLIST_SIZE] = {
|
||||
{ "eaxreverb", EAXREVERB_EFFECT, AL_EFFECT_EAXREVERB },
|
||||
{ "reverb", REVERB_EFFECT, AL_EFFECT_REVERB },
|
||||
{ "autowah", AUTOWAH_EFFECT, AL_EFFECT_AUTOWAH },
|
||||
{ "chorus", CHORUS_EFFECT, AL_EFFECT_CHORUS },
|
||||
{ "compressor", COMPRESSOR_EFFECT, AL_EFFECT_COMPRESSOR },
|
||||
{ "distortion", DISTORTION_EFFECT, AL_EFFECT_DISTORTION },
|
||||
{ "echo", ECHO_EFFECT, AL_EFFECT_ECHO },
|
||||
{ "equalizer", EQUALIZER_EFFECT, AL_EFFECT_EQUALIZER },
|
||||
{ "flanger", FLANGER_EFFECT, AL_EFFECT_FLANGER },
|
||||
{ "fshifter", FSHIFTER_EFFECT, AL_EFFECT_FREQUENCY_SHIFTER },
|
||||
{ "modulator", MODULATOR_EFFECT, AL_EFFECT_RING_MODULATOR },
|
||||
{ "pshifter", PSHIFTER_EFFECT, AL_EFFECT_PITCH_SHIFTER },
|
||||
{ "dedicated", DEDICATED_EFFECT, AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT },
|
||||
|
|
@ -535,13 +533,6 @@ static void InitEffectParams(ALeffect *effect, ALenum type)
|
|||
effect->Props.Reverb.DecayHFLimit = AL_REVERB_DEFAULT_DECAY_HFLIMIT;
|
||||
effect->vtab = &ALreverb_vtable;
|
||||
break;
|
||||
case AL_EFFECT_AUTOWAH:
|
||||
effect->Props.Autowah.AttackTime = AL_AUTOWAH_DEFAULT_ATTACK_TIME;
|
||||
effect->Props.Autowah.ReleaseTime = AL_AUTOWAH_DEFAULT_RELEASE_TIME;
|
||||
effect->Props.Autowah.Resonance = AL_AUTOWAH_DEFAULT_RESONANCE;
|
||||
effect->Props.Autowah.PeakGain = AL_AUTOWAH_DEFAULT_PEAK_GAIN;
|
||||
effect->vtab = &ALautowah_vtable;
|
||||
break;
|
||||
case AL_EFFECT_CHORUS:
|
||||
effect->Props.Chorus.Waveform = AL_CHORUS_DEFAULT_WAVEFORM;
|
||||
effect->Props.Chorus.Phase = AL_CHORUS_DEFAULT_PHASE;
|
||||
|
|
@ -593,12 +584,6 @@ static void InitEffectParams(ALeffect *effect, ALenum type)
|
|||
effect->Props.Chorus.Delay = AL_FLANGER_DEFAULT_DELAY;
|
||||
effect->vtab = &ALflanger_vtable;
|
||||
break;
|
||||
case AL_EFFECT_FREQUENCY_SHIFTER:
|
||||
effect->Props.Fshifter.Frequency = AL_FREQUENCY_SHIFTER_DEFAULT_FREQUENCY;
|
||||
effect->Props.Fshifter.LeftDirection = AL_FREQUENCY_SHIFTER_DEFAULT_LEFT_DIRECTION;
|
||||
effect->Props.Fshifter.RightDirection = AL_FREQUENCY_SHIFTER_DEFAULT_RIGHT_DIRECTION;
|
||||
effect->vtab = &ALfshifter_vtable;
|
||||
break;
|
||||
case AL_EFFECT_RING_MODULATOR:
|
||||
effect->Props.Modulator.Frequency = AL_RING_MODULATOR_DEFAULT_FREQUENCY;
|
||||
effect->Props.Modulator.HighPassCutoff = AL_RING_MODULATOR_DEFAULT_HIGHPASS_CUTOFF;
|
||||
|
|
|
|||
|
|
@ -28,9 +28,6 @@
|
|||
#include "alError.h"
|
||||
|
||||
|
||||
#define FILTER_MIN_GAIN 0.0f
|
||||
#define FILTER_MAX_GAIN 4.0f /* +12dB */
|
||||
|
||||
extern inline void LockFilterList(ALCdevice *device);
|
||||
extern inline void UnlockFilterList(ALCdevice *device);
|
||||
|
||||
|
|
@ -350,7 +347,7 @@ static void ALlowpass_setParamf(ALfilter *filter, ALCcontext *context, ALenum pa
|
|||
switch(param)
|
||||
{
|
||||
case AL_LOWPASS_GAIN:
|
||||
if(!(val >= FILTER_MIN_GAIN && val <= FILTER_MAX_GAIN))
|
||||
if(!(val >= AL_LOWPASS_MIN_GAIN && val <= AL_LOWPASS_MAX_GAIN))
|
||||
SETERR_RETURN(context, AL_INVALID_VALUE,, "Low-pass gain %f out of range", val);
|
||||
filter->Gain = val;
|
||||
break;
|
||||
|
|
@ -403,7 +400,7 @@ static void ALhighpass_setParamf(ALfilter *filter, ALCcontext *context, ALenum p
|
|||
switch(param)
|
||||
{
|
||||
case AL_HIGHPASS_GAIN:
|
||||
if(!(val >= FILTER_MIN_GAIN && val <= FILTER_MAX_GAIN))
|
||||
if(!(val >= AL_HIGHPASS_MIN_GAIN && val <= AL_HIGHPASS_MAX_GAIN))
|
||||
SETERR_RETURN(context, AL_INVALID_VALUE,, "High-pass gain out of range");
|
||||
filter->Gain = val;
|
||||
break;
|
||||
|
|
@ -456,7 +453,7 @@ static void ALbandpass_setParamf(ALfilter *filter, ALCcontext *context, ALenum p
|
|||
switch(param)
|
||||
{
|
||||
case AL_BANDPASS_GAIN:
|
||||
if(!(val >= FILTER_MIN_GAIN && val <= FILTER_MAX_GAIN))
|
||||
if(!(val >= AL_BANDPASS_MIN_GAIN && val <= AL_BANDPASS_MAX_GAIN))
|
||||
SETERR_RETURN(context, AL_INVALID_VALUE,, "Band-pass gain out of range");
|
||||
filter->Gain = val;
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -229,16 +229,17 @@ static inline bool SourceShouldUpdate(ALsource *source, ALCcontext *context)
|
|||
/** Can only be called while the mixer is locked! */
|
||||
static void SendStateChangeEvent(ALCcontext *context, ALuint id, ALenum state)
|
||||
{
|
||||
AsyncEvent evt = ASYNC_EVENT(EventType_SourceStateChange);
|
||||
ALbitfieldSOFT enabledevt;
|
||||
AsyncEvent evt;
|
||||
|
||||
enabledevt = ATOMIC_LOAD(&context->EnabledEvts, almemory_order_acquire);
|
||||
if(!(enabledevt&EventType_SourceStateChange)) return;
|
||||
|
||||
evt.u.user.type = AL_EVENT_TYPE_SOURCE_STATE_CHANGED_SOFT;
|
||||
evt.u.user.id = id;
|
||||
evt.u.user.param = state;
|
||||
snprintf(evt.u.user.msg, sizeof(evt.u.user.msg), "Source ID %u state changed to %s", id,
|
||||
evt.EnumType = EventType_SourceStateChange;
|
||||
evt.Type = AL_EVENT_TYPE_SOURCE_STATE_CHANGED_SOFT;
|
||||
evt.ObjectId = id;
|
||||
evt.Param = state;
|
||||
snprintf(evt.Message, sizeof(evt.Message), "Source ID %u state changed to %s", id,
|
||||
(state==AL_INITIAL) ? "AL_INITIAL" :
|
||||
(state==AL_PLAYING) ? "AL_PLAYING" :
|
||||
(state==AL_PAUSED) ? "AL_PAUSED" :
|
||||
|
|
@ -1295,7 +1296,7 @@ static ALboolean GetSourcedv(ALsource *Source, ALCcontext *Context, SourceProp p
|
|||
*/
|
||||
values[0] = GetSourceSecOffset(Source, Context, &srcclock);
|
||||
almtx_lock(&device->BackendLock);
|
||||
clocktime = GetClockLatency(device);
|
||||
clocktime = V0(device->Backend,getClockLatency)();
|
||||
almtx_unlock(&device->BackendLock);
|
||||
if(srcclock == (ALuint64)clocktime.ClockTime)
|
||||
values[1] = (ALdouble)clocktime.Latency / 1000000000.0;
|
||||
|
|
@ -1559,7 +1560,7 @@ static ALboolean GetSourcei64v(ALsource *Source, ALCcontext *Context, SourceProp
|
|||
*/
|
||||
values[0] = GetSourceSampleOffset(Source, Context, &srcclock);
|
||||
almtx_lock(&device->BackendLock);
|
||||
clocktime = GetClockLatency(device);
|
||||
clocktime = V0(device->Backend,getClockLatency)();
|
||||
almtx_unlock(&device->BackendLock);
|
||||
if(srcclock == (ALuint64)clocktime.ClockTime)
|
||||
values[1] = clocktime.Latency;
|
||||
|
|
@ -2825,121 +2826,6 @@ done:
|
|||
ALCcontext_DecRef(context);
|
||||
}
|
||||
|
||||
AL_API void AL_APIENTRY alSourceQueueBufferLayersSOFT(ALuint src, ALsizei nb, const ALuint *buffers)
|
||||
{
|
||||
ALCdevice *device;
|
||||
ALCcontext *context;
|
||||
ALbufferlistitem *BufferListStart;
|
||||
ALbufferlistitem *BufferList;
|
||||
ALbuffer *BufferFmt = NULL;
|
||||
ALsource *source;
|
||||
ALsizei i;
|
||||
|
||||
if(nb == 0)
|
||||
return;
|
||||
|
||||
context = GetContextRef();
|
||||
if(!context) return;
|
||||
|
||||
device = context->Device;
|
||||
|
||||
LockSourceList(context);
|
||||
if(!(nb >= 0 && nb < 16))
|
||||
SETERR_GOTO(context, AL_INVALID_VALUE, done, "Queueing %d buffer layers", nb);
|
||||
if((source=LookupSource(context, src)) == NULL)
|
||||
SETERR_GOTO(context, AL_INVALID_NAME, done, "Invalid source ID %u", src);
|
||||
|
||||
if(source->SourceType == AL_STATIC)
|
||||
{
|
||||
/* Can't queue on a Static Source */
|
||||
SETERR_GOTO(context, AL_INVALID_OPERATION, done, "Queueing onto static source %u", src);
|
||||
}
|
||||
|
||||
/* Check for a valid Buffer, for its frequency and format */
|
||||
BufferList = source->queue;
|
||||
while(BufferList)
|
||||
{
|
||||
for(i = 0;i < BufferList->num_buffers;i++)
|
||||
{
|
||||
if((BufferFmt=BufferList->buffers[i]) != NULL)
|
||||
break;
|
||||
}
|
||||
if(BufferFmt) break;
|
||||
BufferList = ATOMIC_LOAD(&BufferList->next, almemory_order_relaxed);
|
||||
}
|
||||
|
||||
LockBufferList(device);
|
||||
BufferListStart = al_calloc(DEF_ALIGN, FAM_SIZE(ALbufferlistitem, buffers, nb));
|
||||
BufferList = BufferListStart;
|
||||
ATOMIC_INIT(&BufferList->next, NULL);
|
||||
BufferList->max_samples = 0;
|
||||
BufferList->num_buffers = 0;
|
||||
for(i = 0;i < nb;i++)
|
||||
{
|
||||
ALbuffer *buffer = NULL;
|
||||
if(buffers[i] && (buffer=LookupBuffer(device, buffers[i])) == NULL)
|
||||
SETERR_GOTO(context, AL_INVALID_NAME, buffer_error, "Queueing invalid buffer ID %u",
|
||||
buffers[i]);
|
||||
|
||||
BufferList->buffers[BufferList->num_buffers++] = buffer;
|
||||
if(!buffer) continue;
|
||||
|
||||
IncrementRef(&buffer->ref);
|
||||
|
||||
BufferList->max_samples = maxi(BufferList->max_samples, buffer->SampleLen);
|
||||
|
||||
if(buffer->MappedAccess != 0 && !(buffer->MappedAccess&AL_MAP_PERSISTENT_BIT_SOFT))
|
||||
SETERR_GOTO(context, AL_INVALID_OPERATION, buffer_error,
|
||||
"Queueing non-persistently mapped buffer %u", buffer->id);
|
||||
|
||||
if(BufferFmt == NULL)
|
||||
BufferFmt = buffer;
|
||||
else if(BufferFmt->Frequency != buffer->Frequency ||
|
||||
BufferFmt->FmtChannels != buffer->FmtChannels ||
|
||||
BufferFmt->OriginalType != buffer->OriginalType)
|
||||
{
|
||||
alSetError(context, AL_INVALID_OPERATION, "Queueing buffer with mismatched format");
|
||||
|
||||
buffer_error:
|
||||
/* A buffer failed (invalid ID or format), so unlock and release
|
||||
* each buffer we had. */
|
||||
while(BufferListStart)
|
||||
{
|
||||
ALbufferlistitem *next = ATOMIC_LOAD(&BufferListStart->next,
|
||||
almemory_order_relaxed);
|
||||
for(i = 0;i < BufferListStart->num_buffers;i++)
|
||||
{
|
||||
if((buffer=BufferListStart->buffers[i]) != NULL)
|
||||
DecrementRef(&buffer->ref);
|
||||
}
|
||||
al_free(BufferListStart);
|
||||
BufferListStart = next;
|
||||
}
|
||||
UnlockBufferList(device);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
/* All buffers good. */
|
||||
UnlockBufferList(device);
|
||||
|
||||
/* Source is now streaming */
|
||||
source->SourceType = AL_STREAMING;
|
||||
|
||||
if(!(BufferList=source->queue))
|
||||
source->queue = BufferListStart;
|
||||
else
|
||||
{
|
||||
ALbufferlistitem *next;
|
||||
while((next=ATOMIC_LOAD(&BufferList->next, almemory_order_relaxed)) != NULL)
|
||||
BufferList = next;
|
||||
ATOMIC_STORE(&BufferList->next, BufferListStart, almemory_order_release);
|
||||
}
|
||||
|
||||
done:
|
||||
UnlockSourceList(context);
|
||||
ALCcontext_DecRef(context);
|
||||
}
|
||||
|
||||
AL_API ALvoid AL_APIENTRY alSourceUnqueueBuffers(ALuint src, ALsizei nb, ALuint *buffers)
|
||||
{
|
||||
ALCcontext *context;
|
||||
|
|
|
|||
|
|
@ -6,16 +6,19 @@
|
|||
#include "AL/alext.h"
|
||||
#include "alMain.h"
|
||||
#include "alError.h"
|
||||
#include "alAuxEffectSlot.h"
|
||||
#include "ringbuffer.h"
|
||||
|
||||
|
||||
int EventThread(void *arg)
|
||||
static int EventThread(void *arg)
|
||||
{
|
||||
ALCcontext *context = arg;
|
||||
bool quitnow = false;
|
||||
|
||||
while(!quitnow)
|
||||
/* Clear all pending posts on the semaphore. */
|
||||
while(alsem_trywait(&context->EventSem) == althrd_success)
|
||||
{
|
||||
}
|
||||
|
||||
while(1)
|
||||
{
|
||||
ALbitfieldSOFT enabledevts;
|
||||
AsyncEvent evt;
|
||||
|
|
@ -25,24 +28,14 @@ int EventThread(void *arg)
|
|||
alsem_wait(&context->EventSem);
|
||||
continue;
|
||||
}
|
||||
if(!evt.EnumType)
|
||||
break;
|
||||
|
||||
almtx_lock(&context->EventCbLock);
|
||||
do {
|
||||
quitnow = evt.EnumType == EventType_KillThread;
|
||||
if(quitnow) break;
|
||||
|
||||
if(evt.EnumType == EventType_ReleaseEffectState)
|
||||
{
|
||||
ALeffectState_DecRef(evt.u.EffectState);
|
||||
continue;
|
||||
}
|
||||
|
||||
enabledevts = ATOMIC_LOAD(&context->EnabledEvts, almemory_order_acquire);
|
||||
if(context->EventCb && (enabledevts&evt.EnumType) == evt.EnumType)
|
||||
context->EventCb(evt.u.user.type, evt.u.user.id, evt.u.user.param,
|
||||
(ALsizei)strlen(evt.u.user.msg), evt.u.user.msg, context->EventParam
|
||||
);
|
||||
} while(ll_ringbuffer_read(context->AsyncEvents, (char*)&evt, 1) != 0);
|
||||
enabledevts = ATOMIC_LOAD(&context->EnabledEvts, almemory_order_acquire);
|
||||
if(context->EventCb && (enabledevts&evt.EnumType) == evt.EnumType)
|
||||
context->EventCb(evt.Type, evt.ObjectId, evt.Param, (ALsizei)strlen(evt.Message),
|
||||
evt.Message, context->EventParam);
|
||||
almtx_unlock(&context->EventCbLock);
|
||||
}
|
||||
return 0;
|
||||
|
|
@ -53,6 +46,7 @@ AL_API void AL_APIENTRY alEventControlSOFT(ALsizei count, const ALenum *types, A
|
|||
ALCcontext *context;
|
||||
ALbitfieldSOFT enabledevts;
|
||||
ALbitfieldSOFT flags = 0;
|
||||
bool isrunning;
|
||||
ALsizei i;
|
||||
|
||||
context = GetContextRef();
|
||||
|
|
@ -80,9 +74,13 @@ AL_API void AL_APIENTRY alEventControlSOFT(ALsizei count, const ALenum *types, A
|
|||
SETERR_GOTO(context, AL_INVALID_ENUM, done, "Invalid event type 0x%04x", types[i]);
|
||||
}
|
||||
|
||||
almtx_lock(&context->EventThrdLock);
|
||||
if(enable)
|
||||
{
|
||||
if(!context->AsyncEvents)
|
||||
context->AsyncEvents = ll_ringbuffer_create(63, sizeof(AsyncEvent), false);
|
||||
enabledevts = ATOMIC_LOAD(&context->EnabledEvts, almemory_order_relaxed);
|
||||
isrunning = !!enabledevts;
|
||||
while(ATOMIC_COMPARE_EXCHANGE_WEAK(&context->EnabledEvts, &enabledevts, enabledevts|flags,
|
||||
almemory_order_acq_rel, almemory_order_acquire) == 0)
|
||||
{
|
||||
|
|
@ -90,20 +88,35 @@ AL_API void AL_APIENTRY alEventControlSOFT(ALsizei count, const ALenum *types, A
|
|||
* just try again.
|
||||
*/
|
||||
}
|
||||
if(!isrunning && flags)
|
||||
althrd_create(&context->EventThread, EventThread, context);
|
||||
}
|
||||
else
|
||||
{
|
||||
enabledevts = ATOMIC_LOAD(&context->EnabledEvts, almemory_order_relaxed);
|
||||
isrunning = !!enabledevts;
|
||||
while(ATOMIC_COMPARE_EXCHANGE_WEAK(&context->EnabledEvts, &enabledevts, enabledevts&~flags,
|
||||
almemory_order_acq_rel, almemory_order_acquire) == 0)
|
||||
{
|
||||
}
|
||||
/* Wait to ensure the event handler sees the changed flags before
|
||||
* returning.
|
||||
*/
|
||||
almtx_lock(&context->EventCbLock);
|
||||
almtx_unlock(&context->EventCbLock);
|
||||
if(isrunning && !(enabledevts&~flags))
|
||||
{
|
||||
static const AsyncEvent kill_evt = { 0 };
|
||||
while(ll_ringbuffer_write(context->AsyncEvents, (const char*)&kill_evt, 1) == 0)
|
||||
althrd_yield();
|
||||
alsem_post(&context->EventSem);
|
||||
althrd_join(context->EventThread, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Wait to ensure the event handler sees the changed flags before
|
||||
* returning.
|
||||
*/
|
||||
almtx_lock(&context->EventCbLock);
|
||||
almtx_unlock(&context->EventCbLock);
|
||||
}
|
||||
}
|
||||
almtx_unlock(&context->EventThrdLock);
|
||||
|
||||
done:
|
||||
ALCcontext_DecRef(context);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue