mirror of
https://github.com/love2d/megasource.git
synced 2026-08-20 04:30:45 +02:00
Update OpenAL Soft to 1.18.2
This commit is contained in:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user