mirror of
https://github.com/love2d/megasource.git
synced 2026-08-19 12:14:41 +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" */
|
||||
|
||||
Reference in New Issue
Block a user