aboutsummaryrefslogtreecommitdiffstats
path: root/Alc
diff options
context:
space:
mode:
authorChris Robinson <[email protected]>2017-02-23 00:23:16 -0800
committerChris Robinson <[email protected]>2017-02-23 01:32:44 -0800
commit08948079e93cbb7321be5715df36f54c5e6be3b7 (patch)
tree5901fce0305094cc843698671c2689208e2f8df5 /Alc
parent0ce4c9b8fa90df6111fb81debf583b0fc9200063 (diff)
Alter how panpot/pair-wise panning works
This change allows pair-wise panning to mostly go through the normal ambisonic panning methods, with one special-case. First, a term is added to the stereo decoder matrix's X coefficient so that a centered sound is reduced by -3dB on each output channel. Panning in front creates a similar gain response to the typical L = sqrt(1-pan) R = sqrt(pan) for pan = [0,1]. Panning behind the listener can reduce (up to) an additional -10dB, creating a audible difference between front and back sounds as if simulating head obstruction. Secondly, as a special-case, the source positions are warped when calculating the ambisonic coefficients so that full left panning is reached at -30 degrees and full right at +30 degrees. This is to retain the expected 60-degree stereo width. This warping does not apply to B-Format buffer input, although it otherwise has the same gain responses.
Diffstat (limited to 'Alc')
-rw-r--r--Alc/ALu.c38
-rw-r--r--Alc/panning.c16
2 files changed, 22 insertions, 32 deletions
diff --git a/Alc/ALu.c b/Alc/ALu.c
index bc48dd59..5a5e6fdf 100644
--- a/Alc/ALu.c
+++ b/Alc/ALu.c
@@ -679,23 +679,12 @@ static void CalcNonAttnSourceParams(ALvoice *voice, const struct ALsourceProps *
}
if(Device->Render_Mode == StereoPair)
- {
- /* Clamp X so it remains within 30 degrees of 0 or 180 degree azimuth. */
- ALfloat x = sinf(chans[c].angle) * cosf(chans[c].elevation);
- coeffs[0] = clampf(-x, -0.5f, 0.5f) + 0.5f;
- voice->Direct.Params[c].Gains.Target[0] = sqrtf(coeffs[0]) * DryGain;
- voice->Direct.Params[c].Gains.Target[1] = sqrtf(1.0f-coeffs[0]) * DryGain;
- for(j = 2;j < MAX_OUTPUT_CHANNELS;j++)
- voice->Direct.Params[c].Gains.Target[j] = 0.0f;
-
- CalcAngleCoeffs(chans[c].angle, chans[c].elevation, 0.0f, coeffs);
- }
+ CalcAnglePairwiseCoeffs(chans[c].angle, chans[c].elevation, 0.0f, coeffs);
else
- {
CalcAngleCoeffs(chans[c].angle, chans[c].elevation, 0.0f, coeffs);
- ComputePanningGains(Device->Dry, coeffs, DryGain,
- voice->Direct.Params[c].Gains.Target);
- }
+ ComputePanningGains(Device->Dry,
+ coeffs, DryGain, voice->Direct.Params[c].Gains.Target
+ );
for(i = 0;i < NumSends;i++)
{
@@ -1173,22 +1162,15 @@ static void CalcAttnSourceParams(ALvoice *voice, const struct ALsourceProps *pro
if(Device->Render_Mode == StereoPair)
{
- /* Clamp X so it remains within 30 degrees of 0 or 180 degree azimuth. */
- ALfloat x = -dir[0] * (0.5f * (cosf(spread*0.5f) + 1.0f));
- x = clampf(x, -0.5f, 0.5f) + 0.5f;
- voice->Direct.Params[0].Gains.Target[0] = sqrtf(x) * DryGain;
- voice->Direct.Params[0].Gains.Target[1] = sqrtf(1.0f-x) * DryGain;
- for(i = 2;i < MAX_OUTPUT_CHANNELS;i++)
- voice->Direct.Params[0].Gains.Target[i] = 0.0f;
-
- CalcDirectionCoeffs(dir, spread, coeffs);
+ ALfloat ev = asinf(clampf(dir[1], -1.0f, 1.0f));
+ ALfloat az = atan2f(dir[0], -dir[2]);
+ CalcAnglePairwiseCoeffs(az, ev, radius, coeffs);
}
else
- {
CalcDirectionCoeffs(dir, spread, coeffs);
- ComputePanningGains(Device->Dry, coeffs, DryGain,
- voice->Direct.Params[0].Gains.Target);
- }
+ ComputePanningGains(Device->Dry,
+ coeffs, DryGain, voice->Direct.Params[0].Gains.Target
+ );
for(i = 0;i < NumSends;i++)
{
diff --git a/Alc/panning.c b/Alc/panning.c
index 72b55792..7b551100 100644
--- a/Alc/panning.c
+++ b/Alc/panning.c
@@ -202,6 +202,14 @@ void CalcAngleCoeffs(ALfloat azimuth, ALfloat elevation, ALfloat spread, ALfloat
CalcDirectionCoeffs(dir, spread, coeffs);
}
+void CalcAnglePairwiseCoeffs(ALfloat azimuth, ALfloat elevation, ALfloat spread, ALfloat coeffs[MAX_AMBI_COEFFS])
+{
+ ALfloat sign = (azimuth < 0.0f) ? -1.0f : 1.0f;
+ if(!(fabsf(azimuth) > F_PI_2))
+ azimuth = minf(fabsf(azimuth) * F_PI_2 / (F_PI/6.0f), F_PI_2) * sign;
+ CalcAngleCoeffs(azimuth, elevation, spread, coeffs);
+}
+
void ComputeAmbientGainsMC(const ChannelConfig *chancoeffs, ALsizei numchans, ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS])
{
@@ -237,7 +245,7 @@ void ComputePanningGainsMC(const ChannelConfig *chancoeffs, ALsizei numchans, AL
float gain = 0.0f;
for(j = 0;j < numcoeffs;j++)
gain += chancoeffs[i][j]*coeffs[j];
- gains[i] = gain * ingain;
+ gains[i] = clampf(gain, 0.0f, 1.0f) * ingain;
}
for(;i < MAX_OUTPUT_CHANNELS;i++)
gains[i] = 0.0f;
@@ -262,7 +270,7 @@ void ComputeFirstOrderGainsMC(const ChannelConfig *chancoeffs, ALsizei numchans,
float gain = 0.0f;
for(j = 0;j < 4;j++)
gain += chancoeffs[i][j] * mtx[j];
- gains[i] = gain * ingain;
+ gains[i] = clampf(gain, 0.0f, 1.0f) * ingain;
}
for(;i < MAX_OUTPUT_CHANNELS;i++)
gains[i] = 0.0f;
@@ -454,8 +462,8 @@ static bool MakeSpeakerMap(ALCdevice *device, const AmbDecConf *conf, ALsizei sp
static const ChannelMap MonoCfg[1] = {
{ FrontCenter, { 1.0f } },
}, StereoCfg[2] = {
- { FrontLeft, { 5.00000000e-1f, 2.88675135e-1f, 0.0f, 0.00000000e+0f } },
- { FrontRight, { 5.00000000e-1f, -2.88675135e-1f, 0.0f, 0.00000000e+0f } },
+ { FrontLeft, { 5.00000000e-1f, 2.88675135e-1f, 0.0f, 1.19573156e-1f } },
+ { FrontRight, { 5.00000000e-1f, -2.88675135e-1f, 0.0f, 1.19573156e-1f } },
}, QuadCfg[4] = {
{ BackLeft, { 3.53553391e-1f, 2.04124145e-1f, 0.0f, -2.04124145e-1f } },
{ FrontLeft, { 3.53553391e-1f, 2.04124145e-1f, 0.0f, 2.04124145e-1f } },