aboutsummaryrefslogtreecommitdiffstats
path: root/OpenAL32/Include/alu.h
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2019-04-07 23:39:04 +0200
committerSven Gothel <[email protected]>2019-04-07 23:39:04 +0200
commit73233ce69919fc19c53ce8663c5b8cc05227f07e (patch)
treef2b6ccc1a14d7c387f33398a44ea4511d7ecb212 /OpenAL32/Include/alu.h
parent8efa4c7ba5ee8eb399d31a9884e45f743d4625ad (diff)
parent99a55c445211fea77af6ab61cbc6a6ec4fbdc9b9 (diff)
Merge branch 'v1.19' of git://repo.or.cz/openal-soft into v1.19v1.19
Diffstat (limited to 'OpenAL32/Include/alu.h')
-rw-r--r--OpenAL32/Include/alu.h454
1 files changed, 329 insertions, 125 deletions
diff --git a/OpenAL32/Include/alu.h b/OpenAL32/Include/alu.h
index a309c4ab..c572fd71 100644
--- a/OpenAL32/Include/alu.h
+++ b/OpenAL32/Include/alu.h
@@ -12,31 +12,56 @@
#include "alMain.h"
#include "alBuffer.h"
-#include "alFilter.h"
#include "hrtf.h"
#include "align.h"
#include "math_defs.h"
+#include "filters/defs.h"
+#include "filters/nfc.h"
#define MAX_PITCH (255)
-/* Maximum number of buffer samples before the current pos needed for resampling. */
-#define MAX_PRE_SAMPLES 12
-
-/* Maximum number of buffer samples after the current pos needed for resampling. */
-#define MAX_POST_SAMPLES 12
+/* Maximum number of samples to pad on either end of a buffer for resampling.
+ * Note that both the beginning and end need padding!
+ */
+#define MAX_RESAMPLE_PADDING 24
#ifdef __cplusplus
extern "C" {
#endif
+struct BSincTable;
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
+};
-/* The number of distinct scale and phase intervals within the filter table. */
+enum Resampler {
+ PointResampler,
+ LinearResampler,
+ FIR4Resampler,
+ BSinc12Resampler,
+ BSinc24Resampler,
+
+ ResamplerMax = BSinc24Resampler
+};
+extern enum Resampler ResamplerDefault;
+
+/* The number of distinct scale and phase intervals within the bsinc filter
+ * table.
+ */
#define BSINC_SCALE_BITS 4
#define BSINC_SCALE_COUNT (1<<BSINC_SCALE_BITS)
#define BSINC_PHASE_BITS 4
@@ -48,16 +73,29 @@ struct ALvoice;
*/
typedef struct BsincState {
ALfloat sf; /* Scale interpolation factor. */
- ALuint m; /* Coefficient count. */
- ALint l; /* Left coefficient offset. */
- struct {
- const ALfloat *filter; /* Filter coefficients. */
- const ALfloat *scDelta; /* Scale deltas. */
- const ALfloat *phDelta; /* Phase deltas. */
- const ALfloat *spDelta; /* Scale-phase deltas. */
- } coeffs[BSINC_PHASE_COUNT];
+ ALsizei m; /* Coefficient count. */
+ ALsizei l; /* Left coefficient offset. */
+ /* Filter coefficients, followed by the scale, phase, and scale-phase
+ * delta coefficients. Starting at phase index 0, each subsequent phase
+ * index follows contiguously.
+ */
+ const ALfloat *filter;
} BsincState;
+typedef union InterpState {
+ BsincState bsinc;
+} InterpState;
+
+typedef const ALfloat* (*ResamplerFunc)(const InterpState *state,
+ const ALfloat *restrict src, ALsizei frac, ALint increment,
+ ALfloat *restrict dst, ALsizei dstlen
+);
+
+void BsincPrepare(const ALuint increment, BsincState *state, const struct BSincTable *table);
+
+extern const struct BSincTable bsinc12;
+extern const struct BSincTable bsinc24;
+
typedef union aluVector {
alignas(16) ALfloat v[4];
@@ -75,6 +113,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 +136,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 +144,199 @@ 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;
+ BiquadFilter LowPass;
+ BiquadFilter 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;
struct {
- enum ActiveFilters ActiveType;
- ALfilterState LowPass;
- ALfilterState HighPass;
- } Filters[MAX_INPUT_CHANNELS];
+ HrtfParams Old;
+ HrtfParams Target;
+ HrtfState State;
+ } Hrtf;
struct {
- HrtfParams Params;
- HrtfState State;
- } Hrtf[MAX_INPUT_CHANNELS];
- MixGains Gains[MAX_INPUT_CHANNELS][MAX_OUTPUT_CHANNELS];
+ ALfloat Current[MAX_OUTPUT_CHANNELS];
+ ALfloat Target[MAX_OUTPUT_CHANNELS];
+ } Gains;
} DirectParams;
typedef struct SendParams {
- ALfloat (*OutBuffer)[BUFFERSIZE];
-
- ALboolean Moving;
- ALuint Counter;
+ BiquadFilter LowPass;
+ BiquadFilter 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;
+
+ 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[];
+};
+
+#define VOICE_IS_STATIC (1<<0)
+#define VOICE_IS_FADING (1<<1) /* Fading sources use gain stepping for smooth transitions. */
+#define VOICE_HAS_HRTF (1<<2)
+#define VOICE_HAS_NFC (1<<3)
+
+typedef struct ALvoice {
+ struct ALvoiceProps *Props;
+
+ ATOMIC(struct ALvoiceProps*) Update;
+
+ 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;
-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);
+ /** 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_RESAMPLE_PADDING];
+
+ 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)
@@ -245,83 +384,148 @@ inline ALuint64 maxu64(ALuint64 a, ALuint64 b)
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];
+inline size_t minz(size_t a, size_t b)
+{ return ((a > b) ? b : a); }
+inline size_t maxz(size_t a, size_t b)
+{ return ((a > b) ? a : b); }
+inline size_t clampz(size_t val, size_t min, size_t max)
+{ return minz(max, maxz(min, val)); }
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)
-{
- 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)
+inline ALfloat cubic(ALfloat val1, ALfloat val2, ALfloat val3, ALfloat val4, ALfloat mu)
{
- 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;
+ ALfloat mu2 = mu*mu, mu3 = mu2*mu;
+ ALfloat a0 = -0.5f*mu3 + mu2 + -0.5f*mu;
+ ALfloat a1 = 1.5f*mu3 + -2.5f*mu2 + 1.0f;
+ ALfloat a2 = -1.5f*mu3 + 2.0f*mu2 + 0.5f*mu;
+ ALfloat a3 = 0.5f*mu3 + -0.5f*mu2;
+ return val1*a0 + val2*a1 + val3*a2 + val4*a3;
}
+enum HrtfRequestMode {
+ Hrtf_Default = 0,
+ Hrtf_Enable = 1,
+ Hrtf_Disable = 2,
+};
+
+void aluInit(void);
+
void aluInitMixer(void);
-ALvoid aluInitPanning(ALCdevice *Device);
+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);
+
+void aluSelectPostProcess(ALCdevice *device);
/**
- * ComputeDirectionalGains
+ * Calculates ambisonic encoder coefficients using the X, Y, and Z direction
+ * components, which must represent a normalized (unit length) vector, and the
+ * spread is the angular width of the sound (0...tau).
+ *
+ * NOTE: The components use ambisonic coordinates. As a result:
+ *
+ * Ambisonic Y = OpenAL -X
+ * Ambisonic Z = OpenAL Y
+ * Ambisonic X = OpenAL -Z
*
- * Sets channel gains based on a direction. The direction must be a 3-component
- * vector no longer than 1 unit.
+ * The components are ordered such that OpenAL's X, Y, and Z are the first,
+ * second, and third parameters respectively -- simply negate X and Z.
*/
-void ComputeDirectionalGains(const ALCdevice *device, const ALfloat dir[3], ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]);
+void CalcAmbiCoeffs(const ALfloat y, const ALfloat z, const ALfloat x, const ALfloat spread,
+ ALfloat coeffs[MAX_AMBI_COEFFS]);
/**
- * ComputeAngleGains
+ * CalcDirectionCoeffs
*
- * 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 an OpenAL direction vector. The
+ * vector must be normalized (unit length), and the spread is the angular width
+ * of the sound (0...tau).
*/
-void ComputeAngleGains(const ALCdevice *device, ALfloat angle, ALfloat elevation, ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]);
+inline void CalcDirectionCoeffs(const ALfloat dir[3], ALfloat spread, ALfloat coeffs[MAX_AMBI_COEFFS])
+{
+ /* Convert from OpenAL coords to Ambisonics. */
+ CalcAmbiCoeffs(-dir[0], dir[1], -dir[2], spread, coeffs);
+}
/**
- * ComputeAmbientGains
+ * CalcAngleCoeffs
*
- * Sets channel gains for ambient, omni-directional sounds.
+ * Calculates ambisonic coefficients based on azimuth and elevation. The
+ * azimuth and elevation parameters are in radians, going right and up
+ * respectively.
*/
-void ComputeAmbientGains(const ALCdevice *device, ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]);
+inline void CalcAngleCoeffs(ALfloat azimuth, ALfloat elevation, ALfloat spread, ALfloat coeffs[MAX_AMBI_COEFFS])
+{
+ ALfloat x = -sinf(azimuth) * cosf(elevation);
+ ALfloat y = sinf(elevation);
+ ALfloat z = cosf(azimuth) * cosf(elevation);
+
+ CalcAmbiCoeffs(x, y, z, spread, coeffs);
+}
/**
- * ComputeBFormatGains
+ * ScaleAzimuthFront
*
- * 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.
+ * Scales the given azimuth toward the side (+/- pi/2 radians) for positions in
+ * front.
*/
-void ComputeBFormatGains(const ALCdevice *device, const ALfloat mtx[4], ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]);
+inline float ScaleAzimuthFront(float azimuth, float scale)
+{
+ ALfloat sign = copysignf(1.0f, azimuth);
+ if(!(fabsf(azimuth) > F_PI_2))
+ return minf(fabsf(azimuth) * scale, F_PI_2) * sign;
+ return azimuth;
+}
+
+
+void ComputePanningGainsMC(const ChannelConfig *chancoeffs, ALsizei numchans, ALsizei numcoeffs, const ALfloat*restrict coeffs, ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]);
+void ComputePanningGainsBF(const BFChannelConfig *chanmap, ALsizei numchans, const ALfloat*restrict coeffs, ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]);
+
+/**
+ * ComputePanGains
+ *
+ * Computes panning gains using the given channel decoder coefficients and the
+ * pre-calculated direction or angle coefficients. For B-Format sources, the
+ * coeffs are a 'slice' of a transform matrix for the input channel, used to
+ * scale and orient the sound samples.
+ */
+inline void ComputePanGains(const MixParams *dry, const ALfloat*restrict coeffs, ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS])
+{
+ if(dry->CoeffCount > 0)
+ ComputePanningGainsMC(dry->Ambi.Coeffs, dry->NumChannels, dry->CoeffCount,
+ coeffs, ingain, gains);
+ else
+ ComputePanningGainsBF(dry->Ambi.Map, dry->NumChannels, coeffs, ingain, gains);
+}
-ALvoid UpdateContextSources(ALCcontext *context);
+ALboolean MixSource(struct ALvoice *voice, ALuint SourceID, ALCcontext *Context, 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);
+void aluMixData(ALCdevice *device, ALvoid *OutBuffer, ALsizei NumSamples);
+/* Caller must lock the device, and the mixer must not be running. */
+void aluHandleDisconnect(ALCdevice *device, const char *msg, ...) DECL_FORMAT(printf, 2, 3);
-ALvoid MixSource(struct ALvoice *voice, struct ALsource *source, ALCdevice *Device, ALuint SamplesToDo);
+void UpdateContextProps(ALCcontext *context);
-ALvoid aluMixData(ALCdevice *device, ALvoid *buffer, ALsizei size);
-/* Caller must lock the device. */
-ALvoid aluHandleDisconnect(ALCdevice *device);
+extern MixerFunc MixSamples;
+extern RowMixerFunc MixRowSamples;
extern ALfloat ConeScale;
extern ALfloat ZScale;
+extern ALboolean OverrideReverbSpeedOfSound;
#ifdef __cplusplus
}