From e7ea579ca5f3c0da6cfe80ec9a7295bca60198aa Mon Sep 17 00:00:00 2001
From: Chris Robinson <chris.kcat@gmail.com>
Date: Fri, 12 May 2023 18:02:12 -0700
Subject: Avoid using al::vector unnecessarily

---
 alc/effects/chorus.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

(limited to 'alc/effects/chorus.cpp')

diff --git a/alc/effects/chorus.cpp b/alc/effects/chorus.cpp
index 10ccf9f6..7c281aa5 100644
--- a/alc/effects/chorus.cpp
+++ b/alc/effects/chorus.cpp
@@ -25,6 +25,7 @@
 #include <climits>
 #include <cstdlib>
 #include <iterator>
+#include <vector>
 
 #include "alc/effects/base.h"
 #include "almalloc.h"
@@ -41,7 +42,6 @@
 #include "core/resampler_limits.h"
 #include "intrusive_ptr.h"
 #include "opthelpers.h"
-#include "vector.h"
 
 
 namespace {
@@ -49,7 +49,7 @@ namespace {
 using uint = unsigned int;
 
 struct ChorusState final : public EffectState {
-    al::vector<float,16> mDelayBuffer;
+    std::vector<float> mDelayBuffer;
     uint mOffset{0};
 
     uint mLfoOffset{0};
-- 
cgit v1.2.3


From f098f253324d4d9b0669e061fab006295d826a53 Mon Sep 17 00:00:00 2001
From: Chris Robinson <chris.kcat@gmail.com>
Date: Thu, 14 Sep 2023 07:31:25 -0700
Subject: Store channel positions as vectors instead of angles

To avoid extraneous conversions between angles and vectors
---
 alc/alu.cpp                | 279 ++++++++++++++++++++++++++-------------------
 alc/effects/chorus.cpp     |   8 +-
 alc/effects/dedicated.cpp  |   2 +-
 alc/effects/distortion.cpp |   2 +-
 alc/effects/fshifter.cpp   |   8 +-
 alc/effects/pshifter.cpp   |   2 +-
 core/mixer.h               |   4 +-
 7 files changed, 175 insertions(+), 130 deletions(-)

(limited to 'alc/effects/chorus.cpp')

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]);
-- 
cgit v1.2.3


From bfee94dfec64dd22ad8d985e71803fbe411f7a1a Mon Sep 17 00:00:00 2001
From: Chris Robinson <chris.kcat@gmail.com>
Date: Sun, 15 Oct 2023 02:38:20 -0700
Subject: Use a span for a known array length instead of a raw pointer

---
 alc/alu.cpp                 | 28 ++++++++++++++--------------
 alc/effects/chorus.cpp      |  4 ++--
 alc/effects/convolution.cpp |  6 +++---
 alc/effects/dedicated.cpp   |  2 +-
 alc/effects/distortion.cpp  |  2 +-
 alc/effects/echo.cpp        |  4 ++--
 alc/effects/fshifter.cpp    |  4 ++--
 alc/effects/pshifter.cpp    |  2 +-
 alc/effects/reverb.cpp      |  8 ++++----
 core/mixer.cpp              |  7 +++----
 core/mixer.h                |  4 ++--
 11 files changed, 35 insertions(+), 36 deletions(-)

(limited to 'alc/effects/chorus.cpp')

diff --git a/alc/alu.cpp b/alc/alu.cpp
index 1585b8f2..7aefcfb5 100644
--- a/alc/alu.cpp
+++ b/alc/alu.cpp
@@ -929,12 +929,12 @@ void CalcPanningAndFilters(Voice *voice, const float xpos, const float ypos, con
 
         if(!(coverage > 0.0f))
         {
-            ComputePanGains(&Device->Dry, coeffs.data(), DryGain.Base*scales[0],
+            ComputePanGains(&Device->Dry, coeffs, DryGain.Base*scales[0],
                 voice->mChans[0].mDryParams.Gains.Target);
             for(uint i{0};i < NumSends;i++)
             {
                 if(const EffectSlot *Slot{SendSlots[i]})
-                    ComputePanGains(&Slot->Wet, coeffs.data(), WetGain[i].Base*scales[0],
+                    ComputePanGains(&Slot->Wet, coeffs, WetGain[i].Base*scales[0],
                         voice->mChans[0].mWetParams[i].Gains.Target);
             }
         }
@@ -1038,13 +1038,13 @@ void CalcPanningAndFilters(Voice *voice, const float xpos, const float ypos, con
                 for(size_t x{0};x < MaxAmbiChannels;++x)
                     coeffs[x] += mixmatrix[acn][x] * scale;
 
-                ComputePanGains(&Device->Dry, coeffs.data(), DryGain.Base,
+                ComputePanGains(&Device->Dry, coeffs, DryGain.Base,
                     voice->mChans[c].mDryParams.Gains.Target);
 
                 for(uint i{0};i < NumSends;i++)
                 {
                     if(const EffectSlot *Slot{SendSlots[i]})
-                        ComputePanGains(&Slot->Wet, coeffs.data(), WetGain[i].Base,
+                        ComputePanGains(&Slot->Wet, coeffs, WetGain[i].Base,
                             voice->mChans[c].mWetParams[i].Gains.Target);
                 }
 
@@ -1097,7 +1097,7 @@ void CalcPanningAndFilters(Voice *voice, const float xpos, const float ypos, con
             for(uint i{0};i < NumSends;i++)
             {
                 if(const EffectSlot *Slot{SendSlots[i]})
-                    ComputePanGains(&Slot->Wet, coeffs.data(), WetGain[i].Base,
+                    ComputePanGains(&Slot->Wet, coeffs, WetGain[i].Base,
                         voice->mChans[c].mWetParams[i].Gains.Target);
             }
         }
@@ -1125,7 +1125,7 @@ void CalcPanningAndFilters(Voice *voice, const float xpos, const float ypos, con
                 for(uint i{0};i < NumSends;i++)
                 {
                     if(const EffectSlot *Slot{SendSlots[i]})
-                        ComputePanGains(&Slot->Wet, coeffs.data(), WetGain[i].Base,
+                        ComputePanGains(&Slot->Wet, coeffs, WetGain[i].Base,
                             voice->mChans[0].mWetParams[i].Gains.Target);
                 }
             }
@@ -1166,7 +1166,7 @@ void CalcPanningAndFilters(Voice *voice, const float xpos, const float ypos, con
                 for(uint i{0};i < NumSends;i++)
                 {
                     if(const EffectSlot *Slot{SendSlots[i]})
-                        ComputePanGains(&Slot->Wet, coeffs.data(), WetGain[i].Base,
+                        ComputePanGains(&Slot->Wet, coeffs, WetGain[i].Base,
                             voice->mChans[c].mWetParams[i].Gains.Target);
                 }
             }
@@ -1206,7 +1206,7 @@ void CalcPanningAndFilters(Voice *voice, const float xpos, const float ypos, con
                 for(uint i{0};i < NumSends;i++)
                 {
                     if(const EffectSlot *Slot{SendSlots[i]})
-                        ComputePanGains(&Slot->Wet, coeffs.data(), WetGain[i].Base,
+                        ComputePanGains(&Slot->Wet, coeffs, WetGain[i].Base,
                             voice->mChans[c].mWetParams[i].Gains.Target);
                 }
             }
@@ -1247,12 +1247,12 @@ void CalcPanningAndFilters(Voice *voice, const float xpos, const float ypos, con
                 };
                 const auto coeffs = calc_coeffs(Device->mRenderMode);
 
-                ComputePanGains(&Device->Dry, coeffs.data(), DryGain.Base,
+                ComputePanGains(&Device->Dry, coeffs, DryGain.Base,
                     voice->mChans[0].mDryParams.Gains.Target);
                 for(uint i{0};i < NumSends;i++)
                 {
                     if(const EffectSlot *Slot{SendSlots[i]})
-                        ComputePanGains(&Slot->Wet, coeffs.data(), WetGain[i].Base,
+                        ComputePanGains(&Slot->Wet, coeffs, WetGain[i].Base,
                             voice->mChans[0].mWetParams[i].Gains.Target);
                 }
             }
@@ -1296,12 +1296,12 @@ void CalcPanningAndFilters(Voice *voice, const float xpos, const float ypos, con
                         pos = ScaleAzimuthFront3(pos);
                     const auto coeffs = CalcDirectionCoeffs(pos, 0.0f);
 
-                    ComputePanGains(&Device->Dry, coeffs.data(), DryGain.Base,
+                    ComputePanGains(&Device->Dry, coeffs, DryGain.Base,
                         voice->mChans[c].mDryParams.Gains.Target);
                     for(uint i{0};i < NumSends;i++)
                     {
                         if(const EffectSlot *Slot{SendSlots[i]})
-                            ComputePanGains(&Slot->Wet, coeffs.data(), WetGain[i].Base,
+                            ComputePanGains(&Slot->Wet, coeffs, WetGain[i].Base,
                                 voice->mChans[c].mWetParams[i].Gains.Target);
                     }
                 }
@@ -1343,12 +1343,12 @@ void CalcPanningAndFilters(Voice *voice, const float xpos, const float ypos, con
                 const auto coeffs = CalcDirectionCoeffs((Device->mRenderMode==RenderMode::Pairwise)
                     ? ScaleAzimuthFront3(chans[c].pos) : chans[c].pos, spread);
 
-                ComputePanGains(&Device->Dry, coeffs.data(), DryGain.Base,
+                ComputePanGains(&Device->Dry, coeffs, DryGain.Base,
                     voice->mChans[c].mDryParams.Gains.Target);
                 for(uint i{0};i < NumSends;i++)
                 {
                     if(const EffectSlot *Slot{SendSlots[i]})
-                        ComputePanGains(&Slot->Wet, coeffs.data(), WetGain[i].Base,
+                        ComputePanGains(&Slot->Wet, coeffs, WetGain[i].Base,
                             voice->mChans[c].mWetParams[i].Gains.Target);
                 }
             }
diff --git a/alc/effects/chorus.cpp b/alc/effects/chorus.cpp
index c84531d4..9cbc922f 100644
--- a/alc/effects/chorus.cpp
+++ b/alc/effects/chorus.cpp
@@ -133,8 +133,8 @@ void ChorusState::update(const ContextBase *Context, const EffectSlot *Slot,
     auto &rcoeffs = (device->mRenderMode != RenderMode::Pairwise) ? rcoeffs_nrml : rcoeffs_pw;
 
     mOutTarget = target.Main->Buffer;
-    ComputePanGains(target.Main, lcoeffs.data(), Slot->Gain, mGains[0].Target);
-    ComputePanGains(target.Main, rcoeffs.data(), Slot->Gain, mGains[1].Target);
+    ComputePanGains(target.Main, lcoeffs, Slot->Gain, mGains[0].Target);
+    ComputePanGains(target.Main, rcoeffs, Slot->Gain, mGains[1].Target);
 
     float rate{props->Chorus.Rate};
     if(!(rate > 0.0f))
diff --git a/alc/effects/convolution.cpp b/alc/effects/convolution.cpp
index 06c34a37..5d1a6500 100644
--- a/alc/effects/convolution.cpp
+++ b/alc/effects/convolution.cpp
@@ -547,7 +547,7 @@ void ConvolutionState::update(const ContextBase *context, const EffectSlot *slot
             for(size_t x{0};x < 4;++x)
                 coeffs[x] = mixmatrix[acn][x] * scale;
 
-            ComputePanGains(target.Main, coeffs.data(), gain, (*mChans)[c].Target);
+            ComputePanGains(target.Main, coeffs, gain, (*mChans)[c].Target);
         }
     }
     else
@@ -616,14 +616,14 @@ void ConvolutionState::update(const ContextBase *context, const EffectSlot *slot
             {
                 if(chanmap[i].channel == LFE) continue;
                 const auto coeffs = CalcDirectionCoeffs(ScaleAzimuthFront(chanmap[i].pos), 0.0f);
-                ComputePanGains(target.Main, coeffs.data(), gain, (*mChans)[i].Target);
+                ComputePanGains(target.Main, coeffs, gain, (*mChans)[i].Target);
             }
         }
         else for(size_t i{0};i < chanmap.size();++i)
         {
             if(chanmap[i].channel == LFE) continue;
             const auto coeffs = CalcDirectionCoeffs(chanmap[i].pos, 0.0f);
-            ComputePanGains(target.Main, coeffs.data(), gain, (*mChans)[i].Target);
+            ComputePanGains(target.Main, coeffs, gain, (*mChans)[i].Target);
         }
     }
 }
diff --git a/alc/effects/dedicated.cpp b/alc/effects/dedicated.cpp
index e82b13d9..9ac68bec 100644
--- a/alc/effects/dedicated.cpp
+++ b/alc/effects/dedicated.cpp
@@ -97,7 +97,7 @@ void DedicatedState::update(const ContextBase*, const EffectSlot *slot,
             static constexpr auto coeffs = CalcDirectionCoeffs(std::array{0.0f, 0.0f, -1.0f});
 
             mOutTarget = target.Main->Buffer;
-            ComputePanGains(target.Main, coeffs.data(), Gain, mTargetGains);
+            ComputePanGains(target.Main, coeffs, Gain, mTargetGains);
         }
     }
 }
diff --git a/alc/effects/distortion.cpp b/alc/effects/distortion.cpp
index 392d81c8..3d77ff35 100644
--- a/alc/effects/distortion.cpp
+++ b/alc/effects/distortion.cpp
@@ -98,7 +98,7 @@ void DistortionState::update(const ContextBase *context, const EffectSlot *slot,
     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);
+    ComputePanGains(target.Main, coeffs, slot->Gain*props->Distortion.Gain, mGain);
 }
 
 void DistortionState::process(const size_t samplesToDo, const al::span<const FloatBufferLine> samplesIn, const al::span<FloatBufferLine> samplesOut)
diff --git a/alc/effects/echo.cpp b/alc/effects/echo.cpp
index 7824c246..714649c9 100644
--- a/alc/effects/echo.cpp
+++ b/alc/effects/echo.cpp
@@ -118,8 +118,8 @@ void EchoState::update(const ContextBase *context, const EffectSlot *slot,
     const auto coeffs1 = CalcAngleCoeffs( angle, 0.0f, 0.0f);
 
     mOutTarget = target.Main->Buffer;
-    ComputePanGains(target.Main, coeffs0.data(), slot->Gain, mGains[0].Target);
-    ComputePanGains(target.Main, coeffs1.data(), slot->Gain, mGains[1].Target);
+    ComputePanGains(target.Main, coeffs0, slot->Gain, mGains[0].Target);
+    ComputePanGains(target.Main, coeffs1, slot->Gain, mGains[1].Target);
 }
 
 void EchoState::process(const size_t samplesToDo, const al::span<const FloatBufferLine> samplesIn, const al::span<FloatBufferLine> samplesOut)
diff --git a/alc/effects/fshifter.cpp b/alc/effects/fshifter.cpp
index ec0cc29f..d3989e84 100644
--- a/alc/effects/fshifter.cpp
+++ b/alc/effects/fshifter.cpp
@@ -172,8 +172,8 @@ void FshifterState::update(const ContextBase *context, const EffectSlot *slot,
     auto &rcoeffs = (device->mRenderMode != RenderMode::Pairwise) ? rcoeffs_nrml : rcoeffs_pw;
 
     mOutTarget = target.Main->Buffer;
-    ComputePanGains(target.Main, lcoeffs.data(), slot->Gain, mGains[0].Target);
-    ComputePanGains(target.Main, rcoeffs.data(), slot->Gain, mGains[1].Target);
+    ComputePanGains(target.Main, lcoeffs, slot->Gain, mGains[0].Target);
+    ComputePanGains(target.Main, rcoeffs, slot->Gain, mGains[1].Target);
 }
 
 void FshifterState::process(const size_t samplesToDo, const al::span<const FloatBufferLine> samplesIn, const al::span<FloatBufferLine> samplesOut)
diff --git a/alc/effects/pshifter.cpp b/alc/effects/pshifter.cpp
index 2460cf78..95269009 100644
--- a/alc/effects/pshifter.cpp
+++ b/alc/effects/pshifter.cpp
@@ -145,7 +145,7 @@ void PshifterState::update(const ContextBase*, const EffectSlot *slot,
     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);
+    ComputePanGains(target.Main, coeffs, slot->Gain, mTargetGains);
 }
 
 void PshifterState::process(const size_t samplesToDo,
diff --git a/alc/effects/reverb.cpp b/alc/effects/reverb.cpp
index b00f638b..9727f400 100644
--- a/alc/effects/reverb.cpp
+++ b/alc/effects/reverb.cpp
@@ -1108,9 +1108,9 @@ void ReverbPipeline::update3DPanning(const al::span<const float,3> ReflectionsPa
         auto latecoeffs = mult_matrix(latemat);
 
         for(size_t i{0u};i < NUM_LINES;i++)
-            ComputePanGains(mainMix, earlycoeffs[i].data(), earlyGain, mEarly.TargetGains[i]);
+            ComputePanGains(mainMix, earlycoeffs[i], earlyGain, mEarly.TargetGains[i]);
         for(size_t i{0u};i < NUM_LINES;i++)
-            ComputePanGains(mainMix, latecoeffs[i].data(), lateGain, mLate.TargetGains[i]);
+            ComputePanGains(mainMix, latecoeffs[i], lateGain, mLate.TargetGains[i]);
     }
     else
     {
@@ -1140,9 +1140,9 @@ void ReverbPipeline::update3DPanning(const al::span<const float,3> ReflectionsPa
         auto latecoeffs = mult_matrix(LateA2B, latemat);
 
         for(size_t i{0u};i < NUM_LINES;i++)
-            ComputePanGains(mainMix, earlycoeffs[i].data(), earlyGain, mEarly.TargetGains[i]);
+            ComputePanGains(mainMix, earlycoeffs[i], earlyGain, mEarly.TargetGains[i]);
         for(size_t i{0u};i < NUM_LINES;i++)
-            ComputePanGains(mainMix, latecoeffs[i].data(), lateGain, mLate.TargetGains[i]);
+            ComputePanGains(mainMix, latecoeffs[i], lateGain, mLate.TargetGains[i]);
     }
 }
 
diff --git a/core/mixer.cpp b/core/mixer.cpp
index 066c57bd..806ac8b8 100644
--- a/core/mixer.cpp
+++ b/core/mixer.cpp
@@ -82,14 +82,13 @@ std::array<float,MaxAmbiChannels> CalcAmbiCoeffs(const float y, const float z, c
     return coeffs;
 }
 
-void ComputePanGains(const MixParams *mix, const float*RESTRICT coeffs, const float ingain,
-    const al::span<float,MaxAmbiChannels> gains)
+void ComputePanGains(const MixParams *mix, const al::span<const float,MaxAmbiChannels> coeffs,
+    const float ingain, const al::span<float,MaxAmbiChannels> gains)
 {
     auto ambimap = mix->AmbiMap.cbegin();
 
     auto iter = std::transform(ambimap, ambimap+mix->Buffer.size(), gains.begin(),
         [coeffs,ingain](const BFChannelConfig &chanmap) noexcept -> float
-        { return chanmap.Scale * coeffs[chanmap.Index] * ingain; }
-    );
+        { return chanmap.Scale * coeffs[chanmap.Index] * ingain; });
     std::fill(iter, gains.end(), 0.0f);
 }
diff --git a/core/mixer.h b/core/mixer.h
index a9c1f931..9062ebac 100644
--- a/core/mixer.h
+++ b/core/mixer.h
@@ -103,7 +103,7 @@ inline std::array<float,MaxAmbiChannels> CalcAngleCoeffs(const float azimuth,
  * coeffs are a 'slice' of a transform matrix for the input channel, used to
  * scale and orient the sound samples.
  */
-void ComputePanGains(const MixParams *mix, const float*RESTRICT coeffs, const float ingain,
-    const al::span<float,MaxAmbiChannels> gains);
+void ComputePanGains(const MixParams *mix, const al::span<const float,MaxAmbiChannels> coeffs,
+    const float ingain, const al::span<float,MaxAmbiChannels> gains);
 
 #endif /* CORE_MIXER_H */
-- 
cgit v1.2.3