Limit convolution processing to the output ambisonic order
[openal-soft.git] / alc / alu.h
blob1d4126be6bda405117fa084739693e7ddfb18e4b
1 #ifndef ALU_H
2 #define ALU_H
4 #include <array>
5 #include <cmath>
6 #include <cstddef>
7 #include <type_traits>
9 #include "AL/al.h"
11 #include "alcmain.h"
12 #include "alspan.h"
14 struct ALbufferlistitem;
15 struct ALeffectslot;
18 #define MAX_PITCH 10
19 #define MAX_SENDS 6
22 using MixerFunc = void(*)(const al::span<const float> InSamples,
23 const al::span<FloatBufferLine> OutBuffer, float *CurrentGains, const float *TargetGains,
24 const size_t Counter, const size_t OutPos);
26 extern MixerFunc MixSamples;
29 #define GAIN_MIX_MAX 1000.0f /* +60dB */
31 #define GAIN_SILENCE_THRESHOLD 0.00001f /* -100dB */
33 #define SPEEDOFSOUNDMETRESPERSEC 343.3f
34 #define AIRABSORBGAINHF 0.99426f /* -0.05dB */
36 /* Target gain for the reverb decay feedback reaching the decay time. */
37 #define REVERB_DECAY_GAIN 0.001f /* -60 dB */
39 #define FRACTIONBITS 12
40 #define FRACTIONONE (1<<FRACTIONBITS)
41 #define FRACTIONMASK (FRACTIONONE-1)
44 inline float lerp(float val1, float val2, float mu) noexcept
45 { return val1 + (val2-val1)*mu; }
46 inline float cubic(float val1, float val2, float val3, float val4, float mu) noexcept
48 const float mu2{mu*mu}, mu3{mu2*mu};
49 const float a0{-0.5f*mu3 + mu2 + -0.5f*mu};
50 const float a1{ 1.5f*mu3 + -2.5f*mu2 + 1.0f};
51 const float a2{-1.5f*mu3 + 2.0f*mu2 + 0.5f*mu};
52 const float a3{ 0.5f*mu3 + -0.5f*mu2};
53 return val1*a0 + val2*a1 + val3*a2 + val4*a3;
57 enum HrtfRequestMode {
58 Hrtf_Default = 0,
59 Hrtf_Enable = 1,
60 Hrtf_Disable = 2,
63 void aluInit(void);
65 void aluInitMixer(void);
67 /* aluInitRenderer
69 * Set up the appropriate panning method and mixing method given the device
70 * properties.
72 void aluInitRenderer(ALCdevice *device, int hrtf_id, HrtfRequestMode hrtf_appreq,
73 HrtfRequestMode hrtf_userreq);
75 void aluInitEffectPanning(ALeffectslot *slot, ALCdevice *device);
77 /**
78 * Calculates ambisonic encoder coefficients using the X, Y, and Z direction
79 * components, which must represent a normalized (unit length) vector, and the
80 * spread is the angular width of the sound (0...tau).
82 * NOTE: The components use ambisonic coordinates. As a result:
84 * Ambisonic Y = OpenAL -X
85 * Ambisonic Z = OpenAL Y
86 * Ambisonic X = OpenAL -Z
88 * The components are ordered such that OpenAL's X, Y, and Z are the first,
89 * second, and third parameters respectively -- simply negate X and Z.
91 std::array<float,MAX_AMBI_CHANNELS> CalcAmbiCoeffs(const float y, const float z, const float x,
92 const float spread);
94 /**
95 * CalcDirectionCoeffs
97 * Calculates ambisonic coefficients based on an OpenAL direction vector. The
98 * vector must be normalized (unit length), and the spread is the angular width
99 * of the sound (0...tau).
101 inline std::array<float,MAX_AMBI_CHANNELS> CalcDirectionCoeffs(const float (&dir)[3],
102 const float spread)
104 /* Convert from OpenAL coords to Ambisonics. */
105 return CalcAmbiCoeffs(-dir[0], dir[1], -dir[2], spread);
109 * CalcAngleCoeffs
111 * Calculates ambisonic coefficients based on azimuth and elevation. The
112 * azimuth and elevation parameters are in radians, going right and up
113 * respectively.
115 inline std::array<float,MAX_AMBI_CHANNELS> CalcAngleCoeffs(const float azimuth,
116 const float elevation, const float spread)
118 const float x{-std::sin(azimuth) * std::cos(elevation)};
119 const float y{ std::sin(elevation)};
120 const float z{ std::cos(azimuth) * std::cos(elevation)};
122 return CalcAmbiCoeffs(x, y, z, spread);
127 * ComputePanGains
129 * Computes panning gains using the given channel decoder coefficients and the
130 * pre-calculated direction or angle coefficients. For B-Format sources, the
131 * coeffs are a 'slice' of a transform matrix for the input channel, used to
132 * scale and orient the sound samples.
134 void ComputePanGains(const MixParams *mix, const float*RESTRICT coeffs, const float ingain,
135 const al::span<float,MAX_OUTPUT_CHANNELS> gains);
138 /** Helper to set an identity/pass-through panning for ambisonic mixing (3D input). */
139 template<typename T, typename I, typename F>
140 auto SetAmbiPanIdentity(T iter, I count, F func) -> std::enable_if_t<std::is_integral<I>::value>
142 if(count < 1) return;
144 std::array<float,MAX_AMBI_CHANNELS> coeffs{{1.0f}};
145 func(*iter, coeffs);
146 ++iter;
147 for(I i{1};i < count;++i,++iter)
149 coeffs[i-1] = 0.0f;
150 coeffs[i ] = 1.0f;
151 func(*iter, coeffs);
156 extern const float ConeScale;
157 extern const float ZScale;
159 #endif