mirror of
https://github.com/love2d/megasource.git
synced 2026-08-20 04:30:45 +02:00
Update OpenAL Soft to 1.18.2
This commit is contained in:
@@ -4,6 +4,7 @@
|
||||
#include "alMain.h"
|
||||
#include "alEffect.h"
|
||||
|
||||
#include "atomic.h"
|
||||
#include "align.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
@@ -14,15 +15,22 @@ struct ALeffectStateVtable;
|
||||
struct ALeffectslot;
|
||||
|
||||
typedef struct ALeffectState {
|
||||
RefCount Ref;
|
||||
const struct ALeffectStateVtable *vtbl;
|
||||
|
||||
ALfloat (*OutBuffer)[BUFFERSIZE];
|
||||
ALsizei OutChannels;
|
||||
} ALeffectState;
|
||||
|
||||
void ALeffectState_Construct(ALeffectState *state);
|
||||
void ALeffectState_Destruct(ALeffectState *state);
|
||||
|
||||
struct ALeffectStateVtable {
|
||||
void (*const Destruct)(ALeffectState *state);
|
||||
|
||||
ALboolean (*const deviceUpdate)(ALeffectState *state, ALCdevice *device);
|
||||
void (*const update)(ALeffectState *state, ALCdevice *device, const struct ALeffectslot *slot);
|
||||
void (*const process)(ALeffectState *state, ALuint samplesToDo, const ALfloat *restrict samplesIn, ALfloat (*restrict samplesOut)[BUFFERSIZE], ALuint numChannels);
|
||||
void (*const update)(ALeffectState *state, const ALCdevice *device, const struct ALeffectslot *slot, const union ALeffectProps *props);
|
||||
void (*const process)(ALeffectState *state, ALsizei samplesToDo, const ALfloat (*restrict samplesIn)[BUFFERSIZE], ALfloat (*restrict samplesOut)[BUFFERSIZE], ALsizei numChannels);
|
||||
|
||||
void (*const Delete)(void *ptr);
|
||||
};
|
||||
@@ -30,8 +38,8 @@ struct ALeffectStateVtable {
|
||||
#define DEFINE_ALEFFECTSTATE_VTABLE(T) \
|
||||
DECLARE_THUNK(T, ALeffectState, void, Destruct) \
|
||||
DECLARE_THUNK1(T, ALeffectState, ALboolean, deviceUpdate, ALCdevice*) \
|
||||
DECLARE_THUNK2(T, ALeffectState, void, update, ALCdevice*, const ALeffectslot*) \
|
||||
DECLARE_THUNK4(T, ALeffectState, void, process, ALuint, const ALfloat*restrict, ALfloatBUFFERSIZE*restrict, ALuint) \
|
||||
DECLARE_THUNK3(T, ALeffectState, void, update, const ALCdevice*, const ALeffectslot*, const ALeffectProps*) \
|
||||
DECLARE_THUNK4(T, ALeffectState, void, process, ALsizei, const ALfloatBUFFERSIZE*restrict, ALfloatBUFFERSIZE*restrict, ALsizei) \
|
||||
static void T##_ALeffectState_Delete(void *ptr) \
|
||||
{ return T##_Delete(STATIC_UPCAST(T, ALeffectState, (ALeffectState*)ptr)); } \
|
||||
\
|
||||
@@ -64,36 +72,101 @@ static const struct ALeffectStateFactoryVtable T##_ALeffectStateFactory_vtable =
|
||||
}
|
||||
|
||||
|
||||
#define MAX_EFFECT_CHANNELS (4)
|
||||
|
||||
|
||||
struct ALeffectslotArray {
|
||||
ALsizei count;
|
||||
struct ALeffectslot *slot[];
|
||||
};
|
||||
|
||||
|
||||
struct ALeffectslotProps {
|
||||
ALfloat Gain;
|
||||
ALboolean AuxSendAuto;
|
||||
|
||||
ALenum Type;
|
||||
ALeffectProps Props;
|
||||
|
||||
ALeffectState *State;
|
||||
|
||||
ATOMIC(struct ALeffectslotProps*) next;
|
||||
};
|
||||
|
||||
|
||||
typedef struct ALeffectslot {
|
||||
ALenum EffectType;
|
||||
ALeffectProps EffectProps;
|
||||
ALfloat Gain;
|
||||
ALboolean AuxSendAuto;
|
||||
|
||||
volatile ALfloat Gain;
|
||||
volatile ALboolean AuxSendAuto;
|
||||
struct {
|
||||
ALenum Type;
|
||||
ALeffectProps Props;
|
||||
|
||||
ATOMIC(ALenum) NeedsUpdate;
|
||||
ALeffectState *EffectState;
|
||||
ALeffectState *State;
|
||||
} Effect;
|
||||
|
||||
alignas(16) ALfloat WetBuffer[1][BUFFERSIZE];
|
||||
ATOMIC_FLAG PropsClean;
|
||||
|
||||
RefCount ref;
|
||||
|
||||
ATOMIC(struct ALeffectslotProps*) Update;
|
||||
ATOMIC(struct ALeffectslotProps*) FreeList;
|
||||
|
||||
struct {
|
||||
ALfloat Gain;
|
||||
ALboolean AuxSendAuto;
|
||||
|
||||
ALenum EffectType;
|
||||
ALeffectState *EffectState;
|
||||
|
||||
ALfloat RoomRolloff; /* Added to the source's room rolloff, not multiplied. */
|
||||
ALfloat DecayTime;
|
||||
ALfloat DecayHFRatio;
|
||||
ALboolean DecayHFLimit;
|
||||
ALfloat AirAbsorptionGainHF;
|
||||
} Params;
|
||||
|
||||
/* Self ID */
|
||||
ALuint id;
|
||||
|
||||
ALsizei NumChannels;
|
||||
BFChannelConfig ChanMap[MAX_EFFECT_CHANNELS];
|
||||
/* Wet buffer configuration is ACN channel order with N3D scaling:
|
||||
* * Channel 0 is the unattenuated mono signal.
|
||||
* * Channel 1 is OpenAL -X
|
||||
* * Channel 2 is OpenAL Y
|
||||
* * Channel 3 is OpenAL -Z
|
||||
* 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 pan (ComputeFirstOrderGains) for
|
||||
* first-order device output (FOAOut).
|
||||
*/
|
||||
alignas(16) ALfloat WetBuffer[MAX_EFFECT_CHANNELS][BUFFERSIZE];
|
||||
} ALeffectslot;
|
||||
|
||||
inline void LockEffectSlotsRead(ALCcontext *context)
|
||||
{ LockUIntMapRead(&context->EffectSlotMap); }
|
||||
inline void UnlockEffectSlotsRead(ALCcontext *context)
|
||||
{ UnlockUIntMapRead(&context->EffectSlotMap); }
|
||||
inline void LockEffectSlotsWrite(ALCcontext *context)
|
||||
{ LockUIntMapWrite(&context->EffectSlotMap); }
|
||||
inline void UnlockEffectSlotsWrite(ALCcontext *context)
|
||||
{ UnlockUIntMapWrite(&context->EffectSlotMap); }
|
||||
|
||||
inline struct ALeffectslot *LookupEffectSlot(ALCcontext *context, ALuint id)
|
||||
{ return (struct ALeffectslot*)LookupUIntMapKey(&context->EffectSlotMap, id); }
|
||||
{ return (struct ALeffectslot*)LookupUIntMapKeyNoLock(&context->EffectSlotMap, id); }
|
||||
inline struct ALeffectslot *RemoveEffectSlot(ALCcontext *context, ALuint id)
|
||||
{ return (struct ALeffectslot*)RemoveUIntMapKey(&context->EffectSlotMap, id); }
|
||||
{ return (struct ALeffectslot*)RemoveUIntMapKeyNoLock(&context->EffectSlotMap, id); }
|
||||
|
||||
ALenum InitEffectSlot(ALeffectslot *slot);
|
||||
void DeinitEffectSlot(ALeffectslot *slot);
|
||||
void UpdateEffectSlotProps(ALeffectslot *slot);
|
||||
void UpdateAllEffectSlotProps(ALCcontext *context);
|
||||
ALvoid ReleaseALAuxiliaryEffectSlots(ALCcontext *Context);
|
||||
|
||||
|
||||
ALeffectStateFactory *ALnullStateFactory_getFactory(void);
|
||||
ALeffectStateFactory *ALreverbStateFactory_getFactory(void);
|
||||
ALeffectStateFactory *ALautowahStateFactory_getFactory(void);
|
||||
ALeffectStateFactory *ALchorusStateFactory_getFactory(void);
|
||||
ALeffectStateFactory *ALcompressorStateFactory_getFactory(void);
|
||||
ALeffectStateFactory *ALdistortionStateFactory_getFactory(void);
|
||||
|
||||
@@ -17,28 +17,26 @@ enum UserFmtType {
|
||||
UserFmtUInt = AL_UNSIGNED_INT_SOFT,
|
||||
UserFmtFloat = AL_FLOAT_SOFT,
|
||||
UserFmtDouble = AL_DOUBLE_SOFT,
|
||||
UserFmtByte3 = AL_BYTE3_SOFT,
|
||||
UserFmtUByte3 = AL_UNSIGNED_BYTE3_SOFT,
|
||||
UserFmtMulaw,
|
||||
UserFmtAlaw,
|
||||
UserFmtMulaw = AL_MULAW_SOFT,
|
||||
UserFmtAlaw = 0x10000000,
|
||||
UserFmtIMA4,
|
||||
UserFmtMSADPCM,
|
||||
};
|
||||
enum UserFmtChannels {
|
||||
UserFmtMono = AL_MONO_SOFT,
|
||||
UserFmtStereo = AL_STEREO_SOFT,
|
||||
UserFmtRear = AL_REAR_SOFT,
|
||||
UserFmtQuad = AL_QUAD_SOFT,
|
||||
UserFmtX51 = AL_5POINT1_SOFT, /* (WFX order) */
|
||||
UserFmtX61 = AL_6POINT1_SOFT, /* (WFX order) */
|
||||
UserFmtX71 = AL_7POINT1_SOFT, /* (WFX order) */
|
||||
UserFmtBFormat2D = 0x10000000, /* WXY */
|
||||
UserFmtBFormat3D, /* WXYZ */
|
||||
UserFmtMono = AL_MONO_SOFT,
|
||||
UserFmtStereo = AL_STEREO_SOFT,
|
||||
UserFmtRear = AL_REAR_SOFT,
|
||||
UserFmtQuad = AL_QUAD_SOFT,
|
||||
UserFmtX51 = AL_5POINT1_SOFT, /* (WFX order) */
|
||||
UserFmtX61 = AL_6POINT1_SOFT, /* (WFX order) */
|
||||
UserFmtX71 = AL_7POINT1_SOFT, /* (WFX order) */
|
||||
UserFmtBFormat2D = AL_BFORMAT2D_SOFT, /* WXY */
|
||||
UserFmtBFormat3D = AL_BFORMAT3D_SOFT, /* WXYZ */
|
||||
};
|
||||
|
||||
ALuint BytesFromUserFmt(enum UserFmtType type) DECL_CONST;
|
||||
ALuint ChannelsFromUserFmt(enum UserFmtChannels chans) DECL_CONST;
|
||||
inline ALuint FrameSizeFromUserFmt(enum UserFmtChannels chans, enum UserFmtType type)
|
||||
ALsizei BytesFromUserFmt(enum UserFmtType type);
|
||||
ALsizei ChannelsFromUserFmt(enum UserFmtChannels chans);
|
||||
inline ALsizei FrameSizeFromUserFmt(enum UserFmtChannels chans, enum UserFmtType type)
|
||||
{
|
||||
return ChannelsFromUserFmt(chans) * BytesFromUserFmt(type);
|
||||
}
|
||||
@@ -63,9 +61,9 @@ enum FmtChannels {
|
||||
};
|
||||
#define MAX_INPUT_CHANNELS (8)
|
||||
|
||||
ALuint BytesFromFmt(enum FmtType type) DECL_CONST;
|
||||
ALuint ChannelsFromFmt(enum FmtChannels chans) DECL_CONST;
|
||||
inline ALuint FrameSizeFromFmt(enum FmtChannels chans, enum FmtType type)
|
||||
ALsizei BytesFromFmt(enum FmtType type);
|
||||
ALsizei ChannelsFromFmt(enum FmtChannels chans);
|
||||
inline ALsizei FrameSizeFromFmt(enum FmtChannels chans, enum FmtType type)
|
||||
{
|
||||
return ChannelsFromFmt(chans) * BytesFromFmt(type);
|
||||
}
|
||||
@@ -80,14 +78,15 @@ typedef struct ALbuffer {
|
||||
|
||||
enum FmtChannels FmtChannels;
|
||||
enum FmtType FmtType;
|
||||
ALuint BytesAlloc;
|
||||
|
||||
enum UserFmtChannels OriginalChannels;
|
||||
enum UserFmtType OriginalType;
|
||||
ALsizei OriginalSize;
|
||||
ALsizei OriginalAlign;
|
||||
|
||||
ALsizei LoopStart;
|
||||
ALsizei LoopEnd;
|
||||
ALsizei LoopStart;
|
||||
ALsizei LoopEnd;
|
||||
|
||||
ATOMIC(ALsizei) UnpackAlign;
|
||||
ATOMIC(ALsizei) PackAlign;
|
||||
@@ -106,10 +105,19 @@ void DeleteBuffer(ALCdevice *device, ALbuffer *buffer);
|
||||
|
||||
ALenum LoadData(ALbuffer *buffer, ALuint freq, ALenum NewFormat, ALsizei frames, enum UserFmtChannels SrcChannels, enum UserFmtType SrcType, const ALvoid *data, ALsizei align, ALboolean storesrc);
|
||||
|
||||
inline void LockBuffersRead(ALCdevice *device)
|
||||
{ LockUIntMapRead(&device->BufferMap); }
|
||||
inline void UnlockBuffersRead(ALCdevice *device)
|
||||
{ UnlockUIntMapRead(&device->BufferMap); }
|
||||
inline void LockBuffersWrite(ALCdevice *device)
|
||||
{ LockUIntMapWrite(&device->BufferMap); }
|
||||
inline void UnlockBuffersWrite(ALCdevice *device)
|
||||
{ UnlockUIntMapWrite(&device->BufferMap); }
|
||||
|
||||
inline struct ALbuffer *LookupBuffer(ALCdevice *device, ALuint id)
|
||||
{ return (struct ALbuffer*)LookupUIntMapKey(&device->BufferMap, id); }
|
||||
{ return (struct ALbuffer*)LookupUIntMapKeyNoLock(&device->BufferMap, id); }
|
||||
inline struct ALbuffer *RemoveBuffer(ALCdevice *device, ALuint id)
|
||||
{ return (struct ALbuffer*)RemoveUIntMapKey(&device->BufferMap, id); }
|
||||
{ return (struct ALbuffer*)RemoveUIntMapKeyNoLock(&device->BufferMap, id); }
|
||||
|
||||
ALvoid ReleaseALBuffers(ALCdevice *device);
|
||||
|
||||
|
||||
@@ -10,17 +10,16 @@ extern "C" {
|
||||
struct ALeffect;
|
||||
|
||||
enum {
|
||||
EAXREVERB = 0,
|
||||
REVERB,
|
||||
AUTOWAH,
|
||||
CHORUS,
|
||||
COMPRESSOR,
|
||||
DISTORTION,
|
||||
ECHO,
|
||||
EQUALIZER,
|
||||
FLANGER,
|
||||
MODULATOR,
|
||||
DEDICATED,
|
||||
AL__EAXREVERB = 0,
|
||||
AL__REVERB,
|
||||
AL__CHORUS,
|
||||
AL__COMPRESSOR,
|
||||
AL__DISTORTION,
|
||||
AL__ECHO,
|
||||
AL__EQUALIZER,
|
||||
AL__FLANGER,
|
||||
AL__MODULATOR,
|
||||
AL__DEDICATED,
|
||||
|
||||
MAX_EFFECTS
|
||||
};
|
||||
@@ -51,7 +50,6 @@ 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;
|
||||
@@ -93,13 +91,6 @@ typedef union ALeffectProps {
|
||||
ALfloat LFReference;
|
||||
} Reverb;
|
||||
|
||||
struct {
|
||||
ALfloat AttackTime;
|
||||
ALfloat ReleaseTime;
|
||||
ALfloat PeakGain;
|
||||
ALfloat Resonance;
|
||||
} Autowah;
|
||||
|
||||
struct {
|
||||
ALint Waveform;
|
||||
ALint Phase;
|
||||
@@ -176,10 +167,19 @@ typedef struct ALeffect {
|
||||
ALuint id;
|
||||
} ALeffect;
|
||||
|
||||
inline void LockEffectsRead(ALCdevice *device)
|
||||
{ LockUIntMapRead(&device->EffectMap); }
|
||||
inline void UnlockEffectsRead(ALCdevice *device)
|
||||
{ UnlockUIntMapRead(&device->EffectMap); }
|
||||
inline void LockEffectsWrite(ALCdevice *device)
|
||||
{ LockUIntMapWrite(&device->EffectMap); }
|
||||
inline void UnlockEffectsWrite(ALCdevice *device)
|
||||
{ UnlockUIntMapWrite(&device->EffectMap); }
|
||||
|
||||
inline struct ALeffect *LookupEffect(ALCdevice *device, ALuint id)
|
||||
{ return (struct ALeffect*)LookupUIntMapKey(&device->EffectMap, id); }
|
||||
{ return (struct ALeffect*)LookupUIntMapKeyNoLock(&device->EffectMap, id); }
|
||||
inline struct ALeffect *RemoveEffect(ALCdevice *device, ALuint id)
|
||||
{ return (struct ALeffect*)RemoveUIntMapKey(&device->EffectMap, id); }
|
||||
{ return (struct ALeffect*)RemoveUIntMapKeyNoLock(&device->EffectMap, id); }
|
||||
|
||||
inline ALboolean IsReverbEffect(ALenum type)
|
||||
{ return type == AL_EFFECT_REVERB || type == AL_EFFECT_EAXREVERB; }
|
||||
|
||||
@@ -42,13 +42,11 @@ typedef enum ALfilterType {
|
||||
typedef struct ALfilterState {
|
||||
ALfloat x[2]; /* History of two last input samples */
|
||||
ALfloat y[2]; /* History of two last output samples */
|
||||
ALfloat b0, b1, b2; /* Transfer function coefficients "b" */
|
||||
ALfloat a1, a2; /* Transfer function coefficients "a" (a0 is pre-applied) */
|
||||
ALfloat b1, b2; /* Transfer function coefficients "b" (b0 is input_gain) */
|
||||
ALfloat input_gain;
|
||||
|
||||
void (*process)(struct ALfilterState *self, ALfloat *restrict dst, const ALfloat *src, ALuint numsamples);
|
||||
} ALfilterState;
|
||||
#define ALfilterState_process(a, ...) ((a)->process((a), __VA_ARGS__))
|
||||
/* Currently only a C-based filter process method is implemented. */
|
||||
#define ALfilterState_process ALfilterState_processC
|
||||
|
||||
/* Calculates the rcpQ (i.e. 1/Q) coefficient for shelving filters, using the
|
||||
* reference gain and shelf slope parameter.
|
||||
@@ -79,26 +77,18 @@ inline void ALfilterState_clear(ALfilterState *filter)
|
||||
|
||||
void ALfilterState_setParams(ALfilterState *filter, ALfilterType type, ALfloat gain, ALfloat freq_mult, ALfloat rcpQ);
|
||||
|
||||
inline ALfloat ALfilterState_processSingle(ALfilterState *filter, ALfloat sample)
|
||||
inline void ALfilterState_copyParams(ALfilterState *restrict dst, const ALfilterState *restrict src)
|
||||
{
|
||||
ALfloat outsmp;
|
||||
|
||||
outsmp = filter->input_gain * sample +
|
||||
filter->b1 * filter->x[0] +
|
||||
filter->b2 * filter->x[1] -
|
||||
filter->a1 * filter->y[0] -
|
||||
filter->a2 * filter->y[1];
|
||||
filter->x[1] = filter->x[0];
|
||||
filter->x[0] = sample;
|
||||
filter->y[1] = filter->y[0];
|
||||
filter->y[0] = outsmp;
|
||||
|
||||
return outsmp;
|
||||
dst->b0 = src->b0;
|
||||
dst->b1 = src->b1;
|
||||
dst->b2 = src->b2;
|
||||
dst->a1 = src->a1;
|
||||
dst->a2 = src->a2;
|
||||
}
|
||||
|
||||
void ALfilterState_processC(ALfilterState *filter, ALfloat *restrict dst, const ALfloat *src, ALuint numsamples);
|
||||
void ALfilterState_processC(ALfilterState *filter, ALfloat *restrict dst, const ALfloat *restrict src, ALsizei numsamples);
|
||||
|
||||
inline void ALfilterState_processPassthru(ALfilterState *filter, const ALfloat *src, ALuint numsamples)
|
||||
inline void ALfilterState_processPassthru(ALfilterState *filter, const ALfloat *restrict src, ALsizei numsamples)
|
||||
{
|
||||
if(numsamples >= 2)
|
||||
{
|
||||
@@ -151,10 +141,19 @@ typedef struct ALfilter {
|
||||
#define ALfilter_GetParamf(x, c, p, v) ((x)->GetParamf((x),(c),(p),(v)))
|
||||
#define ALfilter_GetParamfv(x, c, p, v) ((x)->GetParamfv((x),(c),(p),(v)))
|
||||
|
||||
inline void LockFiltersRead(ALCdevice *device)
|
||||
{ LockUIntMapRead(&device->FilterMap); }
|
||||
inline void UnlockFiltersRead(ALCdevice *device)
|
||||
{ UnlockUIntMapRead(&device->FilterMap); }
|
||||
inline void LockFiltersWrite(ALCdevice *device)
|
||||
{ LockUIntMapWrite(&device->FilterMap); }
|
||||
inline void UnlockFiltersWrite(ALCdevice *device)
|
||||
{ UnlockUIntMapWrite(&device->FilterMap); }
|
||||
|
||||
inline struct ALfilter *LookupFilter(ALCdevice *device, ALuint id)
|
||||
{ return (struct ALfilter*)LookupUIntMapKey(&device->FilterMap, id); }
|
||||
{ return (struct ALfilter*)LookupUIntMapKeyNoLock(&device->FilterMap, id); }
|
||||
inline struct ALfilter *RemoveFilter(ALCdevice *device, ALuint id)
|
||||
{ return (struct ALfilter*)RemoveUIntMapKey(&device->FilterMap, id); }
|
||||
{ return (struct ALfilter*)RemoveUIntMapKeyNoLock(&device->FilterMap, id); }
|
||||
|
||||
ALvoid ReleaseALFilters(ALCdevice *device);
|
||||
|
||||
|
||||
@@ -8,20 +8,57 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct ALlistenerProps {
|
||||
ALfloat Position[3];
|
||||
ALfloat Velocity[3];
|
||||
ALfloat Forward[3];
|
||||
ALfloat Up[3];
|
||||
ALfloat Gain;
|
||||
ALfloat MetersPerUnit;
|
||||
|
||||
ALfloat DopplerFactor;
|
||||
ALfloat DopplerVelocity;
|
||||
ALfloat SpeedOfSound;
|
||||
ALboolean SourceDistanceModel;
|
||||
enum DistanceModel DistanceModel;
|
||||
|
||||
ATOMIC(struct ALlistenerProps*) next;
|
||||
};
|
||||
|
||||
typedef struct ALlistener {
|
||||
aluVector Position;
|
||||
aluVector Velocity;
|
||||
volatile ALfloat Forward[3];
|
||||
volatile ALfloat Up[3];
|
||||
volatile ALfloat Gain;
|
||||
volatile ALfloat MetersPerUnit;
|
||||
alignas(16) ALfloat Position[3];
|
||||
ALfloat Velocity[3];
|
||||
ALfloat Forward[3];
|
||||
ALfloat Up[3];
|
||||
ALfloat Gain;
|
||||
ALfloat MetersPerUnit;
|
||||
|
||||
/* Pointer to the most recent property values that are awaiting an update.
|
||||
*/
|
||||
ATOMIC(struct ALlistenerProps*) Update;
|
||||
|
||||
/* A linked list of unused property containers, free to use for future
|
||||
* updates.
|
||||
*/
|
||||
ATOMIC(struct ALlistenerProps*) FreeList;
|
||||
|
||||
struct {
|
||||
aluMatrixd Matrix;
|
||||
aluMatrixf Matrix;
|
||||
aluVector Velocity;
|
||||
|
||||
ALfloat Gain;
|
||||
ALfloat MetersPerUnit;
|
||||
|
||||
ALfloat DopplerFactor;
|
||||
ALfloat SpeedOfSound;
|
||||
|
||||
ALboolean SourceDistanceModel;
|
||||
enum DistanceModel DistanceModel;
|
||||
} Params;
|
||||
} ALlistener;
|
||||
|
||||
void UpdateListenerProps(ALCcontext *context);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stddef.h>
|
||||
#include <stdarg.h>
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
@@ -20,6 +21,124 @@
|
||||
#include "AL/alc.h"
|
||||
#include "AL/alext.h"
|
||||
|
||||
#include "static_assert.h"
|
||||
#include "align.h"
|
||||
#include "atomic.h"
|
||||
#include "uintmap.h"
|
||||
#include "vector.h"
|
||||
#include "alstring.h"
|
||||
#include "almalloc.h"
|
||||
#include "threads.h"
|
||||
|
||||
#ifndef ALC_SOFT_loopback2
|
||||
#define ALC_SOFT_loopback2 1
|
||||
#define ALC_AMBISONIC_LAYOUT_SOFT 0x1997
|
||||
#define ALC_AMBISONIC_SCALING_SOFT 0x1998
|
||||
#define ALC_AMBISONIC_ORDER_SOFT 0x1999
|
||||
|
||||
#define ALC_BFORMAT3D_SOFT 0x1508
|
||||
|
||||
/* Ambisonic layouts */
|
||||
#define ALC_ACN_SOFT 0x1600
|
||||
#define ALC_FUMA_SOFT 0x1601
|
||||
|
||||
/* Ambisonic scalings (normalization) */
|
||||
/*#define ALC_FUMA_SOFT*/
|
||||
#define ALC_SN3D_SOFT 0x1602
|
||||
#define ALC_N3D_SOFT 0x1603
|
||||
|
||||
typedef ALCboolean (ALC_APIENTRY*LPALCISAMBISONICFORMATSUPPORTEDSOFT)(ALCdevice *device, ALCenum layout, ALCenum scaling, ALsizei order);
|
||||
#ifdef AL_ALEXT_PROTOTYPES
|
||||
ALC_API ALCboolean ALC_APIENTRY alcIsAmbisonicFormatSupportedSOFT(ALCdevice *device, ALCenum layout, ALCenum scaling, ALsizei order);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef ALC_SOFT_device_clock
|
||||
#define ALC_SOFT_device_clock 1
|
||||
typedef int64_t ALCint64SOFT;
|
||||
typedef uint64_t ALCuint64SOFT;
|
||||
#define ALC_DEVICE_CLOCK_SOFT 0x1600
|
||||
#define ALC_DEVICE_LATENCY_SOFT 0x1601
|
||||
#define ALC_DEVICE_CLOCK_LATENCY_SOFT 0x1602
|
||||
typedef void (ALC_APIENTRY*LPALCGETINTEGER64VSOFT)(ALCdevice *device, ALCenum pname, ALsizei size, ALCint64SOFT *values);
|
||||
#ifdef AL_ALEXT_PROTOTYPES
|
||||
ALC_API void ALC_APIENTRY alcGetInteger64vSOFT(ALCdevice *device, ALCenum pname, ALsizei size, ALCint64SOFT *values);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef AL_SOFT_buffer_samples2
|
||||
#define AL_SOFT_buffer_samples2 1
|
||||
/* Channel configurations */
|
||||
#define AL_MONO_SOFT 0x1500
|
||||
#define AL_STEREO_SOFT 0x1501
|
||||
#define AL_REAR_SOFT 0x1502
|
||||
#define AL_QUAD_SOFT 0x1503
|
||||
#define AL_5POINT1_SOFT 0x1504
|
||||
#define AL_6POINT1_SOFT 0x1505
|
||||
#define AL_7POINT1_SOFT 0x1506
|
||||
#define AL_BFORMAT2D_SOFT 0x1507
|
||||
#define AL_BFORMAT3D_SOFT 0x1508
|
||||
|
||||
/* Sample types */
|
||||
#define AL_BYTE_SOFT 0x1400
|
||||
#define AL_UNSIGNED_BYTE_SOFT 0x1401
|
||||
#define AL_SHORT_SOFT 0x1402
|
||||
#define AL_UNSIGNED_SHORT_SOFT 0x1403
|
||||
#define AL_INT_SOFT 0x1404
|
||||
#define AL_UNSIGNED_INT_SOFT 0x1405
|
||||
#define AL_FLOAT_SOFT 0x1406
|
||||
#define AL_DOUBLE_SOFT 0x1407
|
||||
#define AL_BYTE3_SOFT 0x1408
|
||||
#define AL_UNSIGNED_BYTE3_SOFT 0x1409
|
||||
#define AL_MULAW_SOFT 0x140A
|
||||
|
||||
/* Storage formats */
|
||||
#define AL_MONO8_SOFT 0x1100
|
||||
#define AL_MONO16_SOFT 0x1101
|
||||
#define AL_MONO32F_SOFT 0x10010
|
||||
#define AL_STEREO8_SOFT 0x1102
|
||||
#define AL_STEREO16_SOFT 0x1103
|
||||
#define AL_STEREO32F_SOFT 0x10011
|
||||
#define AL_QUAD8_SOFT 0x1204
|
||||
#define AL_QUAD16_SOFT 0x1205
|
||||
#define AL_QUAD32F_SOFT 0x1206
|
||||
#define AL_REAR8_SOFT 0x1207
|
||||
#define AL_REAR16_SOFT 0x1208
|
||||
#define AL_REAR32F_SOFT 0x1209
|
||||
#define AL_5POINT1_8_SOFT 0x120A
|
||||
#define AL_5POINT1_16_SOFT 0x120B
|
||||
#define AL_5POINT1_32F_SOFT 0x120C
|
||||
#define AL_6POINT1_8_SOFT 0x120D
|
||||
#define AL_6POINT1_16_SOFT 0x120E
|
||||
#define AL_6POINT1_32F_SOFT 0x120F
|
||||
#define AL_7POINT1_8_SOFT 0x1210
|
||||
#define AL_7POINT1_16_SOFT 0x1211
|
||||
#define AL_7POINT1_32F_SOFT 0x1212
|
||||
#define AL_BFORMAT2D_8_SOFT 0x20021
|
||||
#define AL_BFORMAT2D_16_SOFT 0x20022
|
||||
#define AL_BFORMAT2D_32F_SOFT 0x20023
|
||||
#define AL_BFORMAT3D_8_SOFT 0x20031
|
||||
#define AL_BFORMAT3D_16_SOFT 0x20032
|
||||
#define AL_BFORMAT3D_32F_SOFT 0x20033
|
||||
|
||||
/* Buffer attributes */
|
||||
#define AL_INTERNAL_FORMAT_SOFT 0x2008
|
||||
#define AL_BYTE_LENGTH_SOFT 0x2009
|
||||
#define AL_SAMPLE_LENGTH_SOFT 0x200A
|
||||
#define AL_SEC_LENGTH_SOFT 0x200B
|
||||
|
||||
#if 0
|
||||
typedef void (AL_APIENTRY*LPALBUFFERSAMPLESSOFT)(ALuint,ALuint,ALenum,ALsizei,ALenum,ALenum,const ALvoid*);
|
||||
typedef void (AL_APIENTRY*LPALGETBUFFERSAMPLESSOFT)(ALuint,ALsizei,ALsizei,ALenum,ALenum,ALvoid*);
|
||||
typedef ALboolean (AL_APIENTRY*LPALISBUFFERFORMATSUPPORTEDSOFT)(ALenum);
|
||||
#ifdef AL_ALEXT_PROTOTYPES
|
||||
AL_API void AL_APIENTRY alBufferSamplesSOFT(ALuint buffer, ALuint samplerate, ALenum internalformat, ALsizei samples, ALenum channels, ALenum type, const ALvoid *data);
|
||||
AL_API void AL_APIENTRY alGetBufferSamplesSOFT(ALuint buffer, ALsizei offset, ALsizei samples, ALenum channels, ALenum type, ALvoid *data);
|
||||
AL_API ALboolean AL_APIENTRY alIsBufferFormatSupportedSOFT(ALenum format);
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(_WIN64)
|
||||
#define SZFMT "%I64u"
|
||||
@@ -30,24 +149,59 @@
|
||||
#endif
|
||||
|
||||
|
||||
#include "static_assert.h"
|
||||
#include "align.h"
|
||||
#include "atomic.h"
|
||||
#include "uintmap.h"
|
||||
#include "vector.h"
|
||||
#include "alstring.h"
|
||||
|
||||
#include "hrtf.h"
|
||||
|
||||
#ifndef ALC_SOFT_device_clock
|
||||
#define ALC_SOFT_device_clock 1
|
||||
typedef int64_t ALCint64SOFT;
|
||||
typedef uint64_t ALCuint64SOFT;
|
||||
#define ALC_DEVICE_CLOCK_SOFT 0x1600
|
||||
typedef void (ALC_APIENTRY*LPALCGETINTEGER64VSOFT)(ALCdevice *device, ALCenum pname, ALsizei size, ALCint64SOFT *values);
|
||||
#ifdef AL_ALEXT_PROTOTYPES
|
||||
ALC_API void ALC_APIENTRY alcGetInteger64vSOFT(ALCdevice *device, ALCenum pname, ALsizei size, ALCint64SOFT *values);
|
||||
#ifdef __GNUC__
|
||||
/* Because of a long-standing deficiency in C, you're not allowed to implicitly
|
||||
* cast a pointer-to-type-array to a pointer-to-const-type-array. For example,
|
||||
*
|
||||
* int (*ptr)[10];
|
||||
* const int (*cptr)[10] = ptr;
|
||||
*
|
||||
* is not allowed and most compilers will generate noisy warnings about
|
||||
* incompatible types, even though it just makes the array elements const.
|
||||
* Clang will allow it if you make the array type a typedef, like this:
|
||||
*
|
||||
* typedef int int10[10];
|
||||
* int10 *ptr;
|
||||
* const int10 *cptr = ptr;
|
||||
*
|
||||
* however GCC does not and still issues the incompatible type warning. The
|
||||
* "proper" way to fix it is to add an explicit cast for the constified type,
|
||||
* but that removes the vast majority of otherwise useful type-checking you'd
|
||||
* get, and runs the risk of improper casts if types are later changed. Leaving
|
||||
* it non-const can also be an issue if you use it as a function parameter, and
|
||||
* happen to have a const type as input (and also reduce the capabilities of
|
||||
* the compiler to better optimize the function).
|
||||
*
|
||||
* So to work around the problem, we use a macro. The macro first assigns the
|
||||
* incoming variable to the specified non-const type to ensure it's the correct
|
||||
* type, then casts the variable as the desired constified type. Very ugly, but
|
||||
* I'd rather not have hundreds of lines of warnings because I want to tell the
|
||||
* compiler that some array(s) can't be changed by the code, or have lots of
|
||||
* error-prone casts.
|
||||
*/
|
||||
#define SAFE_CONST(T, var) __extension__({ \
|
||||
T _tmp = (var); \
|
||||
(const T)_tmp; \
|
||||
})
|
||||
#else
|
||||
/* Non-GNU-compatible compilers have to use a straight cast with no extra
|
||||
* checks, due to the lack of multi-statement expressions.
|
||||
*/
|
||||
#define SAFE_CONST(T, var) ((const T)(var))
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __GNUC__
|
||||
/* This helps cast away the const-ness of a pointer without accidentally
|
||||
* changing the pointer type. This is necessary due to Clang's inability to use
|
||||
* atomic_load on a const _Atomic variable.
|
||||
*/
|
||||
#define CONST_CAST(T, V) __extension__({ \
|
||||
const T _tmp = (V); \
|
||||
(T)_tmp; \
|
||||
})
|
||||
#else
|
||||
#define CONST_CAST(T, V) ((T)(V))
|
||||
#endif
|
||||
|
||||
|
||||
@@ -81,13 +235,17 @@ typedef ALuint64SOFT ALuint64;
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define DECL_CONST __attribute__((const))
|
||||
#define DECL_FORMAT(x, y, z) __attribute__((format(x, (y), (z))))
|
||||
#else
|
||||
#define DECL_CONST
|
||||
#define DECL_FORMAT(x, y, z)
|
||||
#endif
|
||||
|
||||
/* Calculates the size of a struct with N elements of a flexible array member.
|
||||
* GCC and Clang allow offsetof(Type, fam[N]) for this, but MSVC seems to have
|
||||
* trouble, so a bit more verbose workaround is needed.
|
||||
*/
|
||||
#define FAM_SIZE(T, M, N) (offsetof(T, M) + sizeof(((T*)NULL)->M[0])*(N))
|
||||
|
||||
#if defined(__GNUC__) && defined(__i386__)
|
||||
/* force_align_arg_pointer is required for proper function arguments aligning
|
||||
* when SSE code is used. Some systems (Windows, QNX) do not guarantee our
|
||||
@@ -119,7 +277,7 @@ static const union {
|
||||
} EndianTest = { 1 };
|
||||
#define IS_LITTLE_ENDIAN (EndianTest.b[0] == 1)
|
||||
|
||||
#define COUNTOF(x) (sizeof((x))/sizeof((x)[0]))
|
||||
#define COUNTOF(x) (sizeof(x) / sizeof(0[x]))
|
||||
|
||||
|
||||
#define DERIVE_FROM_TYPE(t) t t##_parent
|
||||
@@ -208,6 +366,12 @@ static void T##_Delete(void *ptr) { al_free(ptr); }
|
||||
{ \
|
||||
memset(_res, 0, sizeof(T)); \
|
||||
T##_Construct(_res, EXTRACT_NEW_ARGS
|
||||
#define NEW_OBJ0(_res, T) do { \
|
||||
_res = T##_New(sizeof(T)); \
|
||||
if(_res) \
|
||||
{ \
|
||||
memset(_res, 0, sizeof(T)); \
|
||||
T##_Construct(_res EXTRACT_NEW_ARGS
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
@@ -215,6 +379,8 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
struct Hrtf;
|
||||
struct HrtfEntry;
|
||||
struct Compressor;
|
||||
|
||||
|
||||
#define DEFAULT_OUTPUT_RATE (44100)
|
||||
@@ -236,6 +402,31 @@ 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);
|
||||
}
|
||||
|
||||
/* Scales the given value using 64-bit integer math, rounding the result. */
|
||||
inline ALuint64 ScaleRound(ALuint64 val, ALuint64 new_scale, ALuint64 old_scale)
|
||||
{
|
||||
return (val*new_scale + old_scale/2) / old_scale;
|
||||
}
|
||||
|
||||
/* Scales the given value using 64-bit integer math, flooring the result. */
|
||||
inline ALuint64 ScaleFloor(ALuint64 val, ALuint64 new_scale, ALuint64 old_scale)
|
||||
{
|
||||
return val * new_scale / old_scale;
|
||||
}
|
||||
|
||||
/* Scales the given value using 64-bit integer math, ceiling the result. */
|
||||
inline ALuint64 ScaleCeil(ALuint64 val, ALuint64 new_scale, ALuint64 old_scale)
|
||||
{
|
||||
return (val*new_scale + old_scale-1) / old_scale;
|
||||
}
|
||||
|
||||
/* Fast float-to-int conversion. Assumes the FPU is already in round-to-zero
|
||||
* mode. */
|
||||
inline ALint fastf2i(ALfloat f)
|
||||
@@ -252,45 +443,12 @@ inline ALint fastf2i(ALfloat f)
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Fast float-to-uint conversion. Assumes the FPU is already in round-to-zero
|
||||
* mode. */
|
||||
inline ALuint fastf2u(ALfloat f)
|
||||
{ return fastf2i(f); }
|
||||
|
||||
|
||||
enum DevProbe {
|
||||
ALL_DEVICE_PROBE,
|
||||
CAPTURE_DEVICE_PROBE
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
ALCenum (*OpenPlayback)(ALCdevice*, const ALCchar*);
|
||||
void (*ClosePlayback)(ALCdevice*);
|
||||
ALCboolean (*ResetPlayback)(ALCdevice*);
|
||||
ALCboolean (*StartPlayback)(ALCdevice*);
|
||||
void (*StopPlayback)(ALCdevice*);
|
||||
|
||||
ALCenum (*OpenCapture)(ALCdevice*, const ALCchar*);
|
||||
void (*CloseCapture)(ALCdevice*);
|
||||
void (*StartCapture)(ALCdevice*);
|
||||
void (*StopCapture)(ALCdevice*);
|
||||
ALCenum (*CaptureSamples)(ALCdevice*, void*, ALCuint);
|
||||
ALCuint (*AvailableSamples)(ALCdevice*);
|
||||
} BackendFuncs;
|
||||
|
||||
ALCboolean alc_sndio_init(BackendFuncs *func_list);
|
||||
void alc_sndio_deinit(void);
|
||||
void alc_sndio_probe(enum DevProbe type);
|
||||
ALCboolean alc_ca_init(BackendFuncs *func_list);
|
||||
void alc_ca_deinit(void);
|
||||
void alc_ca_probe(enum DevProbe type);
|
||||
ALCboolean alc_opensl_init(BackendFuncs *func_list);
|
||||
void alc_opensl_deinit(void);
|
||||
void alc_opensl_probe(enum DevProbe type);
|
||||
ALCboolean alc_qsa_init(BackendFuncs *func_list);
|
||||
void alc_qsa_deinit(void);
|
||||
void alc_qsa_probe(enum DevProbe type);
|
||||
|
||||
struct ALCbackend;
|
||||
|
||||
|
||||
@@ -317,10 +475,31 @@ enum Channel {
|
||||
SideLeft,
|
||||
SideRight,
|
||||
|
||||
BFormatW,
|
||||
BFormatX,
|
||||
BFormatY,
|
||||
BFormatZ,
|
||||
UpperFrontLeft,
|
||||
UpperFrontRight,
|
||||
UpperBackLeft,
|
||||
UpperBackRight,
|
||||
LowerFrontLeft,
|
||||
LowerFrontRight,
|
||||
LowerBackLeft,
|
||||
LowerBackRight,
|
||||
|
||||
Aux0,
|
||||
Aux1,
|
||||
Aux2,
|
||||
Aux3,
|
||||
Aux4,
|
||||
Aux5,
|
||||
Aux6,
|
||||
Aux7,
|
||||
Aux8,
|
||||
Aux9,
|
||||
Aux10,
|
||||
Aux11,
|
||||
Aux12,
|
||||
Aux13,
|
||||
Aux14,
|
||||
Aux15,
|
||||
|
||||
InvalidChannel
|
||||
};
|
||||
@@ -345,23 +524,37 @@ enum DevFmtChannels {
|
||||
DevFmtX51 = ALC_5POINT1_SOFT,
|
||||
DevFmtX61 = ALC_6POINT1_SOFT,
|
||||
DevFmtX71 = ALC_7POINT1_SOFT,
|
||||
DevFmtAmbi3D = ALC_BFORMAT3D_SOFT,
|
||||
|
||||
/* Similar to 5.1, except using rear channels instead of sides */
|
||||
DevFmtX51Rear = 0x80000000,
|
||||
|
||||
DevFmtBFormat3D,
|
||||
|
||||
DevFmtChannelsDefault = DevFmtStereo
|
||||
};
|
||||
#define MAX_OUTPUT_CHANNELS (8)
|
||||
#define MAX_OUTPUT_CHANNELS (16)
|
||||
|
||||
ALuint BytesFromDevFmt(enum DevFmtType type) DECL_CONST;
|
||||
ALuint ChannelsFromDevFmt(enum DevFmtChannels chans) DECL_CONST;
|
||||
inline ALuint FrameSizeFromDevFmt(enum DevFmtChannels chans, enum DevFmtType type)
|
||||
ALsizei BytesFromDevFmt(enum DevFmtType type);
|
||||
ALsizei ChannelsFromDevFmt(enum DevFmtChannels chans, ALsizei ambiorder);
|
||||
inline ALsizei FrameSizeFromDevFmt(enum DevFmtChannels chans, enum DevFmtType type, ALsizei ambiorder)
|
||||
{
|
||||
return ChannelsFromDevFmt(chans) * BytesFromDevFmt(type);
|
||||
return ChannelsFromDevFmt(chans, ambiorder) * BytesFromDevFmt(type);
|
||||
}
|
||||
|
||||
enum AmbiLayout {
|
||||
AmbiLayout_FuMa = ALC_FUMA_SOFT, /* FuMa channel order */
|
||||
AmbiLayout_ACN = ALC_ACN_SOFT, /* ACN channel order */
|
||||
|
||||
AmbiLayout_Default = AmbiLayout_ACN
|
||||
};
|
||||
|
||||
enum AmbiNorm {
|
||||
AmbiNorm_FuMa = ALC_FUMA_SOFT, /* FuMa normalization */
|
||||
AmbiNorm_SN3D = ALC_SN3D_SOFT, /* SN3D normalization */
|
||||
AmbiNorm_N3D = ALC_N3D_SOFT, /* N3D normalization */
|
||||
|
||||
AmbiNorm_Default = AmbiNorm_SN3D
|
||||
};
|
||||
|
||||
|
||||
extern const struct EffectList {
|
||||
const char *name;
|
||||
@@ -378,25 +571,57 @@ enum DeviceType {
|
||||
};
|
||||
|
||||
|
||||
enum HrtfMode {
|
||||
DisabledHrtf,
|
||||
BasicHrtf,
|
||||
FullHrtf
|
||||
enum RenderMode {
|
||||
NormalRender,
|
||||
StereoPair,
|
||||
HrtfRender
|
||||
};
|
||||
|
||||
|
||||
/* The maximum number of Ambisonics coefficients. For a given order (o), the
|
||||
* size needed will be (o+1)**2, thus zero-order has 1, first-order has 4,
|
||||
* second-order has 9, and third-order has 16. */
|
||||
#define MAX_AMBI_COEFFS 16
|
||||
* second-order has 9, third-order has 16, and fourth-order has 25.
|
||||
*/
|
||||
#define MAX_AMBI_ORDER 3
|
||||
#define MAX_AMBI_COEFFS ((MAX_AMBI_ORDER+1) * (MAX_AMBI_ORDER+1))
|
||||
|
||||
/* A bitmask of ambisonic channels with height information. If none of these
|
||||
* channels are used/needed, there's no height (e.g. with most surround sound
|
||||
* speaker setups). This only specifies up to 4th order, which is the highest
|
||||
* order a 32-bit mask value can specify (a 64-bit mask could handle up to 7th
|
||||
* order). This is ACN ordering, with bit 0 being ACN 0, etc.
|
||||
*/
|
||||
#define AMBI_PERIPHONIC_MASK (0xfe7ce4)
|
||||
|
||||
/* The maximum number of Ambisonic coefficients for 2D (non-periphonic)
|
||||
* representation. This is 2 per each order above zero-order, plus 1 for zero-
|
||||
* order. Or simply, o*2 + 1.
|
||||
*/
|
||||
#define MAX_AMBI2D_COEFFS (MAX_AMBI_ORDER*2 + 1)
|
||||
|
||||
|
||||
typedef ALfloat ChannelConfig[MAX_AMBI_COEFFS];
|
||||
typedef struct BFChannelConfig {
|
||||
ALfloat Scale;
|
||||
ALsizei Index;
|
||||
} BFChannelConfig;
|
||||
|
||||
typedef union AmbiConfig {
|
||||
/* Ambisonic coefficients for mixing to the dry buffer. */
|
||||
ChannelConfig Coeffs[MAX_OUTPUT_CHANNELS];
|
||||
/* Coefficient channel mapping for mixing to the dry buffer. */
|
||||
BFChannelConfig Map[MAX_OUTPUT_CHANNELS];
|
||||
} AmbiConfig;
|
||||
|
||||
|
||||
#define HRTF_HISTORY_BITS (6)
|
||||
#define HRTF_HISTORY_LENGTH (1<<HRTF_HISTORY_BITS)
|
||||
#define HRTF_HISTORY_MASK (HRTF_HISTORY_LENGTH-1)
|
||||
|
||||
#define HRIR_BITS (7)
|
||||
#define HRIR_LENGTH (1<<HRIR_BITS)
|
||||
#define HRIR_MASK (HRIR_LENGTH-1)
|
||||
|
||||
typedef struct HrtfState {
|
||||
alignas(16) ALfloat History[HRTF_HISTORY_LENGTH];
|
||||
alignas(16) ALfloat Values[HRIR_LENGTH][2];
|
||||
@@ -404,18 +629,43 @@ typedef struct HrtfState {
|
||||
|
||||
typedef struct HrtfParams {
|
||||
alignas(16) ALfloat Coeffs[HRIR_LENGTH][2];
|
||||
alignas(16) ALfloat CoeffStep[HRIR_LENGTH][2];
|
||||
ALuint Delay[2];
|
||||
ALint DelayStep[2];
|
||||
ALsizei Delay[2];
|
||||
ALfloat Gain;
|
||||
} HrtfParams;
|
||||
|
||||
typedef struct DirectHrtfState {
|
||||
/* HRTF filter state for dry buffer content */
|
||||
ALsizei Offset;
|
||||
ALsizei IrSize;
|
||||
struct {
|
||||
alignas(16) ALfloat Values[HRIR_LENGTH][2];
|
||||
alignas(16) ALfloat Coeffs[HRIR_LENGTH][2];
|
||||
} Chan[];
|
||||
} DirectHrtfState;
|
||||
|
||||
typedef struct EnumeratedHrtf {
|
||||
al_string name;
|
||||
|
||||
struct HrtfEntry *hrtf;
|
||||
} EnumeratedHrtf;
|
||||
TYPEDEF_VECTOR(EnumeratedHrtf, vector_EnumeratedHrtf)
|
||||
|
||||
|
||||
/* Maximum delay in samples for speaker distance compensation. */
|
||||
#define MAX_DELAY_LENGTH 1024
|
||||
|
||||
typedef struct DistanceComp {
|
||||
ALfloat Gain;
|
||||
ALsizei Length; /* Valid range is [0...MAX_DELAY_LENGTH). */
|
||||
ALfloat *Buffer;
|
||||
} DistanceComp;
|
||||
|
||||
/* Size for temporary storage of buffer data, in ALfloats. Larger values need
|
||||
* more memory, while smaller values may need more iterations. The value needs
|
||||
* to be a sensible size, however, as it constrains the max stepping value used
|
||||
* for mixing, as well as the maximum number of samples per mixing iteration.
|
||||
*/
|
||||
#define BUFFERSIZE (2048u)
|
||||
#define BUFFERSIZE 2048
|
||||
|
||||
struct ALCdevice_struct
|
||||
{
|
||||
@@ -424,25 +674,31 @@ struct ALCdevice_struct
|
||||
ALCboolean Connected;
|
||||
enum DeviceType Type;
|
||||
|
||||
ALuint Frequency;
|
||||
ALuint UpdateSize;
|
||||
ALuint NumUpdates;
|
||||
ALuint Frequency;
|
||||
ALuint UpdateSize;
|
||||
ALuint NumUpdates;
|
||||
enum DevFmtChannels FmtChans;
|
||||
enum DevFmtType FmtType;
|
||||
ALboolean IsHeadphones;
|
||||
ALboolean IsHeadphones;
|
||||
ALsizei AmbiOrder;
|
||||
/* For DevFmtAmbi* output only, specifies the channel order and
|
||||
* normalization.
|
||||
*/
|
||||
enum AmbiLayout AmbiLayout;
|
||||
enum AmbiNorm AmbiScale;
|
||||
|
||||
al_string DeviceName;
|
||||
|
||||
ATOMIC(ALCenum) LastError;
|
||||
|
||||
// Maximum number of sources that can be created
|
||||
ALuint MaxNoOfSources;
|
||||
ALuint SourcesMax;
|
||||
// Maximum number of slots that can be created
|
||||
ALuint AuxiliaryEffectSlotMax;
|
||||
ALuint AuxiliaryEffectSlotMax;
|
||||
|
||||
ALCuint NumMonoSources;
|
||||
ALCuint NumStereoSources;
|
||||
ALuint NumAuxSends;
|
||||
ALCuint NumMonoSources;
|
||||
ALCuint NumStereoSources;
|
||||
ALsizei NumAuxSends;
|
||||
|
||||
// Map of Buffers for this device
|
||||
UIntMap BufferMap;
|
||||
@@ -453,27 +709,31 @@ struct ALCdevice_struct
|
||||
// Map of Filters for this device
|
||||
UIntMap FilterMap;
|
||||
|
||||
/* HRTF filter tables */
|
||||
vector_HrtfEntry Hrtf_List;
|
||||
al_string Hrtf_Name;
|
||||
const struct Hrtf *Hrtf;
|
||||
ALCenum Hrtf_Status;
|
||||
enum HrtfMode Hrtf_Mode;
|
||||
HrtfState Hrtf_State[MAX_OUTPUT_CHANNELS];
|
||||
HrtfParams Hrtf_Params[MAX_OUTPUT_CHANNELS];
|
||||
ALuint Hrtf_Offset;
|
||||
/* HRTF state and info */
|
||||
DirectHrtfState *Hrtf;
|
||||
al_string HrtfName;
|
||||
struct Hrtf *HrtfHandle;
|
||||
vector_EnumeratedHrtf HrtfList;
|
||||
ALCenum HrtfStatus;
|
||||
|
||||
// Stereo-to-binaural filter
|
||||
/* UHJ encoder state */
|
||||
struct Uhj2Encoder *Uhj_Encoder;
|
||||
|
||||
/* High quality Ambisonic decoder */
|
||||
struct BFormatDec *AmbiDecoder;
|
||||
|
||||
/* Stereo-to-binaural filter */
|
||||
struct bs2b *Bs2b;
|
||||
|
||||
/* First-order ambisonic upsampler for higher-order output */
|
||||
struct AmbiUpsampler *AmbiUp;
|
||||
|
||||
/* Rendering mode. */
|
||||
enum RenderMode Render_Mode;
|
||||
|
||||
// Device flags
|
||||
ALuint Flags;
|
||||
|
||||
enum Channel ChannelName[MAX_OUTPUT_CHANNELS];
|
||||
ChannelConfig AmbiCoeffs[MAX_OUTPUT_CHANNELS];
|
||||
ALfloat AmbiScale; /* Scale for first-order XYZ inputs using AmbCoeffs. */
|
||||
ALuint NumChannels;
|
||||
|
||||
ALuint64 ClockBase;
|
||||
ALuint SamplesDone;
|
||||
|
||||
@@ -481,9 +741,55 @@ struct ALCdevice_struct
|
||||
alignas(16) ALfloat SourceData[BUFFERSIZE];
|
||||
alignas(16) ALfloat ResampledData[BUFFERSIZE];
|
||||
alignas(16) ALfloat FilteredData[BUFFERSIZE];
|
||||
alignas(16) ALfloat NFCtrlData[BUFFERSIZE];
|
||||
|
||||
/* Dry path buffer mix. */
|
||||
alignas(16) ALfloat (*DryBuffer)[BUFFERSIZE];
|
||||
/* The "dry" path corresponds to the main output. */
|
||||
struct {
|
||||
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 instead to map each output to a coefficient index.
|
||||
*/
|
||||
ALsizei CoeffCount;
|
||||
|
||||
ALfloat (*Buffer)[BUFFERSIZE];
|
||||
ALsizei NumChannels;
|
||||
ALsizei NumChannelsPerOrder[MAX_AMBI_ORDER+1];
|
||||
} Dry;
|
||||
|
||||
/* First-order ambisonics output, to be upsampled to the dry buffer if different. */
|
||||
struct {
|
||||
AmbiConfig Ambi;
|
||||
/* Will only be 4 or 0. */
|
||||
ALsizei CoeffCount;
|
||||
|
||||
ALfloat (*Buffer)[BUFFERSIZE];
|
||||
ALsizei NumChannels;
|
||||
} FOAOut;
|
||||
|
||||
/* "Real" output, which will be written to the device buffer. May alias the
|
||||
* dry buffer.
|
||||
*/
|
||||
struct {
|
||||
enum Channel ChannelName[MAX_OUTPUT_CHANNELS];
|
||||
|
||||
ALfloat (*Buffer)[BUFFERSIZE];
|
||||
ALsizei NumChannels;
|
||||
} RealOut;
|
||||
|
||||
struct Compressor *Limiter;
|
||||
|
||||
/* The average speaker distance as determined by the ambdec configuration
|
||||
* (or alternatively, by the NFC-HOA reference delay). Only used for NFC.
|
||||
*/
|
||||
ALfloat AvgSpeakerDist;
|
||||
|
||||
/* Delay buffers used to compensate for speaker distances. */
|
||||
DistanceComp ChannelDelay[MAX_OUTPUT_CHANNELS];
|
||||
|
||||
/* Dithering control. */
|
||||
ALfloat DitherDepth;
|
||||
ALuint DitherSeed;
|
||||
|
||||
/* Running count of the mixer invocations, in 31.1 fixed point. This
|
||||
* actually increments *twice* when mixing, first at the start and then at
|
||||
@@ -492,34 +798,27 @@ struct ALCdevice_struct
|
||||
*/
|
||||
RefCount MixCount;
|
||||
|
||||
/* Default effect slot */
|
||||
struct ALeffectslot *DefaultSlot;
|
||||
|
||||
// Contexts created on this device
|
||||
ATOMIC(ALCcontext*) ContextList;
|
||||
|
||||
almtx_t BackendLock;
|
||||
struct ALCbackend *Backend;
|
||||
|
||||
void *ExtraData; // For the backend's use
|
||||
|
||||
ALCdevice *volatile next;
|
||||
|
||||
/* Memory space used by the default slot (Playback devices only) */
|
||||
alignas(16) ALCbyte _slot_mem[];
|
||||
};
|
||||
|
||||
// Frequency was requested by the app or config file
|
||||
#define DEVICE_FREQUENCY_REQUEST (1<<1)
|
||||
#define DEVICE_FREQUENCY_REQUEST (1u<<1)
|
||||
// Channel configuration was requested by the config file
|
||||
#define DEVICE_CHANNELS_REQUEST (1<<2)
|
||||
#define DEVICE_CHANNELS_REQUEST (1u<<2)
|
||||
// Sample type was requested by the config file
|
||||
#define DEVICE_SAMPLE_TYPE_REQUEST (1<<3)
|
||||
#define DEVICE_SAMPLE_TYPE_REQUEST (1u<<3)
|
||||
|
||||
// Specifies if the DSP is paused at user request
|
||||
#define DEVICE_PAUSED (1<<30)
|
||||
#define DEVICE_PAUSED (1u<<30)
|
||||
|
||||
// Specifies if the device is currently running
|
||||
#define DEVICE_RUNNING (1<<31)
|
||||
#define DEVICE_RUNNING (1u<<31)
|
||||
|
||||
|
||||
/* Nanosecond resolution for the device clock time. */
|
||||
@@ -533,8 +832,7 @@ struct ALCdevice_struct
|
||||
#define RECORD_THREAD_NAME "alsoft-record"
|
||||
|
||||
|
||||
struct ALCcontext_struct
|
||||
{
|
||||
struct ALCcontext_struct {
|
||||
RefCount ref;
|
||||
|
||||
struct ALlistener *Listener;
|
||||
@@ -544,28 +842,39 @@ struct ALCcontext_struct
|
||||
|
||||
ATOMIC(ALenum) LastError;
|
||||
|
||||
ATOMIC(ALenum) UpdateSources;
|
||||
enum DistanceModel DistanceModel;
|
||||
ALboolean SourceDistanceModel;
|
||||
|
||||
volatile enum DistanceModel DistanceModel;
|
||||
volatile ALboolean SourceDistanceModel;
|
||||
ALfloat DopplerFactor;
|
||||
ALfloat DopplerVelocity;
|
||||
ALfloat SpeedOfSound;
|
||||
ATOMIC(ALenum) DeferUpdates;
|
||||
|
||||
volatile ALfloat DopplerFactor;
|
||||
volatile ALfloat DopplerVelocity;
|
||||
volatile ALfloat SpeedOfSound;
|
||||
volatile ALenum DeferUpdates;
|
||||
RWLock PropLock;
|
||||
|
||||
struct ALvoice *Voices;
|
||||
/* Counter for the pre-mixing updates, in 31.1 fixed point (lowest bit
|
||||
* indicates if updates are currently happening).
|
||||
*/
|
||||
RefCount UpdateCount;
|
||||
ATOMIC(ALenum) HoldUpdates;
|
||||
|
||||
ALfloat GainBoost;
|
||||
|
||||
struct ALvoice **Voices;
|
||||
ALsizei VoiceCount;
|
||||
ALsizei MaxVoices;
|
||||
|
||||
VECTOR(struct ALeffectslot*) ActiveAuxSlots;
|
||||
ATOMIC(struct ALeffectslotArray*) ActiveAuxSlots;
|
||||
|
||||
/* Default effect slot */
|
||||
struct ALeffectslot *DefaultSlot;
|
||||
|
||||
ALCdevice *Device;
|
||||
const ALCchar *ExtensionList;
|
||||
|
||||
ALCcontext *volatile next;
|
||||
|
||||
/* Memory space used by the listener */
|
||||
/* Memory space used by the listener (and possibly default effect slot) */
|
||||
alignas(16) ALCbyte _listener_mem[];
|
||||
};
|
||||
|
||||
@@ -574,6 +883,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);
|
||||
|
||||
@@ -583,21 +894,13 @@ void ALCdevice_Unlock(ALCdevice *device);
|
||||
void ALCcontext_DeferUpdates(ALCcontext *context);
|
||||
void ALCcontext_ProcessUpdates(ALCcontext *context);
|
||||
|
||||
inline void LockContext(ALCcontext *context)
|
||||
{ ALCdevice_Lock(context->Device); }
|
||||
|
||||
inline void UnlockContext(ALCcontext *context)
|
||||
{ ALCdevice_Unlock(context->Device); }
|
||||
|
||||
|
||||
void *al_malloc(size_t alignment, size_t size);
|
||||
void *al_calloc(size_t alignment, size_t size);
|
||||
void al_free(void *ptr);
|
||||
|
||||
|
||||
typedef struct {
|
||||
#ifdef HAVE_FENV_H
|
||||
DERIVE_FROM_TYPE(fenv_t);
|
||||
#ifdef _WIN32
|
||||
int round_mode;
|
||||
#endif
|
||||
#else
|
||||
int state;
|
||||
#endif
|
||||
@@ -607,15 +910,19 @@ typedef struct {
|
||||
} FPUCtl;
|
||||
void SetMixerFPUMode(FPUCtl *ctl);
|
||||
void RestoreFPUMode(const FPUCtl *ctl);
|
||||
#ifdef __GNUC__
|
||||
/* Use an alternate macro set with GCC to avoid accidental continue or break
|
||||
* statements within the mixer mode.
|
||||
*/
|
||||
#define START_MIXER_MODE() __extension__({ FPUCtl _oldMode; SetMixerFPUMode(&_oldMode);
|
||||
#define END_MIXER_MODE() RestoreFPUMode(&_oldMode); })
|
||||
#else
|
||||
#define START_MIXER_MODE() do { FPUCtl _oldMode; SetMixerFPUMode(&_oldMode);
|
||||
#define END_MIXER_MODE() RestoreFPUMode(&_oldMode); } while(0)
|
||||
#endif
|
||||
#define LEAVE_MIXER_MODE() RestoreFPUMode(&_oldMode)
|
||||
|
||||
|
||||
typedef struct RingBuffer RingBuffer;
|
||||
RingBuffer *CreateRingBuffer(ALsizei frame_size, ALsizei length);
|
||||
void DestroyRingBuffer(RingBuffer *ring);
|
||||
ALsizei RingBufferSize(RingBuffer *ring);
|
||||
void WriteRingBuffer(RingBuffer *ring, const ALubyte *data, ALsizei len);
|
||||
void ReadRingBuffer(RingBuffer *ring, ALubyte *data, ALsizei len);
|
||||
|
||||
typedef struct ll_ringbuffer ll_ringbuffer_t;
|
||||
typedef struct ll_ringbuffer_data {
|
||||
char *buf;
|
||||
@@ -651,26 +958,26 @@ void SetRTPriority(void);
|
||||
void SetDefaultChannelOrder(ALCdevice *device);
|
||||
void SetDefaultWFXChannelOrder(ALCdevice *device);
|
||||
|
||||
const ALCchar *DevFmtTypeString(enum DevFmtType type) DECL_CONST;
|
||||
const ALCchar *DevFmtChannelsString(enum DevFmtChannels chans) DECL_CONST;
|
||||
const ALCchar *DevFmtTypeString(enum DevFmtType type);
|
||||
const ALCchar *DevFmtChannelsString(enum DevFmtChannels chans);
|
||||
|
||||
/**
|
||||
* GetChannelIdxByName
|
||||
*
|
||||
* Returns the device's channel index given a channel name (e.g. FrontCenter),
|
||||
* or -1 if it doesn't exist.
|
||||
* Returns the index for the given channel name (e.g. FrontCenter), or -1 if it
|
||||
* doesn't exist.
|
||||
*/
|
||||
inline ALint GetChannelIdxByName(const ALCdevice *device, enum Channel chan)
|
||||
inline ALint GetChannelIndex(const enum Channel names[MAX_OUTPUT_CHANNELS], enum Channel chan)
|
||||
{
|
||||
ALint i = 0;
|
||||
ALint i;
|
||||
for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
|
||||
{
|
||||
if(device->ChannelName[i] == chan)
|
||||
if(names[i] == chan)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
#define GetChannelIdxByName(x, c) GetChannelIndex((x).ChannelName, (c))
|
||||
|
||||
extern FILE *LogFile;
|
||||
|
||||
@@ -681,6 +988,13 @@ void al_print(const char *type, const char *func, const char *fmt, ...) DECL_FOR
|
||||
#define AL_PRINT(T, ...) al_print((T), __FUNCTION__, __VA_ARGS__)
|
||||
#endif
|
||||
|
||||
#ifdef __ANDROID__
|
||||
#include <android/log.h>
|
||||
#define LOG_ANDROID(T, MSG, ...) __android_log_print(T, "openal", "AL lib: %s: "MSG, __FUNCTION__ , ## __VA_ARGS__)
|
||||
#else
|
||||
#define LOG_ANDROID(T, MSG, ...) ((void)0)
|
||||
#endif
|
||||
|
||||
enum LogLevel {
|
||||
NoLog,
|
||||
LogError,
|
||||
@@ -698,16 +1012,19 @@ extern enum LogLevel LogLevel;
|
||||
#define TRACE(...) do { \
|
||||
if(LogLevel >= LogTrace) \
|
||||
AL_PRINT("(II)", __VA_ARGS__); \
|
||||
LOG_ANDROID(ANDROID_LOG_DEBUG, __VA_ARGS__); \
|
||||
} while(0)
|
||||
|
||||
#define WARN(...) do { \
|
||||
if(LogLevel >= LogWarning) \
|
||||
AL_PRINT("(WW)", __VA_ARGS__); \
|
||||
LOG_ANDROID(ANDROID_LOG_WARN, __VA_ARGS__); \
|
||||
} while(0)
|
||||
|
||||
#define ERR(...) do { \
|
||||
if(LogLevel >= LogError) \
|
||||
AL_PRINT("(EE)", __VA_ARGS__); \
|
||||
LOG_ANDROID(ANDROID_LOG_ERROR, __VA_ARGS__); \
|
||||
} while(0)
|
||||
|
||||
|
||||
@@ -725,15 +1042,42 @@ enum {
|
||||
|
||||
void FillCPUCaps(ALuint capfilter);
|
||||
|
||||
FILE *OpenDataFile(const char *fname, const char *subdir);
|
||||
|
||||
vector_al_string SearchDataFiles(const char *match, const char *subdir);
|
||||
|
||||
/* Small hack to use a pointer-to-array type as a normal argument type.
|
||||
* Shouldn't be used directly. */
|
||||
/* Small hack to use a pointer-to-array types as a normal argument type.
|
||||
* Shouldn't be used directly.
|
||||
*/
|
||||
typedef ALfloat ALfloatBUFFERSIZE[BUFFERSIZE];
|
||||
typedef ALfloat ALfloat2[2];
|
||||
|
||||
|
||||
/* The compressor requires the following information for proper
|
||||
* initialization:
|
||||
*
|
||||
* PreGainDb - Gain applied before detection (in dB).
|
||||
* PostGainDb - Gain applied after compression (in dB).
|
||||
* SummedLink - Whether to use summed (true) or maxed (false) linking.
|
||||
* RmsSensing - Whether to use RMS (true) or Peak (false) sensing.
|
||||
* AttackTimeMin - Minimum attack time (in seconds).
|
||||
* AttackTimeMax - Maximum attack time. Automates when min != max.
|
||||
* ReleaseTimeMin - Minimum release time (in seconds).
|
||||
* ReleaseTimeMax - Maximum release time. Automates when min != max.
|
||||
* Ratio - Compression ratio (x:1). Set to 0 for true limiter.
|
||||
* ThresholdDb - Triggering threshold (in dB).
|
||||
* KneeDb - Knee width (below threshold; in dB).
|
||||
* SampleRate - Sample rate to process.
|
||||
*/
|
||||
struct Compressor *CompressorInit(const ALfloat PreGainDb, const ALfloat PostGainDb,
|
||||
const ALboolean SummedLink, const ALboolean RmsSensing, const ALfloat AttackTimeMin,
|
||||
const ALfloat AttackTimeMax, const ALfloat ReleaseTimeMin, const ALfloat ReleaseTimeMax,
|
||||
const ALfloat Ratio, const ALfloat ThresholdDb, const ALfloat KneeDb,
|
||||
const ALuint SampleRate);
|
||||
|
||||
ALuint GetCompressorSampleRate(const struct Compressor *Comp);
|
||||
|
||||
void ApplyCompression(struct Compressor *Comp, const ALsizei NumChans, const ALsizei SamplesToDo,
|
||||
ALfloat (*restrict OutBuffer)[BUFFERSIZE]);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
#ifndef _AL_SOURCE_H_
|
||||
#define _AL_SOURCE_H_
|
||||
|
||||
#define MAX_SENDS 4
|
||||
|
||||
#include "bool.h"
|
||||
#include "alMain.h"
|
||||
#include "alu.h"
|
||||
#include "hrtf.h"
|
||||
#include "atomic.h"
|
||||
|
||||
#define MAX_SENDS 16
|
||||
#define DEFAULT_SENDS 2
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@@ -17,95 +20,48 @@ struct ALsource;
|
||||
|
||||
typedef struct ALbufferlistitem {
|
||||
struct ALbuffer *buffer;
|
||||
struct ALbufferlistitem *volatile next;
|
||||
struct ALbufferlistitem *volatile prev;
|
||||
ATOMIC(struct ALbufferlistitem*) next;
|
||||
} ALbufferlistitem;
|
||||
|
||||
|
||||
typedef struct ALvoice {
|
||||
struct ALsource *volatile Source;
|
||||
|
||||
/** Method to update mixing parameters. */
|
||||
ALvoid (*Update)(struct ALvoice *self, const struct ALsource *source, const ALCcontext *context);
|
||||
|
||||
/** Current target parameters used for mixing. */
|
||||
ALint Step;
|
||||
|
||||
ALboolean IsHrtf;
|
||||
|
||||
ALuint Offset; /* Number of output samples mixed since starting. */
|
||||
|
||||
alignas(16) ALfloat PrevSamples[MAX_INPUT_CHANNELS][MAX_PRE_SAMPLES];
|
||||
|
||||
BsincState SincState;
|
||||
|
||||
DirectParams Direct;
|
||||
SendParams Send[MAX_SENDS];
|
||||
} ALvoice;
|
||||
|
||||
|
||||
typedef struct ALsource {
|
||||
/** Source properties. */
|
||||
volatile ALfloat Pitch;
|
||||
volatile ALfloat Gain;
|
||||
volatile ALfloat OuterGain;
|
||||
volatile ALfloat MinGain;
|
||||
volatile ALfloat MaxGain;
|
||||
volatile ALfloat InnerAngle;
|
||||
volatile ALfloat OuterAngle;
|
||||
volatile ALfloat RefDistance;
|
||||
volatile ALfloat MaxDistance;
|
||||
volatile ALfloat RollOffFactor;
|
||||
aluVector Position;
|
||||
aluVector Velocity;
|
||||
aluVector Direction;
|
||||
volatile ALfloat Orientation[2][3];
|
||||
volatile ALboolean HeadRelative;
|
||||
volatile ALboolean Looping;
|
||||
volatile enum DistanceModel DistanceModel;
|
||||
volatile ALboolean DirectChannels;
|
||||
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;
|
||||
ALboolean Looping;
|
||||
enum DistanceModel DistanceModel;
|
||||
enum Resampler Resampler;
|
||||
ALboolean DirectChannels;
|
||||
enum SpatializeMode Spatialize;
|
||||
|
||||
volatile ALboolean DryGainHFAuto;
|
||||
volatile ALboolean WetGainAuto;
|
||||
volatile ALboolean WetGainHFAuto;
|
||||
volatile ALfloat OuterGainHF;
|
||||
ALboolean DryGainHFAuto;
|
||||
ALboolean WetGainAuto;
|
||||
ALboolean WetGainHFAuto;
|
||||
ALfloat OuterGainHF;
|
||||
|
||||
volatile ALfloat AirAbsorptionFactor;
|
||||
volatile ALfloat RoomRolloffFactor;
|
||||
volatile ALfloat DopplerFactor;
|
||||
ALfloat AirAbsorptionFactor;
|
||||
ALfloat RoomRolloffFactor;
|
||||
ALfloat DopplerFactor;
|
||||
|
||||
volatile ALfloat Radius;
|
||||
|
||||
/**
|
||||
* Last user-specified offset, and the offset type (bytes, samples, or
|
||||
* seconds).
|
||||
/* NOTE: Stereo pan angles are specified in radians, counter-clockwise
|
||||
* rather than clockwise.
|
||||
*/
|
||||
ALdouble Offset;
|
||||
ALenum OffsetType;
|
||||
ALfloat StereoPan[2];
|
||||
|
||||
/** Source type (static, streaming, or undetermined) */
|
||||
volatile ALint SourceType;
|
||||
|
||||
/** Source state (initial, playing, paused, or stopped) */
|
||||
volatile ALenum state;
|
||||
ALenum new_state;
|
||||
|
||||
/**
|
||||
* Source offset in samples, relative to the currently playing buffer, NOT
|
||||
* the whole queue, and the fractional (fixed-point) offset to the next
|
||||
* sample.
|
||||
*/
|
||||
ALuint position;
|
||||
ALuint position_fraction;
|
||||
|
||||
/** Source Buffer Queue info. */
|
||||
ATOMIC(ALbufferlistitem*) queue;
|
||||
ATOMIC(ALbufferlistitem*) current_buffer;
|
||||
RWLock queue_lock;
|
||||
|
||||
/** Current buffer sample info. */
|
||||
ALuint NumChannels;
|
||||
ALuint SampleSize;
|
||||
ALfloat Radius;
|
||||
|
||||
/** Direct filter and auxiliary send info. */
|
||||
struct {
|
||||
@@ -122,22 +78,46 @@ typedef struct ALsource {
|
||||
ALfloat HFReference;
|
||||
ALfloat GainLF;
|
||||
ALfloat LFReference;
|
||||
} Send[MAX_SENDS];
|
||||
} *Send;
|
||||
|
||||
/** Source needs to update its mixing parameters. */
|
||||
ATOMIC(ALenum) NeedsUpdate;
|
||||
/**
|
||||
* Last user-specified offset, and the offset type (bytes, samples, or
|
||||
* seconds).
|
||||
*/
|
||||
ALdouble Offset;
|
||||
ALenum OffsetType;
|
||||
|
||||
/** Source type (static, streaming, or undetermined) */
|
||||
ALint SourceType;
|
||||
|
||||
/** Source state (initial, playing, paused, or stopped) */
|
||||
ATOMIC(ALenum) state;
|
||||
|
||||
/** Source Buffer Queue head. */
|
||||
RWLock queue_lock;
|
||||
ALbufferlistitem *queue;
|
||||
|
||||
ATOMIC_FLAG PropsClean;
|
||||
|
||||
/** Self ID */
|
||||
ALuint id;
|
||||
} ALsource;
|
||||
|
||||
inline struct ALsource *LookupSource(ALCcontext *context, ALuint id)
|
||||
{ return (struct ALsource*)LookupUIntMapKey(&context->SourceMap, id); }
|
||||
inline struct ALsource *RemoveSource(ALCcontext *context, ALuint id)
|
||||
{ return (struct ALsource*)RemoveUIntMapKey(&context->SourceMap, id); }
|
||||
inline void LockSourcesRead(ALCcontext *context)
|
||||
{ LockUIntMapRead(&context->SourceMap); }
|
||||
inline void UnlockSourcesRead(ALCcontext *context)
|
||||
{ UnlockUIntMapRead(&context->SourceMap); }
|
||||
inline void LockSourcesWrite(ALCcontext *context)
|
||||
{ LockUIntMapWrite(&context->SourceMap); }
|
||||
inline void UnlockSourcesWrite(ALCcontext *context)
|
||||
{ UnlockUIntMapWrite(&context->SourceMap); }
|
||||
|
||||
ALvoid SetSourceState(ALsource *Source, ALCcontext *Context, ALenum state);
|
||||
ALboolean ApplyOffset(ALsource *Source);
|
||||
inline struct ALsource *LookupSource(ALCcontext *context, ALuint id)
|
||||
{ return (struct ALsource*)LookupUIntMapKeyNoLock(&context->SourceMap, id); }
|
||||
inline struct ALsource *RemoveSource(ALCcontext *context, ALuint id)
|
||||
{ return (struct ALsource*)RemoveUIntMapKeyNoLock(&context->SourceMap, id); }
|
||||
|
||||
void UpdateAllSourceProps(ALCcontext *context);
|
||||
|
||||
ALvoid ReleaseALSources(ALCcontext *Context);
|
||||
|
||||
|
||||
@@ -13,9 +13,11 @@
|
||||
#include "alMain.h"
|
||||
#include "alBuffer.h"
|
||||
#include "alFilter.h"
|
||||
#include "alAuxEffectSlot.h"
|
||||
|
||||
#include "hrtf.h"
|
||||
#include "align.h"
|
||||
#include "nfcfilter.h"
|
||||
#include "math_defs.h"
|
||||
|
||||
|
||||
@@ -33,9 +35,30 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
struct ALsource;
|
||||
struct ALbufferlistitem;
|
||||
struct ALvoice;
|
||||
struct ALeffectslot;
|
||||
|
||||
|
||||
#define DITHER_RNG_SEED 22222
|
||||
|
||||
|
||||
enum SpatializeMode {
|
||||
SpatializeOff = AL_FALSE,
|
||||
SpatializeOn = AL_TRUE,
|
||||
SpatializeAuto = AL_AUTO_SOFT
|
||||
};
|
||||
|
||||
enum Resampler {
|
||||
PointResampler,
|
||||
LinearResampler,
|
||||
FIR4Resampler,
|
||||
BSincResampler,
|
||||
|
||||
ResamplerMax = BSincResampler
|
||||
};
|
||||
extern enum Resampler ResamplerDefault;
|
||||
|
||||
/* The number of distinct scale and phase intervals within the filter table. */
|
||||
#define BSINC_SCALE_BITS 4
|
||||
#define BSINC_SCALE_COUNT (1<<BSINC_SCALE_BITS)
|
||||
@@ -58,6 +81,17 @@ typedef struct BsincState {
|
||||
} coeffs[BSINC_PHASE_COUNT];
|
||||
} BsincState;
|
||||
|
||||
typedef union InterpState {
|
||||
BsincState bsinc;
|
||||
} InterpState;
|
||||
|
||||
ALboolean BsincPrepare(const ALuint increment, BsincState *state);
|
||||
|
||||
typedef const ALfloat* (*ResamplerFunc)(const InterpState *state,
|
||||
const ALfloat *restrict src, ALsizei frac, ALint increment,
|
||||
ALfloat *restrict dst, ALsizei dstlen
|
||||
);
|
||||
|
||||
|
||||
typedef union aluVector {
|
||||
alignas(16) ALfloat v[4];
|
||||
@@ -75,6 +109,7 @@ inline void aluVectorSet(aluVector *vector, ALfloat x, ALfloat y, ALfloat z, ALf
|
||||
typedef union aluMatrixf {
|
||||
alignas(16) ALfloat m[4][4];
|
||||
} aluMatrixf;
|
||||
extern const aluMatrixf IdentityMatrixf;
|
||||
|
||||
inline void aluMatrixfSetRow(aluMatrixf *matrix, ALuint row,
|
||||
ALfloat m0, ALfloat m1, ALfloat m2, ALfloat m3)
|
||||
@@ -97,31 +132,6 @@ inline void aluMatrixfSet(aluMatrixf *matrix, ALfloat m00, ALfloat m01, ALfloat
|
||||
}
|
||||
|
||||
|
||||
typedef union aluMatrixd {
|
||||
alignas(16) ALdouble m[4][4];
|
||||
} aluMatrixd;
|
||||
|
||||
inline void aluMatrixdSetRow(aluMatrixd *matrix, ALuint row,
|
||||
ALdouble m0, ALdouble m1, ALdouble m2, ALdouble m3)
|
||||
{
|
||||
matrix->m[row][0] = m0;
|
||||
matrix->m[row][1] = m1;
|
||||
matrix->m[row][2] = m2;
|
||||
matrix->m[row][3] = m3;
|
||||
}
|
||||
|
||||
inline void aluMatrixdSet(aluMatrixd *matrix, ALdouble m00, ALdouble m01, ALdouble m02, ALdouble m03,
|
||||
ALdouble m10, ALdouble m11, ALdouble m12, ALdouble m13,
|
||||
ALdouble m20, ALdouble m21, ALdouble m22, ALdouble m23,
|
||||
ALdouble m30, ALdouble m31, ALdouble m32, ALdouble m33)
|
||||
{
|
||||
aluMatrixdSetRow(matrix, 0, m00, m01, m02, m03);
|
||||
aluMatrixdSetRow(matrix, 1, m10, m11, m12, m13);
|
||||
aluMatrixdSetRow(matrix, 2, m20, m21, m22, m23);
|
||||
aluMatrixdSetRow(matrix, 3, m30, m31, m32, m33);
|
||||
}
|
||||
|
||||
|
||||
enum ActiveFilters {
|
||||
AF_None = 0,
|
||||
AF_LowPass = 1,
|
||||
@@ -130,74 +140,200 @@ enum ActiveFilters {
|
||||
};
|
||||
|
||||
|
||||
typedef struct MixGains {
|
||||
ALfloat Current;
|
||||
ALfloat Step;
|
||||
ALfloat Target;
|
||||
} MixGains;
|
||||
typedef struct MixHrtfParams {
|
||||
const ALfloat (*Coeffs)[2];
|
||||
ALsizei Delay[2];
|
||||
ALfloat Gain;
|
||||
ALfloat GainStep;
|
||||
} MixHrtfParams;
|
||||
|
||||
|
||||
typedef struct DirectParams {
|
||||
ALfloat (*OutBuffer)[BUFFERSIZE];
|
||||
ALuint OutChannels;
|
||||
ALfilterState LowPass;
|
||||
ALfilterState HighPass;
|
||||
|
||||
/* If not 'moving', gain/coefficients are set directly without fading. */
|
||||
ALboolean Moving;
|
||||
/* Stepping counter for gain/coefficient fading. */
|
||||
ALuint Counter;
|
||||
/* Last direction (relative to listener) and gain of a moving source. */
|
||||
aluVector LastDir;
|
||||
ALfloat LastGain;
|
||||
NfcFilter NFCtrlFilter[MAX_AMBI_ORDER];
|
||||
|
||||
struct {
|
||||
enum ActiveFilters ActiveType;
|
||||
ALfilterState LowPass;
|
||||
ALfilterState HighPass;
|
||||
} Filters[MAX_INPUT_CHANNELS];
|
||||
|
||||
struct {
|
||||
HrtfParams Params;
|
||||
HrtfParams Old;
|
||||
HrtfParams Target;
|
||||
HrtfState State;
|
||||
} Hrtf[MAX_INPUT_CHANNELS];
|
||||
MixGains Gains[MAX_INPUT_CHANNELS][MAX_OUTPUT_CHANNELS];
|
||||
} Hrtf;
|
||||
|
||||
struct {
|
||||
ALfloat Current[MAX_OUTPUT_CHANNELS];
|
||||
ALfloat Target[MAX_OUTPUT_CHANNELS];
|
||||
} Gains;
|
||||
} DirectParams;
|
||||
|
||||
typedef struct SendParams {
|
||||
ALfloat (*OutBuffer)[BUFFERSIZE];
|
||||
|
||||
ALboolean Moving;
|
||||
ALuint Counter;
|
||||
ALfilterState LowPass;
|
||||
ALfilterState HighPass;
|
||||
|
||||
struct {
|
||||
enum ActiveFilters ActiveType;
|
||||
ALfilterState LowPass;
|
||||
ALfilterState HighPass;
|
||||
} Filters[MAX_INPUT_CHANNELS];
|
||||
|
||||
/* Gain control, which applies to each input channel to a single (mono)
|
||||
* output buffer. */
|
||||
MixGains Gains[MAX_INPUT_CHANNELS];
|
||||
ALfloat Current[MAX_OUTPUT_CHANNELS];
|
||||
ALfloat Target[MAX_OUTPUT_CHANNELS];
|
||||
} Gains;
|
||||
} SendParams;
|
||||
|
||||
|
||||
typedef const ALfloat* (*ResamplerFunc)(const BsincState *state,
|
||||
const ALfloat *src, ALuint frac, ALuint increment, ALfloat *restrict dst, ALuint dstlen
|
||||
);
|
||||
struct ALvoiceProps {
|
||||
ATOMIC(struct ALvoiceProps*) next;
|
||||
|
||||
typedef void (*MixerFunc)(const ALfloat *data, ALuint OutChans,
|
||||
ALfloat (*restrict OutBuffer)[BUFFERSIZE], struct MixGains *Gains,
|
||||
ALuint Counter, ALuint OutPos, ALuint BufferSize);
|
||||
typedef void (*HrtfMixerFunc)(ALfloat (*restrict OutBuffer)[BUFFERSIZE], const ALfloat *data,
|
||||
ALuint Counter, ALuint Offset, ALuint OutPos,
|
||||
const ALuint IrSize, const HrtfParams *hrtfparams,
|
||||
HrtfState *hrtfstate, ALuint BufferSize);
|
||||
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;
|
||||
enum Resampler Resampler;
|
||||
ALboolean DirectChannels;
|
||||
enum SpatializeMode SpatializeMode;
|
||||
|
||||
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 'fading', gain targets are used directly without fading. */
|
||||
#define VOICE_IS_FADING (1<<0)
|
||||
#define VOICE_HAS_HRTF (1<<1)
|
||||
#define VOICE_HAS_NFC (1<<2)
|
||||
|
||||
typedef struct ALvoice {
|
||||
struct ALvoiceProps *Props;
|
||||
|
||||
ATOMIC(struct ALvoiceProps*) Update;
|
||||
ATOMIC(struct ALvoiceProps*) FreeList;
|
||||
|
||||
ATOMIC(struct ALsource*) Source;
|
||||
ATOMIC(bool) Playing;
|
||||
|
||||
/**
|
||||
* Source offset in samples, relative to the currently playing buffer, NOT
|
||||
* the whole queue, and the fractional (fixed-point) offset to the next
|
||||
* sample.
|
||||
*/
|
||||
ATOMIC(ALuint) position;
|
||||
ATOMIC(ALsizei) position_fraction;
|
||||
|
||||
/* Current buffer queue item being played. */
|
||||
ATOMIC(struct ALbufferlistitem*) current_buffer;
|
||||
|
||||
/* Buffer queue item to loop to at end of queue (will be NULL for non-
|
||||
* looping voices).
|
||||
*/
|
||||
ATOMIC(struct ALbufferlistitem*) loop_buffer;
|
||||
|
||||
/**
|
||||
* Number of channels and bytes-per-sample for the attached source's
|
||||
* buffer(s).
|
||||
*/
|
||||
ALsizei NumChannels;
|
||||
ALsizei SampleSize;
|
||||
|
||||
/** Current target parameters used for mixing. */
|
||||
ALint Step;
|
||||
|
||||
ResamplerFunc Resampler;
|
||||
|
||||
ALuint Flags;
|
||||
|
||||
ALuint Offset; /* Number of output samples mixed since starting. */
|
||||
|
||||
alignas(16) ALfloat PrevSamples[MAX_INPUT_CHANNELS][MAX_PRE_SAMPLES];
|
||||
|
||||
InterpState ResampleState;
|
||||
|
||||
struct {
|
||||
enum ActiveFilters FilterType;
|
||||
DirectParams Params[MAX_INPUT_CHANNELS];
|
||||
|
||||
ALfloat (*Buffer)[BUFFERSIZE];
|
||||
ALsizei Channels;
|
||||
ALsizei ChannelsPerOrder[MAX_AMBI_ORDER+1];
|
||||
} Direct;
|
||||
|
||||
struct {
|
||||
enum ActiveFilters FilterType;
|
||||
SendParams Params[MAX_INPUT_CHANNELS];
|
||||
|
||||
ALfloat (*Buffer)[BUFFERSIZE];
|
||||
ALsizei Channels;
|
||||
} Send[];
|
||||
} ALvoice;
|
||||
|
||||
void DeinitVoice(ALvoice *voice);
|
||||
|
||||
|
||||
typedef void (*MixerFunc)(const ALfloat *data, ALsizei OutChans,
|
||||
ALfloat (*restrict OutBuffer)[BUFFERSIZE], ALfloat *CurrentGains,
|
||||
const ALfloat *TargetGains, ALsizei Counter, ALsizei OutPos,
|
||||
ALsizei BufferSize);
|
||||
typedef void (*RowMixerFunc)(ALfloat *OutBuffer, const ALfloat *gains,
|
||||
const ALfloat (*restrict data)[BUFFERSIZE], ALsizei InChans,
|
||||
ALsizei InPos, ALsizei BufferSize);
|
||||
typedef void (*HrtfMixerFunc)(ALfloat *restrict LeftOut, ALfloat *restrict RightOut,
|
||||
const ALfloat *data, ALsizei Offset, ALsizei OutPos,
|
||||
const ALsizei IrSize, MixHrtfParams *hrtfparams,
|
||||
HrtfState *hrtfstate, ALsizei BufferSize);
|
||||
typedef void (*HrtfMixerBlendFunc)(ALfloat *restrict LeftOut, ALfloat *restrict RightOut,
|
||||
const ALfloat *data, ALsizei Offset, ALsizei OutPos,
|
||||
const ALsizei IrSize, const HrtfParams *oldparams,
|
||||
MixHrtfParams *newparams, HrtfState *hrtfstate,
|
||||
ALsizei BufferSize);
|
||||
typedef void (*HrtfDirectMixerFunc)(ALfloat *restrict LeftOut, ALfloat *restrict RightOut,
|
||||
const ALfloat *data, ALsizei Offset, const ALsizei IrSize,
|
||||
const ALfloat (*restrict Coeffs)[2],
|
||||
ALfloat (*restrict Values)[2], ALsizei BufferSize);
|
||||
|
||||
|
||||
#define GAIN_MIX_MAX (16.0f) /* +24dB */
|
||||
|
||||
#define GAIN_SILENCE_THRESHOLD (0.00001f) /* -100dB */
|
||||
|
||||
#define SPEEDOFSOUNDMETRESPERSEC (343.3f)
|
||||
#define AIRABSORBGAINHF (0.99426f) /* -0.05dB */
|
||||
|
||||
/* Target gain for the reverb decay feedback reaching the decay time. */
|
||||
#define REVERB_DECAY_GAIN (0.001f) /* -60 dB */
|
||||
|
||||
#define FRACTIONBITS (12)
|
||||
#define FRACTIONONE (1<<FRACTIONBITS)
|
||||
#define FRACTIONMASK (FRACTIONONE-1)
|
||||
@@ -246,79 +382,129 @@ inline ALuint64 clampu64(ALuint64 val, ALuint64 min, ALuint64 max)
|
||||
{ return minu64(max, maxu64(min, val)); }
|
||||
|
||||
|
||||
union ResamplerCoeffs {
|
||||
ALfloat FIR4[FRACTIONONE][4];
|
||||
ALfloat FIR8[FRACTIONONE][8];
|
||||
};
|
||||
extern alignas(16) union ResamplerCoeffs ResampleCoeffs;
|
||||
|
||||
extern alignas(16) const ALfloat bsincTab[18840];
|
||||
extern alignas(16) const ALfloat sinc4Tab[FRACTIONONE][4];
|
||||
|
||||
|
||||
inline ALfloat lerp(ALfloat val1, ALfloat val2, ALfloat mu)
|
||||
{
|
||||
return val1 + (val2-val1)*mu;
|
||||
}
|
||||
inline ALfloat resample_fir4(ALfloat val0, ALfloat val1, ALfloat val2, ALfloat val3, ALuint frac)
|
||||
inline ALfloat resample_fir4(ALfloat val0, ALfloat val1, ALfloat val2, ALfloat val3, ALsizei frac)
|
||||
{
|
||||
const ALfloat *k = ResampleCoeffs.FIR4[frac];
|
||||
return k[0]*val0 + k[1]*val1 + k[2]*val2 + k[3]*val3;
|
||||
}
|
||||
inline ALfloat resample_fir8(ALfloat val0, ALfloat val1, ALfloat val2, ALfloat val3, ALfloat val4, ALfloat val5, ALfloat val6, ALfloat val7, ALuint frac)
|
||||
{
|
||||
const ALfloat *k = ResampleCoeffs.FIR8[frac];
|
||||
return k[0]*val0 + k[1]*val1 + k[2]*val2 + k[3]*val3 +
|
||||
k[4]*val4 + k[5]*val5 + k[6]*val6 + k[7]*val7;
|
||||
return sinc4Tab[frac][0]*val0 + sinc4Tab[frac][1]*val1 +
|
||||
sinc4Tab[frac][2]*val2 + sinc4Tab[frac][3]*val3;
|
||||
}
|
||||
|
||||
|
||||
enum HrtfRequestMode {
|
||||
Hrtf_Default = 0,
|
||||
Hrtf_Enable = 1,
|
||||
Hrtf_Disable = 2,
|
||||
};
|
||||
|
||||
void aluInitMixer(void);
|
||||
|
||||
ALvoid aluInitPanning(ALCdevice *Device);
|
||||
MixerFunc SelectMixer(void);
|
||||
RowMixerFunc SelectRowMixer(void);
|
||||
ResamplerFunc SelectResampler(enum Resampler resampler);
|
||||
|
||||
/* aluInitRenderer
|
||||
*
|
||||
* Set up the appropriate panning method and mixing method given the device
|
||||
* properties.
|
||||
*/
|
||||
void aluInitRenderer(ALCdevice *device, ALint hrtf_id, enum HrtfRequestMode hrtf_appreq, enum HrtfRequestMode hrtf_userreq);
|
||||
|
||||
void aluInitEffectPanning(struct ALeffectslot *slot);
|
||||
|
||||
/**
|
||||
* ComputeDirectionalGains
|
||||
* CalcDirectionCoeffs
|
||||
*
|
||||
* Sets channel gains based on a direction. The direction must be a 3-component
|
||||
* vector no longer than 1 unit.
|
||||
* 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).
|
||||
*/
|
||||
void ComputeDirectionalGains(const ALCdevice *device, const ALfloat dir[3], ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]);
|
||||
void CalcDirectionCoeffs(const ALfloat dir[3], ALfloat spread, ALfloat coeffs[MAX_AMBI_COEFFS]);
|
||||
|
||||
/**
|
||||
* ComputeAngleGains
|
||||
* CalcAngleCoeffs
|
||||
*
|
||||
* Sets channel gains based on angle and elevation. The angle and elevation
|
||||
* parameters are in radians, going right and up respectively.
|
||||
* Calculates ambisonic coefficients based on azimuth and elevation. The
|
||||
* azimuth and elevation parameters are in radians, going right and up
|
||||
* respectively.
|
||||
*/
|
||||
void ComputeAngleGains(const ALCdevice *device, ALfloat angle, ALfloat elevation, ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]);
|
||||
inline void CalcAngleCoeffs(ALfloat azimuth, ALfloat elevation, ALfloat spread, ALfloat coeffs[MAX_AMBI_COEFFS])
|
||||
{
|
||||
ALfloat dir[3] = {
|
||||
sinf(azimuth) * cosf(elevation),
|
||||
sinf(elevation),
|
||||
-cosf(azimuth) * cosf(elevation)
|
||||
};
|
||||
CalcDirectionCoeffs(dir, spread, coeffs);
|
||||
}
|
||||
|
||||
/**
|
||||
* CalcAnglePairwiseCoeffs
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
void CalcAnglePairwiseCoeffs(ALfloat azimuth, ALfloat elevation, ALfloat spread, ALfloat coeffs[MAX_AMBI_COEFFS]);
|
||||
|
||||
/**
|
||||
* ComputeAmbientGains
|
||||
*
|
||||
* Sets channel gains for ambient, omni-directional sounds.
|
||||
* Computes channel gains for ambient, omni-directional sounds.
|
||||
*/
|
||||
void ComputeAmbientGains(const ALCdevice *device, ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]);
|
||||
#define ComputeAmbientGains(b, g, o) do { \
|
||||
if((b).CoeffCount > 0) \
|
||||
ComputeAmbientGainsMC((b).Ambi.Coeffs, (b).NumChannels, g, o); \
|
||||
else \
|
||||
ComputeAmbientGainsBF((b).Ambi.Map, (b).NumChannels, g, o); \
|
||||
} while (0)
|
||||
void ComputeAmbientGainsMC(const ChannelConfig *chancoeffs, ALsizei numchans, ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]);
|
||||
void ComputeAmbientGainsBF(const BFChannelConfig *chanmap, ALsizei numchans, ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]);
|
||||
|
||||
/**
|
||||
* ComputeBFormatGains
|
||||
* ComputePanningGains
|
||||
*
|
||||
* Sets channel gains for a given (first-order) B-Format channel. The matrix is
|
||||
* a 1x4 'slice' of the rotation matrix for a given channel used to orient the
|
||||
* coefficients.
|
||||
* Computes panning gains using the given channel decoder coefficients and the
|
||||
* pre-calculated direction or angle coefficients.
|
||||
*/
|
||||
void ComputeBFormatGains(const ALCdevice *device, const ALfloat mtx[4], ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]);
|
||||
#define ComputePanningGains(b, c, g, o) do { \
|
||||
if((b).CoeffCount > 0) \
|
||||
ComputePanningGainsMC((b).Ambi.Coeffs, (b).NumChannels, (b).CoeffCount, c, g, o);\
|
||||
else \
|
||||
ComputePanningGainsBF((b).Ambi.Map, (b).NumChannels, c, g, o); \
|
||||
} while (0)
|
||||
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]);
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
#define ComputeFirstOrderGains(b, m, g, o) do { \
|
||||
if((b).CoeffCount > 0) \
|
||||
ComputeFirstOrderGainsMC((b).Ambi.Coeffs, (b).NumChannels, m, g, o); \
|
||||
else \
|
||||
ComputeFirstOrderGainsBF((b).Ambi.Map, (b).NumChannels, m, g, o); \
|
||||
} while (0)
|
||||
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]);
|
||||
|
||||
|
||||
ALvoid UpdateContextSources(ALCcontext *context);
|
||||
ALboolean MixSource(struct ALvoice *voice, struct ALsource *Source, ALCdevice *Device, ALsizei SamplesToDo);
|
||||
|
||||
ALvoid CalcSourceParams(struct ALvoice *voice, const struct ALsource *source, const ALCcontext *ALContext);
|
||||
ALvoid CalcNonAttnSourceParams(struct ALvoice *voice, const struct ALsource *source, const ALCcontext *ALContext);
|
||||
|
||||
ALvoid MixSource(struct ALvoice *voice, struct ALsource *source, ALCdevice *Device, ALuint SamplesToDo);
|
||||
|
||||
ALvoid aluMixData(ALCdevice *device, ALvoid *buffer, ALsizei size);
|
||||
void aluMixData(ALCdevice *device, ALvoid *OutBuffer, ALsizei NumSamples);
|
||||
/* Caller must lock the device. */
|
||||
ALvoid aluHandleDisconnect(ALCdevice *device);
|
||||
void aluHandleDisconnect(ALCdevice *device);
|
||||
|
||||
extern ALfloat ConeScale;
|
||||
extern ALfloat ZScale;
|
||||
|
||||
@@ -63,10 +63,10 @@ struct bs2b {
|
||||
* [0] - first channel, [1] - second channel
|
||||
*/
|
||||
struct t_last_sample {
|
||||
float asis[2];
|
||||
float lo[2];
|
||||
float hi[2];
|
||||
} last_sample;
|
||||
float asis;
|
||||
float lo;
|
||||
float hi;
|
||||
} last_sample[2];
|
||||
};
|
||||
|
||||
/* Clear buffers and set new coefficients with new crossfeed level and sample
|
||||
@@ -85,38 +85,7 @@ int bs2b_get_srate(struct bs2b *bs2b);
|
||||
/* Clear buffer */
|
||||
void bs2b_clear(struct bs2b *bs2b);
|
||||
|
||||
/* Crossfeeds one stereo sample that are pointed by sample.
|
||||
* [0] - first channel, [1] - second channel.
|
||||
* Returns crossfided sample by sample pointer.
|
||||
*/
|
||||
inline void bs2b_cross_feed(struct bs2b *bs2b, float *restrict sample)
|
||||
{
|
||||
/* Single pole IIR filter.
|
||||
* O[n] = a0*I[n] + a1*I[n-1] + b1*O[n-1]
|
||||
*/
|
||||
|
||||
/* Lowpass filter */
|
||||
#define lo_filter(in, out_1) (bs2b->a0_lo*(in) + bs2b->b1_lo*(out_1))
|
||||
|
||||
/* Highboost filter */
|
||||
#define hi_filter(in, in_1, out_1) (bs2b->a0_hi*(in) + bs2b->a1_hi*(in_1) + bs2b->b1_hi*(out_1))
|
||||
|
||||
/* Lowpass filter */
|
||||
bs2b->last_sample.lo[0] = lo_filter(sample[0], bs2b->last_sample.lo[0]);
|
||||
bs2b->last_sample.lo[1] = lo_filter(sample[1], bs2b->last_sample.lo[1]);
|
||||
|
||||
/* Highboost filter */
|
||||
bs2b->last_sample.hi[0] = hi_filter(sample[0], bs2b->last_sample.asis[0], bs2b->last_sample.hi[0]);
|
||||
bs2b->last_sample.hi[1] = hi_filter(sample[1], bs2b->last_sample.asis[1], bs2b->last_sample.hi[1]);
|
||||
bs2b->last_sample.asis[0] = sample[0];
|
||||
bs2b->last_sample.asis[1] = sample[1];
|
||||
|
||||
/* Crossfeed */
|
||||
sample[0] = bs2b->last_sample.hi[0] + bs2b->last_sample.lo[1];
|
||||
sample[1] = bs2b->last_sample.hi[1] + bs2b->last_sample.lo[0];
|
||||
#undef hi_filter
|
||||
#undef lo_filter
|
||||
} /* bs2b_cross_feed */
|
||||
void bs2b_cross_feed(struct bs2b *bs2b, float *restrict Left, float *restrict Right, int SamplesToDo);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
|
||||
@@ -29,16 +29,19 @@
|
||||
#include "alAuxEffectSlot.h"
|
||||
#include "alThunk.h"
|
||||
#include "alError.h"
|
||||
#include "alListener.h"
|
||||
#include "alSource.h"
|
||||
|
||||
#include "almalloc.h"
|
||||
|
||||
|
||||
extern inline void LockEffectSlotsRead(ALCcontext *context);
|
||||
extern inline void UnlockEffectSlotsRead(ALCcontext *context);
|
||||
extern inline void LockEffectSlotsWrite(ALCcontext *context);
|
||||
extern inline void UnlockEffectSlotsWrite(ALCcontext *context);
|
||||
extern inline struct ALeffectslot *LookupEffectSlot(ALCcontext *context, ALuint id);
|
||||
extern inline struct ALeffectslot *RemoveEffectSlot(ALCcontext *context, ALuint id);
|
||||
|
||||
static ALenum AddEffectSlotArray(ALCcontext *Context, ALeffectslot **start, ALsizei count);
|
||||
static void RemoveEffectSlotArray(ALCcontext *Context, const ALeffectslot *slot);
|
||||
|
||||
|
||||
static UIntMap EffectStateFactoryMap;
|
||||
static inline ALeffectStateFactory *getFactoryByType(ALenum type)
|
||||
{
|
||||
@@ -48,24 +51,32 @@ static inline ALeffectStateFactory *getFactoryByType(ALenum type)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void ALeffectState_IncRef(ALeffectState *state);
|
||||
static void ALeffectState_DecRef(ALeffectState *state);
|
||||
|
||||
#define DO_UPDATEPROPS() do { \
|
||||
if(!ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire)) \
|
||||
UpdateEffectSlotProps(slot); \
|
||||
else \
|
||||
ATOMIC_FLAG_CLEAR(&slot->PropsClean, almemory_order_release); \
|
||||
} while(0)
|
||||
|
||||
|
||||
AL_API ALvoid AL_APIENTRY alGenAuxiliaryEffectSlots(ALsizei n, ALuint *effectslots)
|
||||
{
|
||||
ALCcontext *context;
|
||||
VECTOR(ALeffectslot*) slotvec;
|
||||
ALeffectslot **tmpslots = NULL;
|
||||
ALsizei cur;
|
||||
ALenum err;
|
||||
|
||||
context = GetContextRef();
|
||||
if(!context) return;
|
||||
|
||||
VECTOR_INIT(slotvec);
|
||||
|
||||
if(!(n >= 0))
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
|
||||
if(!VECTOR_RESERVE(slotvec, n))
|
||||
SET_ERROR_AND_GOTO(context, AL_OUT_OF_MEMORY, done);
|
||||
tmpslots = al_malloc(DEF_ALIGN, sizeof(ALeffectslot*)*n);
|
||||
|
||||
LockEffectSlotsWrite(context);
|
||||
for(cur = 0;cur < n;cur++)
|
||||
{
|
||||
ALeffectslot *slot = al_calloc(16, sizeof(ALeffectslot));
|
||||
@@ -73,37 +84,57 @@ AL_API ALvoid AL_APIENTRY alGenAuxiliaryEffectSlots(ALsizei n, ALuint *effectslo
|
||||
if(!slot || (err=InitEffectSlot(slot)) != AL_NO_ERROR)
|
||||
{
|
||||
al_free(slot);
|
||||
UnlockEffectSlotsWrite(context);
|
||||
|
||||
alDeleteAuxiliaryEffectSlots(cur, effectslots);
|
||||
SET_ERROR_AND_GOTO(context, err, done);
|
||||
}
|
||||
|
||||
err = NewThunkEntry(&slot->id);
|
||||
if(err == AL_NO_ERROR)
|
||||
err = InsertUIntMapEntry(&context->EffectSlotMap, slot->id, slot);
|
||||
err = InsertUIntMapEntryNoLock(&context->EffectSlotMap, slot->id, slot);
|
||||
if(err != AL_NO_ERROR)
|
||||
{
|
||||
FreeThunkEntry(slot->id);
|
||||
DELETE_OBJ(slot->EffectState);
|
||||
ALeffectState_DecRef(slot->Effect.State);
|
||||
if(slot->Params.EffectState)
|
||||
ALeffectState_DecRef(slot->Params.EffectState);
|
||||
al_free(slot);
|
||||
UnlockEffectSlotsWrite(context);
|
||||
|
||||
alDeleteAuxiliaryEffectSlots(cur, effectslots);
|
||||
SET_ERROR_AND_GOTO(context, err, done);
|
||||
}
|
||||
|
||||
VECTOR_PUSH_BACK(slotvec, slot);
|
||||
aluInitEffectPanning(slot);
|
||||
|
||||
tmpslots[cur] = slot;
|
||||
effectslots[cur] = slot->id;
|
||||
}
|
||||
err = AddEffectSlotArray(context, VECTOR_ITER_BEGIN(slotvec), n);
|
||||
if(err != AL_NO_ERROR)
|
||||
if(n > 0)
|
||||
{
|
||||
alDeleteAuxiliaryEffectSlots(cur, effectslots);
|
||||
SET_ERROR_AND_GOTO(context, err, done);
|
||||
struct ALeffectslotArray *curarray = ATOMIC_LOAD(&context->ActiveAuxSlots, almemory_order_acquire);
|
||||
struct ALeffectslotArray *newarray = NULL;
|
||||
ALsizei newcount = curarray->count + n;
|
||||
ALCdevice *device;
|
||||
|
||||
newarray = al_calloc(DEF_ALIGN, FAM_SIZE(struct ALeffectslotArray, slot, newcount));
|
||||
newarray->count = newcount;
|
||||
memcpy(newarray->slot, tmpslots, sizeof(ALeffectslot*)*n);
|
||||
if(curarray)
|
||||
memcpy(newarray->slot+n, curarray->slot, sizeof(ALeffectslot*)*curarray->count);
|
||||
|
||||
newarray = ATOMIC_EXCHANGE_PTR(&context->ActiveAuxSlots, newarray,
|
||||
almemory_order_acq_rel);
|
||||
device = context->Device;
|
||||
while((ATOMIC_LOAD(&device->MixCount, almemory_order_acquire)&1))
|
||||
althrd_yield();
|
||||
al_free(newarray);
|
||||
}
|
||||
UnlockEffectSlotsWrite(context);
|
||||
|
||||
done:
|
||||
VECTOR_DEINIT(slotvec);
|
||||
|
||||
al_free(tmpslots);
|
||||
ALCcontext_DecRef(context);
|
||||
}
|
||||
|
||||
@@ -116,6 +147,7 @@ AL_API ALvoid AL_APIENTRY alDeleteAuxiliaryEffectSlots(ALsizei n, const ALuint *
|
||||
context = GetContextRef();
|
||||
if(!context) return;
|
||||
|
||||
LockEffectSlotsWrite(context);
|
||||
if(!(n >= 0))
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
|
||||
for(i = 0;i < n;i++)
|
||||
@@ -127,20 +159,51 @@ AL_API ALvoid AL_APIENTRY alDeleteAuxiliaryEffectSlots(ALsizei n, const ALuint *
|
||||
}
|
||||
|
||||
// All effectslots are valid
|
||||
if(n > 0)
|
||||
{
|
||||
struct ALeffectslotArray *curarray = ATOMIC_LOAD(&context->ActiveAuxSlots, almemory_order_acquire);
|
||||
struct ALeffectslotArray *newarray = NULL;
|
||||
ALsizei newcount = curarray->count - n;
|
||||
ALCdevice *device;
|
||||
ALsizei j, k;
|
||||
|
||||
assert(newcount >= 0);
|
||||
newarray = al_calloc(DEF_ALIGN, FAM_SIZE(struct ALeffectslotArray, slot, newcount));
|
||||
newarray->count = newcount;
|
||||
for(i = j = 0;i < newarray->count;)
|
||||
{
|
||||
slot = curarray->slot[j++];
|
||||
for(k = 0;k < n;k++)
|
||||
{
|
||||
if(slot->id == effectslots[k])
|
||||
break;
|
||||
}
|
||||
if(k == n)
|
||||
newarray->slot[i++] = slot;
|
||||
}
|
||||
|
||||
newarray = ATOMIC_EXCHANGE_PTR(&context->ActiveAuxSlots, newarray,
|
||||
almemory_order_acq_rel);
|
||||
device = context->Device;
|
||||
while((ATOMIC_LOAD(&device->MixCount, almemory_order_acquire)&1))
|
||||
althrd_yield();
|
||||
al_free(newarray);
|
||||
}
|
||||
|
||||
for(i = 0;i < n;i++)
|
||||
{
|
||||
if((slot=RemoveEffectSlot(context, effectslots[i])) == NULL)
|
||||
continue;
|
||||
FreeThunkEntry(slot->id);
|
||||
|
||||
RemoveEffectSlotArray(context, slot);
|
||||
DELETE_OBJ(slot->EffectState);
|
||||
DeinitEffectSlot(slot);
|
||||
|
||||
memset(slot, 0, sizeof(*slot));
|
||||
al_free(slot);
|
||||
}
|
||||
|
||||
done:
|
||||
UnlockEffectSlotsWrite(context);
|
||||
ALCcontext_DecRef(context);
|
||||
}
|
||||
|
||||
@@ -152,7 +215,9 @@ AL_API ALboolean AL_APIENTRY alIsAuxiliaryEffectSlot(ALuint effectslot)
|
||||
context = GetContextRef();
|
||||
if(!context) return AL_FALSE;
|
||||
|
||||
LockEffectSlotsRead(context);
|
||||
ret = (LookupEffectSlot(context, effectslot) ? AL_TRUE : AL_FALSE);
|
||||
UnlockEffectSlotsRead(context);
|
||||
|
||||
ALCcontext_DecRef(context);
|
||||
|
||||
@@ -170,35 +235,43 @@ AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSloti(ALuint effectslot, ALenum param
|
||||
context = GetContextRef();
|
||||
if(!context) return;
|
||||
|
||||
device = context->Device;
|
||||
WriteLock(&context->PropLock);
|
||||
LockEffectSlotsRead(context);
|
||||
if((slot=LookupEffectSlot(context, effectslot)) == NULL)
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
|
||||
switch(param)
|
||||
{
|
||||
case AL_EFFECTSLOT_EFFECT:
|
||||
device = context->Device;
|
||||
|
||||
LockEffectsRead(device);
|
||||
effect = (value ? LookupEffect(device, value) : NULL);
|
||||
if(!(value == 0 || effect != NULL))
|
||||
{
|
||||
UnlockEffectsRead(device);
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
|
||||
|
||||
}
|
||||
err = InitializeEffect(device, slot, effect);
|
||||
UnlockEffectsRead(device);
|
||||
|
||||
if(err != AL_NO_ERROR)
|
||||
SET_ERROR_AND_GOTO(context, err, done);
|
||||
ATOMIC_STORE(&context->UpdateSources, AL_TRUE);
|
||||
break;
|
||||
|
||||
case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:
|
||||
if(!(value == AL_TRUE || value == AL_FALSE))
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
|
||||
|
||||
slot->AuxSendAuto = value;
|
||||
ATOMIC_STORE(&context->UpdateSources, AL_TRUE);
|
||||
break;
|
||||
|
||||
default:
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
|
||||
}
|
||||
DO_UPDATEPROPS();
|
||||
|
||||
done:
|
||||
UnlockEffectSlotsRead(context);
|
||||
WriteUnlock(&context->PropLock);
|
||||
ALCcontext_DecRef(context);
|
||||
}
|
||||
|
||||
@@ -217,6 +290,7 @@ AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotiv(ALuint effectslot, ALenum para
|
||||
context = GetContextRef();
|
||||
if(!context) return;
|
||||
|
||||
LockEffectSlotsRead(context);
|
||||
if(LookupEffectSlot(context, effectslot) == NULL)
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
|
||||
switch(param)
|
||||
@@ -226,6 +300,7 @@ AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotiv(ALuint effectslot, ALenum para
|
||||
}
|
||||
|
||||
done:
|
||||
UnlockEffectSlotsRead(context);
|
||||
ALCcontext_DecRef(context);
|
||||
}
|
||||
|
||||
@@ -237,6 +312,8 @@ AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotf(ALuint effectslot, ALenum param
|
||||
context = GetContextRef();
|
||||
if(!context) return;
|
||||
|
||||
WriteLock(&context->PropLock);
|
||||
LockEffectSlotsRead(context);
|
||||
if((slot=LookupEffectSlot(context, effectslot)) == NULL)
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
|
||||
switch(param)
|
||||
@@ -244,16 +321,17 @@ AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotf(ALuint effectslot, ALenum param
|
||||
case AL_EFFECTSLOT_GAIN:
|
||||
if(!(value >= 0.0f && value <= 1.0f))
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
|
||||
|
||||
slot->Gain = value;
|
||||
ATOMIC_STORE(&slot->NeedsUpdate, AL_TRUE);
|
||||
break;
|
||||
|
||||
default:
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
|
||||
}
|
||||
DO_UPDATEPROPS();
|
||||
|
||||
done:
|
||||
UnlockEffectSlotsRead(context);
|
||||
WriteUnlock(&context->PropLock);
|
||||
ALCcontext_DecRef(context);
|
||||
}
|
||||
|
||||
@@ -271,6 +349,7 @@ AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotfv(ALuint effectslot, ALenum para
|
||||
context = GetContextRef();
|
||||
if(!context) return;
|
||||
|
||||
LockEffectSlotsRead(context);
|
||||
if(LookupEffectSlot(context, effectslot) == NULL)
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
|
||||
switch(param)
|
||||
@@ -280,6 +359,7 @@ AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotfv(ALuint effectslot, ALenum para
|
||||
}
|
||||
|
||||
done:
|
||||
UnlockEffectSlotsRead(context);
|
||||
ALCcontext_DecRef(context);
|
||||
}
|
||||
|
||||
@@ -291,6 +371,7 @@ AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSloti(ALuint effectslot, ALenum pa
|
||||
context = GetContextRef();
|
||||
if(!context) return;
|
||||
|
||||
LockEffectSlotsRead(context);
|
||||
if((slot=LookupEffectSlot(context, effectslot)) == NULL)
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
|
||||
switch(param)
|
||||
@@ -304,6 +385,7 @@ AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSloti(ALuint effectslot, ALenum pa
|
||||
}
|
||||
|
||||
done:
|
||||
UnlockEffectSlotsRead(context);
|
||||
ALCcontext_DecRef(context);
|
||||
}
|
||||
|
||||
@@ -322,6 +404,7 @@ AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotiv(ALuint effectslot, ALenum p
|
||||
context = GetContextRef();
|
||||
if(!context) return;
|
||||
|
||||
LockEffectSlotsRead(context);
|
||||
if(LookupEffectSlot(context, effectslot) == NULL)
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
|
||||
switch(param)
|
||||
@@ -331,6 +414,7 @@ AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotiv(ALuint effectslot, ALenum p
|
||||
}
|
||||
|
||||
done:
|
||||
UnlockEffectSlotsRead(context);
|
||||
ALCcontext_DecRef(context);
|
||||
}
|
||||
|
||||
@@ -342,6 +426,7 @@ AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotf(ALuint effectslot, ALenum pa
|
||||
context = GetContextRef();
|
||||
if(!context) return;
|
||||
|
||||
LockEffectSlotsRead(context);
|
||||
if((slot=LookupEffectSlot(context, effectslot)) == NULL)
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
|
||||
switch(param)
|
||||
@@ -355,6 +440,7 @@ AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotf(ALuint effectslot, ALenum pa
|
||||
}
|
||||
|
||||
done:
|
||||
UnlockEffectSlotsRead(context);
|
||||
ALCcontext_DecRef(context);
|
||||
}
|
||||
|
||||
@@ -372,6 +458,7 @@ AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotfv(ALuint effectslot, ALenum p
|
||||
context = GetContextRef();
|
||||
if(!context) return;
|
||||
|
||||
LockEffectSlotsRead(context);
|
||||
if(LookupEffectSlot(context, effectslot) == NULL)
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
|
||||
switch(param)
|
||||
@@ -381,47 +468,18 @@ AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotfv(ALuint effectslot, ALenum p
|
||||
}
|
||||
|
||||
done:
|
||||
UnlockEffectSlotsRead(context);
|
||||
ALCcontext_DecRef(context);
|
||||
}
|
||||
|
||||
|
||||
static ALenum AddEffectSlotArray(ALCcontext *context, ALeffectslot **start, ALsizei count)
|
||||
{
|
||||
ALenum err = AL_NO_ERROR;
|
||||
|
||||
LockContext(context);
|
||||
if(!VECTOR_INSERT(context->ActiveAuxSlots, VECTOR_ITER_END(context->ActiveAuxSlots), start, start+count))
|
||||
err = AL_OUT_OF_MEMORY;
|
||||
UnlockContext(context);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static void RemoveEffectSlotArray(ALCcontext *context, const ALeffectslot *slot)
|
||||
{
|
||||
ALeffectslot **iter;
|
||||
|
||||
LockContext(context);
|
||||
#define MATCH_SLOT(_i) (slot == *(_i))
|
||||
VECTOR_FIND_IF(iter, ALeffectslot*, context->ActiveAuxSlots, MATCH_SLOT);
|
||||
if(iter != VECTOR_ITER_END(context->ActiveAuxSlots))
|
||||
{
|
||||
*iter = VECTOR_BACK(context->ActiveAuxSlots);
|
||||
VECTOR_POP_BACK(context->ActiveAuxSlots);
|
||||
}
|
||||
#undef MATCH_SLOT
|
||||
UnlockContext(context);
|
||||
}
|
||||
|
||||
|
||||
void InitEffectFactoryMap(void)
|
||||
{
|
||||
InitUIntMap(&EffectStateFactoryMap, ~0);
|
||||
InitUIntMap(&EffectStateFactoryMap, INT_MAX);
|
||||
|
||||
InsertUIntMapEntry(&EffectStateFactoryMap, AL_EFFECT_NULL, ALnullStateFactory_getFactory);
|
||||
InsertUIntMapEntry(&EffectStateFactoryMap, AL_EFFECT_EAXREVERB, ALreverbStateFactory_getFactory);
|
||||
InsertUIntMapEntry(&EffectStateFactoryMap, AL_EFFECT_REVERB, ALreverbStateFactory_getFactory);
|
||||
InsertUIntMapEntry(&EffectStateFactoryMap, AL_EFFECT_AUTOWAH, ALautowahStateFactory_getFactory);
|
||||
InsertUIntMapEntry(&EffectStateFactoryMap, AL_EFFECT_CHORUS, ALchorusStateFactory_getFactory);
|
||||
InsertUIntMapEntry(&EffectStateFactoryMap, AL_EFFECT_COMPRESSOR, ALcompressorStateFactory_getFactory);
|
||||
InsertUIntMapEntry(&EffectStateFactoryMap, AL_EFFECT_DISTORTION, ALdistortionStateFactory_getFactory);
|
||||
@@ -442,12 +500,12 @@ void DeinitEffectFactoryMap(void)
|
||||
ALenum InitializeEffect(ALCdevice *Device, ALeffectslot *EffectSlot, ALeffect *effect)
|
||||
{
|
||||
ALenum newtype = (effect ? effect->type : AL_EFFECT_NULL);
|
||||
ALeffectStateFactory *factory;
|
||||
struct ALeffectslotProps *props;
|
||||
ALeffectState *State;
|
||||
|
||||
if(newtype != EffectSlot->EffectType)
|
||||
if(newtype != EffectSlot->Effect.Type)
|
||||
{
|
||||
ALeffectState *State;
|
||||
FPUCtl oldMode;
|
||||
ALeffectStateFactory *factory;
|
||||
|
||||
factory = getFactoryByType(newtype);
|
||||
if(!factory)
|
||||
@@ -456,92 +514,211 @@ ALenum InitializeEffect(ALCdevice *Device, ALeffectslot *EffectSlot, ALeffect *e
|
||||
return AL_INVALID_ENUM;
|
||||
}
|
||||
State = V0(factory,create)();
|
||||
if(!State)
|
||||
return AL_OUT_OF_MEMORY;
|
||||
if(!State) return AL_OUT_OF_MEMORY;
|
||||
|
||||
SetMixerFPUMode(&oldMode);
|
||||
|
||||
ALCdevice_Lock(Device);
|
||||
START_MIXER_MODE();
|
||||
almtx_lock(&Device->BackendLock);
|
||||
State->OutBuffer = Device->Dry.Buffer;
|
||||
State->OutChannels = Device->Dry.NumChannels;
|
||||
if(V(State,deviceUpdate)(Device) == AL_FALSE)
|
||||
{
|
||||
ALCdevice_Unlock(Device);
|
||||
RestoreFPUMode(&oldMode);
|
||||
DELETE_OBJ(State);
|
||||
almtx_unlock(&Device->BackendLock);
|
||||
LEAVE_MIXER_MODE();
|
||||
ALeffectState_DecRef(State);
|
||||
return AL_OUT_OF_MEMORY;
|
||||
}
|
||||
almtx_unlock(&Device->BackendLock);
|
||||
END_MIXER_MODE();
|
||||
|
||||
State = ExchangePtr((XchgPtr*)&EffectSlot->EffectState, State);
|
||||
if(!effect)
|
||||
{
|
||||
memset(&EffectSlot->EffectProps, 0, sizeof(EffectSlot->EffectProps));
|
||||
EffectSlot->EffectType = AL_EFFECT_NULL;
|
||||
EffectSlot->Effect.Type = AL_EFFECT_NULL;
|
||||
memset(&EffectSlot->Effect.Props, 0, sizeof(EffectSlot->Effect.Props));
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(&EffectSlot->EffectProps, &effect->Props, sizeof(effect->Props));
|
||||
EffectSlot->EffectType = effect->type;
|
||||
EffectSlot->Effect.Type = effect->type;
|
||||
EffectSlot->Effect.Props = effect->Props;
|
||||
}
|
||||
|
||||
/* FIXME: This should be done asynchronously, but since the EffectState
|
||||
* object was changed, it needs an update before its Process method can
|
||||
* be called. */
|
||||
ATOMIC_STORE(&EffectSlot->NeedsUpdate, AL_FALSE);
|
||||
V(EffectSlot->EffectState,update)(Device, EffectSlot);
|
||||
ALCdevice_Unlock(Device);
|
||||
|
||||
RestoreFPUMode(&oldMode);
|
||||
|
||||
DELETE_OBJ(State);
|
||||
State = NULL;
|
||||
ALeffectState_DecRef(EffectSlot->Effect.State);
|
||||
EffectSlot->Effect.State = State;
|
||||
}
|
||||
else
|
||||
else if(effect)
|
||||
EffectSlot->Effect.Props = effect->Props;
|
||||
|
||||
/* Remove state references from old effect slot property updates. */
|
||||
props = ATOMIC_LOAD_SEQ(&EffectSlot->FreeList);
|
||||
while(props)
|
||||
{
|
||||
if(effect)
|
||||
{
|
||||
ALCdevice_Lock(Device);
|
||||
memcpy(&EffectSlot->EffectProps, &effect->Props, sizeof(effect->Props));
|
||||
ALCdevice_Unlock(Device);
|
||||
ATOMIC_STORE(&EffectSlot->NeedsUpdate, AL_TRUE);
|
||||
}
|
||||
if(props->State)
|
||||
ALeffectState_DecRef(props->State);
|
||||
props->State = NULL;
|
||||
props = ATOMIC_LOAD(&props->next, almemory_order_relaxed);
|
||||
}
|
||||
|
||||
return AL_NO_ERROR;
|
||||
}
|
||||
|
||||
|
||||
static void ALeffectState_IncRef(ALeffectState *state)
|
||||
{
|
||||
uint ref;
|
||||
ref = IncrementRef(&state->Ref);
|
||||
TRACEREF("%p increasing refcount to %u\n", state, ref);
|
||||
}
|
||||
|
||||
static void ALeffectState_DecRef(ALeffectState *state)
|
||||
{
|
||||
uint ref;
|
||||
ref = DecrementRef(&state->Ref);
|
||||
TRACEREF("%p decreasing refcount to %u\n", state, ref);
|
||||
if(ref == 0) DELETE_OBJ(state);
|
||||
}
|
||||
|
||||
|
||||
void ALeffectState_Construct(ALeffectState *state)
|
||||
{
|
||||
InitRef(&state->Ref, 1);
|
||||
|
||||
state->OutBuffer = NULL;
|
||||
state->OutChannels = 0;
|
||||
}
|
||||
|
||||
void ALeffectState_Destruct(ALeffectState *UNUSED(state))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
ALenum InitEffectSlot(ALeffectslot *slot)
|
||||
{
|
||||
ALeffectStateFactory *factory;
|
||||
ALuint i, c;
|
||||
|
||||
slot->EffectType = AL_EFFECT_NULL;
|
||||
slot->Effect.Type = AL_EFFECT_NULL;
|
||||
|
||||
factory = getFactoryByType(AL_EFFECT_NULL);
|
||||
if(!(slot->EffectState=V0(factory,create)()))
|
||||
if(!(slot->Effect.State=V0(factory,create)()))
|
||||
return AL_OUT_OF_MEMORY;
|
||||
|
||||
slot->Gain = 1.0;
|
||||
slot->AuxSendAuto = AL_TRUE;
|
||||
ATOMIC_INIT(&slot->NeedsUpdate, AL_FALSE);
|
||||
for(c = 0;c < 1;c++)
|
||||
{
|
||||
for(i = 0;i < BUFFERSIZE;i++)
|
||||
slot->WetBuffer[c][i] = 0.0f;
|
||||
}
|
||||
ATOMIC_FLAG_TEST_AND_SET(&slot->PropsClean, almemory_order_relaxed);
|
||||
InitRef(&slot->ref, 0);
|
||||
|
||||
ATOMIC_INIT(&slot->Update, NULL);
|
||||
ATOMIC_INIT(&slot->FreeList, NULL);
|
||||
|
||||
slot->Params.Gain = 1.0f;
|
||||
slot->Params.AuxSendAuto = AL_TRUE;
|
||||
ALeffectState_IncRef(slot->Effect.State);
|
||||
slot->Params.EffectState = slot->Effect.State;
|
||||
slot->Params.RoomRolloff = 0.0f;
|
||||
slot->Params.DecayTime = 0.0f;
|
||||
slot->Params.DecayHFRatio = 0.0f;
|
||||
slot->Params.DecayHFLimit = AL_FALSE;
|
||||
slot->Params.AirAbsorptionGainHF = 1.0f;
|
||||
|
||||
return AL_NO_ERROR;
|
||||
}
|
||||
|
||||
void DeinitEffectSlot(ALeffectslot *slot)
|
||||
{
|
||||
struct ALeffectslotProps *props;
|
||||
size_t count = 0;
|
||||
|
||||
props = ATOMIC_LOAD_SEQ(&slot->Update);
|
||||
if(props)
|
||||
{
|
||||
if(props->State) ALeffectState_DecRef(props->State);
|
||||
TRACE("Freed unapplied AuxiliaryEffectSlot update %p\n", props);
|
||||
al_free(props);
|
||||
}
|
||||
props = ATOMIC_LOAD(&slot->FreeList, almemory_order_relaxed);
|
||||
while(props)
|
||||
{
|
||||
struct ALeffectslotProps *next = ATOMIC_LOAD(&props->next, almemory_order_relaxed);
|
||||
if(props->State) ALeffectState_DecRef(props->State);
|
||||
al_free(props);
|
||||
props = next;
|
||||
++count;
|
||||
}
|
||||
TRACE("Freed "SZFMT" AuxiliaryEffectSlot property object%s\n", count, (count==1)?"":"s");
|
||||
|
||||
ALeffectState_DecRef(slot->Effect.State);
|
||||
if(slot->Params.EffectState)
|
||||
ALeffectState_DecRef(slot->Params.EffectState);
|
||||
}
|
||||
|
||||
void UpdateEffectSlotProps(ALeffectslot *slot)
|
||||
{
|
||||
struct ALeffectslotProps *props;
|
||||
ALeffectState *oldstate;
|
||||
|
||||
/* Get an unused property container, or allocate a new one as needed. */
|
||||
props = ATOMIC_LOAD(&slot->FreeList, almemory_order_relaxed);
|
||||
if(!props)
|
||||
props = al_calloc(16, sizeof(*props));
|
||||
else
|
||||
{
|
||||
struct ALeffectslotProps *next;
|
||||
do {
|
||||
next = ATOMIC_LOAD(&props->next, almemory_order_relaxed);
|
||||
} while(ATOMIC_COMPARE_EXCHANGE_PTR_WEAK(&slot->FreeList, &props, next,
|
||||
almemory_order_seq_cst, almemory_order_acquire) == 0);
|
||||
}
|
||||
|
||||
/* Copy in current property values. */
|
||||
props->Gain = slot->Gain;
|
||||
props->AuxSendAuto = slot->AuxSendAuto;
|
||||
|
||||
props->Type = slot->Effect.Type;
|
||||
props->Props = slot->Effect.Props;
|
||||
/* Swap out any stale effect state object there may be in the container, to
|
||||
* delete it.
|
||||
*/
|
||||
ALeffectState_IncRef(slot->Effect.State);
|
||||
oldstate = props->State;
|
||||
props->State = slot->Effect.State;
|
||||
|
||||
/* Set the new container for updating internal parameters. */
|
||||
props = ATOMIC_EXCHANGE_PTR(&slot->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 ALeffectslotProps*, &slot->FreeList, props);
|
||||
}
|
||||
|
||||
if(oldstate)
|
||||
ALeffectState_DecRef(oldstate);
|
||||
}
|
||||
|
||||
void UpdateAllEffectSlotProps(ALCcontext *context)
|
||||
{
|
||||
struct ALeffectslotArray *auxslots;
|
||||
ALsizei i;
|
||||
|
||||
LockEffectSlotsRead(context);
|
||||
auxslots = ATOMIC_LOAD(&context->ActiveAuxSlots, almemory_order_acquire);
|
||||
for(i = 0;i < auxslots->count;i++)
|
||||
{
|
||||
ALeffectslot *slot = auxslots->slot[i];
|
||||
if(!ATOMIC_FLAG_TEST_AND_SET(&slot->PropsClean, almemory_order_acq_rel))
|
||||
UpdateEffectSlotProps(slot);
|
||||
}
|
||||
UnlockEffectSlotsRead(context);
|
||||
}
|
||||
|
||||
ALvoid ReleaseALAuxiliaryEffectSlots(ALCcontext *Context)
|
||||
{
|
||||
ALsizei pos;
|
||||
for(pos = 0;pos < Context->EffectSlotMap.size;pos++)
|
||||
{
|
||||
ALeffectslot *temp = Context->EffectSlotMap.array[pos].value;
|
||||
Context->EffectSlotMap.array[pos].value = NULL;
|
||||
ALeffectslot *temp = Context->EffectSlotMap.values[pos];
|
||||
Context->EffectSlotMap.values[pos] = NULL;
|
||||
|
||||
DELETE_OBJ(temp->EffectState);
|
||||
DeinitEffectSlot(temp);
|
||||
|
||||
FreeThunkEntry(temp->id);
|
||||
memset(temp, 0, sizeof(ALeffectslot));
|
||||
|
||||
@@ -36,15 +36,19 @@
|
||||
#include "sample_cvt.h"
|
||||
|
||||
|
||||
extern inline void LockBuffersRead(ALCdevice *device);
|
||||
extern inline void UnlockBuffersRead(ALCdevice *device);
|
||||
extern inline void LockBuffersWrite(ALCdevice *device);
|
||||
extern inline void UnlockBuffersWrite(ALCdevice *device);
|
||||
extern inline struct ALbuffer *LookupBuffer(ALCdevice *device, ALuint id);
|
||||
extern inline struct ALbuffer *RemoveBuffer(ALCdevice *device, ALuint id);
|
||||
extern inline ALuint FrameSizeFromUserFmt(enum UserFmtChannels chans, enum UserFmtType type);
|
||||
extern inline ALuint FrameSizeFromFmt(enum FmtChannels chans, enum FmtType type);
|
||||
extern inline ALsizei FrameSizeFromUserFmt(enum UserFmtChannels chans, enum UserFmtType type);
|
||||
extern inline ALsizei FrameSizeFromFmt(enum FmtChannels chans, enum FmtType type);
|
||||
|
||||
static ALboolean IsValidType(ALenum type) DECL_CONST;
|
||||
static ALboolean IsValidChannels(ALenum channels) DECL_CONST;
|
||||
static ALboolean DecomposeUserFormat(ALenum format, enum UserFmtChannels *chans, enum UserFmtType *type) DECL_CONST;
|
||||
static ALboolean DecomposeFormat(ALenum format, enum FmtChannels *chans, enum FmtType *type) DECL_CONST;
|
||||
static ALboolean IsValidType(ALenum type);
|
||||
static ALboolean IsValidChannels(ALenum channels);
|
||||
static ALboolean DecomposeUserFormat(ALenum format, enum UserFmtChannels *chans, enum UserFmtType *type);
|
||||
static ALboolean DecomposeFormat(ALenum format, enum FmtChannels *chans, enum FmtType *type);
|
||||
static ALboolean SanitizeAlignment(enum UserFmtType type, ALsizei *align);
|
||||
|
||||
|
||||
@@ -85,10 +89,12 @@ AL_API ALvoid AL_APIENTRY alDeleteBuffers(ALsizei n, const ALuint *buffers)
|
||||
context = GetContextRef();
|
||||
if(!context) return;
|
||||
|
||||
device = context->Device;
|
||||
|
||||
LockBuffersWrite(device);
|
||||
if(!(n >= 0))
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
|
||||
|
||||
device = context->Device;
|
||||
for(i = 0;i < n;i++)
|
||||
{
|
||||
if(!buffers[i])
|
||||
@@ -108,6 +114,7 @@ AL_API ALvoid AL_APIENTRY alDeleteBuffers(ALsizei n, const ALuint *buffers)
|
||||
}
|
||||
|
||||
done:
|
||||
UnlockBuffersWrite(device);
|
||||
ALCcontext_DecRef(context);
|
||||
}
|
||||
|
||||
@@ -119,8 +126,10 @@ AL_API ALboolean AL_APIENTRY alIsBuffer(ALuint buffer)
|
||||
context = GetContextRef();
|
||||
if(!context) return AL_FALSE;
|
||||
|
||||
LockBuffersRead(context->Device);
|
||||
ret = ((!buffer || LookupBuffer(context->Device, buffer)) ?
|
||||
AL_TRUE : AL_FALSE);
|
||||
UnlockBuffersRead(context->Device);
|
||||
|
||||
ALCcontext_DecRef(context);
|
||||
|
||||
@@ -130,13 +139,13 @@ AL_API ALboolean AL_APIENTRY alIsBuffer(ALuint buffer)
|
||||
|
||||
AL_API ALvoid AL_APIENTRY alBufferData(ALuint buffer, ALenum format, const ALvoid *data, ALsizei size, ALsizei freq)
|
||||
{
|
||||
enum UserFmtChannels srcchannels;
|
||||
enum UserFmtType srctype;
|
||||
enum UserFmtChannels srcchannels = UserFmtMono;
|
||||
enum UserFmtType srctype = UserFmtByte;
|
||||
ALCdevice *device;
|
||||
ALCcontext *context;
|
||||
ALbuffer *albuf;
|
||||
ALenum newformat = AL_NONE;
|
||||
ALuint framesize;
|
||||
ALsizei framesize;
|
||||
ALsizei align;
|
||||
ALenum err;
|
||||
|
||||
@@ -144,6 +153,7 @@ AL_API ALvoid AL_APIENTRY alBufferData(ALuint buffer, ALenum format, const ALvoi
|
||||
if(!context) return;
|
||||
|
||||
device = context->Device;
|
||||
LockBuffersRead(device);
|
||||
if((albuf=LookupBuffer(device, buffer)) == NULL)
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
|
||||
if(!(size >= 0 && freq > 0))
|
||||
@@ -151,7 +161,7 @@ AL_API ALvoid AL_APIENTRY alBufferData(ALuint buffer, ALenum format, const ALvoi
|
||||
if(DecomposeUserFormat(format, &srcchannels, &srctype) == AL_FALSE)
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
|
||||
|
||||
align = ATOMIC_LOAD(&albuf->UnpackAlign);
|
||||
align = ATOMIC_LOAD_SEQ(&albuf->UnpackAlign);
|
||||
if(SanitizeAlignment(srctype, &align) == AL_FALSE)
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
|
||||
switch(srctype)
|
||||
@@ -173,8 +183,6 @@ AL_API ALvoid AL_APIENTRY alBufferData(ALuint buffer, ALenum format, const ALvoi
|
||||
|
||||
case UserFmtInt:
|
||||
case UserFmtUInt:
|
||||
case UserFmtByte3:
|
||||
case UserFmtUByte3:
|
||||
case UserFmtDouble:
|
||||
framesize = FrameSizeFromUserFmt(srcchannels, srctype) * align;
|
||||
if((size%framesize) != 0)
|
||||
@@ -272,25 +280,27 @@ AL_API ALvoid AL_APIENTRY alBufferData(ALuint buffer, ALenum format, const ALvoi
|
||||
}
|
||||
|
||||
done:
|
||||
UnlockBuffersRead(device);
|
||||
ALCcontext_DecRef(context);
|
||||
}
|
||||
|
||||
AL_API ALvoid AL_APIENTRY alBufferSubDataSOFT(ALuint buffer, ALenum format, const ALvoid *data, ALsizei offset, ALsizei length)
|
||||
{
|
||||
enum UserFmtChannels srcchannels;
|
||||
enum UserFmtType srctype;
|
||||
enum UserFmtChannels srcchannels = UserFmtMono;
|
||||
enum UserFmtType srctype = UserFmtByte;
|
||||
ALCdevice *device;
|
||||
ALCcontext *context;
|
||||
ALbuffer *albuf;
|
||||
ALuint byte_align;
|
||||
ALuint channels;
|
||||
ALuint bytes;
|
||||
ALsizei byte_align;
|
||||
ALsizei channels;
|
||||
ALsizei bytes;
|
||||
ALsizei align;
|
||||
|
||||
context = GetContextRef();
|
||||
if(!context) return;
|
||||
|
||||
device = context->Device;
|
||||
LockBuffersRead(device);
|
||||
if((albuf=LookupBuffer(device, buffer)) == NULL)
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
|
||||
if(!(length >= 0 && offset >= 0))
|
||||
@@ -299,7 +309,7 @@ AL_API ALvoid AL_APIENTRY alBufferSubDataSOFT(ALuint buffer, ALenum format, cons
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
|
||||
|
||||
WriteLock(&albuf->lock);
|
||||
align = ATOMIC_LOAD(&albuf->UnpackAlign);
|
||||
align = ATOMIC_LOAD_SEQ(&albuf->UnpackAlign);
|
||||
if(SanitizeAlignment(srctype, &align) == AL_FALSE)
|
||||
{
|
||||
WriteUnlock(&albuf->lock);
|
||||
@@ -351,6 +361,7 @@ AL_API ALvoid AL_APIENTRY alBufferSubDataSOFT(ALuint buffer, ALenum format, cons
|
||||
WriteUnlock(&albuf->lock);
|
||||
|
||||
done:
|
||||
UnlockBuffersRead(device);
|
||||
ALCcontext_DecRef(context);
|
||||
}
|
||||
|
||||
@@ -369,6 +380,7 @@ AL_API void AL_APIENTRY alBufferSamplesSOFT(ALuint buffer,
|
||||
if(!context) return;
|
||||
|
||||
device = context->Device;
|
||||
LockBuffersRead(device);
|
||||
if((albuf=LookupBuffer(device, buffer)) == NULL)
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
|
||||
if(!(samples >= 0 && samplerate != 0))
|
||||
@@ -376,7 +388,7 @@ AL_API void AL_APIENTRY alBufferSamplesSOFT(ALuint buffer,
|
||||
if(IsValidType(type) == AL_FALSE || IsValidChannels(channels) == AL_FALSE)
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
|
||||
|
||||
align = ATOMIC_LOAD(&albuf->UnpackAlign);
|
||||
align = ATOMIC_LOAD_SEQ(&albuf->UnpackAlign);
|
||||
if(SanitizeAlignment(type, &align) == AL_FALSE)
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
|
||||
if((samples%align) != 0)
|
||||
@@ -388,6 +400,7 @@ AL_API void AL_APIENTRY alBufferSamplesSOFT(ALuint buffer,
|
||||
SET_ERROR_AND_GOTO(context, err, done);
|
||||
|
||||
done:
|
||||
UnlockBuffersRead(device);
|
||||
ALCcontext_DecRef(context);
|
||||
}
|
||||
|
||||
@@ -404,6 +417,7 @@ AL_API void AL_APIENTRY alBufferSubSamplesSOFT(ALuint buffer,
|
||||
if(!context) return;
|
||||
|
||||
device = context->Device;
|
||||
LockBuffersRead(device);
|
||||
if((albuf=LookupBuffer(device, buffer)) == NULL)
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
|
||||
if(!(samples >= 0 && offset >= 0))
|
||||
@@ -412,7 +426,7 @@ AL_API void AL_APIENTRY alBufferSubSamplesSOFT(ALuint buffer,
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
|
||||
|
||||
WriteLock(&albuf->lock);
|
||||
align = ATOMIC_LOAD(&albuf->UnpackAlign);
|
||||
align = ATOMIC_LOAD_SEQ(&albuf->UnpackAlign);
|
||||
if(SanitizeAlignment(type, &align) == AL_FALSE)
|
||||
{
|
||||
WriteUnlock(&albuf->lock);
|
||||
@@ -441,6 +455,7 @@ AL_API void AL_APIENTRY alBufferSubSamplesSOFT(ALuint buffer,
|
||||
WriteUnlock(&albuf->lock);
|
||||
|
||||
done:
|
||||
UnlockBuffersRead(device);
|
||||
ALCcontext_DecRef(context);
|
||||
}
|
||||
|
||||
@@ -457,6 +472,7 @@ AL_API void AL_APIENTRY alGetBufferSamplesSOFT(ALuint buffer,
|
||||
if(!context) return;
|
||||
|
||||
device = context->Device;
|
||||
LockBuffersRead(device);
|
||||
if((albuf=LookupBuffer(device, buffer)) == NULL)
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
|
||||
if(!(samples >= 0 && offset >= 0))
|
||||
@@ -465,7 +481,7 @@ AL_API void AL_APIENTRY alGetBufferSamplesSOFT(ALuint buffer,
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
|
||||
|
||||
ReadLock(&albuf->lock);
|
||||
align = ATOMIC_LOAD(&albuf->PackAlign);
|
||||
align = ATOMIC_LOAD_SEQ(&albuf->PackAlign);
|
||||
if(SanitizeAlignment(type, &align) == AL_FALSE)
|
||||
{
|
||||
ReadUnlock(&albuf->lock);
|
||||
@@ -494,6 +510,7 @@ AL_API void AL_APIENTRY alGetBufferSamplesSOFT(ALuint buffer,
|
||||
ReadUnlock(&albuf->lock);
|
||||
|
||||
done:
|
||||
UnlockBuffersRead(device);
|
||||
ALCcontext_DecRef(context);
|
||||
}
|
||||
|
||||
@@ -524,6 +541,7 @@ AL_API void AL_APIENTRY alBufferf(ALuint buffer, ALenum param, ALfloat UNUSED(va
|
||||
if(!context) return;
|
||||
|
||||
device = context->Device;
|
||||
LockBuffersRead(device);
|
||||
if(LookupBuffer(device, buffer) == NULL)
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
|
||||
|
||||
@@ -534,6 +552,7 @@ AL_API void AL_APIENTRY alBufferf(ALuint buffer, ALenum param, ALfloat UNUSED(va
|
||||
}
|
||||
|
||||
done:
|
||||
UnlockBuffersRead(device);
|
||||
ALCcontext_DecRef(context);
|
||||
}
|
||||
|
||||
@@ -547,6 +566,7 @@ AL_API void AL_APIENTRY alBuffer3f(ALuint buffer, ALenum param, ALfloat UNUSED(v
|
||||
if(!context) return;
|
||||
|
||||
device = context->Device;
|
||||
LockBuffersRead(device);
|
||||
if(LookupBuffer(device, buffer) == NULL)
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
|
||||
|
||||
@@ -557,6 +577,7 @@ AL_API void AL_APIENTRY alBuffer3f(ALuint buffer, ALenum param, ALfloat UNUSED(v
|
||||
}
|
||||
|
||||
done:
|
||||
UnlockBuffersRead(device);
|
||||
ALCcontext_DecRef(context);
|
||||
}
|
||||
|
||||
@@ -570,6 +591,7 @@ AL_API void AL_APIENTRY alBufferfv(ALuint buffer, ALenum param, const ALfloat *v
|
||||
if(!context) return;
|
||||
|
||||
device = context->Device;
|
||||
LockBuffersRead(device);
|
||||
if(LookupBuffer(device, buffer) == NULL)
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
|
||||
|
||||
@@ -582,6 +604,7 @@ AL_API void AL_APIENTRY alBufferfv(ALuint buffer, ALenum param, const ALfloat *v
|
||||
}
|
||||
|
||||
done:
|
||||
UnlockBuffersRead(device);
|
||||
ALCcontext_DecRef(context);
|
||||
}
|
||||
|
||||
@@ -596,6 +619,7 @@ AL_API void AL_APIENTRY alBufferi(ALuint buffer, ALenum param, ALint value)
|
||||
if(!context) return;
|
||||
|
||||
device = context->Device;
|
||||
LockBuffersRead(device);
|
||||
if((albuf=LookupBuffer(device, buffer)) == NULL)
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
|
||||
|
||||
@@ -604,13 +628,13 @@ AL_API void AL_APIENTRY alBufferi(ALuint buffer, ALenum param, ALint value)
|
||||
case AL_UNPACK_BLOCK_ALIGNMENT_SOFT:
|
||||
if(!(value >= 0))
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
|
||||
ATOMIC_STORE(&albuf->UnpackAlign, value);
|
||||
ATOMIC_STORE_SEQ(&albuf->UnpackAlign, value);
|
||||
break;
|
||||
|
||||
case AL_PACK_BLOCK_ALIGNMENT_SOFT:
|
||||
if(!(value >= 0))
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
|
||||
ATOMIC_STORE(&albuf->PackAlign, value);
|
||||
ATOMIC_STORE_SEQ(&albuf->PackAlign, value);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -618,6 +642,7 @@ AL_API void AL_APIENTRY alBufferi(ALuint buffer, ALenum param, ALint value)
|
||||
}
|
||||
|
||||
done:
|
||||
UnlockBuffersRead(device);
|
||||
ALCcontext_DecRef(context);
|
||||
}
|
||||
|
||||
@@ -666,6 +691,7 @@ AL_API void AL_APIENTRY alBufferiv(ALuint buffer, ALenum param, const ALint *val
|
||||
if(!context) return;
|
||||
|
||||
device = context->Device;
|
||||
LockBuffersRead(device);
|
||||
if((albuf=LookupBuffer(device, buffer)) == NULL)
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
|
||||
|
||||
@@ -697,6 +723,7 @@ AL_API void AL_APIENTRY alBufferiv(ALuint buffer, ALenum param, const ALint *val
|
||||
}
|
||||
|
||||
done:
|
||||
UnlockBuffersRead(device);
|
||||
ALCcontext_DecRef(context);
|
||||
}
|
||||
|
||||
@@ -711,6 +738,7 @@ AL_API ALvoid AL_APIENTRY alGetBufferf(ALuint buffer, ALenum param, ALfloat *val
|
||||
if(!context) return;
|
||||
|
||||
device = context->Device;
|
||||
LockBuffersRead(device);
|
||||
if((albuf=LookupBuffer(device, buffer)) == NULL)
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
|
||||
|
||||
@@ -732,6 +760,7 @@ AL_API ALvoid AL_APIENTRY alGetBufferf(ALuint buffer, ALenum param, ALfloat *val
|
||||
}
|
||||
|
||||
done:
|
||||
UnlockBuffersRead(device);
|
||||
ALCcontext_DecRef(context);
|
||||
}
|
||||
|
||||
@@ -745,6 +774,7 @@ AL_API void AL_APIENTRY alGetBuffer3f(ALuint buffer, ALenum param, ALfloat *valu
|
||||
if(!context) return;
|
||||
|
||||
device = context->Device;
|
||||
LockBuffersRead(device);
|
||||
if(LookupBuffer(device, buffer) == NULL)
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
|
||||
|
||||
@@ -757,6 +787,7 @@ AL_API void AL_APIENTRY alGetBuffer3f(ALuint buffer, ALenum param, ALfloat *valu
|
||||
}
|
||||
|
||||
done:
|
||||
UnlockBuffersRead(device);
|
||||
ALCcontext_DecRef(context);
|
||||
}
|
||||
|
||||
@@ -777,6 +808,7 @@ AL_API void AL_APIENTRY alGetBufferfv(ALuint buffer, ALenum param, ALfloat *valu
|
||||
if(!context) return;
|
||||
|
||||
device = context->Device;
|
||||
LockBuffersRead(device);
|
||||
if(LookupBuffer(device, buffer) == NULL)
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
|
||||
|
||||
@@ -789,6 +821,7 @@ AL_API void AL_APIENTRY alGetBufferfv(ALuint buffer, ALenum param, ALfloat *valu
|
||||
}
|
||||
|
||||
done:
|
||||
UnlockBuffersRead(device);
|
||||
ALCcontext_DecRef(context);
|
||||
}
|
||||
|
||||
@@ -803,6 +836,7 @@ AL_API ALvoid AL_APIENTRY alGetBufferi(ALuint buffer, ALenum param, ALint *value
|
||||
if(!context) return;
|
||||
|
||||
device = context->Device;
|
||||
LockBuffersRead(device);
|
||||
if((albuf=LookupBuffer(device, buffer)) == NULL)
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
|
||||
|
||||
@@ -842,11 +876,11 @@ AL_API ALvoid AL_APIENTRY alGetBufferi(ALuint buffer, ALenum param, ALint *value
|
||||
break;
|
||||
|
||||
case AL_UNPACK_BLOCK_ALIGNMENT_SOFT:
|
||||
*value = ATOMIC_LOAD(&albuf->UnpackAlign);
|
||||
*value = ATOMIC_LOAD_SEQ(&albuf->UnpackAlign);
|
||||
break;
|
||||
|
||||
case AL_PACK_BLOCK_ALIGNMENT_SOFT:
|
||||
*value = ATOMIC_LOAD(&albuf->PackAlign);
|
||||
*value = ATOMIC_LOAD_SEQ(&albuf->PackAlign);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -854,6 +888,7 @@ AL_API ALvoid AL_APIENTRY alGetBufferi(ALuint buffer, ALenum param, ALint *value
|
||||
}
|
||||
|
||||
done:
|
||||
UnlockBuffersRead(device);
|
||||
ALCcontext_DecRef(context);
|
||||
}
|
||||
|
||||
@@ -867,6 +902,7 @@ AL_API void AL_APIENTRY alGetBuffer3i(ALuint buffer, ALenum param, ALint *value1
|
||||
if(!context) return;
|
||||
|
||||
device = context->Device;
|
||||
LockBuffersRead(device);
|
||||
if(LookupBuffer(device, buffer) == NULL)
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
|
||||
|
||||
@@ -879,6 +915,7 @@ AL_API void AL_APIENTRY alGetBuffer3i(ALuint buffer, ALenum param, ALint *value1
|
||||
}
|
||||
|
||||
done:
|
||||
UnlockBuffersRead(device);
|
||||
ALCcontext_DecRef(context);
|
||||
}
|
||||
|
||||
@@ -908,6 +945,7 @@ AL_API void AL_APIENTRY alGetBufferiv(ALuint buffer, ALenum param, ALint *values
|
||||
if(!context) return;
|
||||
|
||||
device = context->Device;
|
||||
LockBuffersRead(device);
|
||||
if((albuf=LookupBuffer(device, buffer)) == NULL)
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
|
||||
|
||||
@@ -927,6 +965,7 @@ AL_API void AL_APIENTRY alGetBufferiv(ALuint buffer, ALenum param, ALint *values
|
||||
}
|
||||
|
||||
done:
|
||||
UnlockBuffersRead(device);
|
||||
ALCcontext_DecRef(context);
|
||||
}
|
||||
|
||||
@@ -940,14 +979,14 @@ done:
|
||||
*/
|
||||
ALenum LoadData(ALbuffer *ALBuf, ALuint freq, ALenum NewFormat, ALsizei frames, enum UserFmtChannels SrcChannels, enum UserFmtType SrcType, const ALvoid *data, ALsizei align, ALboolean storesrc)
|
||||
{
|
||||
enum FmtChannels DstChannels = FmtMono;
|
||||
enum FmtType DstType = FmtByte;
|
||||
ALuint NewChannels, NewBytes;
|
||||
enum FmtChannels DstChannels;
|
||||
enum FmtType DstType;
|
||||
ALuint64 newsize;
|
||||
ALvoid *temp;
|
||||
|
||||
if(DecomposeFormat(NewFormat, &DstChannels, &DstType) == AL_FALSE ||
|
||||
(long)SrcChannels != (long)DstChannels)
|
||||
if(DecomposeFormat(NewFormat, &DstChannels, &DstType) == AL_FALSE)
|
||||
return AL_INVALID_ENUM;
|
||||
if((long)SrcChannels != (long)DstChannels)
|
||||
return AL_INVALID_ENUM;
|
||||
|
||||
NewChannels = ChannelsFromFmt(DstChannels);
|
||||
@@ -966,13 +1005,25 @@ ALenum LoadData(ALbuffer *ALBuf, ALuint freq, ALenum NewFormat, ALsizei frames,
|
||||
return AL_INVALID_OPERATION;
|
||||
}
|
||||
|
||||
temp = realloc(ALBuf->data, (size_t)newsize);
|
||||
if(!temp && newsize)
|
||||
/* Round up to the next 16-byte multiple. This could reallocate only when
|
||||
* increasing or the new size is less than half the current, but then the
|
||||
* buffer's AL_SIZE would not be very reliable for accounting buffer memory
|
||||
* usage, and reporting the real size could cause problems for apps that
|
||||
* use AL_SIZE to try to get the buffer's play length.
|
||||
*/
|
||||
newsize = (newsize+15) & ~0xf;
|
||||
if(newsize != ALBuf->BytesAlloc)
|
||||
{
|
||||
WriteUnlock(&ALBuf->lock);
|
||||
return AL_OUT_OF_MEMORY;
|
||||
void *temp = al_calloc(16, (size_t)newsize);
|
||||
if(!temp && newsize)
|
||||
{
|
||||
WriteUnlock(&ALBuf->lock);
|
||||
return AL_OUT_OF_MEMORY;
|
||||
}
|
||||
al_free(ALBuf->data);
|
||||
ALBuf->data = temp;
|
||||
ALBuf->BytesAlloc = (ALuint)newsize;
|
||||
}
|
||||
ALBuf->data = temp;
|
||||
|
||||
if(data != NULL)
|
||||
ConvertData(ALBuf->data, (enum UserFmtType)DstType, data, SrcType, NewChannels, frames, align);
|
||||
@@ -1021,7 +1072,7 @@ ALenum LoadData(ALbuffer *ALBuf, ALuint freq, ALenum NewFormat, ALsizei frames,
|
||||
}
|
||||
|
||||
|
||||
ALuint BytesFromUserFmt(enum UserFmtType type)
|
||||
ALsizei BytesFromUserFmt(enum UserFmtType type)
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
@@ -1033,8 +1084,6 @@ ALuint BytesFromUserFmt(enum UserFmtType type)
|
||||
case UserFmtUInt: return sizeof(ALuint);
|
||||
case UserFmtFloat: return sizeof(ALfloat);
|
||||
case UserFmtDouble: return sizeof(ALdouble);
|
||||
case UserFmtByte3: return sizeof(ALbyte[3]);
|
||||
case UserFmtUByte3: return sizeof(ALubyte[3]);
|
||||
case UserFmtMulaw: return sizeof(ALubyte);
|
||||
case UserFmtAlaw: return sizeof(ALubyte);
|
||||
case UserFmtIMA4: break; /* not handled here */
|
||||
@@ -1042,7 +1091,7 @@ ALuint BytesFromUserFmt(enum UserFmtType type)
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
ALuint ChannelsFromUserFmt(enum UserFmtChannels chans)
|
||||
ALsizei ChannelsFromUserFmt(enum UserFmtChannels chans)
|
||||
{
|
||||
switch(chans)
|
||||
{
|
||||
@@ -1137,7 +1186,7 @@ static ALboolean DecomposeUserFormat(ALenum format, enum UserFmtChannels *chans,
|
||||
return AL_FALSE;
|
||||
}
|
||||
|
||||
ALuint BytesFromFmt(enum FmtType type)
|
||||
ALsizei BytesFromFmt(enum FmtType type)
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
@@ -1147,7 +1196,7 @@ ALuint BytesFromFmt(enum FmtType type)
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
ALuint ChannelsFromFmt(enum FmtChannels chans)
|
||||
ALsizei ChannelsFromFmt(enum FmtChannels chans)
|
||||
{
|
||||
switch(chans)
|
||||
{
|
||||
@@ -1201,13 +1250,13 @@ static ALboolean DecomposeFormat(ALenum format, enum FmtChannels *chans, enum Fm
|
||||
{ AL_7POINT1_16_SOFT, FmtX71, FmtShort },
|
||||
{ AL_7POINT1_32F_SOFT, FmtX71, FmtFloat },
|
||||
|
||||
{ AL_FORMAT_BFORMAT2D_8, FmtBFormat2D, FmtByte },
|
||||
{ AL_FORMAT_BFORMAT2D_16, FmtBFormat2D, FmtShort },
|
||||
{ AL_FORMAT_BFORMAT2D_FLOAT32, FmtBFormat2D, FmtFloat },
|
||||
{ AL_BFORMAT2D_8_SOFT, FmtBFormat2D, FmtByte },
|
||||
{ AL_BFORMAT2D_16_SOFT, FmtBFormat2D, FmtShort },
|
||||
{ AL_BFORMAT2D_32F_SOFT, FmtBFormat2D, FmtFloat },
|
||||
|
||||
{ AL_FORMAT_BFORMAT3D_8, FmtBFormat3D, FmtByte },
|
||||
{ AL_FORMAT_BFORMAT3D_16, FmtBFormat3D, FmtShort },
|
||||
{ AL_FORMAT_BFORMAT3D_FLOAT32, FmtBFormat3D, FmtFloat },
|
||||
{ AL_BFORMAT3D_8_SOFT, FmtBFormat3D, FmtByte },
|
||||
{ AL_BFORMAT3D_16_SOFT, FmtBFormat3D, FmtShort },
|
||||
{ AL_BFORMAT3D_32F_SOFT, FmtBFormat3D, FmtFloat },
|
||||
};
|
||||
ALuint i;
|
||||
|
||||
@@ -1275,8 +1324,7 @@ static ALboolean IsValidType(ALenum type)
|
||||
case AL_UNSIGNED_INT_SOFT:
|
||||
case AL_FLOAT_SOFT:
|
||||
case AL_DOUBLE_SOFT:
|
||||
case AL_BYTE3_SOFT:
|
||||
case AL_UNSIGNED_BYTE3_SOFT:
|
||||
case AL_MULAW_SOFT:
|
||||
return AL_TRUE;
|
||||
}
|
||||
return AL_FALSE;
|
||||
@@ -1293,6 +1341,8 @@ static ALboolean IsValidChannels(ALenum channels)
|
||||
case AL_5POINT1_SOFT:
|
||||
case AL_6POINT1_SOFT:
|
||||
case AL_7POINT1_SOFT:
|
||||
case AL_BFORMAT2D_SOFT:
|
||||
case AL_BFORMAT3D_SOFT:
|
||||
return AL_TRUE;
|
||||
}
|
||||
return AL_FALSE;
|
||||
@@ -1305,7 +1355,7 @@ ALbuffer *NewBuffer(ALCcontext *context)
|
||||
ALbuffer *buffer;
|
||||
ALenum err;
|
||||
|
||||
buffer = calloc(1, sizeof(ALbuffer));
|
||||
buffer = al_calloc(16, sizeof(ALbuffer));
|
||||
if(!buffer)
|
||||
SET_ERROR_AND_RETURN_VALUE(context, AL_OUT_OF_MEMORY, NULL);
|
||||
RWLockInit(&buffer->lock);
|
||||
@@ -1317,7 +1367,7 @@ ALbuffer *NewBuffer(ALCcontext *context)
|
||||
{
|
||||
FreeThunkEntry(buffer->id);
|
||||
memset(buffer, 0, sizeof(ALbuffer));
|
||||
free(buffer);
|
||||
al_free(buffer);
|
||||
|
||||
SET_ERROR_AND_RETURN_VALUE(context, err, NULL);
|
||||
}
|
||||
@@ -1330,10 +1380,10 @@ void DeleteBuffer(ALCdevice *device, ALbuffer *buffer)
|
||||
RemoveBuffer(device, buffer->id);
|
||||
FreeThunkEntry(buffer->id);
|
||||
|
||||
free(buffer->data);
|
||||
al_free(buffer->data);
|
||||
|
||||
memset(buffer, 0, sizeof(*buffer));
|
||||
free(buffer);
|
||||
al_free(buffer);
|
||||
}
|
||||
|
||||
|
||||
@@ -1347,13 +1397,13 @@ ALvoid ReleaseALBuffers(ALCdevice *device)
|
||||
ALsizei i;
|
||||
for(i = 0;i < device->BufferMap.size;i++)
|
||||
{
|
||||
ALbuffer *temp = device->BufferMap.array[i].value;
|
||||
device->BufferMap.array[i].value = NULL;
|
||||
ALbuffer *temp = device->BufferMap.values[i];
|
||||
device->BufferMap.values[i] = NULL;
|
||||
|
||||
free(temp->data);
|
||||
al_free(temp->data);
|
||||
|
||||
FreeThunkEntry(temp->id);
|
||||
memset(temp, 0, sizeof(ALbuffer));
|
||||
free(temp);
|
||||
al_free(temp);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,6 +34,10 @@
|
||||
|
||||
ALboolean DisabledEffects[MAX_EFFECTS];
|
||||
|
||||
extern inline void LockEffectsRead(ALCdevice *device);
|
||||
extern inline void UnlockEffectsRead(ALCdevice *device);
|
||||
extern inline void LockEffectsWrite(ALCdevice *device);
|
||||
extern inline void UnlockEffectsWrite(ALCdevice *device);
|
||||
extern inline struct ALeffect *LookupEffect(ALCdevice *device, ALuint id);
|
||||
extern inline struct ALeffect *RemoveEffect(ALCdevice *device, ALuint id);
|
||||
extern inline ALboolean IsReverbEffect(ALenum type);
|
||||
@@ -56,11 +60,11 @@ AL_API ALvoid AL_APIENTRY alGenEffects(ALsizei n, ALuint *effects)
|
||||
device = context->Device;
|
||||
for(cur = 0;cur < n;cur++)
|
||||
{
|
||||
ALeffect *effect = calloc(1, sizeof(ALeffect));
|
||||
ALeffect *effect = al_calloc(16, sizeof(ALeffect));
|
||||
ALenum err = AL_OUT_OF_MEMORY;
|
||||
if(!effect || (err=InitEffect(effect)) != AL_NO_ERROR)
|
||||
{
|
||||
free(effect);
|
||||
al_free(effect);
|
||||
alDeleteEffects(cur, effects);
|
||||
SET_ERROR_AND_GOTO(context, err, done);
|
||||
}
|
||||
@@ -72,7 +76,7 @@ AL_API ALvoid AL_APIENTRY alGenEffects(ALsizei n, ALuint *effects)
|
||||
{
|
||||
FreeThunkEntry(effect->id);
|
||||
memset(effect, 0, sizeof(ALeffect));
|
||||
free(effect);
|
||||
al_free(effect);
|
||||
|
||||
alDeleteEffects(cur, effects);
|
||||
SET_ERROR_AND_GOTO(context, err, done);
|
||||
@@ -95,10 +99,10 @@ AL_API ALvoid AL_APIENTRY alDeleteEffects(ALsizei n, const ALuint *effects)
|
||||
context = GetContextRef();
|
||||
if(!context) return;
|
||||
|
||||
device = context->Device;
|
||||
LockEffectsWrite(device);
|
||||
if(!(n >= 0))
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
|
||||
|
||||
device = context->Device;
|
||||
for(i = 0;i < n;i++)
|
||||
{
|
||||
if(effects[i] && LookupEffect(device, effects[i]) == NULL)
|
||||
@@ -111,10 +115,11 @@ AL_API ALvoid AL_APIENTRY alDeleteEffects(ALsizei n, const ALuint *effects)
|
||||
FreeThunkEntry(effect->id);
|
||||
|
||||
memset(effect, 0, sizeof(*effect));
|
||||
free(effect);
|
||||
al_free(effect);
|
||||
}
|
||||
|
||||
done:
|
||||
UnlockEffectsWrite(device);
|
||||
ALCcontext_DecRef(context);
|
||||
}
|
||||
|
||||
@@ -126,8 +131,10 @@ AL_API ALboolean AL_APIENTRY alIsEffect(ALuint effect)
|
||||
Context = GetContextRef();
|
||||
if(!Context) return AL_FALSE;
|
||||
|
||||
LockEffectsRead(Context->Device);
|
||||
result = ((!effect || LookupEffect(Context->Device, effect)) ?
|
||||
AL_TRUE : AL_FALSE);
|
||||
UnlockEffectsRead(Context->Device);
|
||||
|
||||
ALCcontext_DecRef(Context);
|
||||
|
||||
@@ -144,6 +151,7 @@ AL_API ALvoid AL_APIENTRY alEffecti(ALuint effect, ALenum param, ALint value)
|
||||
if(!Context) return;
|
||||
|
||||
Device = Context->Device;
|
||||
LockEffectsWrite(Device);
|
||||
if((ALEffect=LookupEffect(Device, effect)) == NULL)
|
||||
alSetError(Context, AL_INVALID_NAME);
|
||||
else
|
||||
@@ -170,6 +178,7 @@ AL_API ALvoid AL_APIENTRY alEffecti(ALuint effect, ALenum param, ALint value)
|
||||
V(ALEffect,setParami)(Context, param, value);
|
||||
}
|
||||
}
|
||||
UnlockEffectsWrite(Device);
|
||||
|
||||
ALCcontext_DecRef(Context);
|
||||
}
|
||||
@@ -191,6 +200,7 @@ AL_API ALvoid AL_APIENTRY alEffectiv(ALuint effect, ALenum param, const ALint *v
|
||||
if(!Context) return;
|
||||
|
||||
Device = Context->Device;
|
||||
LockEffectsWrite(Device);
|
||||
if((ALEffect=LookupEffect(Device, effect)) == NULL)
|
||||
alSetError(Context, AL_INVALID_NAME);
|
||||
else
|
||||
@@ -198,6 +208,7 @@ AL_API ALvoid AL_APIENTRY alEffectiv(ALuint effect, ALenum param, const ALint *v
|
||||
/* Call the appropriate handler */
|
||||
V(ALEffect,setParamiv)(Context, param, values);
|
||||
}
|
||||
UnlockEffectsWrite(Device);
|
||||
|
||||
ALCcontext_DecRef(Context);
|
||||
}
|
||||
@@ -212,6 +223,7 @@ AL_API ALvoid AL_APIENTRY alEffectf(ALuint effect, ALenum param, ALfloat value)
|
||||
if(!Context) return;
|
||||
|
||||
Device = Context->Device;
|
||||
LockEffectsWrite(Device);
|
||||
if((ALEffect=LookupEffect(Device, effect)) == NULL)
|
||||
alSetError(Context, AL_INVALID_NAME);
|
||||
else
|
||||
@@ -219,6 +231,7 @@ AL_API ALvoid AL_APIENTRY alEffectf(ALuint effect, ALenum param, ALfloat value)
|
||||
/* Call the appropriate handler */
|
||||
V(ALEffect,setParamf)(Context, param, value);
|
||||
}
|
||||
UnlockEffectsWrite(Device);
|
||||
|
||||
ALCcontext_DecRef(Context);
|
||||
}
|
||||
@@ -233,6 +246,7 @@ AL_API ALvoid AL_APIENTRY alEffectfv(ALuint effect, ALenum param, const ALfloat
|
||||
if(!Context) return;
|
||||
|
||||
Device = Context->Device;
|
||||
LockEffectsWrite(Device);
|
||||
if((ALEffect=LookupEffect(Device, effect)) == NULL)
|
||||
alSetError(Context, AL_INVALID_NAME);
|
||||
else
|
||||
@@ -240,6 +254,7 @@ AL_API ALvoid AL_APIENTRY alEffectfv(ALuint effect, ALenum param, const ALfloat
|
||||
/* Call the appropriate handler */
|
||||
V(ALEffect,setParamfv)(Context, param, values);
|
||||
}
|
||||
UnlockEffectsWrite(Device);
|
||||
|
||||
ALCcontext_DecRef(Context);
|
||||
}
|
||||
@@ -254,6 +269,7 @@ AL_API ALvoid AL_APIENTRY alGetEffecti(ALuint effect, ALenum param, ALint *value
|
||||
if(!Context) return;
|
||||
|
||||
Device = Context->Device;
|
||||
LockEffectsRead(Device);
|
||||
if((ALEffect=LookupEffect(Device, effect)) == NULL)
|
||||
alSetError(Context, AL_INVALID_NAME);
|
||||
else
|
||||
@@ -266,6 +282,7 @@ AL_API ALvoid AL_APIENTRY alGetEffecti(ALuint effect, ALenum param, ALint *value
|
||||
V(ALEffect,getParami)(Context, param, value);
|
||||
}
|
||||
}
|
||||
UnlockEffectsRead(Device);
|
||||
|
||||
ALCcontext_DecRef(Context);
|
||||
}
|
||||
@@ -287,6 +304,7 @@ AL_API ALvoid AL_APIENTRY alGetEffectiv(ALuint effect, ALenum param, ALint *valu
|
||||
if(!Context) return;
|
||||
|
||||
Device = Context->Device;
|
||||
LockEffectsRead(Device);
|
||||
if((ALEffect=LookupEffect(Device, effect)) == NULL)
|
||||
alSetError(Context, AL_INVALID_NAME);
|
||||
else
|
||||
@@ -294,6 +312,7 @@ AL_API ALvoid AL_APIENTRY alGetEffectiv(ALuint effect, ALenum param, ALint *valu
|
||||
/* Call the appropriate handler */
|
||||
V(ALEffect,getParamiv)(Context, param, values);
|
||||
}
|
||||
UnlockEffectsRead(Device);
|
||||
|
||||
ALCcontext_DecRef(Context);
|
||||
}
|
||||
@@ -308,6 +327,7 @@ AL_API ALvoid AL_APIENTRY alGetEffectf(ALuint effect, ALenum param, ALfloat *val
|
||||
if(!Context) return;
|
||||
|
||||
Device = Context->Device;
|
||||
LockEffectsRead(Device);
|
||||
if((ALEffect=LookupEffect(Device, effect)) == NULL)
|
||||
alSetError(Context, AL_INVALID_NAME);
|
||||
else
|
||||
@@ -315,6 +335,7 @@ AL_API ALvoid AL_APIENTRY alGetEffectf(ALuint effect, ALenum param, ALfloat *val
|
||||
/* Call the appropriate handler */
|
||||
V(ALEffect,getParamf)(Context, param, value);
|
||||
}
|
||||
UnlockEffectsRead(Device);
|
||||
|
||||
ALCcontext_DecRef(Context);
|
||||
}
|
||||
@@ -329,6 +350,7 @@ AL_API ALvoid AL_APIENTRY alGetEffectfv(ALuint effect, ALenum param, ALfloat *va
|
||||
if(!Context) return;
|
||||
|
||||
Device = Context->Device;
|
||||
LockEffectsRead(Device);
|
||||
if((ALEffect=LookupEffect(Device, effect)) == NULL)
|
||||
alSetError(Context, AL_INVALID_NAME);
|
||||
else
|
||||
@@ -336,6 +358,7 @@ AL_API ALvoid AL_APIENTRY alGetEffectfv(ALuint effect, ALenum param, ALfloat *va
|
||||
/* Call the appropriate handler */
|
||||
V(ALEffect,getParamfv)(Context, param, values);
|
||||
}
|
||||
UnlockEffectsRead(Device);
|
||||
|
||||
ALCcontext_DecRef(Context);
|
||||
}
|
||||
@@ -352,13 +375,13 @@ ALvoid ReleaseALEffects(ALCdevice *device)
|
||||
ALsizei i;
|
||||
for(i = 0;i < device->EffectMap.size;i++)
|
||||
{
|
||||
ALeffect *temp = device->EffectMap.array[i].value;
|
||||
device->EffectMap.array[i].value = NULL;
|
||||
ALeffect *temp = device->EffectMap.values[i];
|
||||
device->EffectMap.values[i] = NULL;
|
||||
|
||||
// Release effect structure
|
||||
FreeThunkEntry(temp->id);
|
||||
memset(temp, 0, sizeof(ALeffect));
|
||||
free(temp);
|
||||
al_free(temp);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -427,13 +450,6 @@ static void InitEffectParams(ALeffect *effect, ALenum type)
|
||||
effect->Props.Reverb.DecayHFLimit = AL_REVERB_DEFAULT_DECAY_HFLIMIT;
|
||||
SET_VTABLE1(ALreverb, effect);
|
||||
break;
|
||||
case AL_EFFECT_AUTOWAH:
|
||||
effect->Props.Autowah.AttackTime = AL_AUTOWAH_DEFAULT_ATTACK_TIME;
|
||||
effect->Props.Autowah.PeakGain = AL_AUTOWAH_DEFAULT_PEAK_GAIN;
|
||||
effect->Props.Autowah.ReleaseTime = AL_AUTOWAH_DEFAULT_RELEASE_TIME;
|
||||
effect->Props.Autowah.Resonance = AL_AUTOWAH_DEFAULT_RESONANCE;
|
||||
SET_VTABLE1(ALautowah, effect);
|
||||
break;
|
||||
case AL_EFFECT_CHORUS:
|
||||
effect->Props.Chorus.Waveform = AL_CHORUS_DEFAULT_WAVEFORM;
|
||||
effect->Props.Chorus.Phase = AL_CHORUS_DEFAULT_PHASE;
|
||||
@@ -651,9 +667,9 @@ ALvoid LoadReverbPreset(const char *name, ALeffect *effect)
|
||||
return;
|
||||
}
|
||||
|
||||
if(!DisabledEffects[EAXREVERB])
|
||||
if(!DisabledEffects[AL__EAXREVERB])
|
||||
InitEffectParams(effect, AL_EFFECT_EAXREVERB);
|
||||
else if(!DisabledEffects[REVERB])
|
||||
else if(!DisabledEffects[AL__REVERB])
|
||||
InitEffectParams(effect, AL_EFFECT_REVERB);
|
||||
else
|
||||
InitEffectParams(effect, AL_EFFECT_NULL);
|
||||
|
||||
@@ -36,6 +36,8 @@ ALboolean TrapALError = AL_FALSE;
|
||||
ALvoid alSetError(ALCcontext *Context, ALenum errorCode)
|
||||
{
|
||||
ALenum curerr = AL_NO_ERROR;
|
||||
|
||||
WARN("Error generated on context %p, code 0x%04x\n", Context, errorCode);
|
||||
if(TrapALError)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
@@ -46,7 +48,8 @@ ALvoid alSetError(ALCcontext *Context, ALenum errorCode)
|
||||
raise(SIGTRAP);
|
||||
#endif
|
||||
}
|
||||
ATOMIC_COMPARE_EXCHANGE_STRONG(ALenum, &Context->LastError, &curerr, errorCode);
|
||||
|
||||
(void)(ATOMIC_COMPARE_EXCHANGE_STRONG_SEQ(&Context->LastError, &curerr, errorCode));
|
||||
}
|
||||
|
||||
AL_API ALenum AL_APIENTRY alGetError(void)
|
||||
@@ -57,6 +60,8 @@ AL_API ALenum AL_APIENTRY alGetError(void)
|
||||
Context = GetContextRef();
|
||||
if(!Context)
|
||||
{
|
||||
WARN("Querying error state on null context (implicitly 0x%04x)\n",
|
||||
AL_INVALID_OPERATION);
|
||||
if(TrapALError)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
@@ -69,7 +74,7 @@ AL_API ALenum AL_APIENTRY alGetError(void)
|
||||
return AL_INVALID_OPERATION;
|
||||
}
|
||||
|
||||
errorCode = ATOMIC_EXCHANGE(ALenum, &Context->LastError, AL_NO_ERROR);
|
||||
errorCode = ATOMIC_EXCHANGE_SEQ(&Context->LastError, AL_NO_ERROR);
|
||||
|
||||
ALCcontext_DecRef(Context);
|
||||
|
||||
|
||||
@@ -36,20 +36,17 @@
|
||||
|
||||
|
||||
const struct EffectList EffectList[] = {
|
||||
{ "eaxreverb", EAXREVERB, "AL_EFFECT_EAXREVERB", AL_EFFECT_EAXREVERB },
|
||||
{ "reverb", REVERB, "AL_EFFECT_REVERB", AL_EFFECT_REVERB },
|
||||
#if 0
|
||||
{ "autowah", AUTOWAH, "AL_EFFECT_AUTOWAH", AL_EFFECT_AUTOWAH },
|
||||
#endif
|
||||
{ "chorus", CHORUS, "AL_EFFECT_CHORUS", AL_EFFECT_CHORUS },
|
||||
{ "compressor", COMPRESSOR, "AL_EFFECT_COMPRESSOR", AL_EFFECT_COMPRESSOR },
|
||||
{ "distortion", DISTORTION, "AL_EFFECT_DISTORTION", AL_EFFECT_DISTORTION },
|
||||
{ "echo", ECHO, "AL_EFFECT_ECHO", AL_EFFECT_ECHO },
|
||||
{ "equalizer", EQUALIZER, "AL_EFFECT_EQUALIZER", AL_EFFECT_EQUALIZER },
|
||||
{ "flanger", FLANGER, "AL_EFFECT_FLANGER", AL_EFFECT_FLANGER },
|
||||
{ "modulator", MODULATOR, "AL_EFFECT_RING_MODULATOR", AL_EFFECT_RING_MODULATOR },
|
||||
{ "dedicated", DEDICATED, "AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT", AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT },
|
||||
{ "dedicated", DEDICATED, "AL_EFFECT_DEDICATED_DIALOGUE", AL_EFFECT_DEDICATED_DIALOGUE },
|
||||
{ "eaxreverb", AL__EAXREVERB, "AL_EFFECT_EAXREVERB", AL_EFFECT_EAXREVERB },
|
||||
{ "reverb", AL__REVERB, "AL_EFFECT_REVERB", AL_EFFECT_REVERB },
|
||||
{ "chorus", AL__CHORUS, "AL_EFFECT_CHORUS", AL_EFFECT_CHORUS },
|
||||
{ "compressor", AL__COMPRESSOR, "AL_EFFECT_COMPRESSOR", AL_EFFECT_COMPRESSOR },
|
||||
{ "distortion", AL__DISTORTION, "AL_EFFECT_DISTORTION", AL_EFFECT_DISTORTION },
|
||||
{ "echo", AL__ECHO, "AL_EFFECT_ECHO", AL_EFFECT_ECHO },
|
||||
{ "equalizer", AL__EQUALIZER, "AL_EFFECT_EQUALIZER", AL_EFFECT_EQUALIZER },
|
||||
{ "flanger", AL__FLANGER, "AL_EFFECT_FLANGER", AL_EFFECT_FLANGER },
|
||||
{ "modulator", AL__MODULATOR, "AL_EFFECT_RING_MODULATOR", AL_EFFECT_RING_MODULATOR },
|
||||
{ "dedicated", AL__DEDICATED, "AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT", AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT },
|
||||
{ "dedicated", AL__DEDICATED, "AL_EFFECT_DEDICATED_DIALOGUE", AL_EFFECT_DEDICATED_DIALOGUE },
|
||||
{ NULL, 0, NULL, (ALenum)0 }
|
||||
};
|
||||
|
||||
|
||||
@@ -29,11 +29,15 @@
|
||||
#include "alError.h"
|
||||
|
||||
|
||||
extern inline void LockFiltersRead(ALCdevice *device);
|
||||
extern inline void UnlockFiltersRead(ALCdevice *device);
|
||||
extern inline void LockFiltersWrite(ALCdevice *device);
|
||||
extern inline void UnlockFiltersWrite(ALCdevice *device);
|
||||
extern inline struct ALfilter *LookupFilter(ALCdevice *device, ALuint id);
|
||||
extern inline struct ALfilter *RemoveFilter(ALCdevice *device, ALuint id);
|
||||
extern inline void ALfilterState_clear(ALfilterState *filter);
|
||||
extern inline void ALfilterState_processPassthru(ALfilterState *filter, const ALfloat *src, ALuint numsamples);
|
||||
extern inline ALfloat ALfilterState_processSingle(ALfilterState *filter, ALfloat sample);
|
||||
extern inline void ALfilterState_copyParams(ALfilterState *restrict dst, const ALfilterState *restrict src);
|
||||
extern inline void ALfilterState_processPassthru(ALfilterState *filter, const ALfloat *restrict src, ALsizei numsamples);
|
||||
extern inline ALfloat calc_rcpQ_from_slope(ALfloat gain, ALfloat slope);
|
||||
extern inline ALfloat calc_rcpQ_from_bandwidth(ALfloat freq_mult, ALfloat bandwidth);
|
||||
|
||||
@@ -56,7 +60,7 @@ AL_API ALvoid AL_APIENTRY alGenFilters(ALsizei n, ALuint *filters)
|
||||
device = context->Device;
|
||||
for(cur = 0;cur < n;cur++)
|
||||
{
|
||||
ALfilter *filter = calloc(1, sizeof(ALfilter));
|
||||
ALfilter *filter = al_calloc(16, sizeof(ALfilter));
|
||||
if(!filter)
|
||||
{
|
||||
alDeleteFilters(cur, filters);
|
||||
@@ -71,7 +75,7 @@ AL_API ALvoid AL_APIENTRY alGenFilters(ALsizei n, ALuint *filters)
|
||||
{
|
||||
FreeThunkEntry(filter->id);
|
||||
memset(filter, 0, sizeof(ALfilter));
|
||||
free(filter);
|
||||
al_free(filter);
|
||||
|
||||
alDeleteFilters(cur, filters);
|
||||
SET_ERROR_AND_GOTO(context, err, done);
|
||||
@@ -94,10 +98,10 @@ AL_API ALvoid AL_APIENTRY alDeleteFilters(ALsizei n, const ALuint *filters)
|
||||
context = GetContextRef();
|
||||
if(!context) return;
|
||||
|
||||
device = context->Device;
|
||||
LockFiltersWrite(device);
|
||||
if(!(n >= 0))
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
|
||||
|
||||
device = context->Device;
|
||||
for(i = 0;i < n;i++)
|
||||
{
|
||||
if(filters[i] && LookupFilter(device, filters[i]) == NULL)
|
||||
@@ -110,10 +114,11 @@ AL_API ALvoid AL_APIENTRY alDeleteFilters(ALsizei n, const ALuint *filters)
|
||||
FreeThunkEntry(filter->id);
|
||||
|
||||
memset(filter, 0, sizeof(*filter));
|
||||
free(filter);
|
||||
al_free(filter);
|
||||
}
|
||||
|
||||
done:
|
||||
UnlockFiltersWrite(device);
|
||||
ALCcontext_DecRef(context);
|
||||
}
|
||||
|
||||
@@ -125,8 +130,10 @@ AL_API ALboolean AL_APIENTRY alIsFilter(ALuint filter)
|
||||
Context = GetContextRef();
|
||||
if(!Context) return AL_FALSE;
|
||||
|
||||
LockFiltersRead(Context->Device);
|
||||
result = ((!filter || LookupFilter(Context->Device, filter)) ?
|
||||
AL_TRUE : AL_FALSE);
|
||||
UnlockFiltersRead(Context->Device);
|
||||
|
||||
ALCcontext_DecRef(Context);
|
||||
|
||||
@@ -143,6 +150,7 @@ AL_API ALvoid AL_APIENTRY alFilteri(ALuint filter, ALenum param, ALint value)
|
||||
if(!Context) return;
|
||||
|
||||
Device = Context->Device;
|
||||
LockFiltersWrite(Device);
|
||||
if((ALFilter=LookupFilter(Device, filter)) == NULL)
|
||||
alSetError(Context, AL_INVALID_NAME);
|
||||
else
|
||||
@@ -161,6 +169,7 @@ AL_API ALvoid AL_APIENTRY alFilteri(ALuint filter, ALenum param, ALint value)
|
||||
ALfilter_SetParami(ALFilter, Context, param, value);
|
||||
}
|
||||
}
|
||||
UnlockFiltersWrite(Device);
|
||||
|
||||
ALCcontext_DecRef(Context);
|
||||
}
|
||||
@@ -182,6 +191,7 @@ AL_API ALvoid AL_APIENTRY alFilteriv(ALuint filter, ALenum param, const ALint *v
|
||||
if(!Context) return;
|
||||
|
||||
Device = Context->Device;
|
||||
LockFiltersWrite(Device);
|
||||
if((ALFilter=LookupFilter(Device, filter)) == NULL)
|
||||
alSetError(Context, AL_INVALID_NAME);
|
||||
else
|
||||
@@ -189,6 +199,7 @@ AL_API ALvoid AL_APIENTRY alFilteriv(ALuint filter, ALenum param, const ALint *v
|
||||
/* Call the appropriate handler */
|
||||
ALfilter_SetParamiv(ALFilter, Context, param, values);
|
||||
}
|
||||
UnlockFiltersWrite(Device);
|
||||
|
||||
ALCcontext_DecRef(Context);
|
||||
}
|
||||
@@ -203,6 +214,7 @@ AL_API ALvoid AL_APIENTRY alFilterf(ALuint filter, ALenum param, ALfloat value)
|
||||
if(!Context) return;
|
||||
|
||||
Device = Context->Device;
|
||||
LockFiltersWrite(Device);
|
||||
if((ALFilter=LookupFilter(Device, filter)) == NULL)
|
||||
alSetError(Context, AL_INVALID_NAME);
|
||||
else
|
||||
@@ -210,6 +222,7 @@ AL_API ALvoid AL_APIENTRY alFilterf(ALuint filter, ALenum param, ALfloat value)
|
||||
/* Call the appropriate handler */
|
||||
ALfilter_SetParamf(ALFilter, Context, param, value);
|
||||
}
|
||||
UnlockFiltersWrite(Device);
|
||||
|
||||
ALCcontext_DecRef(Context);
|
||||
}
|
||||
@@ -224,6 +237,7 @@ AL_API ALvoid AL_APIENTRY alFilterfv(ALuint filter, ALenum param, const ALfloat
|
||||
if(!Context) return;
|
||||
|
||||
Device = Context->Device;
|
||||
LockFiltersWrite(Device);
|
||||
if((ALFilter=LookupFilter(Device, filter)) == NULL)
|
||||
alSetError(Context, AL_INVALID_NAME);
|
||||
else
|
||||
@@ -231,6 +245,7 @@ AL_API ALvoid AL_APIENTRY alFilterfv(ALuint filter, ALenum param, const ALfloat
|
||||
/* Call the appropriate handler */
|
||||
ALfilter_SetParamfv(ALFilter, Context, param, values);
|
||||
}
|
||||
UnlockFiltersWrite(Device);
|
||||
|
||||
ALCcontext_DecRef(Context);
|
||||
}
|
||||
@@ -245,6 +260,7 @@ AL_API ALvoid AL_APIENTRY alGetFilteri(ALuint filter, ALenum param, ALint *value
|
||||
if(!Context) return;
|
||||
|
||||
Device = Context->Device;
|
||||
LockFiltersRead(Device);
|
||||
if((ALFilter=LookupFilter(Device, filter)) == NULL)
|
||||
alSetError(Context, AL_INVALID_NAME);
|
||||
else
|
||||
@@ -257,6 +273,7 @@ AL_API ALvoid AL_APIENTRY alGetFilteri(ALuint filter, ALenum param, ALint *value
|
||||
ALfilter_GetParami(ALFilter, Context, param, value);
|
||||
}
|
||||
}
|
||||
UnlockFiltersRead(Device);
|
||||
|
||||
ALCcontext_DecRef(Context);
|
||||
}
|
||||
@@ -278,6 +295,7 @@ AL_API ALvoid AL_APIENTRY alGetFilteriv(ALuint filter, ALenum param, ALint *valu
|
||||
if(!Context) return;
|
||||
|
||||
Device = Context->Device;
|
||||
LockFiltersRead(Device);
|
||||
if((ALFilter=LookupFilter(Device, filter)) == NULL)
|
||||
alSetError(Context, AL_INVALID_NAME);
|
||||
else
|
||||
@@ -285,6 +303,7 @@ AL_API ALvoid AL_APIENTRY alGetFilteriv(ALuint filter, ALenum param, ALint *valu
|
||||
/* Call the appropriate handler */
|
||||
ALfilter_GetParamiv(ALFilter, Context, param, values);
|
||||
}
|
||||
UnlockFiltersRead(Device);
|
||||
|
||||
ALCcontext_DecRef(Context);
|
||||
}
|
||||
@@ -299,6 +318,7 @@ AL_API ALvoid AL_APIENTRY alGetFilterf(ALuint filter, ALenum param, ALfloat *val
|
||||
if(!Context) return;
|
||||
|
||||
Device = Context->Device;
|
||||
LockFiltersRead(Device);
|
||||
if((ALFilter=LookupFilter(Device, filter)) == NULL)
|
||||
alSetError(Context, AL_INVALID_NAME);
|
||||
else
|
||||
@@ -306,6 +326,7 @@ AL_API ALvoid AL_APIENTRY alGetFilterf(ALuint filter, ALenum param, ALfloat *val
|
||||
/* Call the appropriate handler */
|
||||
ALfilter_GetParamf(ALFilter, Context, param, value);
|
||||
}
|
||||
UnlockFiltersRead(Device);
|
||||
|
||||
ALCcontext_DecRef(Context);
|
||||
}
|
||||
@@ -320,6 +341,7 @@ AL_API ALvoid AL_APIENTRY alGetFilterfv(ALuint filter, ALenum param, ALfloat *va
|
||||
if(!Context) return;
|
||||
|
||||
Device = Context->Device;
|
||||
LockFiltersRead(Device);
|
||||
if((ALFilter=LookupFilter(Device, filter)) == NULL)
|
||||
alSetError(Context, AL_INVALID_NAME);
|
||||
else
|
||||
@@ -327,6 +349,7 @@ AL_API ALvoid AL_APIENTRY alGetFilterfv(ALuint filter, ALenum param, ALfloat *va
|
||||
/* Call the appropriate handler */
|
||||
ALfilter_GetParamfv(ALFilter, Context, param, values);
|
||||
}
|
||||
UnlockFiltersRead(Device);
|
||||
|
||||
ALCcontext_DecRef(Context);
|
||||
}
|
||||
@@ -340,7 +363,7 @@ void ALfilterState_setParams(ALfilterState *filter, ALfilterType type, ALfloat g
|
||||
ALfloat b[3] = { 1.0f, 0.0f, 0.0f };
|
||||
|
||||
// Limit gain to -100dB
|
||||
gain = maxf(gain, 0.00001f);
|
||||
assert(gain > 0.00001f);
|
||||
|
||||
w0 = F_TAU * freq_mult;
|
||||
sin_w0 = sinf(w0);
|
||||
@@ -406,11 +429,9 @@ void ALfilterState_setParams(ALfilterState *filter, ALfilterType type, ALfloat g
|
||||
|
||||
filter->a1 = a[1] / a[0];
|
||||
filter->a2 = a[2] / a[0];
|
||||
filter->b0 = b[0] / a[0];
|
||||
filter->b1 = b[1] / a[0];
|
||||
filter->b2 = b[2] / a[0];
|
||||
filter->input_gain = b[0] / a[0];
|
||||
|
||||
filter->process = ALfilterState_processC;
|
||||
}
|
||||
|
||||
|
||||
@@ -613,13 +634,13 @@ ALvoid ReleaseALFilters(ALCdevice *device)
|
||||
ALsizei i;
|
||||
for(i = 0;i < device->FilterMap.size;i++)
|
||||
{
|
||||
ALfilter *temp = device->FilterMap.array[i].value;
|
||||
device->FilterMap.array[i].value = NULL;
|
||||
ALfilter *temp = device->FilterMap.values[i];
|
||||
device->FilterMap.values[i] = NULL;
|
||||
|
||||
// Release filter structure
|
||||
FreeThunkEntry(temp->id);
|
||||
memset(temp, 0, sizeof(ALfilter));
|
||||
free(temp);
|
||||
al_free(temp);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -33,29 +33,29 @@ AL_API ALvoid AL_APIENTRY alListenerf(ALenum param, ALfloat value)
|
||||
context = GetContextRef();
|
||||
if(!context) return;
|
||||
|
||||
WriteLock(&context->PropLock);
|
||||
switch(param)
|
||||
{
|
||||
case AL_GAIN:
|
||||
if(!(value >= 0.0f && isfinite(value)))
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
|
||||
|
||||
context->Listener->Gain = value;
|
||||
ATOMIC_STORE(&context->UpdateSources, AL_TRUE);
|
||||
break;
|
||||
|
||||
case AL_METERS_PER_UNIT:
|
||||
if(!(value >= 0.0f && isfinite(value)))
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
|
||||
|
||||
context->Listener->MetersPerUnit = value;
|
||||
ATOMIC_STORE(&context->UpdateSources, AL_TRUE);
|
||||
break;
|
||||
|
||||
default:
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
|
||||
}
|
||||
if(!ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire))
|
||||
UpdateListenerProps(context);
|
||||
|
||||
done:
|
||||
WriteUnlock(&context->PropLock);
|
||||
ALCcontext_DecRef(context);
|
||||
}
|
||||
|
||||
@@ -67,33 +67,33 @@ AL_API ALvoid AL_APIENTRY alListener3f(ALenum param, ALfloat value1, ALfloat val
|
||||
context = GetContextRef();
|
||||
if(!context) return;
|
||||
|
||||
WriteLock(&context->PropLock);
|
||||
switch(param)
|
||||
{
|
||||
case AL_POSITION:
|
||||
if(!(isfinite(value1) && isfinite(value2) && isfinite(value3)))
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
|
||||
|
||||
LockContext(context);
|
||||
aluVectorSet(&context->Listener->Position, value1, value2, value3, 1.0f);
|
||||
ATOMIC_STORE(&context->UpdateSources, AL_TRUE);
|
||||
UnlockContext(context);
|
||||
context->Listener->Position[0] = value1;
|
||||
context->Listener->Position[1] = value2;
|
||||
context->Listener->Position[2] = value3;
|
||||
break;
|
||||
|
||||
case AL_VELOCITY:
|
||||
if(!(isfinite(value1) && isfinite(value2) && isfinite(value3)))
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
|
||||
|
||||
LockContext(context);
|
||||
aluVectorSet(&context->Listener->Velocity, value1, value2, value3, 0.0f);
|
||||
ATOMIC_STORE(&context->UpdateSources, AL_TRUE);
|
||||
UnlockContext(context);
|
||||
context->Listener->Velocity[0] = value1;
|
||||
context->Listener->Velocity[1] = value2;
|
||||
context->Listener->Velocity[2] = value3;
|
||||
break;
|
||||
|
||||
default:
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
|
||||
}
|
||||
if(!ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire))
|
||||
UpdateListenerProps(context);
|
||||
|
||||
done:
|
||||
WriteUnlock(&context->PropLock);
|
||||
ALCcontext_DecRef(context);
|
||||
}
|
||||
|
||||
@@ -121,6 +121,7 @@ AL_API ALvoid AL_APIENTRY alListenerfv(ALenum param, const ALfloat *values)
|
||||
context = GetContextRef();
|
||||
if(!context) return;
|
||||
|
||||
WriteLock(&context->PropLock);
|
||||
if(!(values))
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
|
||||
switch(param)
|
||||
@@ -129,8 +130,6 @@ AL_API ALvoid AL_APIENTRY alListenerfv(ALenum param, const ALfloat *values)
|
||||
if(!(isfinite(values[0]) && isfinite(values[1]) && isfinite(values[2]) &&
|
||||
isfinite(values[3]) && isfinite(values[4]) && isfinite(values[5])))
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
|
||||
|
||||
LockContext(context);
|
||||
/* AT then UP */
|
||||
context->Listener->Forward[0] = values[0];
|
||||
context->Listener->Forward[1] = values[1];
|
||||
@@ -138,15 +137,16 @@ AL_API ALvoid AL_APIENTRY alListenerfv(ALenum param, const ALfloat *values)
|
||||
context->Listener->Up[0] = values[3];
|
||||
context->Listener->Up[1] = values[4];
|
||||
context->Listener->Up[2] = values[5];
|
||||
ATOMIC_STORE(&context->UpdateSources, AL_TRUE);
|
||||
UnlockContext(context);
|
||||
break;
|
||||
|
||||
default:
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
|
||||
}
|
||||
if(!ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire))
|
||||
UpdateListenerProps(context);
|
||||
|
||||
done:
|
||||
WriteUnlock(&context->PropLock);
|
||||
ALCcontext_DecRef(context);
|
||||
}
|
||||
|
||||
@@ -158,13 +158,17 @@ AL_API ALvoid AL_APIENTRY alListeneri(ALenum param, ALint UNUSED(value))
|
||||
context = GetContextRef();
|
||||
if(!context) return;
|
||||
|
||||
WriteLock(&context->PropLock);
|
||||
switch(param)
|
||||
{
|
||||
default:
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
|
||||
}
|
||||
if(!ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire))
|
||||
UpdateListenerProps(context);
|
||||
|
||||
done:
|
||||
WriteUnlock(&context->PropLock);
|
||||
ALCcontext_DecRef(context);
|
||||
}
|
||||
|
||||
@@ -184,13 +188,17 @@ AL_API void AL_APIENTRY alListener3i(ALenum param, ALint value1, ALint value2, A
|
||||
context = GetContextRef();
|
||||
if(!context) return;
|
||||
|
||||
WriteLock(&context->PropLock);
|
||||
switch(param)
|
||||
{
|
||||
default:
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
|
||||
}
|
||||
if(!ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire))
|
||||
UpdateListenerProps(context);
|
||||
|
||||
done:
|
||||
WriteUnlock(&context->PropLock);
|
||||
ALCcontext_DecRef(context);
|
||||
}
|
||||
|
||||
@@ -224,6 +232,7 @@ AL_API void AL_APIENTRY alListeneriv(ALenum param, const ALint *values)
|
||||
context = GetContextRef();
|
||||
if(!context) return;
|
||||
|
||||
WriteLock(&context->PropLock);
|
||||
if(!(values))
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
|
||||
switch(param)
|
||||
@@ -231,8 +240,11 @@ AL_API void AL_APIENTRY alListeneriv(ALenum param, const ALint *values)
|
||||
default:
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
|
||||
}
|
||||
if(!ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire))
|
||||
UpdateListenerProps(context);
|
||||
|
||||
done:
|
||||
WriteUnlock(&context->PropLock);
|
||||
ALCcontext_DecRef(context);
|
||||
}
|
||||
|
||||
@@ -244,6 +256,7 @@ AL_API ALvoid AL_APIENTRY alGetListenerf(ALenum param, ALfloat *value)
|
||||
context = GetContextRef();
|
||||
if(!context) return;
|
||||
|
||||
ReadLock(&context->PropLock);
|
||||
if(!(value))
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
|
||||
switch(param)
|
||||
@@ -261,6 +274,7 @@ AL_API ALvoid AL_APIENTRY alGetListenerf(ALenum param, ALfloat *value)
|
||||
}
|
||||
|
||||
done:
|
||||
ReadUnlock(&context->PropLock);
|
||||
ALCcontext_DecRef(context);
|
||||
}
|
||||
|
||||
@@ -272,24 +286,21 @@ AL_API ALvoid AL_APIENTRY alGetListener3f(ALenum param, ALfloat *value1, ALfloat
|
||||
context = GetContextRef();
|
||||
if(!context) return;
|
||||
|
||||
ReadLock(&context->PropLock);
|
||||
if(!(value1 && value2 && value3))
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
|
||||
switch(param)
|
||||
{
|
||||
case AL_POSITION:
|
||||
LockContext(context);
|
||||
*value1 = context->Listener->Position.v[0];
|
||||
*value2 = context->Listener->Position.v[1];
|
||||
*value3 = context->Listener->Position.v[2];
|
||||
UnlockContext(context);
|
||||
*value1 = context->Listener->Position[0];
|
||||
*value2 = context->Listener->Position[1];
|
||||
*value3 = context->Listener->Position[2];
|
||||
break;
|
||||
|
||||
case AL_VELOCITY:
|
||||
LockContext(context);
|
||||
*value1 = context->Listener->Velocity.v[0];
|
||||
*value2 = context->Listener->Velocity.v[1];
|
||||
*value3 = context->Listener->Velocity.v[2];
|
||||
UnlockContext(context);
|
||||
*value1 = context->Listener->Velocity[0];
|
||||
*value2 = context->Listener->Velocity[1];
|
||||
*value3 = context->Listener->Velocity[2];
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -297,6 +308,7 @@ AL_API ALvoid AL_APIENTRY alGetListener3f(ALenum param, ALfloat *value1, ALfloat
|
||||
}
|
||||
|
||||
done:
|
||||
ReadUnlock(&context->PropLock);
|
||||
ALCcontext_DecRef(context);
|
||||
}
|
||||
|
||||
@@ -321,12 +333,12 @@ AL_API ALvoid AL_APIENTRY alGetListenerfv(ALenum param, ALfloat *values)
|
||||
context = GetContextRef();
|
||||
if(!context) return;
|
||||
|
||||
ReadLock(&context->PropLock);
|
||||
if(!(values))
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
|
||||
switch(param)
|
||||
{
|
||||
case AL_ORIENTATION:
|
||||
LockContext(context);
|
||||
// AT then UP
|
||||
values[0] = context->Listener->Forward[0];
|
||||
values[1] = context->Listener->Forward[1];
|
||||
@@ -334,7 +346,6 @@ AL_API ALvoid AL_APIENTRY alGetListenerfv(ALenum param, ALfloat *values)
|
||||
values[3] = context->Listener->Up[0];
|
||||
values[4] = context->Listener->Up[1];
|
||||
values[5] = context->Listener->Up[2];
|
||||
UnlockContext(context);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -342,6 +353,7 @@ AL_API ALvoid AL_APIENTRY alGetListenerfv(ALenum param, ALfloat *values)
|
||||
}
|
||||
|
||||
done:
|
||||
ReadUnlock(&context->PropLock);
|
||||
ALCcontext_DecRef(context);
|
||||
}
|
||||
|
||||
@@ -353,6 +365,7 @@ AL_API ALvoid AL_APIENTRY alGetListeneri(ALenum param, ALint *value)
|
||||
context = GetContextRef();
|
||||
if(!context) return;
|
||||
|
||||
ReadLock(&context->PropLock);
|
||||
if(!(value))
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
|
||||
switch(param)
|
||||
@@ -362,6 +375,7 @@ AL_API ALvoid AL_APIENTRY alGetListeneri(ALenum param, ALint *value)
|
||||
}
|
||||
|
||||
done:
|
||||
ReadUnlock(&context->PropLock);
|
||||
ALCcontext_DecRef(context);
|
||||
}
|
||||
|
||||
@@ -373,24 +387,21 @@ AL_API void AL_APIENTRY alGetListener3i(ALenum param, ALint *value1, ALint *valu
|
||||
context = GetContextRef();
|
||||
if(!context) return;
|
||||
|
||||
ReadLock(&context->PropLock);
|
||||
if(!(value1 && value2 && value3))
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
|
||||
switch (param)
|
||||
{
|
||||
case AL_POSITION:
|
||||
LockContext(context);
|
||||
*value1 = (ALint)context->Listener->Position.v[0];
|
||||
*value2 = (ALint)context->Listener->Position.v[1];
|
||||
*value3 = (ALint)context->Listener->Position.v[2];
|
||||
UnlockContext(context);
|
||||
*value1 = (ALint)context->Listener->Position[0];
|
||||
*value2 = (ALint)context->Listener->Position[1];
|
||||
*value3 = (ALint)context->Listener->Position[2];
|
||||
break;
|
||||
|
||||
case AL_VELOCITY:
|
||||
LockContext(context);
|
||||
*value1 = (ALint)context->Listener->Velocity.v[0];
|
||||
*value2 = (ALint)context->Listener->Velocity.v[1];
|
||||
*value3 = (ALint)context->Listener->Velocity.v[2];
|
||||
UnlockContext(context);
|
||||
*value1 = (ALint)context->Listener->Velocity[0];
|
||||
*value2 = (ALint)context->Listener->Velocity[1];
|
||||
*value3 = (ALint)context->Listener->Velocity[2];
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -398,6 +409,7 @@ AL_API void AL_APIENTRY alGetListener3i(ALenum param, ALint *value1, ALint *valu
|
||||
}
|
||||
|
||||
done:
|
||||
ReadUnlock(&context->PropLock);
|
||||
ALCcontext_DecRef(context);
|
||||
}
|
||||
|
||||
@@ -417,12 +429,12 @@ AL_API void AL_APIENTRY alGetListeneriv(ALenum param, ALint* values)
|
||||
context = GetContextRef();
|
||||
if(!context) return;
|
||||
|
||||
ReadLock(&context->PropLock);
|
||||
if(!(values))
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
|
||||
switch(param)
|
||||
{
|
||||
case AL_ORIENTATION:
|
||||
LockContext(context);
|
||||
// AT then UP
|
||||
values[0] = (ALint)context->Listener->Forward[0];
|
||||
values[1] = (ALint)context->Listener->Forward[1];
|
||||
@@ -430,7 +442,6 @@ AL_API void AL_APIENTRY alGetListeneriv(ALenum param, ALint* values)
|
||||
values[3] = (ALint)context->Listener->Up[0];
|
||||
values[4] = (ALint)context->Listener->Up[1];
|
||||
values[5] = (ALint)context->Listener->Up[2];
|
||||
UnlockContext(context);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -438,5 +449,62 @@ AL_API void AL_APIENTRY alGetListeneriv(ALenum param, ALint* values)
|
||||
}
|
||||
|
||||
done:
|
||||
ReadUnlock(&context->PropLock);
|
||||
ALCcontext_DecRef(context);
|
||||
}
|
||||
|
||||
|
||||
void UpdateListenerProps(ALCcontext *context)
|
||||
{
|
||||
ALlistener *listener = context->Listener;
|
||||
struct ALlistenerProps *props;
|
||||
|
||||
/* Get an unused proprty container, or allocate a new one as needed. */
|
||||
props = ATOMIC_LOAD(&listener->FreeList, almemory_order_acquire);
|
||||
if(!props)
|
||||
props = al_calloc(16, sizeof(*props));
|
||||
else
|
||||
{
|
||||
struct ALlistenerProps *next;
|
||||
do {
|
||||
next = ATOMIC_LOAD(&props->next, almemory_order_relaxed);
|
||||
} while(ATOMIC_COMPARE_EXCHANGE_PTR_WEAK(&listener->FreeList, &props, next,
|
||||
almemory_order_seq_cst, almemory_order_acquire) == 0);
|
||||
}
|
||||
|
||||
/* Copy in current property values. */
|
||||
props->Position[0] = listener->Position[0];
|
||||
props->Position[1] = listener->Position[1];
|
||||
props->Position[2] = listener->Position[2];
|
||||
|
||||
props->Velocity[0] = listener->Velocity[0];
|
||||
props->Velocity[1] = listener->Velocity[1];
|
||||
props->Velocity[2] = listener->Velocity[2];
|
||||
|
||||
props->Forward[0] = listener->Forward[0];
|
||||
props->Forward[1] = listener->Forward[1];
|
||||
props->Forward[2] = listener->Forward[2];
|
||||
props->Up[0] = listener->Up[0];
|
||||
props->Up[1] = listener->Up[1];
|
||||
props->Up[2] = listener->Up[2];
|
||||
|
||||
props->Gain = listener->Gain;
|
||||
props->MetersPerUnit = listener->MetersPerUnit;
|
||||
|
||||
props->DopplerFactor = context->DopplerFactor;
|
||||
props->DopplerVelocity = context->DopplerVelocity;
|
||||
props->SpeedOfSound = context->SpeedOfSound;
|
||||
|
||||
props->SourceDistanceModel = context->SourceDistanceModel;
|
||||
props->DistanceModel = context->DistanceModel;;
|
||||
|
||||
/* Set the new container for updating internal parameters. */
|
||||
props = ATOMIC_EXCHANGE_PTR(&listener->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 ALlistenerProps*, &listener->FreeList, props);
|
||||
}
|
||||
}
|
||||
|
||||
+1132
-665
File diff suppressed because it is too large
Load Diff
@@ -20,12 +20,15 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "version.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "alMain.h"
|
||||
#include "AL/alc.h"
|
||||
#include "AL/al.h"
|
||||
#include "AL/alext.h"
|
||||
#include "alError.h"
|
||||
#include "alListener.h"
|
||||
#include "alSource.h"
|
||||
#include "alAuxEffectSlot.h"
|
||||
|
||||
@@ -44,6 +47,12 @@ static const ALchar alErrInvalidValue[] = "Invalid Value";
|
||||
static const ALchar alErrInvalidOp[] = "Invalid Operation";
|
||||
static const ALchar alErrOutOfMemory[] = "Out of Memory";
|
||||
|
||||
/* Resampler strings */
|
||||
static const ALchar alPointResampler[] = "Nearest";
|
||||
static const ALchar alLinearResampler[] = "Linear";
|
||||
static const ALchar alSinc4Resampler[] = "4-Point Sinc";
|
||||
static const ALchar alBSincResampler[] = "Band-limited Sinc (12/24)";
|
||||
|
||||
AL_API ALvoid AL_APIENTRY alEnable(ALenum capability)
|
||||
{
|
||||
ALCcontext *context;
|
||||
@@ -51,18 +60,21 @@ AL_API ALvoid AL_APIENTRY alEnable(ALenum capability)
|
||||
context = GetContextRef();
|
||||
if(!context) return;
|
||||
|
||||
WriteLock(&context->PropLock);
|
||||
switch(capability)
|
||||
{
|
||||
case AL_SOURCE_DISTANCE_MODEL:
|
||||
context->SourceDistanceModel = AL_TRUE;
|
||||
ATOMIC_STORE(&context->UpdateSources, AL_TRUE);
|
||||
break;
|
||||
|
||||
default:
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
|
||||
}
|
||||
if(!ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire))
|
||||
UpdateListenerProps(context);
|
||||
|
||||
done:
|
||||
WriteUnlock(&context->PropLock);
|
||||
ALCcontext_DecRef(context);
|
||||
}
|
||||
|
||||
@@ -73,18 +85,21 @@ AL_API ALvoid AL_APIENTRY alDisable(ALenum capability)
|
||||
context = GetContextRef();
|
||||
if(!context) return;
|
||||
|
||||
WriteLock(&context->PropLock);
|
||||
switch(capability)
|
||||
{
|
||||
case AL_SOURCE_DISTANCE_MODEL:
|
||||
context->SourceDistanceModel = AL_FALSE;
|
||||
ATOMIC_STORE(&context->UpdateSources, AL_TRUE);
|
||||
break;
|
||||
|
||||
default:
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
|
||||
}
|
||||
if(!ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire))
|
||||
UpdateListenerProps(context);
|
||||
|
||||
done:
|
||||
WriteUnlock(&context->PropLock);
|
||||
ALCcontext_DecRef(context);
|
||||
}
|
||||
|
||||
@@ -143,7 +158,22 @@ AL_API ALboolean AL_APIENTRY alGetBoolean(ALenum pname)
|
||||
break;
|
||||
|
||||
case AL_DEFERRED_UPDATES_SOFT:
|
||||
value = context->DeferUpdates;
|
||||
if(ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire))
|
||||
value = AL_TRUE;
|
||||
break;
|
||||
|
||||
case AL_GAIN_LIMIT_SOFT:
|
||||
if(GAIN_MIX_MAX/context->GainBoost != 0.0f)
|
||||
value = AL_TRUE;
|
||||
break;
|
||||
|
||||
case AL_NUM_RESAMPLERS_SOFT:
|
||||
/* Always non-0. */
|
||||
value = AL_TRUE;
|
||||
break;
|
||||
|
||||
case AL_DEFAULT_RESAMPLER_SOFT:
|
||||
value = ResamplerDefault ? AL_TRUE : AL_FALSE;
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -183,7 +213,20 @@ AL_API ALdouble AL_APIENTRY alGetDouble(ALenum pname)
|
||||
break;
|
||||
|
||||
case AL_DEFERRED_UPDATES_SOFT:
|
||||
value = (ALdouble)context->DeferUpdates;
|
||||
if(ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire))
|
||||
value = (ALdouble)AL_TRUE;
|
||||
break;
|
||||
|
||||
case AL_GAIN_LIMIT_SOFT:
|
||||
value = (ALdouble)GAIN_MIX_MAX/context->GainBoost;
|
||||
break;
|
||||
|
||||
case AL_NUM_RESAMPLERS_SOFT:
|
||||
value = (ALdouble)(ResamplerMax + 1);
|
||||
break;
|
||||
|
||||
case AL_DEFAULT_RESAMPLER_SOFT:
|
||||
value = (ALdouble)ResamplerDefault;
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -223,7 +266,20 @@ AL_API ALfloat AL_APIENTRY alGetFloat(ALenum pname)
|
||||
break;
|
||||
|
||||
case AL_DEFERRED_UPDATES_SOFT:
|
||||
value = (ALfloat)context->DeferUpdates;
|
||||
if(ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire))
|
||||
value = (ALfloat)AL_TRUE;
|
||||
break;
|
||||
|
||||
case AL_GAIN_LIMIT_SOFT:
|
||||
value = GAIN_MIX_MAX/context->GainBoost;
|
||||
break;
|
||||
|
||||
case AL_NUM_RESAMPLERS_SOFT:
|
||||
value = (ALfloat)(ResamplerMax + 1);
|
||||
break;
|
||||
|
||||
case AL_DEFAULT_RESAMPLER_SOFT:
|
||||
value = (ALfloat)ResamplerDefault;
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -263,7 +319,20 @@ AL_API ALint AL_APIENTRY alGetInteger(ALenum pname)
|
||||
break;
|
||||
|
||||
case AL_DEFERRED_UPDATES_SOFT:
|
||||
value = (ALint)context->DeferUpdates;
|
||||
if(ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire))
|
||||
value = (ALint)AL_TRUE;
|
||||
break;
|
||||
|
||||
case AL_GAIN_LIMIT_SOFT:
|
||||
value = (ALint)(GAIN_MIX_MAX/context->GainBoost);
|
||||
break;
|
||||
|
||||
case AL_NUM_RESAMPLERS_SOFT:
|
||||
value = ResamplerMax + 1;
|
||||
break;
|
||||
|
||||
case AL_DEFAULT_RESAMPLER_SOFT:
|
||||
value = ResamplerDefault;
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -303,7 +372,20 @@ AL_API ALint64SOFT AL_APIENTRY alGetInteger64SOFT(ALenum pname)
|
||||
break;
|
||||
|
||||
case AL_DEFERRED_UPDATES_SOFT:
|
||||
value = (ALint64SOFT)context->DeferUpdates;
|
||||
if(ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire))
|
||||
value = (ALint64SOFT)AL_TRUE;
|
||||
break;
|
||||
|
||||
case AL_GAIN_LIMIT_SOFT:
|
||||
value = (ALint64SOFT)(GAIN_MIX_MAX/context->GainBoost);
|
||||
break;
|
||||
|
||||
case AL_NUM_RESAMPLERS_SOFT:
|
||||
value = (ALint64SOFT)(ResamplerMax + 1);
|
||||
break;
|
||||
|
||||
case AL_DEFAULT_RESAMPLER_SOFT:
|
||||
value = (ALint64SOFT)ResamplerDefault;
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -329,6 +411,9 @@ AL_API ALvoid AL_APIENTRY alGetBooleanv(ALenum pname, ALboolean *values)
|
||||
case AL_DISTANCE_MODEL:
|
||||
case AL_SPEED_OF_SOUND:
|
||||
case AL_DEFERRED_UPDATES_SOFT:
|
||||
case AL_GAIN_LIMIT_SOFT:
|
||||
case AL_NUM_RESAMPLERS_SOFT:
|
||||
case AL_DEFAULT_RESAMPLER_SOFT:
|
||||
values[0] = alGetBoolean(pname);
|
||||
return;
|
||||
}
|
||||
@@ -362,6 +447,9 @@ AL_API ALvoid AL_APIENTRY alGetDoublev(ALenum pname, ALdouble *values)
|
||||
case AL_DISTANCE_MODEL:
|
||||
case AL_SPEED_OF_SOUND:
|
||||
case AL_DEFERRED_UPDATES_SOFT:
|
||||
case AL_GAIN_LIMIT_SOFT:
|
||||
case AL_NUM_RESAMPLERS_SOFT:
|
||||
case AL_DEFAULT_RESAMPLER_SOFT:
|
||||
values[0] = alGetDouble(pname);
|
||||
return;
|
||||
}
|
||||
@@ -395,6 +483,9 @@ AL_API ALvoid AL_APIENTRY alGetFloatv(ALenum pname, ALfloat *values)
|
||||
case AL_DISTANCE_MODEL:
|
||||
case AL_SPEED_OF_SOUND:
|
||||
case AL_DEFERRED_UPDATES_SOFT:
|
||||
case AL_GAIN_LIMIT_SOFT:
|
||||
case AL_NUM_RESAMPLERS_SOFT:
|
||||
case AL_DEFAULT_RESAMPLER_SOFT:
|
||||
values[0] = alGetFloat(pname);
|
||||
return;
|
||||
}
|
||||
@@ -428,6 +519,9 @@ AL_API ALvoid AL_APIENTRY alGetIntegerv(ALenum pname, ALint *values)
|
||||
case AL_DISTANCE_MODEL:
|
||||
case AL_SPEED_OF_SOUND:
|
||||
case AL_DEFERRED_UPDATES_SOFT:
|
||||
case AL_GAIN_LIMIT_SOFT:
|
||||
case AL_NUM_RESAMPLERS_SOFT:
|
||||
case AL_DEFAULT_RESAMPLER_SOFT:
|
||||
values[0] = alGetInteger(pname);
|
||||
return;
|
||||
}
|
||||
@@ -459,6 +553,9 @@ AL_API void AL_APIENTRY alGetInteger64vSOFT(ALenum pname, ALint64SOFT *values)
|
||||
case AL_DISTANCE_MODEL:
|
||||
case AL_SPEED_OF_SOUND:
|
||||
case AL_DEFERRED_UPDATES_SOFT:
|
||||
case AL_GAIN_LIMIT_SOFT:
|
||||
case AL_NUM_RESAMPLERS_SOFT:
|
||||
case AL_DEFAULT_RESAMPLER_SOFT:
|
||||
values[0] = alGetInteger64SOFT(pname);
|
||||
return;
|
||||
}
|
||||
@@ -547,8 +644,11 @@ AL_API ALvoid AL_APIENTRY alDopplerFactor(ALfloat value)
|
||||
if(!(value >= 0.0f && isfinite(value)))
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
|
||||
|
||||
WriteLock(&context->PropLock);
|
||||
context->DopplerFactor = value;
|
||||
ATOMIC_STORE(&context->UpdateSources, AL_TRUE);
|
||||
if(!ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire))
|
||||
UpdateListenerProps(context);
|
||||
WriteUnlock(&context->PropLock);
|
||||
|
||||
done:
|
||||
ALCcontext_DecRef(context);
|
||||
@@ -564,8 +664,11 @@ AL_API ALvoid AL_APIENTRY alDopplerVelocity(ALfloat value)
|
||||
if(!(value >= 0.0f && isfinite(value)))
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
|
||||
|
||||
WriteLock(&context->PropLock);
|
||||
context->DopplerVelocity = value;
|
||||
ATOMIC_STORE(&context->UpdateSources, AL_TRUE);
|
||||
if(!ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire))
|
||||
UpdateListenerProps(context);
|
||||
WriteUnlock(&context->PropLock);
|
||||
|
||||
done:
|
||||
ALCcontext_DecRef(context);
|
||||
@@ -581,8 +684,11 @@ AL_API ALvoid AL_APIENTRY alSpeedOfSound(ALfloat value)
|
||||
if(!(value > 0.0f && isfinite(value)))
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
|
||||
|
||||
WriteLock(&context->PropLock);
|
||||
context->SpeedOfSound = value;
|
||||
ATOMIC_STORE(&context->UpdateSources, AL_TRUE);
|
||||
if(!ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire))
|
||||
UpdateListenerProps(context);
|
||||
WriteUnlock(&context->PropLock);
|
||||
|
||||
done:
|
||||
ALCcontext_DecRef(context);
|
||||
@@ -601,9 +707,14 @@ AL_API ALvoid AL_APIENTRY alDistanceModel(ALenum value)
|
||||
value == AL_NONE))
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
|
||||
|
||||
WriteLock(&context->PropLock);
|
||||
context->DistanceModel = value;
|
||||
if(!context->SourceDistanceModel)
|
||||
ATOMIC_STORE(&context->UpdateSources, AL_TRUE);
|
||||
{
|
||||
if(!ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire))
|
||||
UpdateListenerProps(context);
|
||||
}
|
||||
WriteUnlock(&context->PropLock);
|
||||
|
||||
done:
|
||||
ALCcontext_DecRef(context);
|
||||
@@ -633,3 +744,36 @@ AL_API ALvoid AL_APIENTRY alProcessUpdatesSOFT(void)
|
||||
|
||||
ALCcontext_DecRef(context);
|
||||
}
|
||||
|
||||
|
||||
AL_API const ALchar* AL_APIENTRY alGetStringiSOFT(ALenum pname, ALsizei index)
|
||||
{
|
||||
const char *ResamplerNames[] = {
|
||||
alPointResampler, alLinearResampler,
|
||||
alSinc4Resampler, alBSincResampler,
|
||||
};
|
||||
const ALchar *value = NULL;
|
||||
ALCcontext *context;
|
||||
|
||||
static_assert(COUNTOF(ResamplerNames) == ResamplerMax+1, "Incorrect ResamplerNames list");
|
||||
|
||||
context = GetContextRef();
|
||||
if(!context) return NULL;
|
||||
|
||||
switch(pname)
|
||||
{
|
||||
case AL_RESAMPLER_NAME_SOFT:
|
||||
if(index < 0 || (size_t)index >= COUNTOF(ResamplerNames))
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
|
||||
value = ResamplerNames[index];
|
||||
break;
|
||||
|
||||
default:
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
|
||||
}
|
||||
|
||||
done:
|
||||
ALCcontext_DecRef(context);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
@@ -25,15 +25,17 @@
|
||||
#include "alMain.h"
|
||||
#include "alThunk.h"
|
||||
|
||||
#include "almalloc.h"
|
||||
|
||||
static ATOMIC(ALenum) *ThunkArray;
|
||||
static ALuint ThunkArraySize;
|
||||
|
||||
static ATOMIC_FLAG *ThunkArray;
|
||||
static ALsizei ThunkArraySize;
|
||||
static RWLock ThunkLock;
|
||||
|
||||
void ThunkInit(void)
|
||||
{
|
||||
RWLockInit(&ThunkLock);
|
||||
ThunkArraySize = 1;
|
||||
ThunkArraySize = 1024;
|
||||
ThunkArray = al_calloc(16, ThunkArraySize * sizeof(*ThunkArray));
|
||||
}
|
||||
|
||||
@@ -47,12 +49,12 @@ void ThunkExit(void)
|
||||
ALenum NewThunkEntry(ALuint *index)
|
||||
{
|
||||
void *NewList;
|
||||
ALuint i;
|
||||
ALsizei i;
|
||||
|
||||
ReadLock(&ThunkLock);
|
||||
for(i = 0;i < ThunkArraySize;i++)
|
||||
{
|
||||
if(ATOMIC_EXCHANGE(ALenum, &ThunkArray[i], AL_TRUE) == AL_FALSE)
|
||||
if(!ATOMIC_FLAG_TEST_AND_SET(&ThunkArray[i], almemory_order_acq_rel))
|
||||
{
|
||||
ReadUnlock(&ThunkLock);
|
||||
*index = i+1;
|
||||
@@ -67,7 +69,7 @@ ALenum NewThunkEntry(ALuint *index)
|
||||
*/
|
||||
for(;i < ThunkArraySize;i++)
|
||||
{
|
||||
if(ATOMIC_EXCHANGE(ALenum, &ThunkArray[i], AL_TRUE) == AL_FALSE)
|
||||
if(!ATOMIC_FLAG_TEST_AND_SET(&ThunkArray[i], almemory_order_acq_rel))
|
||||
{
|
||||
WriteUnlock(&ThunkLock);
|
||||
*index = i+1;
|
||||
@@ -87,17 +89,20 @@ ALenum NewThunkEntry(ALuint *index)
|
||||
ThunkArray = NewList;
|
||||
ThunkArraySize *= 2;
|
||||
|
||||
ATOMIC_STORE(&ThunkArray[i], AL_TRUE);
|
||||
ATOMIC_FLAG_TEST_AND_SET(&ThunkArray[i], almemory_order_seq_cst);
|
||||
*index = ++i;
|
||||
|
||||
for(;i < ThunkArraySize;i++)
|
||||
ATOMIC_FLAG_CLEAR(&ThunkArray[i], almemory_order_relaxed);
|
||||
WriteUnlock(&ThunkLock);
|
||||
|
||||
*index = i+1;
|
||||
return AL_NO_ERROR;
|
||||
}
|
||||
|
||||
void FreeThunkEntry(ALuint index)
|
||||
{
|
||||
ReadLock(&ThunkLock);
|
||||
if(index > 0 && index <= ThunkArraySize)
|
||||
ATOMIC_STORE(&ThunkArray[index-1], AL_FALSE);
|
||||
if(index > 0 && (ALsizei)index <= ThunkArraySize)
|
||||
ATOMIC_FLAG_CLEAR(&ThunkArray[index-1], almemory_order_release);
|
||||
ReadUnlock(&ThunkLock);
|
||||
}
|
||||
|
||||
@@ -174,14 +174,6 @@ typedef ALubyte ALmulaw;
|
||||
typedef ALubyte ALalaw;
|
||||
typedef ALubyte ALima4;
|
||||
typedef ALubyte ALmsadpcm;
|
||||
typedef struct {
|
||||
ALbyte b[3];
|
||||
} ALbyte3;
|
||||
static_assert(sizeof(ALbyte3)==sizeof(ALbyte[3]), "ALbyte3 size is not 3");
|
||||
typedef struct {
|
||||
ALubyte b[3];
|
||||
} ALubyte3;
|
||||
static_assert(sizeof(ALubyte3)==sizeof(ALubyte[3]), "ALubyte3 size is not 3");
|
||||
|
||||
static inline ALshort DecodeMuLaw(ALmulaw val)
|
||||
{ return muLawDecompressionTable[val]; }
|
||||
@@ -498,320 +490,128 @@ static void EncodeMSADPCMBlock(ALmsadpcm *dst, const ALshort *src, ALint *sample
|
||||
}
|
||||
|
||||
|
||||
static inline ALint DecodeByte3(ALbyte3 val)
|
||||
{
|
||||
if(IS_LITTLE_ENDIAN)
|
||||
return (val.b[2]<<16) | (((ALubyte)val.b[1])<<8) | ((ALubyte)val.b[0]);
|
||||
return (val.b[0]<<16) | (((ALubyte)val.b[1])<<8) | ((ALubyte)val.b[2]);
|
||||
}
|
||||
/* Define same-type pass-through sample conversion functions (excludes ADPCM,
|
||||
* which are block-based). */
|
||||
#define DECL_TEMPLATE(T) \
|
||||
static inline T Conv_##T##_##T(T val) { return val; }
|
||||
|
||||
static inline ALbyte3 EncodeByte3(ALint val)
|
||||
{
|
||||
if(IS_LITTLE_ENDIAN)
|
||||
{
|
||||
ALbyte3 ret = {{ val, val>>8, val>>16 }};
|
||||
return ret;
|
||||
}
|
||||
else
|
||||
{
|
||||
ALbyte3 ret = {{ val>>16, val>>8, val }};
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
DECL_TEMPLATE(ALbyte);
|
||||
DECL_TEMPLATE(ALubyte);
|
||||
DECL_TEMPLATE(ALshort);
|
||||
DECL_TEMPLATE(ALushort);
|
||||
DECL_TEMPLATE(ALint);
|
||||
DECL_TEMPLATE(ALuint);
|
||||
DECL_TEMPLATE(ALalaw);
|
||||
DECL_TEMPLATE(ALmulaw);
|
||||
|
||||
static inline ALint DecodeUByte3(ALubyte3 val)
|
||||
{
|
||||
if(IS_LITTLE_ENDIAN)
|
||||
return (val.b[2]<<16) | (val.b[1]<<8) | (val.b[0]);
|
||||
return (val.b[0]<<16) | (val.b[1]<<8) | val.b[2];
|
||||
}
|
||||
|
||||
static inline ALubyte3 EncodeUByte3(ALint val)
|
||||
{
|
||||
if(IS_LITTLE_ENDIAN)
|
||||
{
|
||||
ALubyte3 ret = {{ val, val>>8, val>>16 }};
|
||||
return ret;
|
||||
}
|
||||
else
|
||||
{
|
||||
ALubyte3 ret = {{ val>>16, val>>8, val }};
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static inline ALbyte Conv_ALbyte_ALbyte(ALbyte val)
|
||||
{ return val; }
|
||||
static inline ALbyte Conv_ALbyte_ALubyte(ALubyte val)
|
||||
{ return val-128; }
|
||||
static inline ALbyte Conv_ALbyte_ALshort(ALshort val)
|
||||
{ return val>>8; }
|
||||
static inline ALbyte Conv_ALbyte_ALushort(ALushort val)
|
||||
{ return (val>>8)-128; }
|
||||
static inline ALbyte Conv_ALbyte_ALint(ALint val)
|
||||
{ return val>>24; }
|
||||
static inline ALbyte Conv_ALbyte_ALuint(ALuint val)
|
||||
{ return (val>>24)-128; }
|
||||
static inline ALbyte Conv_ALbyte_ALfloat(ALfloat val)
|
||||
{
|
||||
if(val > 1.0f) return 127;
|
||||
if(val < -1.0f) return -128;
|
||||
return (ALint)(val * 127.0f);
|
||||
}
|
||||
static inline ALbyte Conv_ALbyte_ALdouble(ALdouble val)
|
||||
{
|
||||
if(val > 1.0) return 127;
|
||||
if(val < -1.0) return -128;
|
||||
return (ALint)(val * 127.0);
|
||||
}
|
||||
static inline ALbyte Conv_ALbyte_ALmulaw(ALmulaw val)
|
||||
{ return Conv_ALbyte_ALshort(DecodeMuLaw(val)); }
|
||||
static inline ALbyte Conv_ALbyte_ALalaw(ALalaw val)
|
||||
{ return Conv_ALbyte_ALshort(DecodeALaw(val)); }
|
||||
static inline ALbyte Conv_ALbyte_ALbyte3(ALbyte3 val)
|
||||
{ return DecodeByte3(val)>>16; }
|
||||
static inline ALbyte Conv_ALbyte_ALubyte3(ALubyte3 val)
|
||||
{ return (DecodeUByte3(val)>>16)-128; }
|
||||
|
||||
static inline ALubyte Conv_ALubyte_ALbyte(ALbyte val)
|
||||
{ return val+128; }
|
||||
static inline ALubyte Conv_ALubyte_ALubyte(ALubyte val)
|
||||
{ return val; }
|
||||
static inline ALubyte Conv_ALubyte_ALshort(ALshort val)
|
||||
{ return (val>>8)+128; }
|
||||
static inline ALubyte Conv_ALubyte_ALushort(ALushort val)
|
||||
{ return val>>8; }
|
||||
static inline ALubyte Conv_ALubyte_ALint(ALint val)
|
||||
{ return (val>>24)+128; }
|
||||
static inline ALubyte Conv_ALubyte_ALuint(ALuint val)
|
||||
{ return val>>24; }
|
||||
static inline ALubyte Conv_ALubyte_ALfloat(ALfloat val)
|
||||
{
|
||||
if(val > 1.0f) return 255;
|
||||
if(val < -1.0f) return 0;
|
||||
return (ALint)(val * 127.0f) + 128;
|
||||
}
|
||||
static inline ALubyte Conv_ALubyte_ALdouble(ALdouble val)
|
||||
{
|
||||
if(val > 1.0) return 255;
|
||||
if(val < -1.0) return 0;
|
||||
return (ALint)(val * 127.0) + 128;
|
||||
}
|
||||
static inline ALubyte Conv_ALubyte_ALmulaw(ALmulaw val)
|
||||
{ return Conv_ALubyte_ALshort(DecodeMuLaw(val)); }
|
||||
static inline ALubyte Conv_ALubyte_ALalaw(ALalaw val)
|
||||
{ return Conv_ALubyte_ALshort(DecodeALaw(val)); }
|
||||
static inline ALubyte Conv_ALubyte_ALbyte3(ALbyte3 val)
|
||||
{ return (DecodeByte3(val)>>16)+128; }
|
||||
static inline ALubyte Conv_ALubyte_ALubyte3(ALubyte3 val)
|
||||
{ return DecodeUByte3(val)>>16; }
|
||||
|
||||
static inline ALshort Conv_ALshort_ALbyte(ALbyte val)
|
||||
{ return val<<8; }
|
||||
static inline ALshort Conv_ALshort_ALubyte(ALubyte val)
|
||||
{ return (val-128)<<8; }
|
||||
static inline ALshort Conv_ALshort_ALshort(ALshort val)
|
||||
{ return val; }
|
||||
static inline ALshort Conv_ALshort_ALushort(ALushort val)
|
||||
{ return val-32768; }
|
||||
static inline ALshort Conv_ALshort_ALint(ALint val)
|
||||
{ return val>>16; }
|
||||
static inline ALshort Conv_ALshort_ALuint(ALuint val)
|
||||
{ return (val>>16)-32768; }
|
||||
static inline ALshort Conv_ALshort_ALfloat(ALfloat val)
|
||||
{
|
||||
if(val > 1.0f) return 32767;
|
||||
if(val < -1.0f) return -32768;
|
||||
return (ALint)(val * 32767.0f);
|
||||
}
|
||||
static inline ALshort Conv_ALshort_ALdouble(ALdouble val)
|
||||
{
|
||||
if(val > 1.0) return 32767;
|
||||
if(val < -1.0) return -32768;
|
||||
return (ALint)(val * 32767.0);
|
||||
}
|
||||
static inline ALshort Conv_ALshort_ALmulaw(ALmulaw val)
|
||||
{ return Conv_ALshort_ALshort(DecodeMuLaw(val)); }
|
||||
static inline ALshort Conv_ALshort_ALalaw(ALalaw val)
|
||||
{ return Conv_ALshort_ALshort(DecodeALaw(val)); }
|
||||
static inline ALshort Conv_ALshort_ALbyte3(ALbyte3 val)
|
||||
{ return DecodeByte3(val)>>8; }
|
||||
static inline ALshort Conv_ALshort_ALubyte3(ALubyte3 val)
|
||||
{ return (DecodeUByte3(val)>>8)-32768; }
|
||||
|
||||
static inline ALushort Conv_ALushort_ALbyte(ALbyte val)
|
||||
{ return (val+128)<<8; }
|
||||
static inline ALushort Conv_ALushort_ALubyte(ALubyte val)
|
||||
{ return val<<8; }
|
||||
static inline ALushort Conv_ALushort_ALshort(ALshort val)
|
||||
{ return val+32768; }
|
||||
static inline ALushort Conv_ALushort_ALushort(ALushort val)
|
||||
{ return val; }
|
||||
static inline ALushort Conv_ALushort_ALint(ALint val)
|
||||
{ return (val>>16)+32768; }
|
||||
static inline ALushort Conv_ALushort_ALuint(ALuint val)
|
||||
{ return val>>16; }
|
||||
static inline ALushort Conv_ALushort_ALfloat(ALfloat val)
|
||||
{
|
||||
if(val > 1.0f) return 65535;
|
||||
if(val < -1.0f) return 0;
|
||||
return (ALint)(val * 32767.0f) + 32768;
|
||||
}
|
||||
static inline ALushort Conv_ALushort_ALdouble(ALdouble val)
|
||||
{
|
||||
if(val > 1.0) return 65535;
|
||||
if(val < -1.0) return 0;
|
||||
return (ALint)(val * 32767.0) + 32768;
|
||||
}
|
||||
static inline ALushort Conv_ALushort_ALmulaw(ALmulaw val)
|
||||
{ return Conv_ALushort_ALshort(DecodeMuLaw(val)); }
|
||||
static inline ALushort Conv_ALushort_ALalaw(ALalaw val)
|
||||
{ return Conv_ALushort_ALshort(DecodeALaw(val)); }
|
||||
static inline ALushort Conv_ALushort_ALbyte3(ALbyte3 val)
|
||||
{ return (DecodeByte3(val)>>8)+32768; }
|
||||
static inline ALushort Conv_ALushort_ALubyte3(ALubyte3 val)
|
||||
{ return DecodeUByte3(val)>>8; }
|
||||
|
||||
static inline ALint Conv_ALint_ALbyte(ALbyte val)
|
||||
{ return val<<24; }
|
||||
static inline ALint Conv_ALint_ALubyte(ALubyte val)
|
||||
{ return (val-128)<<24; }
|
||||
static inline ALint Conv_ALint_ALshort(ALshort val)
|
||||
{ return val<<16; }
|
||||
static inline ALint Conv_ALint_ALushort(ALushort val)
|
||||
{ return (val-32768)<<16; }
|
||||
static inline ALint Conv_ALint_ALint(ALint val)
|
||||
{ return val; }
|
||||
static inline ALint Conv_ALint_ALuint(ALuint val)
|
||||
{ return val-2147483648u; }
|
||||
static inline ALint Conv_ALint_ALfloat(ALfloat val)
|
||||
{
|
||||
if(val > 1.0f) return 2147483647;
|
||||
if(val < -1.0f) return -2147483647-1;
|
||||
return (ALint)(val*16777215.0f) << 7;
|
||||
}
|
||||
static inline ALint Conv_ALint_ALdouble(ALdouble val)
|
||||
{
|
||||
if(val > 1.0) return 2147483647;
|
||||
if(val < -1.0) return -2147483647-1;
|
||||
return (ALint)(val * 2147483647.0);
|
||||
}
|
||||
static inline ALint Conv_ALint_ALmulaw(ALmulaw val)
|
||||
{ return Conv_ALint_ALshort(DecodeMuLaw(val)); }
|
||||
static inline ALint Conv_ALint_ALalaw(ALalaw val)
|
||||
{ return Conv_ALint_ALshort(DecodeALaw(val)); }
|
||||
static inline ALint Conv_ALint_ALbyte3(ALbyte3 val)
|
||||
{ return DecodeByte3(val)<<8; }
|
||||
static inline ALint Conv_ALint_ALubyte3(ALubyte3 val)
|
||||
{ return (DecodeUByte3(val)-8388608)<<8; }
|
||||
|
||||
static inline ALuint Conv_ALuint_ALbyte(ALbyte val)
|
||||
{ return (val+128)<<24; }
|
||||
static inline ALuint Conv_ALuint_ALubyte(ALubyte val)
|
||||
{ return val<<24; }
|
||||
static inline ALuint Conv_ALuint_ALshort(ALshort val)
|
||||
{ return (val+32768)<<16; }
|
||||
static inline ALuint Conv_ALuint_ALushort(ALushort val)
|
||||
{ return val<<16; }
|
||||
static inline ALuint Conv_ALuint_ALint(ALint val)
|
||||
{ return val+2147483648u; }
|
||||
static inline ALuint Conv_ALuint_ALuint(ALuint val)
|
||||
{ return val; }
|
||||
static inline ALuint Conv_ALuint_ALfloat(ALfloat val)
|
||||
{
|
||||
if(val > 1.0f) return 4294967295u;
|
||||
if(val < -1.0f) return 0;
|
||||
return ((ALint)(val*16777215.0f)<<7) + 2147483648u;
|
||||
}
|
||||
static inline ALuint Conv_ALuint_ALdouble(ALdouble val)
|
||||
{
|
||||
if(val > 1.0) return 4294967295u;
|
||||
if(val < -1.0) return 0;
|
||||
return (ALint)(val * 2147483647.0) + 2147483648u;
|
||||
}
|
||||
static inline ALuint Conv_ALuint_ALmulaw(ALmulaw val)
|
||||
{ return Conv_ALuint_ALshort(DecodeMuLaw(val)); }
|
||||
static inline ALuint Conv_ALuint_ALalaw(ALalaw val)
|
||||
{ return Conv_ALuint_ALshort(DecodeALaw(val)); }
|
||||
static inline ALuint Conv_ALuint_ALbyte3(ALbyte3 val)
|
||||
{ return (DecodeByte3(val)+8388608)<<8; }
|
||||
static inline ALuint Conv_ALuint_ALubyte3(ALubyte3 val)
|
||||
{ return DecodeUByte3(val)<<8; }
|
||||
|
||||
static inline ALfloat Conv_ALfloat_ALbyte(ALbyte val)
|
||||
{ return val * (1.0f/127.0f); }
|
||||
static inline ALfloat Conv_ALfloat_ALubyte(ALubyte val)
|
||||
{ return (val-128) * (1.0f/127.0f); }
|
||||
static inline ALfloat Conv_ALfloat_ALshort(ALshort val)
|
||||
{ return val * (1.0f/32767.0f); }
|
||||
static inline ALfloat Conv_ALfloat_ALushort(ALushort val)
|
||||
{ return (val-32768) * (1.0f/32767.0f); }
|
||||
static inline ALfloat Conv_ALfloat_ALint(ALint val)
|
||||
{ return (ALfloat)(val>>7) * (1.0f/16777215.0f); }
|
||||
static inline ALfloat Conv_ALfloat_ALuint(ALuint val)
|
||||
{ return (ALfloat)((ALint)(val>>7)-16777216) * (1.0f/16777215.0f); }
|
||||
/* Slightly special handling for floats and doubles (converts NaN to 0, and
|
||||
* allows float<->double pass-through).
|
||||
*/
|
||||
static inline ALfloat Conv_ALfloat_ALfloat(ALfloat val)
|
||||
{ return (val==val) ? val : 0.0f; }
|
||||
static inline ALfloat Conv_ALfloat_ALdouble(ALdouble val)
|
||||
{ return (val==val) ? (ALfloat)val : 0.0f; }
|
||||
static inline ALfloat Conv_ALfloat_ALmulaw(ALmulaw val)
|
||||
{ return Conv_ALfloat_ALshort(DecodeMuLaw(val)); }
|
||||
static inline ALfloat Conv_ALfloat_ALalaw(ALalaw val)
|
||||
{ return Conv_ALfloat_ALshort(DecodeALaw(val)); }
|
||||
static inline ALfloat Conv_ALfloat_ALbyte3(ALbyte3 val)
|
||||
{ return (ALfloat)(DecodeByte3(val) * (1.0/8388607.0)); }
|
||||
static inline ALfloat Conv_ALfloat_ALubyte3(ALubyte3 val)
|
||||
{ return (ALfloat)((DecodeUByte3(val)-8388608) * (1.0/8388607.0)); }
|
||||
|
||||
static inline ALdouble Conv_ALdouble_ALbyte(ALbyte val)
|
||||
{ return val * (1.0/127.0); }
|
||||
static inline ALdouble Conv_ALdouble_ALubyte(ALubyte val)
|
||||
{ return (val-128) * (1.0/127.0); }
|
||||
static inline ALdouble Conv_ALdouble_ALshort(ALshort val)
|
||||
{ return val * (1.0/32767.0); }
|
||||
static inline ALdouble Conv_ALdouble_ALushort(ALushort val)
|
||||
{ return (val-32768) * (1.0/32767.0); }
|
||||
static inline ALdouble Conv_ALdouble_ALint(ALint val)
|
||||
{ return val * (1.0/2147483647.0); }
|
||||
static inline ALdouble Conv_ALdouble_ALuint(ALuint val)
|
||||
{ return (ALint)(val-2147483648u) * (1.0/2147483647.0); }
|
||||
static inline ALdouble Conv_ALdouble_ALfloat(ALfloat val)
|
||||
{ return (val==val) ? val : 0.0f; }
|
||||
{ return (val==val) ? (ALdouble)val : 0.0; }
|
||||
static inline ALdouble Conv_ALdouble_ALdouble(ALdouble val)
|
||||
{ return (val==val) ? val : 0.0; }
|
||||
static inline ALdouble Conv_ALdouble_ALmulaw(ALmulaw val)
|
||||
{ return Conv_ALdouble_ALshort(DecodeMuLaw(val)); }
|
||||
static inline ALdouble Conv_ALdouble_ALalaw(ALalaw val)
|
||||
{ return Conv_ALdouble_ALshort(DecodeALaw(val)); }
|
||||
static inline ALdouble Conv_ALdouble_ALbyte3(ALbyte3 val)
|
||||
{ return DecodeByte3(val) * (1.0/8388607.0); }
|
||||
static inline ALdouble Conv_ALdouble_ALubyte3(ALubyte3 val)
|
||||
{ return (DecodeUByte3(val)-8388608) * (1.0/8388607.0); }
|
||||
|
||||
#undef DECL_TEMPLATE
|
||||
|
||||
/* Define alternate-sign functions. */
|
||||
#define DECL_TEMPLATE(T1, T2, O) \
|
||||
static inline T1 Conv_##T1##_##T2(T2 val) { return (T1)val - O; } \
|
||||
static inline T2 Conv_##T2##_##T1(T1 val) { return (T2)val + O; }
|
||||
|
||||
DECL_TEMPLATE(ALbyte, ALubyte, 128);
|
||||
DECL_TEMPLATE(ALshort, ALushort, 32768);
|
||||
DECL_TEMPLATE(ALint, ALuint, 2147483648u);
|
||||
|
||||
#undef DECL_TEMPLATE
|
||||
|
||||
/* Define int-type to int-type functions */
|
||||
#define DECL_TEMPLATE(T, ST, UT, SH) \
|
||||
static inline T Conv_##T##_##ST(ST val){ return val >> SH; } \
|
||||
static inline T Conv_##T##_##UT(UT val){ return Conv_##ST##_##UT(val) >> SH; }\
|
||||
static inline ST Conv_##ST##_##T(T val){ return val << SH; } \
|
||||
static inline UT Conv_##UT##_##T(T val){ return Conv_##UT##_##ST(val << SH); }
|
||||
|
||||
#define DECL_TEMPLATE2(T1, T2, SH) \
|
||||
DECL_TEMPLATE(AL##T1, AL##T2, ALu##T2, SH) \
|
||||
DECL_TEMPLATE(ALu##T1, ALu##T2, AL##T2, SH)
|
||||
|
||||
DECL_TEMPLATE2(byte, short, 8)
|
||||
DECL_TEMPLATE2(short, int, 16)
|
||||
DECL_TEMPLATE2(byte, int, 24)
|
||||
|
||||
#undef DECL_TEMPLATE2
|
||||
#undef DECL_TEMPLATE
|
||||
|
||||
/* Define int-type to fp functions */
|
||||
#define DECL_TEMPLATE(T, ST, UT, OP) \
|
||||
static inline T Conv_##T##_##ST(ST val) { return (T)val * OP; } \
|
||||
static inline T Conv_##T##_##UT(UT val) { return (T)Conv_##ST##_##UT(val) * OP; }
|
||||
|
||||
#define DECL_TEMPLATE2(T1, T2, OP) \
|
||||
DECL_TEMPLATE(T1, AL##T2, ALu##T2, OP)
|
||||
|
||||
DECL_TEMPLATE2(ALfloat, byte, (1.0f/128.0f))
|
||||
DECL_TEMPLATE2(ALdouble, byte, (1.0/128.0))
|
||||
DECL_TEMPLATE2(ALfloat, short, (1.0f/32768.0f))
|
||||
DECL_TEMPLATE2(ALdouble, short, (1.0/32768.0))
|
||||
DECL_TEMPLATE2(ALdouble, int, (1.0/2147483648.0))
|
||||
|
||||
/* Special handling for int32 to float32, since it would overflow. */
|
||||
static inline ALfloat Conv_ALfloat_ALint(ALint val)
|
||||
{ return (ALfloat)(val>>7) * (1.0f/16777216.0f); }
|
||||
static inline ALfloat Conv_ALfloat_ALuint(ALuint val)
|
||||
{ return (ALfloat)(Conv_ALint_ALuint(val)>>7) * (1.0f/16777216.0f); }
|
||||
|
||||
#undef DECL_TEMPLATE2
|
||||
#undef DECL_TEMPLATE
|
||||
|
||||
/* Define fp to int-type functions */
|
||||
#define DECL_TEMPLATE(FT, T, smin, smax) \
|
||||
static inline AL##T Conv_AL##T##_##FT(FT val) \
|
||||
{ \
|
||||
val *= (FT)smax + 1; \
|
||||
if(val >= (FT)smax) return smax; \
|
||||
if(val <= (FT)smin) return smin; \
|
||||
return (AL##T)val; \
|
||||
} \
|
||||
static inline ALu##T Conv_ALu##T##_##FT(FT val) \
|
||||
{ return Conv_ALu##T##_AL##T(Conv_AL##T##_##FT(val)); }
|
||||
|
||||
DECL_TEMPLATE(ALfloat, byte, -128, 127)
|
||||
DECL_TEMPLATE(ALdouble, byte, -128, 127)
|
||||
DECL_TEMPLATE(ALfloat, short, -32768, 32767)
|
||||
DECL_TEMPLATE(ALdouble, short, -32768, 32767)
|
||||
DECL_TEMPLATE(ALdouble, int, -2147483647-1, 2147483647)
|
||||
|
||||
/* Special handling for float32 to int32, since it would overflow. */
|
||||
static inline ALint Conv_ALint_ALfloat(ALfloat val)
|
||||
{
|
||||
val *= 16777216.0f;
|
||||
if(val >= 16777215.0f) return 0x7fffff80/*16777215 << 7*/;
|
||||
if(val <= -16777216.0f) return 0x80000000/*-16777216 << 7*/;
|
||||
return (ALint)val << 7;
|
||||
}
|
||||
static inline ALuint Conv_ALuint_ALfloat(ALfloat val)
|
||||
{ return Conv_ALuint_ALint(Conv_ALint_ALfloat(val)); }
|
||||
|
||||
#undef DECL_TEMPLATE
|
||||
|
||||
/* Define muLaw and aLaw functions (goes through short functions). */
|
||||
#define DECL_TEMPLATE(T) \
|
||||
static inline ALmulaw Conv_ALmulaw_##T(T val) \
|
||||
{ return EncodeMuLaw(Conv_ALshort_##T(val)); }
|
||||
|
||||
DECL_TEMPLATE(ALbyte)
|
||||
DECL_TEMPLATE(ALubyte)
|
||||
DECL_TEMPLATE(ALshort)
|
||||
DECL_TEMPLATE(ALushort)
|
||||
DECL_TEMPLATE(ALint)
|
||||
DECL_TEMPLATE(ALuint)
|
||||
DECL_TEMPLATE(ALfloat)
|
||||
DECL_TEMPLATE(ALdouble)
|
||||
static inline ALmulaw Conv_ALmulaw_ALmulaw(ALmulaw val)
|
||||
{ return val; }
|
||||
DECL_TEMPLATE(ALalaw)
|
||||
DECL_TEMPLATE(ALbyte3)
|
||||
DECL_TEMPLATE(ALubyte3)
|
||||
|
||||
#undef DECL_TEMPLATE
|
||||
|
||||
#define DECL_TEMPLATE(T) \
|
||||
{ return EncodeMuLaw(Conv_ALshort_##T(val)); } \
|
||||
static inline T Conv_##T##_ALmulaw(ALmulaw val) \
|
||||
{ return Conv_##T##_ALshort(DecodeMuLaw(val)); } \
|
||||
\
|
||||
static inline ALalaw Conv_ALalaw_##T(T val) \
|
||||
{ return EncodeALaw(Conv_ALshort_##T(val)); }
|
||||
{ return EncodeALaw(Conv_ALshort_##T(val)); } \
|
||||
static inline T Conv_##T##_ALalaw(ALalaw val) \
|
||||
{ return Conv_##T##_ALshort(DecodeALaw(val)); }
|
||||
|
||||
DECL_TEMPLATE(ALbyte)
|
||||
DECL_TEMPLATE(ALubyte)
|
||||
@@ -821,53 +621,14 @@ DECL_TEMPLATE(ALint)
|
||||
DECL_TEMPLATE(ALuint)
|
||||
DECL_TEMPLATE(ALfloat)
|
||||
DECL_TEMPLATE(ALdouble)
|
||||
DECL_TEMPLATE(ALmulaw)
|
||||
static inline ALalaw Conv_ALalaw_ALalaw(ALalaw val)
|
||||
{ return val; }
|
||||
DECL_TEMPLATE(ALbyte3)
|
||||
DECL_TEMPLATE(ALubyte3)
|
||||
|
||||
#undef DECL_TEMPLATE
|
||||
|
||||
#define DECL_TEMPLATE(T) \
|
||||
static inline ALbyte3 Conv_ALbyte3_##T(T val) \
|
||||
{ return EncodeByte3(Conv_ALint_##T(val)>>8); }
|
||||
|
||||
DECL_TEMPLATE(ALbyte)
|
||||
DECL_TEMPLATE(ALubyte)
|
||||
DECL_TEMPLATE(ALshort)
|
||||
DECL_TEMPLATE(ALushort)
|
||||
DECL_TEMPLATE(ALint)
|
||||
DECL_TEMPLATE(ALuint)
|
||||
DECL_TEMPLATE(ALfloat)
|
||||
DECL_TEMPLATE(ALdouble)
|
||||
DECL_TEMPLATE(ALmulaw)
|
||||
DECL_TEMPLATE(ALalaw)
|
||||
static inline ALbyte3 Conv_ALbyte3_ALbyte3(ALbyte3 val)
|
||||
{ return val; }
|
||||
DECL_TEMPLATE(ALubyte3)
|
||||
|
||||
#undef DECL_TEMPLATE
|
||||
|
||||
#define DECL_TEMPLATE(T) \
|
||||
static inline ALubyte3 Conv_ALubyte3_##T(T val) \
|
||||
{ return EncodeUByte3(Conv_ALuint_##T(val)>>8); }
|
||||
|
||||
DECL_TEMPLATE(ALbyte)
|
||||
DECL_TEMPLATE(ALubyte)
|
||||
DECL_TEMPLATE(ALshort)
|
||||
DECL_TEMPLATE(ALushort)
|
||||
DECL_TEMPLATE(ALint)
|
||||
DECL_TEMPLATE(ALuint)
|
||||
DECL_TEMPLATE(ALfloat)
|
||||
DECL_TEMPLATE(ALdouble)
|
||||
DECL_TEMPLATE(ALmulaw)
|
||||
DECL_TEMPLATE(ALalaw)
|
||||
DECL_TEMPLATE(ALbyte3)
|
||||
static inline ALubyte3 Conv_ALubyte3_ALubyte3(ALubyte3 val)
|
||||
{ return val; }
|
||||
|
||||
#undef DECL_TEMPLATE
|
||||
/* Define muLaw <-> aLaw functions. */
|
||||
static inline ALalaw Conv_ALalaw_ALmulaw(ALmulaw val)
|
||||
{ return EncodeALaw(DecodeMuLaw(val)); }
|
||||
static inline ALmulaw Conv_ALmulaw_ALalaw(ALalaw val)
|
||||
{ return EncodeMuLaw(DecodeALaw(val)); }
|
||||
|
||||
|
||||
#define DECL_TEMPLATE(T1, T2) \
|
||||
@@ -892,9 +653,7 @@ DECL_TEMPLATE(T, ALuint) \
|
||||
DECL_TEMPLATE(T, ALfloat) \
|
||||
DECL_TEMPLATE(T, ALdouble) \
|
||||
DECL_TEMPLATE(T, ALmulaw) \
|
||||
DECL_TEMPLATE(T, ALalaw) \
|
||||
DECL_TEMPLATE(T, ALbyte3) \
|
||||
DECL_TEMPLATE(T, ALubyte3)
|
||||
DECL_TEMPLATE(T, ALalaw)
|
||||
|
||||
DECL_TEMPLATE2(ALbyte)
|
||||
DECL_TEMPLATE2(ALubyte)
|
||||
@@ -906,8 +665,6 @@ DECL_TEMPLATE2(ALfloat)
|
||||
DECL_TEMPLATE2(ALdouble)
|
||||
DECL_TEMPLATE2(ALmulaw)
|
||||
DECL_TEMPLATE2(ALalaw)
|
||||
DECL_TEMPLATE2(ALbyte3)
|
||||
DECL_TEMPLATE2(ALubyte3)
|
||||
|
||||
#undef DECL_TEMPLATE2
|
||||
#undef DECL_TEMPLATE
|
||||
@@ -957,8 +714,6 @@ DECL_TEMPLATE(ALfloat)
|
||||
DECL_TEMPLATE(ALdouble)
|
||||
DECL_TEMPLATE(ALmulaw)
|
||||
DECL_TEMPLATE(ALalaw)
|
||||
DECL_TEMPLATE(ALbyte3)
|
||||
DECL_TEMPLATE(ALubyte3)
|
||||
|
||||
#undef DECL_TEMPLATE
|
||||
|
||||
@@ -1010,8 +765,6 @@ DECL_TEMPLATE(ALfloat)
|
||||
DECL_TEMPLATE(ALdouble)
|
||||
DECL_TEMPLATE(ALmulaw)
|
||||
DECL_TEMPLATE(ALalaw)
|
||||
DECL_TEMPLATE(ALbyte3)
|
||||
DECL_TEMPLATE(ALubyte3)
|
||||
|
||||
#undef DECL_TEMPLATE
|
||||
|
||||
@@ -1063,8 +816,6 @@ DECL_TEMPLATE(ALfloat)
|
||||
DECL_TEMPLATE(ALdouble)
|
||||
DECL_TEMPLATE(ALmulaw)
|
||||
DECL_TEMPLATE(ALalaw)
|
||||
DECL_TEMPLATE(ALbyte3)
|
||||
DECL_TEMPLATE(ALubyte3)
|
||||
|
||||
#undef DECL_TEMPLATE
|
||||
|
||||
@@ -1114,8 +865,6 @@ DECL_TEMPLATE(ALfloat)
|
||||
DECL_TEMPLATE(ALdouble)
|
||||
DECL_TEMPLATE(ALmulaw)
|
||||
DECL_TEMPLATE(ALalaw)
|
||||
DECL_TEMPLATE(ALbyte3)
|
||||
DECL_TEMPLATE(ALubyte3)
|
||||
|
||||
#undef DECL_TEMPLATE
|
||||
|
||||
@@ -1192,12 +941,6 @@ static void Convert_##T(T *dst, const ALvoid *src, enum UserFmtType srcType, \
|
||||
case UserFmtMSADPCM: \
|
||||
Convert_##T##_ALmsadpcm(dst, src, numchans, len, align); \
|
||||
break; \
|
||||
case UserFmtByte3: \
|
||||
Convert_##T##_ALbyte3(dst, src, numchans, len, align); \
|
||||
break; \
|
||||
case UserFmtUByte3: \
|
||||
Convert_##T##_ALubyte3(dst, src, numchans, len, align); \
|
||||
break; \
|
||||
} \
|
||||
}
|
||||
|
||||
@@ -1213,8 +956,6 @@ DECL_TEMPLATE(ALmulaw)
|
||||
DECL_TEMPLATE(ALalaw)
|
||||
DECL_TEMPLATE(ALima4)
|
||||
DECL_TEMPLATE(ALmsadpcm)
|
||||
DECL_TEMPLATE(ALbyte3)
|
||||
DECL_TEMPLATE(ALubyte3)
|
||||
|
||||
#undef DECL_TEMPLATE
|
||||
|
||||
@@ -1259,11 +1000,5 @@ void ConvertData(ALvoid *dst, enum UserFmtType dstType, const ALvoid *src, enum
|
||||
case UserFmtMSADPCM:
|
||||
Convert_ALmsadpcm(dst, src, srcType, numchans, len, align);
|
||||
break;
|
||||
case UserFmtByte3:
|
||||
Convert_ALbyte3(dst, src, srcType, numchans, len, align);
|
||||
break;
|
||||
case UserFmtUByte3:
|
||||
Convert_ALubyte3(dst, src, srcType, numchans, len, align);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user