18 #include "math_defs.h"
19 #include "filters/defs.h"
20 #include "filters/nfc.h"
23 #define MAX_PITCH (255)
25 /* Maximum number of samples to pad on either end of a buffer for resampling.
26 * Note that both the beginning and end need padding!
28 #define MAX_RESAMPLE_PADDING 24
37 struct ALbufferlistitem
;
42 #define DITHER_RNG_SEED 22222
46 SpatializeOff
= AL_FALSE
,
47 SpatializeOn
= AL_TRUE
,
48 SpatializeAuto
= AL_AUTO_SOFT
58 ResamplerMax
= BSinc24Resampler
60 extern enum Resampler ResamplerDefault
;
62 /* The number of distinct scale and phase intervals within the bsinc filter
65 #define BSINC_SCALE_BITS 4
66 #define BSINC_SCALE_COUNT (1<<BSINC_SCALE_BITS)
67 #define BSINC_PHASE_BITS 4
68 #define BSINC_PHASE_COUNT (1<<BSINC_PHASE_BITS)
70 /* Interpolator state. Kind of a misnomer since the interpolator itself is
71 * stateless. This just keeps it from having to recompute scale-related
72 * mappings for every sample.
74 typedef struct BsincState
{
75 ALfloat sf
; /* Scale interpolation factor. */
76 ALsizei m
; /* Coefficient count. */
77 ALsizei l
; /* Left coefficient offset. */
78 /* Filter coefficients, followed by the scale, phase, and scale-phase
79 * delta coefficients. Starting at phase index 0, each subsequent phase
80 * index follows contiguously.
82 const ALfloat
*filter
;
85 typedef union InterpState
{
89 typedef const ALfloat
* (*ResamplerFunc
)(const InterpState
*state
,
90 const ALfloat
*restrict src
, ALsizei frac
, ALint increment
,
91 ALfloat
*restrict dst
, ALsizei dstlen
94 void BsincPrepare(const ALuint increment
, BsincState
*state
, const struct BSincTable
*table
);
96 extern const struct BSincTable bsinc12
;
97 extern const struct BSincTable bsinc24
;
100 typedef union aluVector
{
101 alignas(16) ALfloat v
[4];
104 inline void aluVectorSet(aluVector
*vector
, ALfloat x
, ALfloat y
, ALfloat z
, ALfloat w
)
113 typedef union aluMatrixf
{
114 alignas(16) ALfloat m
[4][4];
116 extern const aluMatrixf IdentityMatrixf
;
118 inline void aluMatrixfSetRow(aluMatrixf
*matrix
, ALuint row
,
119 ALfloat m0
, ALfloat m1
, ALfloat m2
, ALfloat m3
)
121 matrix
->m
[row
][0] = m0
;
122 matrix
->m
[row
][1] = m1
;
123 matrix
->m
[row
][2] = m2
;
124 matrix
->m
[row
][3] = m3
;
127 inline void aluMatrixfSet(aluMatrixf
*matrix
, ALfloat m00
, ALfloat m01
, ALfloat m02
, ALfloat m03
,
128 ALfloat m10
, ALfloat m11
, ALfloat m12
, ALfloat m13
,
129 ALfloat m20
, ALfloat m21
, ALfloat m22
, ALfloat m23
,
130 ALfloat m30
, ALfloat m31
, ALfloat m32
, ALfloat m33
)
132 aluMatrixfSetRow(matrix
, 0, m00
, m01
, m02
, m03
);
133 aluMatrixfSetRow(matrix
, 1, m10
, m11
, m12
, m13
);
134 aluMatrixfSetRow(matrix
, 2, m20
, m21
, m22
, m23
);
135 aluMatrixfSetRow(matrix
, 3, m30
, m31
, m32
, m33
);
143 AF_BandPass
= AF_LowPass
| AF_HighPass
147 typedef struct MixHrtfParams
{
148 const ALfloat (*Coeffs
)[2];
155 typedef struct DirectParams
{
156 BiquadFilter LowPass
;
157 BiquadFilter HighPass
;
159 NfcFilter NFCtrlFilter
;
168 ALfloat Current
[MAX_OUTPUT_CHANNELS
];
169 ALfloat Target
[MAX_OUTPUT_CHANNELS
];
173 typedef struct SendParams
{
174 BiquadFilter LowPass
;
175 BiquadFilter HighPass
;
178 ALfloat Current
[MAX_OUTPUT_CHANNELS
];
179 ALfloat Target
[MAX_OUTPUT_CHANNELS
];
184 struct ALvoiceProps
{
185 ATOMIC(struct ALvoiceProps
*) next
;
196 ALfloat RolloffFactor
;
199 ALfloat Direction
[3];
200 ALfloat Orientation
[2][3];
201 ALboolean HeadRelative
;
202 enum DistanceModel DistanceModel
;
203 enum Resampler Resampler
;
204 ALboolean DirectChannels
;
205 enum SpatializeMode SpatializeMode
;
207 ALboolean DryGainHFAuto
;
208 ALboolean WetGainAuto
;
209 ALboolean WetGainHFAuto
;
212 ALfloat AirAbsorptionFactor
;
213 ALfloat RoomRolloffFactor
;
214 ALfloat DopplerFactor
;
216 ALfloat StereoPan
[2];
220 /** Direct filter and auxiliary send info. */
229 struct ALeffectslot
*Slot
;
238 #define VOICE_IS_STATIC (1<<0)
239 #define VOICE_IS_FADING (1<<1) /* Fading sources use gain stepping for smooth transitions. */
240 #define VOICE_HAS_HRTF (1<<2)
241 #define VOICE_HAS_NFC (1<<3)
243 typedef struct ALvoice
{
244 struct ALvoiceProps
*Props
;
246 ATOMIC(struct ALvoiceProps
*) Update
;
248 ATOMIC(struct ALsource
*) Source
;
249 ATOMIC(bool) Playing
;
252 * Source offset in samples, relative to the currently playing buffer, NOT
253 * the whole queue, and the fractional (fixed-point) offset to the next
256 ATOMIC(ALuint
) position
;
257 ATOMIC(ALsizei
) position_fraction
;
259 /* Current buffer queue item being played. */
260 ATOMIC(struct ALbufferlistitem
*) current_buffer
;
262 /* Buffer queue item to loop to at end of queue (will be NULL for non-
265 ATOMIC(struct ALbufferlistitem
*) loop_buffer
;
268 * Number of channels and bytes-per-sample for the attached source's
274 /** Current target parameters used for mixing. */
277 ResamplerFunc Resampler
;
281 ALuint Offset
; /* Number of output samples mixed since starting. */
283 alignas(16) ALfloat PrevSamples
[MAX_INPUT_CHANNELS
][MAX_RESAMPLE_PADDING
];
285 InterpState ResampleState
;
288 enum ActiveFilters FilterType
;
289 DirectParams Params
[MAX_INPUT_CHANNELS
];
291 ALfloat (*Buffer
)[BUFFERSIZE
];
293 ALsizei ChannelsPerOrder
[MAX_AMBI_ORDER
+1];
297 enum ActiveFilters FilterType
;
298 SendParams Params
[MAX_INPUT_CHANNELS
];
300 ALfloat (*Buffer
)[BUFFERSIZE
];
305 void DeinitVoice(ALvoice
*voice
);
308 typedef void (*MixerFunc
)(const ALfloat
*data
, ALsizei OutChans
,
309 ALfloat (*restrict OutBuffer
)[BUFFERSIZE
], ALfloat
*CurrentGains
,
310 const ALfloat
*TargetGains
, ALsizei Counter
, ALsizei OutPos
,
312 typedef void (*RowMixerFunc
)(ALfloat
*OutBuffer
, const ALfloat
*gains
,
313 const ALfloat (*restrict data
)[BUFFERSIZE
], ALsizei InChans
,
314 ALsizei InPos
, ALsizei BufferSize
);
315 typedef void (*HrtfMixerFunc
)(ALfloat
*restrict LeftOut
, ALfloat
*restrict RightOut
,
316 const ALfloat
*data
, ALsizei Offset
, ALsizei OutPos
,
317 const ALsizei IrSize
, MixHrtfParams
*hrtfparams
,
318 HrtfState
*hrtfstate
, ALsizei BufferSize
);
319 typedef void (*HrtfMixerBlendFunc
)(ALfloat
*restrict LeftOut
, ALfloat
*restrict RightOut
,
320 const ALfloat
*data
, ALsizei Offset
, ALsizei OutPos
,
321 const ALsizei IrSize
, const HrtfParams
*oldparams
,
322 MixHrtfParams
*newparams
, HrtfState
*hrtfstate
,
324 typedef void (*HrtfDirectMixerFunc
)(ALfloat
*restrict LeftOut
, ALfloat
*restrict RightOut
,
325 const ALfloat
*data
, ALsizei Offset
, const ALsizei IrSize
,
326 const ALfloat (*restrict Coeffs
)[2],
327 ALfloat (*restrict Values
)[2], ALsizei BufferSize
);
330 #define GAIN_MIX_MAX (16.0f) /* +24dB */
332 #define GAIN_SILENCE_THRESHOLD (0.00001f) /* -100dB */
334 #define SPEEDOFSOUNDMETRESPERSEC (343.3f)
335 #define AIRABSORBGAINHF (0.99426f) /* -0.05dB */
337 /* Target gain for the reverb decay feedback reaching the decay time. */
338 #define REVERB_DECAY_GAIN (0.001f) /* -60 dB */
340 #define FRACTIONBITS (12)
341 #define FRACTIONONE (1<<FRACTIONBITS)
342 #define FRACTIONMASK (FRACTIONONE-1)
345 inline ALfloat
minf(ALfloat a
, ALfloat b
)
346 { return ((a
> b
) ? b
: a
); }
347 inline ALfloat
maxf(ALfloat a
, ALfloat b
)
348 { return ((a
> b
) ? a
: b
); }
349 inline ALfloat
clampf(ALfloat val
, ALfloat min
, ALfloat max
)
350 { return minf(max
, maxf(min
, val
)); }
352 inline ALdouble
mind(ALdouble a
, ALdouble b
)
353 { return ((a
> b
) ? b
: a
); }
354 inline ALdouble
maxd(ALdouble a
, ALdouble b
)
355 { return ((a
> b
) ? a
: b
); }
356 inline ALdouble
clampd(ALdouble val
, ALdouble min
, ALdouble max
)
357 { return mind(max
, maxd(min
, val
)); }
359 inline ALuint
minu(ALuint a
, ALuint b
)
360 { return ((a
> b
) ? b
: a
); }
361 inline ALuint
maxu(ALuint a
, ALuint b
)
362 { return ((a
> b
) ? a
: b
); }
363 inline ALuint
clampu(ALuint val
, ALuint min
, ALuint max
)
364 { return minu(max
, maxu(min
, val
)); }
366 inline ALint
mini(ALint a
, ALint b
)
367 { return ((a
> b
) ? b
: a
); }
368 inline ALint
maxi(ALint a
, ALint b
)
369 { return ((a
> b
) ? a
: b
); }
370 inline ALint
clampi(ALint val
, ALint min
, ALint max
)
371 { return mini(max
, maxi(min
, val
)); }
373 inline ALint64
mini64(ALint64 a
, ALint64 b
)
374 { return ((a
> b
) ? b
: a
); }
375 inline ALint64
maxi64(ALint64 a
, ALint64 b
)
376 { return ((a
> b
) ? a
: b
); }
377 inline ALint64
clampi64(ALint64 val
, ALint64 min
, ALint64 max
)
378 { return mini64(max
, maxi64(min
, val
)); }
380 inline ALuint64
minu64(ALuint64 a
, ALuint64 b
)
381 { return ((a
> b
) ? b
: a
); }
382 inline ALuint64
maxu64(ALuint64 a
, ALuint64 b
)
383 { return ((a
> b
) ? a
: b
); }
384 inline ALuint64
clampu64(ALuint64 val
, ALuint64 min
, ALuint64 max
)
385 { return minu64(max
, maxu64(min
, val
)); }
387 inline size_t minz(size_t a
, size_t b
)
388 { return ((a
> b
) ? b
: a
); }
389 inline size_t maxz(size_t a
, size_t b
)
390 { return ((a
> b
) ? a
: b
); }
391 inline size_t clampz(size_t val
, size_t min
, size_t max
)
392 { return minz(max
, maxz(min
, val
)); }
395 inline ALfloat
lerp(ALfloat val1
, ALfloat val2
, ALfloat mu
)
397 return val1
+ (val2
-val1
)*mu
;
399 inline ALfloat
cubic(ALfloat val1
, ALfloat val2
, ALfloat val3
, ALfloat val4
, ALfloat mu
)
401 ALfloat mu2
= mu
*mu
, mu3
= mu2
*mu
;
402 ALfloat a0
= -0.5f
*mu3
+ mu2
+ -0.5f
*mu
;
403 ALfloat a1
= 1.5f
*mu3
+ -2.5f
*mu2
+ 1.0f
;
404 ALfloat a2
= -1.5f
*mu3
+ 2.0f
*mu2
+ 0.5f
*mu
;
405 ALfloat a3
= 0.5f
*mu3
+ -0.5f
*mu2
;
406 return val1
*a0
+ val2
*a1
+ val3
*a2
+ val4
*a3
;
410 enum HrtfRequestMode
{
418 void aluInitMixer(void);
420 ResamplerFunc
SelectResampler(enum Resampler resampler
);
424 * Set up the appropriate panning method and mixing method given the device
427 void aluInitRenderer(ALCdevice
*device
, ALint hrtf_id
, enum HrtfRequestMode hrtf_appreq
, enum HrtfRequestMode hrtf_userreq
);
429 void aluInitEffectPanning(struct ALeffectslot
*slot
);
431 void aluSelectPostProcess(ALCdevice
*device
);
434 * Calculates ambisonic encoder coefficients using the X, Y, and Z direction
435 * components, which must represent a normalized (unit length) vector, and the
436 * spread is the angular width of the sound (0...tau).
438 * NOTE: The components use ambisonic coordinates. As a result:
440 * Ambisonic Y = OpenAL -X
441 * Ambisonic Z = OpenAL Y
442 * Ambisonic X = OpenAL -Z
444 * The components are ordered such that OpenAL's X, Y, and Z are the first,
445 * second, and third parameters respectively -- simply negate X and Z.
447 void CalcAmbiCoeffs(const ALfloat y
, const ALfloat z
, const ALfloat x
, const ALfloat spread
,
448 ALfloat coeffs
[MAX_AMBI_COEFFS
]);
451 * CalcDirectionCoeffs
453 * Calculates ambisonic coefficients based on an OpenAL direction vector. The
454 * vector must be normalized (unit length), and the spread is the angular width
455 * of the sound (0...tau).
457 inline void CalcDirectionCoeffs(const ALfloat dir
[3], ALfloat spread
, ALfloat coeffs
[MAX_AMBI_COEFFS
])
459 /* Convert from OpenAL coords to Ambisonics. */
460 CalcAmbiCoeffs(-dir
[0], dir
[1], -dir
[2], spread
, coeffs
);
466 * Calculates ambisonic coefficients based on azimuth and elevation. The
467 * azimuth and elevation parameters are in radians, going right and up
470 inline void CalcAngleCoeffs(ALfloat azimuth
, ALfloat elevation
, ALfloat spread
, ALfloat coeffs
[MAX_AMBI_COEFFS
])
472 ALfloat x
= -sinf(azimuth
) * cosf(elevation
);
473 ALfloat y
= sinf(elevation
);
474 ALfloat z
= cosf(azimuth
) * cosf(elevation
);
476 CalcAmbiCoeffs(x
, y
, z
, spread
, coeffs
);
482 * Scales the given azimuth toward the side (+/- pi/2 radians) for positions in
485 inline float ScaleAzimuthFront(float azimuth
, float scale
)
487 ALfloat sign
= copysignf(1.0f
, azimuth
);
488 if(!(fabsf(azimuth
) > F_PI_2
))
489 return minf(fabsf(azimuth
) * scale
, F_PI_2
) * sign
;
494 void ComputePanningGainsMC(const ChannelConfig
*chancoeffs
, ALsizei numchans
, ALsizei numcoeffs
, const ALfloat
*restrict coeffs
, ALfloat ingain
, ALfloat gains
[MAX_OUTPUT_CHANNELS
]);
495 void ComputePanningGainsBF(const BFChannelConfig
*chanmap
, ALsizei numchans
, const ALfloat
*restrict coeffs
, ALfloat ingain
, ALfloat gains
[MAX_OUTPUT_CHANNELS
]);
500 * Computes panning gains using the given channel decoder coefficients and the
501 * pre-calculated direction or angle coefficients.
503 inline void ComputeDryPanGains(const MixParams
*dry
, const ALfloat coeffs
[MAX_AMBI_COEFFS
], ALfloat ingain
, ALfloat gains
[MAX_OUTPUT_CHANNELS
])
505 if(dry
->CoeffCount
> 0)
506 ComputePanningGainsMC(dry
->Ambi
.Coeffs
, dry
->NumChannels
, dry
->CoeffCount
,
507 coeffs
, ingain
, gains
);
509 ComputePanningGainsBF(dry
->Ambi
.Map
, dry
->NumChannels
, coeffs
, ingain
, gains
);
512 * ComputeFirstOrderGains
514 * Sets channel gains for a first-order ambisonics input channel. The matrix is
515 * a 1x4 'slice' of a transform matrix for the input channel, used to scale and
516 * orient the sound samples.
518 inline void ComputeFirstOrderGains(const MixParams
*foa
, const ALfloat mtx
[4], ALfloat ingain
, ALfloat gains
[MAX_OUTPUT_CHANNELS
])
520 if(foa
->CoeffCount
> 0)
521 ComputePanningGainsMC(foa
->Ambi
.Coeffs
, foa
->NumChannels
, 4, mtx
, ingain
, gains
);
523 ComputePanningGainsBF(foa
->Ambi
.Map
, foa
->NumChannels
, mtx
, ingain
, gains
);
527 ALboolean
MixSource(struct ALvoice
*voice
, ALuint SourceID
, ALCcontext
*Context
, ALsizei SamplesToDo
);
529 void aluMixData(ALCdevice
*device
, ALvoid
*OutBuffer
, ALsizei NumSamples
);
530 /* Caller must lock the device, and the mixer must not be running. */
531 void aluHandleDisconnect(ALCdevice
*device
, const char *msg
, ...) DECL_FORMAT(printf
, 2, 3);
533 void UpdateContextProps(ALCcontext
*context
);
535 extern MixerFunc MixSamples
;
536 extern RowMixerFunc MixRowSamples
;
538 extern ALfloat ConeScale
;
539 extern ALfloat ZScale
;
540 extern ALboolean OverrideReverbSpeedOfSound
;