123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967 |
- #ifndef AL_MAIN_H
- #define AL_MAIN_H
- #include <string.h>
- #include <stdio.h>
- #include <stdarg.h>
- #include <assert.h>
- #include <math.h>
- #include <limits.h>
- #ifdef HAVE_STRINGS_H
- #include <strings.h>
- #endif
- #ifdef HAVE_FENV_H
- #include <fenv.h>
- #endif
- #include "AL/al.h"
- #include "AL/alc.h"
- #include "AL/alext.h"
- #if defined(_WIN64)
- #define SZFMT "%I64u"
- #elif defined(_WIN32)
- #define SZFMT "%u"
- #else
- #define SZFMT "%zu"
- #endif
- #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"
- #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
- #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
- #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
- typedef ALint64SOFT ALint64;
- typedef ALuint64SOFT ALuint64;
- #ifndef U64
- #if defined(_MSC_VER)
- #define U64(x) ((ALuint64)(x##ui64))
- #elif SIZEOF_LONG == 8
- #define U64(x) ((ALuint64)(x##ul))
- #elif SIZEOF_LONG_LONG == 8
- #define U64(x) ((ALuint64)(x##ull))
- #endif
- #endif
- #ifndef UINT64_MAX
- #define UINT64_MAX U64(18446744073709551615)
- #endif
- #ifndef UNUSED
- #if defined(__cplusplus)
- #define UNUSED(x)
- #elif defined(__GNUC__)
- #define UNUSED(x) UNUSED_##x __attribute__((unused))
- #elif defined(__LCLINT__)
- #define UNUSED(x) /*@unused@*/ x
- #else
- #define UNUSED(x) x
- #endif
- #endif
- #ifdef __GNUC__
- #define DECL_FORMAT(x, y, z) __attribute__((format(x, (y), (z))))
- #else
- #define DECL_FORMAT(x, y, z)
- #endif
- #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
- * thread functions will be properly aligned on the stack, even though GCC may
- * generate code with the assumption that it is. */
- #define FORCE_ALIGN __attribute__((force_align_arg_pointer))
- #else
- #define FORCE_ALIGN
- #endif
- #ifdef HAVE_C99_VLA
- #define DECL_VLA(T, _name, _size) T _name[(_size)]
- #else
- #define DECL_VLA(T, _name, _size) T *_name = alloca((_size) * sizeof(T))
- #endif
- #ifndef PATH_MAX
- #ifdef MAX_PATH
- #define PATH_MAX MAX_PATH
- #else
- #define PATH_MAX 4096
- #endif
- #endif
- static const union {
- ALuint u;
- ALubyte b[sizeof(ALuint)];
- } EndianTest = { 1 };
- #define IS_LITTLE_ENDIAN (EndianTest.b[0] == 1)
- #define COUNTOF(x) (sizeof((x))/sizeof((x)[0]))
- #define DERIVE_FROM_TYPE(t) t t##_parent
- #define STATIC_CAST(to, obj) (&(obj)->to##_parent)
- #ifdef __GNUC__
- #define STATIC_UPCAST(to, from, obj) __extension__({ \
- static_assert(__builtin_types_compatible_p(from, __typeof(*(obj))), \
- "Invalid upcast object from type"); \
- (to*)((char*)(obj) - offsetof(to, from##_parent)); \
- })
- #else
- #define STATIC_UPCAST(to, from, obj) ((to*)((char*)(obj) - offsetof(to, from##_parent)))
- #endif
- #define DECLARE_FORWARD(T1, T2, rettype, func) \
- rettype T1##_##func(T1 *obj) \
- { return T2##_##func(STATIC_CAST(T2, obj)); }
- #define DECLARE_FORWARD1(T1, T2, rettype, func, argtype1) \
- rettype T1##_##func(T1 *obj, argtype1 a) \
- { return T2##_##func(STATIC_CAST(T2, obj), a); }
- #define DECLARE_FORWARD2(T1, T2, rettype, func, argtype1, argtype2) \
- rettype T1##_##func(T1 *obj, argtype1 a, argtype2 b) \
- { return T2##_##func(STATIC_CAST(T2, obj), a, b); }
- #define DECLARE_FORWARD3(T1, T2, rettype, func, argtype1, argtype2, argtype3) \
- rettype T1##_##func(T1 *obj, argtype1 a, argtype2 b, argtype3 c) \
- { return T2##_##func(STATIC_CAST(T2, obj), a, b, c); }
- #define GET_VTABLE1(T1) (&(T1##_vtable))
- #define GET_VTABLE2(T1, T2) (&(T1##_##T2##_vtable))
- #define SET_VTABLE1(T1, obj) ((obj)->vtbl = GET_VTABLE1(T1))
- #define SET_VTABLE2(T1, T2, obj) (STATIC_CAST(T2, obj)->vtbl = GET_VTABLE2(T1, T2))
- #define DECLARE_THUNK(T1, T2, rettype, func) \
- static rettype T1##_##T2##_##func(T2 *obj) \
- { return T1##_##func(STATIC_UPCAST(T1, T2, obj)); }
- #define DECLARE_THUNK1(T1, T2, rettype, func, argtype1) \
- static rettype T1##_##T2##_##func(T2 *obj, argtype1 a) \
- { return T1##_##func(STATIC_UPCAST(T1, T2, obj), a); }
- #define DECLARE_THUNK2(T1, T2, rettype, func, argtype1, argtype2) \
- static rettype T1##_##T2##_##func(T2 *obj, argtype1 a, argtype2 b) \
- { return T1##_##func(STATIC_UPCAST(T1, T2, obj), a, b); }
- #define DECLARE_THUNK3(T1, T2, rettype, func, argtype1, argtype2, argtype3) \
- static rettype T1##_##T2##_##func(T2 *obj, argtype1 a, argtype2 b, argtype3 c) \
- { return T1##_##func(STATIC_UPCAST(T1, T2, obj), a, b, c); }
- #define DECLARE_THUNK4(T1, T2, rettype, func, argtype1, argtype2, argtype3, argtype4) \
- static rettype T1##_##T2##_##func(T2 *obj, argtype1 a, argtype2 b, argtype3 c, argtype4 d) \
- { return T1##_##func(STATIC_UPCAST(T1, T2, obj), a, b, c, d); }
- #define DECLARE_DEFAULT_ALLOCATORS(T) \
- static void* T##_New(size_t size) { return al_malloc(16, size); } \
- static void T##_Delete(void *ptr) { al_free(ptr); }
- /* Helper to extract an argument list for VCALL. Not used directly. */
- #define EXTRACT_VCALL_ARGS(...) __VA_ARGS__))
- /* Call a "virtual" method on an object, with arguments. */
- #define V(obj, func) ((obj)->vtbl->func((obj), EXTRACT_VCALL_ARGS
- /* Call a "virtual" method on an object, with no arguments. */
- #define V0(obj, func) ((obj)->vtbl->func((obj) EXTRACT_VCALL_ARGS
- #define DELETE_OBJ(obj) do { \
- if((obj) != NULL) \
- { \
- V0((obj),Destruct)(); \
- V0((obj),Delete)(); \
- } \
- } while(0)
- #define EXTRACT_NEW_ARGS(...) __VA_ARGS__); \
- } \
- } while(0)
- #define NEW_OBJ(_res, T) do { \
- _res = T##_New(sizeof(T)); \
- if(_res) \
- { \
- 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
- extern "C" {
- #endif
- struct Hrtf;
- #define DEFAULT_OUTPUT_RATE (44100)
- #define MIN_OUTPUT_RATE (8000)
- /* Find the next power-of-2 for non-power-of-2 numbers. */
- inline ALuint NextPowerOf2(ALuint value)
- {
- if(value > 0)
- {
- value--;
- value |= value>>1;
- value |= value>>2;
- value |= value>>4;
- value |= value>>8;
- value |= value>>16;
- }
- return value+1;
- }
- /* Fast float-to-int conversion. Assumes the FPU is already in round-to-zero
- * mode. */
- inline ALint fastf2i(ALfloat f)
- {
- #ifdef HAVE_LRINTF
- return lrintf(f);
- #elif defined(_MSC_VER) && defined(_M_IX86)
- ALint i;
- __asm fld f
- __asm fistp i
- return i;
- #else
- return (ALint)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;
- enum DistanceModel {
- InverseDistanceClamped = AL_INVERSE_DISTANCE_CLAMPED,
- LinearDistanceClamped = AL_LINEAR_DISTANCE_CLAMPED,
- ExponentDistanceClamped = AL_EXPONENT_DISTANCE_CLAMPED,
- InverseDistance = AL_INVERSE_DISTANCE,
- LinearDistance = AL_LINEAR_DISTANCE,
- ExponentDistance = AL_EXPONENT_DISTANCE,
- DisableDistance = AL_NONE,
- DefaultDistanceModel = InverseDistanceClamped
- };
- enum Channel {
- FrontLeft = 0,
- FrontRight,
- FrontCenter,
- LFE,
- BackLeft,
- BackRight,
- BackCenter,
- SideLeft,
- SideRight,
- 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
- };
- /* Device formats */
- enum DevFmtType {
- DevFmtByte = ALC_BYTE_SOFT,
- DevFmtUByte = ALC_UNSIGNED_BYTE_SOFT,
- DevFmtShort = ALC_SHORT_SOFT,
- DevFmtUShort = ALC_UNSIGNED_SHORT_SOFT,
- DevFmtInt = ALC_INT_SOFT,
- DevFmtUInt = ALC_UNSIGNED_INT_SOFT,
- DevFmtFloat = ALC_FLOAT_SOFT,
- DevFmtTypeDefault = DevFmtFloat
- };
- enum DevFmtChannels {
- DevFmtMono = ALC_MONO_SOFT,
- DevFmtStereo = ALC_STEREO_SOFT,
- DevFmtQuad = ALC_QUAD_SOFT,
- DevFmtX51 = ALC_5POINT1_SOFT,
- DevFmtX61 = ALC_6POINT1_SOFT,
- DevFmtX71 = ALC_7POINT1_SOFT,
- /* Similar to 5.1, except using rear channels instead of sides */
- DevFmtX51Rear = 0x80000000,
- /* Ambisonic formats should be kept together */
- DevFmtAmbi1,
- DevFmtAmbi2,
- DevFmtAmbi3,
- DevFmtChannelsDefault = DevFmtStereo
- };
- #define MAX_OUTPUT_CHANNELS (16)
- ALuint BytesFromDevFmt(enum DevFmtType type);
- ALuint ChannelsFromDevFmt(enum DevFmtChannels chans);
- inline ALuint FrameSizeFromDevFmt(enum DevFmtChannels chans, enum DevFmtType type)
- {
- return ChannelsFromDevFmt(chans) * BytesFromDevFmt(type);
- }
- enum AmbiFormat {
- AmbiFormat_FuMa, /* FuMa channel order and normalization */
- AmbiFormat_ACN_SN3D, /* ACN channel order and SN3D normalization */
- AmbiFormat_ACN_N3D, /* ACN channel order and N3D normalization */
- AmbiFormat_Default = AmbiFormat_ACN_SN3D
- };
- extern const struct EffectList {
- const char *name;
- int type;
- const char *ename;
- ALenum val;
- } EffectList[];
- enum DeviceType {
- Playback,
- Capture,
- Loopback
- };
- 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, 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;
- ALuint 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)
- typedef struct HrtfState {
- alignas(16) ALfloat History[HRTF_HISTORY_LENGTH];
- alignas(16) ALfloat Values[HRIR_LENGTH][2];
- } HrtfState;
- typedef struct HrtfParams {
- alignas(16) ALfloat Coeffs[HRIR_LENGTH][2];
- ALuint Delay[2];
- } HrtfParams;
- /* 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)
- struct ALCdevice_struct
- {
- RefCount ref;
- ALCboolean Connected;
- enum DeviceType Type;
- ALuint Frequency;
- ALuint UpdateSize;
- ALuint NumUpdates;
- enum DevFmtChannels FmtChans;
- enum DevFmtType FmtType;
- ALboolean IsHeadphones;
- /* For DevFmtAmbi* output only, specifies the channel order and
- * normalization.
- */
- enum AmbiFormat AmbiFmt;
- al_string DeviceName;
- ATOMIC(ALCenum) LastError;
- // Maximum number of sources that can be created
- ALuint SourcesMax;
- // Maximum number of slots that can be created
- ALuint AuxiliaryEffectSlotMax;
- ALCuint NumMonoSources;
- ALCuint NumStereoSources;
- ALuint NumAuxSends;
- // Map of Buffers for this device
- UIntMap BufferMap;
- // Map of Effects for this device
- UIntMap EffectMap;
- // Map of Filters for this device
- UIntMap FilterMap;
- /* HRTF filter tables */
- struct {
- vector_HrtfEntry List;
- al_string Name;
- ALCenum Status;
- const struct Hrtf *Handle;
- /* HRTF filter state for dry buffer content */
- alignas(16) ALfloat Values[4][HRIR_LENGTH][2];
- alignas(16) ALfloat Coeffs[4][HRIR_LENGTH][2];
- ALuint Offset;
- ALuint IrSize;
- } Hrtf;
- /* 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;
- ALuint64 ClockBase;
- ALuint SamplesDone;
- /* Temp storage used for each source when mixing. */
- alignas(16) ALfloat SourceData[BUFFERSIZE];
- alignas(16) ALfloat ResampledData[BUFFERSIZE];
- alignas(16) ALfloat FilteredData[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.
- */
- ALuint CoeffCount;
- ALfloat (*Buffer)[BUFFERSIZE];
- ALuint NumChannels;
- } Dry;
- /* First-order ambisonics output, to be upsampled to the dry buffer if different. */
- struct {
- AmbiConfig Ambi;
- /* Will only be 4 or 0. */
- ALuint CoeffCount;
- ALfloat (*Buffer)[BUFFERSIZE];
- ALuint 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];
- ALuint NumChannels;
- } RealOut;
- /* Running count of the mixer invocations, in 31.1 fixed point. This
- * actually increments *twice* when mixing, first at the start and then at
- * the end, so the bottom bit indicates if the device is currently mixing
- * and the upper bits indicates how many mixes have been done.
- */
- 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 (1u<<1)
- // Channel configuration was requested by the config file
- #define DEVICE_CHANNELS_REQUEST (1u<<2)
- // Sample type was requested by the config file
- #define DEVICE_SAMPLE_TYPE_REQUEST (1u<<3)
- // Specifies if the DSP is paused at user request
- #define DEVICE_PAUSED (1u<<30)
- // Specifies if the device is currently running
- #define DEVICE_RUNNING (1u<<31)
- /* Nanosecond resolution for the device clock time. */
- #define DEVICE_CLOCK_RES U64(1000000000)
- /* Must be less than 15 characters (16 including terminating null) for
- * compatibility with pthread_setname_np limitations. */
- #define MIXER_THREAD_NAME "alsoft-mixer"
- #define RECORD_THREAD_NAME "alsoft-record"
- struct ALCcontext_struct {
- RefCount ref;
- struct ALlistener *Listener;
- UIntMap SourceMap;
- UIntMap EffectSlotMap;
- ATOMIC(ALenum) LastError;
- enum DistanceModel DistanceModel;
- ALboolean SourceDistanceModel;
- ALfloat DopplerFactor;
- ALfloat DopplerVelocity;
- ALfloat SpeedOfSound;
- ATOMIC(ALenum) DeferUpdates;
- RWLock PropLock;
- /* 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;
- ATOMIC(struct ALeffectslot*) ActiveAuxSlotList;
- ALCdevice *Device;
- const ALCchar *ExtensionList;
- ALCcontext *volatile next;
- /* Memory space used by the listener */
- alignas(16) ALCbyte _listener_mem[];
- };
- ALCcontext *GetContextRef(void);
- void ALCcontext_IncRef(ALCcontext *context);
- void ALCcontext_DecRef(ALCcontext *context);
- void AppendAllDevicesList(const ALCchar *name);
- void AppendCaptureDeviceList(const ALCchar *name);
- void ALCdevice_Lock(ALCdevice *device);
- void ALCdevice_Unlock(ALCdevice *device);
- void ALCcontext_DeferUpdates(ALCcontext *context, ALenum type);
- void ALCcontext_ProcessUpdates(ALCcontext *context);
- inline void LockContext(ALCcontext *context)
- { ALCdevice_Lock(context->Device); }
- inline void UnlockContext(ALCcontext *context)
- { ALCdevice_Unlock(context->Device); }
- enum {
- DeferOff = AL_FALSE,
- DeferAll,
- DeferAllowPlay
- };
- typedef struct {
- #ifdef HAVE_FENV_H
- DERIVE_FROM_TYPE(fenv_t);
- #else
- int state;
- #endif
- #ifdef HAVE_SSE
- int sse_state;
- #endif
- } FPUCtl;
- void SetMixerFPUMode(FPUCtl *ctl);
- void RestoreFPUMode(const FPUCtl *ctl);
- typedef struct ll_ringbuffer ll_ringbuffer_t;
- typedef struct ll_ringbuffer_data {
- char *buf;
- size_t len;
- } ll_ringbuffer_data_t;
- ll_ringbuffer_t *ll_ringbuffer_create(size_t sz, size_t elem_sz);
- void ll_ringbuffer_free(ll_ringbuffer_t *rb);
- void ll_ringbuffer_get_read_vector(const ll_ringbuffer_t *rb, ll_ringbuffer_data_t *vec);
- void ll_ringbuffer_get_write_vector(const ll_ringbuffer_t *rb, ll_ringbuffer_data_t *vec);
- size_t ll_ringbuffer_read(ll_ringbuffer_t *rb, char *dest, size_t cnt);
- size_t ll_ringbuffer_peek(ll_ringbuffer_t *rb, char *dest, size_t cnt);
- void ll_ringbuffer_read_advance(ll_ringbuffer_t *rb, size_t cnt);
- size_t ll_ringbuffer_read_space(const ll_ringbuffer_t *rb);
- int ll_ringbuffer_mlock(ll_ringbuffer_t *rb);
- void ll_ringbuffer_reset(ll_ringbuffer_t *rb);
- size_t ll_ringbuffer_write(ll_ringbuffer_t *rb, const char *src, size_t cnt);
- void ll_ringbuffer_write_advance(ll_ringbuffer_t *rb, size_t cnt);
- size_t ll_ringbuffer_write_space(const ll_ringbuffer_t *rb);
- void ReadALConfig(void);
- void FreeALConfig(void);
- int ConfigValueExists(const char *devName, const char *blockName, const char *keyName);
- const char *GetConfigValue(const char *devName, const char *blockName, const char *keyName, const char *def);
- int GetConfigValueBool(const char *devName, const char *blockName, const char *keyName, int def);
- int ConfigValueStr(const char *devName, const char *blockName, const char *keyName, const char **ret);
- int ConfigValueInt(const char *devName, const char *blockName, const char *keyName, int *ret);
- int ConfigValueUInt(const char *devName, const char *blockName, const char *keyName, unsigned int *ret);
- int ConfigValueFloat(const char *devName, const char *blockName, const char *keyName, float *ret);
- int ConfigValueBool(const char *devName, const char *blockName, const char *keyName, int *ret);
- void SetRTPriority(void);
- void SetDefaultChannelOrder(ALCdevice *device);
- void SetDefaultWFXChannelOrder(ALCdevice *device);
- const ALCchar *DevFmtTypeString(enum DevFmtType type);
- const ALCchar *DevFmtChannelsString(enum DevFmtChannels chans);
- /**
- * GetChannelIdxByName
- *
- * Returns the index for the given channel name (e.g. FrontCenter), or -1 if it
- * doesn't exist.
- */
- inline ALint GetChannelIndex(const enum Channel names[MAX_OUTPUT_CHANNELS], enum Channel chan)
- {
- ALint i;
- for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
- {
- if(names[i] == chan)
- return i;
- }
- return -1;
- }
- #define GetChannelIdxByName(x, c) GetChannelIndex((x).ChannelName, (c))
- extern FILE *LogFile;
- #if defined(__GNUC__) && !defined(_WIN32) && !defined(IN_IDE_PARSER)
- #define AL_PRINT(T, MSG, ...) fprintf(LogFile, "AL lib: %s %s: "MSG, T, __FUNCTION__ , ## __VA_ARGS__)
- #else
- void al_print(const char *type, const char *func, const char *fmt, ...) DECL_FORMAT(printf, 3,4);
- #define AL_PRINT(T, ...) al_print((T), __FUNCTION__, __VA_ARGS__)
- #endif
- enum LogLevel {
- NoLog,
- LogError,
- LogWarning,
- LogTrace,
- LogRef
- };
- extern enum LogLevel LogLevel;
- #define TRACEREF(...) do { \
- if(LogLevel >= LogRef) \
- AL_PRINT("(--)", __VA_ARGS__); \
- } while(0)
- #define TRACE(...) do { \
- if(LogLevel >= LogTrace) \
- AL_PRINT("(II)", __VA_ARGS__); \
- } while(0)
- #define WARN(...) do { \
- if(LogLevel >= LogWarning) \
- AL_PRINT("(WW)", __VA_ARGS__); \
- } while(0)
- #define ERR(...) do { \
- if(LogLevel >= LogError) \
- AL_PRINT("(EE)", __VA_ARGS__); \
- } while(0)
- extern ALint RTPrioLevel;
- extern ALuint CPUCapFlags;
- enum {
- CPU_CAP_SSE = 1<<0,
- CPU_CAP_SSE2 = 1<<1,
- CPU_CAP_SSE3 = 1<<2,
- CPU_CAP_SSE4_1 = 1<<3,
- CPU_CAP_NEON = 1<<4,
- };
- void FillCPUCaps(ALuint capfilter);
- 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. */
- typedef ALfloat ALfloatBUFFERSIZE[BUFFERSIZE];
- #ifdef __cplusplus
- }
- #endif
- #endif
|