aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Robinson <[email protected]>2023-09-14 07:31:25 -0700
committerChris Robinson <[email protected]>2023-09-14 07:31:25 -0700
commitf098f253324d4d9b0669e061fab006295d826a53 (patch)
tree6dada40a46c7b774be224eacaebd6ac64cec1b5c
parent2ea092d6ad43c636713f53532d7e68bd5444b91d (diff)
Store channel positions as vectors instead of angles
To avoid extraneous conversions between angles and vectors
-rw-r--r--alc/alu.cpp279
-rw-r--r--alc/effects/chorus.cpp8
-rw-r--r--alc/effects/dedicated.cpp2
-rw-r--r--alc/effects/distortion.cpp2
-rw-r--r--alc/effects/fshifter.cpp8
-rw-r--r--alc/effects/pshifter.cpp2
-rw-r--r--core/mixer.h4
7 files changed, 175 insertions, 130 deletions
diff --git a/alc/alu.cpp b/alc/alu.cpp
index b7df47e1..1fa9d1d4 100644
--- a/alc/alu.cpp
+++ b/alc/alu.cpp
@@ -135,12 +135,6 @@ float ZScale{1.0f};
float NfcScale{1.0f};
-struct ChanMap {
- Channel channel;
- float angle;
- float elevation;
-};
-
using HrtfDirectMixerFunc = void(*)(const FloatBufferSpan LeftOut, const FloatBufferSpan RightOut,
const al::span<const FloatBufferLine> InSamples, float2 *AccumSamples, float *TempBuf,
HrtfChannelState *ChanState, const size_t IrSize, const size_t BufferSize);
@@ -520,27 +514,76 @@ bool CalcEffectSlotParams(EffectSlot *slot, EffectSlot **sorted_slots, ContextBa
}
-/* Scales the given azimuth toward the side (+/- pi/2 radians) for positions in
- * front.
+/* Scales the azimuth of the given vector by 3 if it's in front. Effectively
+ * scales +/-30 degrees to +/-90 degrees, leaving > +90 and < -90 alone.
*/
-inline float ScaleAzimuthFront(float azimuth, float scale)
+inline std::array<float,3> ScaleAzimuthFront3(std::array<float,3> pos)
{
- const float abs_azi{std::fabs(azimuth)};
- if(!(abs_azi >= al::numbers::pi_v<float>*0.5f))
- return std::copysign(minf(abs_azi*scale, al::numbers::pi_v<float>*0.5f), azimuth);
- return azimuth;
+ if(pos[2] < 0.0f)
+ {
+ /* Normalize the length of the x,z components for a 2D vector of the
+ * azimuth angle. Negate Z since {0,0,-1} is angle 0.
+ */
+ const float len2d{std::sqrt(pos[0]*pos[0] + pos[2]*pos[2])};
+ float x{pos[0] / len2d};
+ float z{-pos[2] / len2d};
+
+ /* Z > cos(pi/6) = -30 < azimuth < 30 degrees. */
+ if(z > 0.866025403785f)
+ {
+ /* Triple the angle represented by x,z. */
+ x = x*3.0f - x*x*x*4.0f;
+ z = z*z*z*4.0f - z*3.0f;
+
+ /* Scale the vector back to fit in 3D. */
+ pos[0] = x * len2d;
+ pos[2] = -z * len2d;
+ }
+ else
+ {
+ /* If azimuth >= 30 degrees, clamp to 90 degrees. */
+ pos[0] = std::copysign(len2d, pos[0]);
+ pos[2] = 0.0f;
+ }
+ }
+ return pos;
}
-/* Wraps the given value in radians to stay between [-pi,+pi] */
-inline float WrapRadians(float r)
+/* Scales the azimuth of the given vector by 1.5 (3/2) if it's in front. */
+inline std::array<float,3> ScaleAzimuthFront3_2(std::array<float,3> pos)
{
- static constexpr float Pi{al::numbers::pi_v<float>};
- static constexpr float Pi2{Pi*2.0f};
- if(r > Pi) return std::fmod(Pi+r, Pi2) - Pi;
- if(r < -Pi) return Pi - std::fmod(Pi-r, Pi2);
- return r;
+ if(pos[2] < 0.0f)
+ {
+ const float len2d{std::sqrt(pos[0]*pos[0] + pos[2]*pos[2])};
+ float x{pos[0] / len2d};
+ float z{-pos[2] / len2d};
+
+ /* Z > cos(pi/3) = -60 < azimuth < 60 degrees. */
+ if(z > 0.5f)
+ {
+ /* Halve the angle represented by x,z. */
+ x = std::copysign(std::sqrt((1.0f - z) * 0.5f), x);
+ z = std::sqrt((1.0f + z) * 0.5f);
+
+ /* Triple the angle represented by x,z. */
+ x = x*3.0f - x*x*x*4.0f;
+ z = z*z*z*4.0f - z*3.0f;
+
+ /* Scale the vector back to fit in 3D. */
+ pos[0] = x * len2d;
+ pos[2] = -z * len2d;
+ }
+ else
+ {
+ /* If azimuth >= 60 degrees, clamp to 90 degrees. */
+ pos[0] = std::copysign(len2d, pos[0]);
+ pos[2] = 0.0f;
+ }
+ }
+ return pos;
}
+
/* Begin ambisonic rotation helpers.
*
* Rotating first-order B-Format just needs a straight-forward X/Y/Z rotation
@@ -696,8 +739,18 @@ void AmbiRotator(AmbiRotateMatrix &matrix, const int order)
/* End ambisonic rotation helpers. */
-constexpr float Deg2Rad(float x) noexcept
-{ return static_cast<float>(al::numbers::pi / 180.0 * x); }
+constexpr float sin30{0.5f};
+constexpr float cos30{0.866025403785f};
+constexpr float sin45{al::numbers::sqrt2_v<float>*0.5f};
+constexpr float cos45{al::numbers::sqrt2_v<float>*0.5f};
+constexpr float sin110{ 0.939692620786f};
+constexpr float cos110{-0.342020143326f};
+
+struct ChanPosMap {
+ Channel channel;
+ std::array<float,3> pos;
+};
+
struct GainTriplet { float Base, HF, LF; };
@@ -706,45 +759,45 @@ void CalcPanningAndFilters(Voice *voice, const float xpos, const float ypos, con
const al::span<const GainTriplet,MAX_SENDS> WetGain, EffectSlot *(&SendSlots)[MAX_SENDS],
const VoiceProps *props, const ContextParams &Context, DeviceBase *Device)
{
- static constexpr ChanMap MonoMap[1]{
- { FrontCenter, 0.0f, 0.0f }
+ static constexpr ChanPosMap MonoMap[1]{
+ { FrontCenter, std::array{0.0f, 0.0f, -1.0f} }
}, RearMap[2]{
- { BackLeft, Deg2Rad(-150.0f), Deg2Rad(0.0f) },
- { BackRight, Deg2Rad( 150.0f), Deg2Rad(0.0f) }
+ { BackLeft, std::array{-sin30, 0.0f, cos30} },
+ { BackRight, std::array{ sin30, 0.0f, cos30} },
}, QuadMap[4]{
- { FrontLeft, Deg2Rad( -45.0f), Deg2Rad(0.0f) },
- { FrontRight, Deg2Rad( 45.0f), Deg2Rad(0.0f) },
- { BackLeft, Deg2Rad(-135.0f), Deg2Rad(0.0f) },
- { BackRight, Deg2Rad( 135.0f), Deg2Rad(0.0f) }
+ { FrontLeft, std::array{-sin45, 0.0f, -cos45} },
+ { FrontRight, std::array{ sin45, 0.0f, -cos45} },
+ { BackLeft, std::array{-sin45, 0.0f, cos45} },
+ { BackRight, std::array{ sin45, 0.0f, cos45} },
}, X51Map[6]{
- { FrontLeft, Deg2Rad( -30.0f), Deg2Rad(0.0f) },
- { FrontRight, Deg2Rad( 30.0f), Deg2Rad(0.0f) },
- { FrontCenter, Deg2Rad( 0.0f), Deg2Rad(0.0f) },
- { LFE, 0.0f, 0.0f },
- { SideLeft, Deg2Rad(-110.0f), Deg2Rad(0.0f) },
- { SideRight, Deg2Rad( 110.0f), Deg2Rad(0.0f) }
+ { FrontLeft, std::array{-sin30, 0.0f, -cos30} },
+ { FrontRight, std::array{ sin30, 0.0f, -cos30} },
+ { FrontCenter, std::array{ 0.0f, 0.0f, -1.0f} },
+ { LFE, {} },
+ { SideLeft, std::array{-sin110, 0.0f, -cos110} },
+ { SideRight, std::array{ sin110, 0.0f, -cos110} },
}, X61Map[7]{
- { FrontLeft, Deg2Rad(-30.0f), Deg2Rad(0.0f) },
- { FrontRight, Deg2Rad( 30.0f), Deg2Rad(0.0f) },
- { FrontCenter, Deg2Rad( 0.0f), Deg2Rad(0.0f) },
- { LFE, 0.0f, 0.0f },
- { BackCenter, Deg2Rad(180.0f), Deg2Rad(0.0f) },
- { SideLeft, Deg2Rad(-90.0f), Deg2Rad(0.0f) },
- { SideRight, Deg2Rad( 90.0f), Deg2Rad(0.0f) }
+ { FrontLeft, std::array{-sin30, 0.0f, -cos30} },
+ { FrontRight, std::array{ sin30, 0.0f, -cos30} },
+ { FrontCenter, std::array{ 0.0f, 0.0f, -1.0f} },
+ { LFE, {} },
+ { BackCenter, std::array{ 0.0f, 0.0f, 1.0f} },
+ { SideLeft, std::array{-1.0f, 0.0f, 0.0f} },
+ { SideRight, std::array{ 1.0f, 0.0f, 0.0f} },
}, X71Map[8]{
- { FrontLeft, Deg2Rad( -30.0f), Deg2Rad(0.0f) },
- { FrontRight, Deg2Rad( 30.0f), Deg2Rad(0.0f) },
- { FrontCenter, Deg2Rad( 0.0f), Deg2Rad(0.0f) },
- { LFE, 0.0f, 0.0f },
- { BackLeft, Deg2Rad(-150.0f), Deg2Rad(0.0f) },
- { BackRight, Deg2Rad( 150.0f), Deg2Rad(0.0f) },
- { SideLeft, Deg2Rad( -90.0f), Deg2Rad(0.0f) },
- { SideRight, Deg2Rad( 90.0f), Deg2Rad(0.0f) }
+ { FrontLeft, std::array{-sin30, 0.0f, -cos30} },
+ { FrontRight, std::array{ sin30, 0.0f, -cos30} },
+ { FrontCenter, std::array{ 0.0f, 0.0f, -1.0f} },
+ { LFE, {} },
+ { BackLeft, std::array{-sin30, 0.0f, cos30} },
+ { BackRight, std::array{ sin30, 0.0f, cos30} },
+ { SideLeft, std::array{ -1.0f, 0.0f, 0.0f} },
+ { SideRight, std::array{ 1.0f, 0.0f, 0.0f} },
};
- ChanMap StereoMap[2]{
- { FrontLeft, Deg2Rad(-30.0f), Deg2Rad(0.0f) },
- { FrontRight, Deg2Rad( 30.0f), Deg2Rad(0.0f) }
+ ChanPosMap StereoMap[2]{
+ { FrontLeft, std::array{-sin30, 0.0f, -cos30} },
+ { FrontRight, std::array{ sin30, 0.0f, -cos30} },
};
const auto Frequency = static_cast<float>(Device->Frequency);
@@ -762,7 +815,7 @@ void CalcPanningAndFilters(Voice *voice, const float xpos, const float ypos, con
}
DirectMode DirectChannels{props->DirectChannels};
- const ChanMap *chans{nullptr};
+ const ChanPosMap *chans{nullptr};
switch(voice->mFmtChannels)
{
case FmtMono:
@@ -774,11 +827,13 @@ void CalcPanningAndFilters(Voice *voice, const float xpos, const float ypos, con
case FmtStereo:
if(DirectChannels == DirectMode::Off)
{
- /* Convert counter-clockwise to clock-wise, and wrap between
- * [-pi,+pi].
- */
- StereoMap[0].angle = WrapRadians(-props->StereoPan[0]);
- StereoMap[1].angle = WrapRadians(-props->StereoPan[1]);
+ for(size_t i{0};i < 2;++i)
+ {
+ /* StereoPan is counter-clockwise in radians. */
+ const float a{props->StereoPan[i]};
+ StereoMap[i].pos[0] = -std::sin(a);
+ StereoMap[i].pos[2] = -std::cos(a);
+ }
}
chans = StereoMap;
break;
@@ -844,20 +899,9 @@ void CalcPanningAndFilters(Voice *voice, const float xpos, const float ypos, con
auto calc_coeffs = [xpos,ypos,zpos](RenderMode mode)
{
if(mode != RenderMode::Pairwise)
- return CalcDirectionCoeffs({xpos, ypos, zpos});
-
- /* Clamp Y, in case rounding errors caused it to end up outside
- * of -1...+1.
- */
- const float ev{std::asin(clampf(ypos, -1.0f, 1.0f))};
- /* Negate Z for right-handed coords with -Z in front. */
- const float az{std::atan2(xpos, -zpos)};
-
- /* A scalar of 1.5 for plain stereo results in +/-60 degrees
- * being moved to +/-90 degrees for direct right and left
- * speaker responses.
- */
- return CalcAngleCoeffs(ScaleAzimuthFront(az, 1.5f), ev, 0.0f);
+ return CalcDirectionCoeffs(std::array{xpos, ypos, zpos}, 0.0f);
+ const auto pos = ScaleAzimuthFront3_2(std::array{xpos, ypos, zpos});
+ return CalcDirectionCoeffs(pos, 0.0f);
};
const auto scales = GetAmbiScales(voice->mAmbiScaling);
auto coeffs = calc_coeffs(Device->mRenderMode);
@@ -1027,7 +1071,7 @@ void CalcPanningAndFilters(Voice *voice, const float xpos, const float ypos, con
if(chans[c].channel == LFE)
continue;
- const auto coeffs = CalcAngleCoeffs(chans[c].angle, chans[c].elevation, 0.0f);
+ const auto coeffs = CalcDirectionCoeffs(chans[c].pos, 0.0f);
for(uint i{0};i < NumSends;i++)
{
@@ -1046,17 +1090,17 @@ void CalcPanningAndFilters(Voice *voice, const float xpos, const float ypos, con
if(Distance > std::numeric_limits<float>::epsilon())
{
- const float src_ev{std::asin(clampf(ypos, -1.0f, 1.0f))};
- const float src_az{std::atan2(xpos, -zpos)};
-
if(voice->mFmtChannels == FmtMono)
{
+ const float src_ev{std::asin(clampf(ypos, -1.0f, 1.0f))};
+ const float src_az{std::atan2(xpos, -zpos)};
+
Device->mHrtf->getCoeffs(src_ev, src_az, Distance*NfcScale, Spread,
voice->mChans[0].mDryParams.Hrtf.Target.Coeffs,
voice->mChans[0].mDryParams.Hrtf.Target.Delay);
voice->mChans[0].mDryParams.Hrtf.Target.Gain = DryGain.Base;
- const auto coeffs = CalcAngleCoeffs(src_az, src_ev, Spread);
+ const auto coeffs = CalcDirectionCoeffs(std::array{xpos, ypos, zpos}, Spread);
for(uint i{0};i < NumSends;i++)
{
if(const EffectSlot *Slot{SendSlots[i]})
@@ -1076,24 +1120,28 @@ void CalcPanningAndFilters(Voice *voice, const float xpos, const float ypos, con
* the source position, at full spread (pi*2), each channel is
* left unchanged.
*/
- const float ev{lerpf(src_ev, chans[c].elevation, inv_pi_v<float>/2.0f * Spread)};
-
- float az{chans[c].angle - src_az};
- if(az < -pi_v<float>) az += pi_v<float>*2.0f;
- else if(az > pi_v<float>) az -= pi_v<float>*2.0f;
-
- az *= inv_pi_v<float>/2.0f * Spread;
+ const float a{1.0f - (inv_pi_v<float>/2.0f)*Spread};
+ std::array pos{
+ lerpf(chans[c].pos[0], xpos, a),
+ lerpf(chans[c].pos[1], ypos, a),
+ lerpf(chans[c].pos[2], zpos, a)};
+ const float len{std::sqrt(pos[0]*pos[0] + pos[1]*pos[1] + pos[2]*pos[2])};
+ if(len < 1.0f)
+ {
+ pos[0] /= len;
+ pos[1] /= len;
+ pos[2] /= len;
+ }
- az += src_az;
- if(az < -pi_v<float>) az += pi_v<float>*2.0f;
- else if(az > pi_v<float>) az -= pi_v<float>*2.0f;
+ const float ev{std::asin(clampf(pos[1], -1.0f, 1.0f))};
+ const float az{std::atan2(pos[0], -pos[2])};
Device->mHrtf->getCoeffs(ev, az, Distance*NfcScale, 0.0f,
voice->mChans[c].mDryParams.Hrtf.Target.Coeffs,
voice->mChans[c].mDryParams.Hrtf.Target.Delay);
voice->mChans[c].mDryParams.Hrtf.Target.Gain = DryGain.Base;
- const auto coeffs = CalcAngleCoeffs(az, ev, 0.0f);
+ const auto coeffs = CalcDirectionCoeffs(pos, 0.0f);
for(uint i{0};i < NumSends;i++)
{
if(const EffectSlot *Slot{SendSlots[i]})
@@ -1123,14 +1171,16 @@ void CalcPanningAndFilters(Voice *voice, const float xpos, const float ypos, con
/* Get the HRIR coefficients and delays for this channel
* position.
*/
- Device->mHrtf->getCoeffs(chans[c].elevation, chans[c].angle,
- std::numeric_limits<float>::infinity(), spread,
+ const float ev{std::asin(chans[c].pos[1])};
+ const float az{std::atan2(chans[c].pos[0], -chans[c].pos[2])};
+
+ Device->mHrtf->getCoeffs(ev, az, std::numeric_limits<float>::infinity(), spread,
voice->mChans[c].mDryParams.Hrtf.Target.Coeffs,
voice->mChans[c].mDryParams.Hrtf.Target.Delay);
voice->mChans[c].mDryParams.Hrtf.Target.Gain = DryGain.Base;
/* Normal panning for auxiliary sends. */
- const auto coeffs = CalcAngleCoeffs(chans[c].angle, chans[c].elevation, spread);
+ const auto coeffs = CalcDirectionCoeffs(chans[c].pos, spread);
for(uint i{0};i < NumSends;i++)
{
@@ -1170,10 +1220,9 @@ void CalcPanningAndFilters(Voice *voice, const float xpos, const float ypos, con
auto calc_coeffs = [xpos,ypos,zpos,Spread](RenderMode mode)
{
if(mode != RenderMode::Pairwise)
- return CalcDirectionCoeffs({xpos, ypos, zpos}, Spread);
- const float ev{std::asin(clampf(ypos, -1.0f, 1.0f))};
- const float az{std::atan2(xpos, -zpos)};
- return CalcAngleCoeffs(ScaleAzimuthFront(az, 1.5f), ev, Spread);
+ return CalcDirectionCoeffs(std::array{xpos, ypos, zpos}, Spread);
+ const auto pos = ScaleAzimuthFront3_2(std::array{xpos, ypos, zpos});
+ return CalcDirectionCoeffs(pos, Spread);
};
const auto coeffs = calc_coeffs(Device->mRenderMode);
@@ -1190,9 +1239,6 @@ void CalcPanningAndFilters(Voice *voice, const float xpos, const float ypos, con
{
using namespace al::numbers;
- const float src_ev{std::asin(clampf(ypos, -1.0f, 1.0f))};
- const float src_az{std::atan2(xpos, -zpos)};
-
for(size_t c{0};c < num_channels;c++)
{
/* Special-case LFE */
@@ -1212,22 +1258,22 @@ void CalcPanningAndFilters(Voice *voice, const float xpos, const float ypos, con
* at the source position, at full spread (pi*2), each
* channel position is left unchanged.
*/
- const float ev{lerpf(src_ev, chans[c].elevation,
- inv_pi_v<float>/2.0f * Spread)};
-
- float az{chans[c].angle - src_az};
- if(az < -pi_v<float>) az += pi_v<float>*2.0f;
- else if(az > pi_v<float>) az -= pi_v<float>*2.0f;
-
- az *= inv_pi_v<float>/2.0f * Spread;
-
- az += src_az;
- if(az < -pi_v<float>) az += pi_v<float>*2.0f;
- else if(az > pi_v<float>) az -= pi_v<float>*2.0f;
+ const float a{1.0f - (inv_pi_v<float>/2.0f)*Spread};
+ std::array pos{
+ lerpf(chans[c].pos[0], xpos, a),
+ lerpf(chans[c].pos[1], ypos, a),
+ lerpf(chans[c].pos[2], zpos, a)};
+ const float len{std::sqrt(pos[0]*pos[0] + pos[1]*pos[1] + pos[2]*pos[2])};
+ if(len < 1.0f)
+ {
+ pos[0] /= len;
+ pos[1] /= len;
+ pos[2] /= len;
+ }
if(Device->mRenderMode == RenderMode::Pairwise)
- az = ScaleAzimuthFront(az, 3.0f);
- const auto coeffs = CalcAngleCoeffs(az, ev, 0.0f);
+ pos = ScaleAzimuthFront3(pos);
+ const auto coeffs = CalcDirectionCoeffs(pos, 0.0f);
ComputePanGains(&Device->Dry, coeffs.data(), DryGain.Base,
voice->mChans[c].mDryParams.Gains.Target);
@@ -1273,9 +1319,8 @@ void CalcPanningAndFilters(Voice *voice, const float xpos, const float ypos, con
continue;
}
- const auto coeffs = CalcAngleCoeffs((Device->mRenderMode == RenderMode::Pairwise)
- ? ScaleAzimuthFront(chans[c].angle, 3.0f) : chans[c].angle,
- chans[c].elevation, spread);
+ const auto coeffs = CalcDirectionCoeffs((Device->mRenderMode==RenderMode::Pairwise)
+ ? ScaleAzimuthFront3(chans[c].pos) : chans[c].pos, spread);
ComputePanGains(&Device->Dry, coeffs.data(), DryGain.Base,
voice->mChans[c].mDryParams.Gains.Target);
diff --git a/alc/effects/chorus.cpp b/alc/effects/chorus.cpp
index 7c281aa5..c84531d4 100644
--- a/alc/effects/chorus.cpp
+++ b/alc/effects/chorus.cpp
@@ -125,10 +125,10 @@ void ChorusState::update(const ContextBase *Context, const EffectSlot *Slot,
/* Gains for left and right sides */
static constexpr auto inv_sqrt2 = static_cast<float>(1.0 / al::numbers::sqrt2);
- static constexpr auto lcoeffs_pw = CalcDirectionCoeffs({-1.0f, 0.0f, 0.0f});
- static constexpr auto rcoeffs_pw = CalcDirectionCoeffs({ 1.0f, 0.0f, 0.0f});
- static constexpr auto lcoeffs_nrml = CalcDirectionCoeffs({-inv_sqrt2, 0.0f, inv_sqrt2});
- static constexpr auto rcoeffs_nrml = CalcDirectionCoeffs({ inv_sqrt2, 0.0f, inv_sqrt2});
+ static constexpr auto lcoeffs_pw = CalcDirectionCoeffs(std::array{-1.0f, 0.0f, 0.0f});
+ static constexpr auto rcoeffs_pw = CalcDirectionCoeffs(std::array{ 1.0f, 0.0f, 0.0f});
+ static constexpr auto lcoeffs_nrml = CalcDirectionCoeffs(std::array{-inv_sqrt2, 0.0f, inv_sqrt2});
+ static constexpr auto rcoeffs_nrml = CalcDirectionCoeffs(std::array{ inv_sqrt2, 0.0f, inv_sqrt2});
auto &lcoeffs = (device->mRenderMode != RenderMode::Pairwise) ? lcoeffs_nrml : lcoeffs_pw;
auto &rcoeffs = (device->mRenderMode != RenderMode::Pairwise) ? rcoeffs_nrml : rcoeffs_pw;
diff --git a/alc/effects/dedicated.cpp b/alc/effects/dedicated.cpp
index 047e6761..e82b13d9 100644
--- a/alc/effects/dedicated.cpp
+++ b/alc/effects/dedicated.cpp
@@ -94,7 +94,7 @@ void DedicatedState::update(const ContextBase*, const EffectSlot *slot,
}
else
{
- static constexpr auto coeffs = CalcDirectionCoeffs({0.0f, 0.0f, -1.0f});
+ static constexpr auto coeffs = CalcDirectionCoeffs(std::array{0.0f, 0.0f, -1.0f});
mOutTarget = target.Main->Buffer;
ComputePanGains(target.Main, coeffs.data(), Gain, mTargetGains);
diff --git a/alc/effects/distortion.cpp b/alc/effects/distortion.cpp
index b4e2167e..392d81c8 100644
--- a/alc/effects/distortion.cpp
+++ b/alc/effects/distortion.cpp
@@ -95,7 +95,7 @@ void DistortionState::update(const ContextBase *context, const EffectSlot *slot,
bandwidth = props->Distortion.EQBandwidth / (cutoff * 0.67f);
mBandpass.setParamsFromBandwidth(BiquadType::BandPass, cutoff/frequency/4.0f, 1.0f, bandwidth);
- static constexpr auto coeffs = CalcDirectionCoeffs({0.0f, 0.0f, -1.0f});
+ static constexpr auto coeffs = CalcDirectionCoeffs(std::array{0.0f, 0.0f, -1.0f});
mOutTarget = target.Main->Buffer;
ComputePanGains(target.Main, coeffs.data(), slot->Gain*props->Distortion.Gain, mGain);
diff --git a/alc/effects/fshifter.cpp b/alc/effects/fshifter.cpp
index 3e6a7385..ec0cc29f 100644
--- a/alc/effects/fshifter.cpp
+++ b/alc/effects/fshifter.cpp
@@ -164,10 +164,10 @@ void FshifterState::update(const ContextBase *context, const EffectSlot *slot,
}
static constexpr auto inv_sqrt2 = static_cast<float>(1.0 / al::numbers::sqrt2);
- static constexpr auto lcoeffs_pw = CalcDirectionCoeffs({-1.0f, 0.0f, 0.0f});
- static constexpr auto rcoeffs_pw = CalcDirectionCoeffs({ 1.0f, 0.0f, 0.0f});
- static constexpr auto lcoeffs_nrml = CalcDirectionCoeffs({-inv_sqrt2, 0.0f, inv_sqrt2});
- static constexpr auto rcoeffs_nrml = CalcDirectionCoeffs({ inv_sqrt2, 0.0f, inv_sqrt2});
+ static constexpr auto lcoeffs_pw = CalcDirectionCoeffs(std::array{-1.0f, 0.0f, 0.0f});
+ static constexpr auto rcoeffs_pw = CalcDirectionCoeffs(std::array{ 1.0f, 0.0f, 0.0f});
+ static constexpr auto lcoeffs_nrml = CalcDirectionCoeffs(std::array{-inv_sqrt2, 0.0f, inv_sqrt2});
+ static constexpr auto rcoeffs_nrml = CalcDirectionCoeffs(std::array{ inv_sqrt2, 0.0f, inv_sqrt2});
auto &lcoeffs = (device->mRenderMode != RenderMode::Pairwise) ? lcoeffs_nrml : lcoeffs_pw;
auto &rcoeffs = (device->mRenderMode != RenderMode::Pairwise) ? rcoeffs_nrml : rcoeffs_pw;
diff --git a/alc/effects/pshifter.cpp b/alc/effects/pshifter.cpp
index 3cec1df9..2460cf78 100644
--- a/alc/effects/pshifter.cpp
+++ b/alc/effects/pshifter.cpp
@@ -142,7 +142,7 @@ void PshifterState::update(const ContextBase*, const EffectSlot *slot,
mPitchShiftI = clampu(fastf2u(pitch*MixerFracOne), MixerFracHalf, MixerFracOne*2);
mPitchShift = static_cast<float>(mPitchShiftI) * float{1.0f/MixerFracOne};
- static constexpr auto coeffs = CalcDirectionCoeffs({0.0f, 0.0f, -1.0f});
+ static constexpr auto coeffs = CalcDirectionCoeffs(std::array{0.0f, 0.0f, -1.0f});
mOutTarget = target.Main->Buffer;
ComputePanGains(target.Main, coeffs.data(), slot->Gain, mTargetGains);
diff --git a/core/mixer.h b/core/mixer.h
index aa7597bb..a9c1f931 100644
--- a/core/mixer.h
+++ b/core/mixer.h
@@ -58,7 +58,7 @@ std::array<float,MaxAmbiChannels> CalcAmbiCoeffs(const float y, const float z, c
* vector must be normalized (unit length), and the spread is the angular width
* of the sound (0...tau).
*/
-inline std::array<float,MaxAmbiChannels> CalcDirectionCoeffs(const float (&dir)[3],
+inline std::array<float,MaxAmbiChannels> CalcDirectionCoeffs(const al::span<const float,3> dir,
const float spread)
{
/* Convert from OpenAL coords to Ambisonics. */
@@ -71,7 +71,7 @@ inline std::array<float,MaxAmbiChannels> CalcDirectionCoeffs(const float (&dir)[
* Calculates ambisonic coefficients based on an OpenAL direction vector. The
* vector must be normalized (unit length).
*/
-constexpr std::array<float,MaxAmbiChannels> CalcDirectionCoeffs(const float (&dir)[3])
+constexpr std::array<float,MaxAmbiChannels> CalcDirectionCoeffs(const al::span<const float,3> dir)
{
/* Convert from OpenAL coords to Ambisonics. */
return CalcAmbiCoeffs(-dir[0], dir[1], -dir[2]);