Use blended HRIRs for the B-Format decode
[openal-soft.git] / alc / alu.h
blobaa698f7d31d3735bcfaa3b88d58bd79c6116ce12
1 #ifndef ALU_H
2 #define ALU_H
4 #include <array>
5 #include <atomic>
6 #include <cmath>
7 #include <cstddef>
9 #include "AL/al.h"
10 #include "AL/alc.h"
11 #include "AL/alext.h"
13 #include "al/buffer.h"
14 #include "alcmain.h"
15 #include "almalloc.h"
16 #include "alspan.h"
17 #include "ambidefs.h"
18 #include "devformat.h"
19 #include "filters/biquad.h"
20 #include "filters/nfc.h"
21 #include "filters/splitter.h"
22 #include "hrtf.h"
23 #include "logging.h"
25 struct ALbufferlistitem;
26 struct ALeffectslot;
27 struct BSincTable;
30 enum class DistanceModel;
32 #define MAX_PITCH 255
33 #define MAX_SENDS 16
36 #define DITHER_RNG_SEED 22222
39 enum SpatializeMode {
40 SpatializeOff = AL_FALSE,
41 SpatializeOn = AL_TRUE,
42 SpatializeAuto = AL_AUTO_SOFT
45 enum class Resampler {
46 Point,
47 Linear,
48 Cubic,
49 BSinc12,
50 BSinc24,
52 Max = BSinc24
54 extern Resampler ResamplerDefault;
56 /* The number of distinct scale and phase intervals within the bsinc filter
57 * table.
59 #define BSINC_SCALE_BITS 4
60 #define BSINC_SCALE_COUNT (1<<BSINC_SCALE_BITS)
61 #define BSINC_PHASE_BITS 4
62 #define BSINC_PHASE_COUNT (1<<BSINC_PHASE_BITS)
64 /* Interpolator state. Kind of a misnomer since the interpolator itself is
65 * stateless. This just keeps it from having to recompute scale-related
66 * mappings for every sample.
68 struct BsincState {
69 ALfloat sf; /* Scale interpolation factor. */
70 ALuint m; /* Coefficient count. */
71 ALuint l; /* Left coefficient offset. */
72 /* Filter coefficients, followed by the scale, phase, and scale-phase
73 * delta coefficients. Starting at phase index 0, each subsequent phase
74 * index follows contiguously.
76 const ALfloat *filter;
79 union InterpState {
80 BsincState bsinc;
83 using ResamplerFunc = const ALfloat*(*)(const InterpState *state, const ALfloat *RESTRICT src,
84 ALuint frac, ALuint increment, const al::span<float> dst);
86 void BsincPrepare(const ALuint increment, BsincState *state, const BSincTable *table);
88 extern const BSincTable bsinc12;
89 extern const BSincTable bsinc24;
92 enum {
93 AF_None = 0,
94 AF_LowPass = 1,
95 AF_HighPass = 2,
96 AF_BandPass = AF_LowPass | AF_HighPass
100 struct MixHrtfFilter {
101 const HrirArray *Coeffs;
102 ALsizei Delay[2];
103 ALfloat Gain;
104 ALfloat GainStep;
108 struct DirectParams {
109 BiquadFilter LowPass;
110 BiquadFilter HighPass;
112 NfcFilter NFCtrlFilter;
114 struct {
115 HrtfFilter Old;
116 HrtfFilter Target;
117 HrtfState State;
118 } Hrtf;
120 struct {
121 ALfloat Current[MAX_OUTPUT_CHANNELS];
122 ALfloat Target[MAX_OUTPUT_CHANNELS];
123 } Gains;
126 struct SendParams {
127 BiquadFilter LowPass;
128 BiquadFilter HighPass;
130 struct {
131 ALfloat Current[MAX_OUTPUT_CHANNELS];
132 ALfloat Target[MAX_OUTPUT_CHANNELS];
133 } Gains;
137 struct ALvoicePropsBase {
138 ALfloat Pitch;
139 ALfloat Gain;
140 ALfloat OuterGain;
141 ALfloat MinGain;
142 ALfloat MaxGain;
143 ALfloat InnerAngle;
144 ALfloat OuterAngle;
145 ALfloat RefDistance;
146 ALfloat MaxDistance;
147 ALfloat RolloffFactor;
148 std::array<ALfloat,3> Position;
149 std::array<ALfloat,3> Velocity;
150 std::array<ALfloat,3> Direction;
151 std::array<ALfloat,3> OrientAt;
152 std::array<ALfloat,3> OrientUp;
153 ALboolean HeadRelative;
154 DistanceModel mDistanceModel;
155 Resampler mResampler;
156 ALboolean DirectChannels;
157 SpatializeMode mSpatializeMode;
159 ALboolean DryGainHFAuto;
160 ALboolean WetGainAuto;
161 ALboolean WetGainHFAuto;
162 ALfloat OuterGainHF;
164 ALfloat AirAbsorptionFactor;
165 ALfloat RoomRolloffFactor;
166 ALfloat DopplerFactor;
168 std::array<ALfloat,2> StereoPan;
170 ALfloat Radius;
172 /** Direct filter and auxiliary send info. */
173 struct {
174 ALfloat Gain;
175 ALfloat GainHF;
176 ALfloat HFReference;
177 ALfloat GainLF;
178 ALfloat LFReference;
179 } Direct;
180 struct SendData {
181 ALeffectslot *Slot;
182 ALfloat Gain;
183 ALfloat GainHF;
184 ALfloat HFReference;
185 ALfloat GainLF;
186 ALfloat LFReference;
187 } Send[MAX_SENDS];
190 struct ALvoiceProps : public ALvoicePropsBase {
191 std::atomic<ALvoiceProps*> next{nullptr};
193 DEF_NEWDEL(ALvoiceProps)
196 #define VOICE_IS_STATIC (1u<<0)
197 #define VOICE_IS_FADING (1u<<1) /* Fading sources use gain stepping for smooth transitions. */
198 #define VOICE_IS_AMBISONIC (1u<<2) /* Voice needs HF scaling for ambisonic upsampling. */
199 #define VOICE_HAS_HRTF (1u<<3)
200 #define VOICE_HAS_NFC (1u<<4)
202 struct ALvoice {
203 enum State {
204 Stopped = 0,
205 Playing = 1,
206 Stopping = 2
209 std::atomic<ALvoiceProps*> mUpdate{nullptr};
211 std::atomic<ALuint> mSourceID{0u};
212 std::atomic<State> mPlayState{Stopped};
214 ALvoicePropsBase mProps;
217 * Source offset in samples, relative to the currently playing buffer, NOT
218 * the whole queue.
220 std::atomic<ALuint> mPosition;
221 /** Fractional (fixed-point) offset to the next sample. */
222 std::atomic<ALuint> mPositionFrac;
224 /* Current buffer queue item being played. */
225 std::atomic<ALbufferlistitem*> mCurrentBuffer;
227 /* Buffer queue item to loop to at end of queue (will be NULL for non-
228 * looping voices).
230 std::atomic<ALbufferlistitem*> mLoopBuffer;
232 /* Properties for the attached buffer(s). */
233 FmtChannels mFmtChannels;
234 ALuint mFrequency;
235 ALuint mNumChannels;
236 ALuint mSampleSize;
238 /** Current target parameters used for mixing. */
239 ALuint mStep;
241 ResamplerFunc mResampler;
243 InterpState mResampleState;
245 ALuint mFlags;
247 struct DirectData {
248 int FilterType;
249 al::span<FloatBufferLine> Buffer;
251 DirectData mDirect;
253 struct SendData {
254 int FilterType;
255 al::span<FloatBufferLine> Buffer;
257 std::array<SendData,MAX_SENDS> mSend;
259 struct ChannelData {
260 alignas(16) std::array<ALfloat,MAX_RESAMPLE_PADDING*2> mPrevSamples;
262 ALfloat mAmbiScale;
263 BandSplitter mAmbiSplitter;
265 DirectParams mDryParams;
266 std::array<SendParams,MAX_SENDS> mWetParams;
268 std::array<ChannelData,MAX_INPUT_CHANNELS> mChans;
270 ALvoice() = default;
271 ALvoice(const ALvoice&) = delete;
272 ALvoice(ALvoice&& rhs) noexcept { *this = std::move(rhs); }
273 ~ALvoice() { delete mUpdate.exchange(nullptr, std::memory_order_acq_rel); }
274 ALvoice& operator=(const ALvoice&) = delete;
275 ALvoice& operator=(ALvoice&& rhs) noexcept
277 ALvoiceProps *old_update{mUpdate.load(std::memory_order_relaxed)};
278 mUpdate.store(rhs.mUpdate.exchange(old_update, std::memory_order_relaxed),
279 std::memory_order_relaxed);
281 mSourceID.store(rhs.mSourceID.load(std::memory_order_relaxed), std::memory_order_relaxed);
282 mPlayState.store(rhs.mPlayState.load(std::memory_order_relaxed),
283 std::memory_order_relaxed);
285 mProps = rhs.mProps;
287 mPosition.store(rhs.mPosition.load(std::memory_order_relaxed), std::memory_order_relaxed);
288 mPositionFrac.store(rhs.mPositionFrac.load(std::memory_order_relaxed),
289 std::memory_order_relaxed);
291 mCurrentBuffer.store(rhs.mCurrentBuffer.load(std::memory_order_relaxed),
292 std::memory_order_relaxed);
293 mLoopBuffer.store(rhs.mLoopBuffer.load(std::memory_order_relaxed),
294 std::memory_order_relaxed);
296 mFmtChannels = rhs.mFmtChannels;
297 mFrequency = rhs.mFrequency;
298 mNumChannels = rhs.mNumChannels;
299 mSampleSize = rhs.mSampleSize;
301 mStep = rhs.mStep;
302 mResampler = rhs.mResampler;
304 mResampleState = rhs.mResampleState;
306 mFlags = rhs.mFlags;
308 mDirect = rhs.mDirect;
309 mSend = rhs.mSend;
310 mChans = rhs.mChans;
312 return *this;
315 void mix(ALvoice::State vstate, ALCcontext *Context, const ALuint SamplesToDo);
319 using MixerFunc = void(*)(const al::span<const float> InSamples,
320 const al::span<FloatBufferLine> OutBuffer, float *CurrentGains, const float *TargetGains,
321 const size_t Counter, const size_t OutPos);
322 using RowMixerFunc = void(*)(const al::span<float> OutBuffer, const al::span<const float> Gains,
323 const float *InSamples, const size_t InStride);
324 using HrtfMixerFunc = void(*)(FloatBufferLine &LeftOut, FloatBufferLine &RightOut,
325 const ALfloat *InSamples, float2 *AccumSamples, const size_t OutPos, const ALuint IrSize,
326 MixHrtfFilter *hrtfparams, const size_t BufferSize);
327 using HrtfMixerBlendFunc = void(*)(FloatBufferLine &LeftOut, FloatBufferLine &RightOut,
328 const ALfloat *InSamples, float2 *AccumSamples, const size_t OutPos, const ALuint IrSize,
329 const HrtfFilter *oldparams, MixHrtfFilter *newparams, const size_t BufferSize);
330 using HrtfDirectMixerFunc = void(*)(FloatBufferLine &LeftOut, FloatBufferLine &RightOut,
331 const al::span<const FloatBufferLine> InSamples, float2 *AccumSamples, DirectHrtfState *State,
332 const size_t BufferSize);
335 #define GAIN_MIX_MAX (1000.0f) /* +60dB */
337 #define GAIN_SILENCE_THRESHOLD (0.00001f) /* -100dB */
339 #define SPEEDOFSOUNDMETRESPERSEC (343.3f)
340 #define AIRABSORBGAINHF (0.99426f) /* -0.05dB */
342 /* Target gain for the reverb decay feedback reaching the decay time. */
343 #define REVERB_DECAY_GAIN (0.001f) /* -60 dB */
345 #define FRACTIONBITS (12)
346 #define FRACTIONONE (1<<FRACTIONBITS)
347 #define FRACTIONMASK (FRACTIONONE-1)
350 inline ALfloat lerp(ALfloat val1, ALfloat val2, ALfloat mu) noexcept
351 { return val1 + (val2-val1)*mu; }
352 inline ALfloat cubic(ALfloat val1, ALfloat val2, ALfloat val3, ALfloat val4, ALfloat mu) noexcept
354 ALfloat mu2 = mu*mu, mu3 = mu2*mu;
355 ALfloat a0 = -0.5f*mu3 + mu2 + -0.5f*mu;
356 ALfloat a1 = 1.5f*mu3 + -2.5f*mu2 + 1.0f;
357 ALfloat a2 = -1.5f*mu3 + 2.0f*mu2 + 0.5f*mu;
358 ALfloat a3 = 0.5f*mu3 + -0.5f*mu2;
359 return val1*a0 + val2*a1 + val3*a2 + val4*a3;
363 enum HrtfRequestMode {
364 Hrtf_Default = 0,
365 Hrtf_Enable = 1,
366 Hrtf_Disable = 2,
369 void aluInit(void);
371 void aluInitMixer(void);
373 ResamplerFunc SelectResampler(Resampler resampler);
375 /* aluInitRenderer
377 * Set up the appropriate panning method and mixing method given the device
378 * properties.
380 void aluInitRenderer(ALCdevice *device, ALint hrtf_id, HrtfRequestMode hrtf_appreq, HrtfRequestMode hrtf_userreq);
382 void aluInitEffectPanning(ALeffectslot *slot, ALCdevice *device);
385 * Calculates ambisonic encoder coefficients using the X, Y, and Z direction
386 * components, which must represent a normalized (unit length) vector, and the
387 * spread is the angular width of the sound (0...tau).
389 * NOTE: The components use ambisonic coordinates. As a result:
391 * Ambisonic Y = OpenAL -X
392 * Ambisonic Z = OpenAL Y
393 * Ambisonic X = OpenAL -Z
395 * The components are ordered such that OpenAL's X, Y, and Z are the first,
396 * second, and third parameters respectively -- simply negate X and Z.
398 void CalcAmbiCoeffs(const ALfloat y, const ALfloat z, const ALfloat x, const ALfloat spread,
399 ALfloat (&coeffs)[MAX_AMBI_CHANNELS]);
402 * CalcDirectionCoeffs
404 * Calculates ambisonic coefficients based on an OpenAL direction vector. The
405 * vector must be normalized (unit length), and the spread is the angular width
406 * of the sound (0...tau).
408 inline void CalcDirectionCoeffs(const ALfloat (&dir)[3], ALfloat spread, ALfloat (&coeffs)[MAX_AMBI_CHANNELS])
410 /* Convert from OpenAL coords to Ambisonics. */
411 CalcAmbiCoeffs(-dir[0], dir[1], -dir[2], spread, coeffs);
415 * CalcAngleCoeffs
417 * Calculates ambisonic coefficients based on azimuth and elevation. The
418 * azimuth and elevation parameters are in radians, going right and up
419 * respectively.
421 inline void CalcAngleCoeffs(ALfloat azimuth, ALfloat elevation, ALfloat spread, ALfloat (&coeffs)[MAX_AMBI_CHANNELS])
423 ALfloat x = -std::sin(azimuth) * std::cos(elevation);
424 ALfloat y = std::sin(elevation);
425 ALfloat z = std::cos(azimuth) * std::cos(elevation);
427 CalcAmbiCoeffs(x, y, z, spread, coeffs);
432 * ComputePanGains
434 * Computes panning gains using the given channel decoder coefficients and the
435 * pre-calculated direction or angle coefficients. For B-Format sources, the
436 * coeffs are a 'slice' of a transform matrix for the input channel, used to
437 * scale and orient the sound samples.
439 void ComputePanGains(const MixParams *mix, const ALfloat*RESTRICT coeffs, ALfloat ingain, ALfloat (&gains)[MAX_OUTPUT_CHANNELS]);
442 inline std::array<ALfloat,MAX_AMBI_CHANNELS> GetAmbiIdentityRow(size_t i) noexcept
444 std::array<ALfloat,MAX_AMBI_CHANNELS> ret{};
445 ret[i] = 1.0f;
446 return ret;
450 void aluMixData(ALCdevice *device, ALvoid *OutBuffer, const ALuint NumSamples);
451 /* Caller must lock the device state, and the mixer must not be running. */
452 void aluHandleDisconnect(ALCdevice *device, const char *msg, ...) DECL_FORMAT(printf, 2, 3);
454 extern MixerFunc MixSamples;
455 extern RowMixerFunc MixRowSamples;
457 extern const ALfloat ConeScale;
458 extern const ALfloat ZScale;
460 #endif