summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Robinson <[email protected]>2014-10-02 18:05:42 -0700
committerChris Robinson <[email protected]>2014-10-02 18:05:42 -0700
commit95ba18cf4e52c439b85ece2daf0b404fa69c7b70 (patch)
tree2367b5d69488633fb8d596cf3e3b328d81b2753f
parent9377d0f23730ff0d42a870627ea9a75059c481f4 (diff)
Make ComputeAngleGains use ComputeDirectionalGains
-rw-r--r--Alc/ALu.c119
-rw-r--r--Alc/effects/chorus.c6
-rw-r--r--Alc/effects/dedicated.c30
-rw-r--r--Alc/effects/echo.c14
-rw-r--r--Alc/effects/flanger.c6
-rw-r--r--Alc/effects/reverb.c62
-rw-r--r--Alc/panning.c230
-rw-r--r--OpenAL32/Include/alMain.h1
-rw-r--r--OpenAL32/Include/alu.h10
9 files changed, 182 insertions, 296 deletions
diff --git a/Alc/ALu.c b/Alc/ALu.c
index 119d6ed4..564ab133 100644
--- a/Alc/ALu.c
+++ b/Alc/ALu.c
@@ -45,6 +45,7 @@ static_assert((INT_MAX>>FRACTIONBITS)/MAX_PITCH > BUFFERSIZE,
struct ChanMap {
enum Channel channel;
ALfloat angle;
+ ALfloat elevation;
};
/* Cone scalar */
@@ -231,51 +232,51 @@ static ALvoid CalcListenerParams(ALlistener *Listener)
ALvoid CalcNonAttnSourceParams(ALvoice *voice, const ALsource *ALSource, const ALCcontext *ALContext)
{
- static const struct ChanMap MonoMap[1] = { { FrontCenter, 0.0f } };
+ static const struct ChanMap MonoMap[1] = { { FrontCenter, 0.0f, 0.0f } };
static const struct ChanMap StereoMap[2] = {
- { FrontLeft, DEG2RAD(-30.0f) },
- { FrontRight, DEG2RAD( 30.0f) }
+ { FrontLeft, DEG2RAD(-30.0f), DEG2RAD(0.0f) },
+ { FrontRight, DEG2RAD( 30.0f), DEG2RAD(0.0f) }
};
static const struct ChanMap StereoWideMap[2] = {
- { FrontLeft, DEG2RAD(-90.0f) },
- { FrontRight, DEG2RAD( 90.0f) }
+ { FrontLeft, DEG2RAD(-90.0f), DEG2RAD(0.0f) },
+ { FrontRight, DEG2RAD( 90.0f), DEG2RAD(0.0f) }
};
static const struct ChanMap RearMap[2] = {
- { BackLeft, DEG2RAD(-150.0f) },
- { BackRight, DEG2RAD( 150.0f) }
+ { BackLeft, DEG2RAD(-150.0f), DEG2RAD(0.0f) },
+ { BackRight, DEG2RAD( 150.0f), DEG2RAD(0.0f) }
};
static const struct ChanMap QuadMap[4] = {
- { FrontLeft, DEG2RAD( -45.0f) },
- { FrontRight, DEG2RAD( 45.0f) },
- { BackLeft, DEG2RAD(-135.0f) },
- { BackRight, DEG2RAD( 135.0f) }
+ { 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) }
};
static const struct ChanMap X51Map[6] = {
- { FrontLeft, DEG2RAD( -30.0f) },
- { FrontRight, DEG2RAD( 30.0f) },
- { FrontCenter, DEG2RAD( 0.0f) },
- { LFE, 0.0f },
- { BackLeft, DEG2RAD(-110.0f) },
- { BackRight, DEG2RAD( 110.0f) }
+ { 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(-110.0f), DEG2RAD(0.0f) },
+ { BackRight, DEG2RAD( 110.0f), DEG2RAD(0.0f) }
};
static const struct ChanMap X61Map[7] = {
- { FrontLeft, DEG2RAD(-30.0f) },
- { FrontRight, DEG2RAD( 30.0f) },
- { FrontCenter, DEG2RAD( 0.0f) },
- { LFE, 0.0f },
- { BackCenter, DEG2RAD(180.0f) },
- { SideLeft, DEG2RAD(-90.0f) },
- { SideRight, DEG2RAD( 90.0f) }
+ { 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) }
};
static const struct ChanMap X71Map[8] = {
- { FrontLeft, DEG2RAD( -30.0f) },
- { FrontRight, DEG2RAD( 30.0f) },
- { FrontCenter, DEG2RAD( 0.0f) },
- { LFE, 0.0f },
- { BackLeft, DEG2RAD(-150.0f) },
- { BackRight, DEG2RAD( 150.0f) },
- { SideLeft, DEG2RAD( -90.0f) },
- { SideRight, DEG2RAD( 90.0f) }
+ { 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) }
};
ALCdevice *Device = ALContext->Device;
@@ -290,7 +291,6 @@ ALvoid CalcNonAttnSourceParams(ALvoice *voice, const ALsource *ALSource, const A
const struct ChanMap *chans = NULL;
ALint num_channels = 0;
ALboolean DirectChannels;
- ALfloat hwidth = 0.0f;
ALfloat Pitch;
ALint i, j, c;
@@ -365,21 +365,13 @@ ALvoid CalcNonAttnSourceParams(ALvoice *voice, const ALsource *ALSource, const A
break;
case FmtStereo:
- if(!(Device->Flags&DEVICE_WIDE_STEREO))
- {
- /* HACK: Place the stereo channels at +/-90 degrees when using non-
- * HRTF stereo output. This helps reduce the "monoization" caused
- * by them panning towards the center. */
- if(Device->FmtChans == DevFmtStereo && !Device->Hrtf)
- chans = StereoWideMap;
- else
- chans = StereoMap;
- }
- else
- {
+ /* HACK: Place the stereo channels at +/-90 degrees when using non-
+ * HRTF stereo output. This helps reduce the "monoization" caused
+ * by them panning towards the center. */
+ if(Device->FmtChans == DevFmtStereo && !Device->Hrtf)
chans = StereoWideMap;
- hwidth = DEG2RAD(60.0f);
- }
+ else
+ chans = StereoMap;
num_channels = 2;
break;
@@ -451,7 +443,7 @@ ALvoid CalcNonAttnSourceParams(ALvoice *voice, const ALsource *ALSource, const A
/* Get the static HRIR coefficients and delays for this
* channel. */
GetLerpedHrtfCoeffs(Device->Hrtf,
- 0.0f, chans[c].angle, 1.0f, DryGain,
+ chans[c].elevation, chans[c].angle, 1.0f, DryGain,
voice->Direct.Mix.Hrtf.Params[c].Coeffs,
voice->Direct.Mix.Hrtf.Params[c].Delay);
}
@@ -464,21 +456,40 @@ ALvoid CalcNonAttnSourceParams(ALvoice *voice, const ALsource *ALSource, const A
}
else
{
- DryGain *= lerp(1.0f, 1.0f/sqrtf((float)Device->NumSpeakers), hwidth/F_PI);
for(c = 0;c < num_channels;c++)
{
MixGains *gains = voice->Direct.Mix.Gains[c];
ALfloat Target[MaxChannels];
+ bool ok = false;
/* Special-case LFE */
if(chans[c].channel == LFE)
{
- for(j = 0;j < MaxChannels;j++)
- gains[j].Target = 0.0f;
- gains[chans[c].channel].Target = DryGain;
- continue;
+ for(i = 0;i < MaxChannels;i++)
+ Target[i] = 0.0f;
+ Target[chans[c].channel] = DryGain;
+ ok = true;
}
- ComputeAngleGains(Device, chans[c].angle, hwidth, DryGain, Target);
+ else for(i = 0;i < (ALint)Device->NumSpeakers;i++)
+ {
+ /* Attempt to match the input channel to an output based on its
+ * location. */
+ if(Device->Speaker[i].Angle == chans[c].angle &&
+ Device->Speaker[i].Elevation == chans[c].elevation)
+ {
+ for(j = 0;j < MaxChannels;j++)
+ Target[j] = 0.0f;
+ Target[Device->Speaker[i].ChanName] = DryGain;
+ ok = true;
+ break;
+ }
+ }
+ if(!ok)
+ {
+ /* All else fails, virtualize it. */
+ ComputeAngleGains(Device, chans[c].angle, chans[c].elevation, DryGain, Target);
+ }
+
for(i = 0;i < MaxChannels;i++)
gains[i].Target = Target[i];
}
diff --git a/Alc/effects/chorus.c b/Alc/effects/chorus.c
index ad45c785..6e541208 100644
--- a/Alc/effects/chorus.c
+++ b/Alc/effects/chorus.c
@@ -93,6 +93,8 @@ static ALboolean ALchorusState_deviceUpdate(ALchorusState *state, ALCdevice *Dev
static ALvoid ALchorusState_update(ALchorusState *state, ALCdevice *Device, const ALeffectslot *Slot)
{
+ static const ALfloat left_dir[3] = { -1.0f, 0.0f, 0.0f };
+ static const ALfloat right_dir[3] = { 1.0f, 0.0f, 0.0f };
ALfloat frequency = (ALfloat)Device->Frequency;
ALfloat rate;
ALint phase;
@@ -111,8 +113,8 @@ static ALvoid ALchorusState_update(ALchorusState *state, ALCdevice *Device, cons
state->delay = fastf2i(Slot->EffectProps.Chorus.Delay * frequency);
/* Gains for left and right sides */
- ComputeAngleGains(Device, atan2f(-1.0f, 0.0f), 0.0f, Slot->Gain, state->Gain[0]);
- ComputeAngleGains(Device, atan2f(+1.0f, 0.0f), 0.0f, Slot->Gain, state->Gain[1]);
+ ComputeDirectionalGains(Device, left_dir, Slot->Gain, state->Gain[0]);
+ ComputeDirectionalGains(Device, right_dir, Slot->Gain, state->Gain[1]);
phase = Slot->EffectProps.Chorus.Phase;
rate = Slot->EffectProps.Chorus.Rate;
diff --git a/Alc/effects/dedicated.c b/Alc/effects/dedicated.c
index 0907d6b0..ea028046 100644
--- a/Alc/effects/dedicated.c
+++ b/Alc/effects/dedicated.c
@@ -48,16 +48,32 @@ static ALboolean ALdedicatedState_deviceUpdate(ALdedicatedState *UNUSED(state),
static ALvoid ALdedicatedState_update(ALdedicatedState *state, ALCdevice *device, const ALeffectslot *Slot)
{
ALfloat Gain;
- ALsizei s;
+ ALuint i;
+
+ for(i = 0;i < MaxChannels;i++)
+ state->gains[i] = 0.0f;
Gain = Slot->Gain * Slot->EffectProps.Dedicated.Gain;
- if(Slot->EffectType == AL_EFFECT_DEDICATED_DIALOGUE)
- ComputeAngleGains(device, atan2f(0.0f, 1.0f), 0.0f, Gain, state->gains);
- else if(Slot->EffectType == AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT)
- {
- for(s = 0;s < MaxChannels;s++)
- state->gains[s] = 0.0f;
+ if(Slot->EffectType == AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT)
state->gains[LFE] = Gain;
+ else if(Slot->EffectType == AL_EFFECT_DEDICATED_DIALOGUE)
+ {
+ ALboolean done = AL_FALSE;
+ /* Dialog goes to the front-center speaker if it exists, otherwise it
+ * plays from the front-center location. */
+ for(i = 0;i < device->NumSpeakers;i++)
+ {
+ if(device->Speaker[i].ChanName == FrontCenter)
+ {
+ state->gains[FrontCenter] = Gain;
+ done = AL_TRUE;
+ }
+ }
+ if(!done)
+ {
+ static const ALfloat front_dir[3] = { 0.0f, 0.0f, -1.0f };
+ ComputeDirectionalGains(device, front_dir, Gain, state->gains);
+ }
}
}
diff --git a/Alc/effects/echo.c b/Alc/effects/echo.c
index 17b7269b..69d9b84f 100644
--- a/Alc/effects/echo.c
+++ b/Alc/effects/echo.c
@@ -83,9 +83,10 @@ static ALboolean ALechoState_deviceUpdate(ALechoState *state, ALCdevice *Device)
static ALvoid ALechoState_update(ALechoState *state, ALCdevice *Device, const ALeffectslot *Slot)
{
+ ALfloat pandir[3] = { 0.0f, 0.0f, 0.0f };
ALuint frequency = Device->Frequency;
- ALfloat lrpan, gain;
- ALfloat dirGain;
+ ALfloat gain = Slot->Gain;
+ ALfloat lrpan;
state->Tap[0].delay = fastf2u(Slot->EffectProps.Echo.Delay * frequency) + 1;
state->Tap[1].delay = fastf2u(Slot->EffectProps.Echo.LRDelay * frequency);
@@ -99,14 +100,13 @@ static ALvoid ALechoState_update(ALechoState *state, ALCdevice *Device, const AL
1.0f - Slot->EffectProps.Echo.Damping,
LOWPASSFREQREF/frequency, 0.0f);
- gain = Slot->Gain;
- dirGain = fabsf(lrpan);
-
/* First tap panning */
- ComputeAngleGains(Device, atan2f(-lrpan, 0.0f), (1.0f-dirGain)*F_PI, gain, state->Gain[0]);
+ pandir[0] = -lrpan;
+ ComputeDirectionalGains(Device, pandir, gain, state->Gain[0]);
/* Second tap panning */
- ComputeAngleGains(Device, atan2f(+lrpan, 0.0f), (1.0f-dirGain)*F_PI, gain, state->Gain[1]);
+ pandir[0] = +lrpan;
+ ComputeDirectionalGains(Device, pandir, gain, state->Gain[1]);
}
static ALvoid ALechoState_process(ALechoState *state, ALuint SamplesToDo, const ALfloat *restrict SamplesIn, ALfloat (*restrict SamplesOut)[BUFFERSIZE])
diff --git a/Alc/effects/flanger.c b/Alc/effects/flanger.c
index 6395f4bf..a38b3b13 100644
--- a/Alc/effects/flanger.c
+++ b/Alc/effects/flanger.c
@@ -93,6 +93,8 @@ static ALboolean ALflangerState_deviceUpdate(ALflangerState *state, ALCdevice *D
static ALvoid ALflangerState_update(ALflangerState *state, ALCdevice *Device, const ALeffectslot *Slot)
{
+ static const ALfloat left_dir[3] = { -1.0f, 0.0f, 0.0f };
+ static const ALfloat right_dir[3] = { 1.0f, 0.0f, 0.0f };
ALfloat frequency = (ALfloat)Device->Frequency;
ALfloat rate;
ALint phase;
@@ -111,8 +113,8 @@ static ALvoid ALflangerState_update(ALflangerState *state, ALCdevice *Device, co
state->delay = fastf2i(Slot->EffectProps.Flanger.Delay * frequency);
/* Gains for left and right sides */
- ComputeAngleGains(Device, atan2f(-1.0f, 0.0f), 0.0f, Slot->Gain, state->Gain[0]);
- ComputeAngleGains(Device, atan2f(+1.0f, 0.0f), 0.0f, Slot->Gain, state->Gain[1]);
+ ComputeDirectionalGains(Device, left_dir, Slot->Gain, state->Gain[0]);
+ ComputeDirectionalGains(Device, right_dir, Slot->Gain, state->Gain[1]);
phase = Slot->EffectProps.Flanger.Phase;
rate = Slot->EffectProps.Flanger.Rate;
diff --git a/Alc/effects/reverb.c b/Alc/effects/reverb.c
index 1e9cd550..8c17076a 100644
--- a/Alc/effects/reverb.c
+++ b/Alc/effects/reverb.c
@@ -1031,44 +1031,54 @@ static ALvoid UpdateEchoLine(ALfloat reverbGain, ALfloat lateGain, ALfloat echoT
// Update the early and late 3D panning gains.
static ALvoid Update3DPanning(const ALCdevice *Device, const ALfloat *ReflectionsPan, const ALfloat *LateReverbPan, ALfloat Gain, ALreverbState *State)
{
- ALfloat earlyPan[3] = { ReflectionsPan[0], ReflectionsPan[1],
- ReflectionsPan[2] };
- ALfloat latePan[3] = { LateReverbPan[0], LateReverbPan[1],
- LateReverbPan[2] };
+ ALfloat earlyPan[3] = { ReflectionsPan[0], ReflectionsPan[1], ReflectionsPan[2] };
+ ALfloat latePan[3] = { LateReverbPan[0], LateReverbPan[1], LateReverbPan[2] };
+ ALfloat earlyLen = 0.0f;
+ ALfloat lateLen = 0.0f;
+ ALfloat length, invlen;
ALfloat ambientGain;
- ALfloat dirGain;
- ALfloat length;
+ ALuint i;
Gain *= ReverbBoost;
- /* Attenuate reverb according to its coverage (dirGain=0 will give
- * Gain*ambientGain, and dirGain=1 will give Gain). */
- ambientGain = minf(sqrtf(2.0f/Device->NumSpeakers), 1.0f);
+ /* Attenuate reverb according to its coverage (len=0 will give
+ * ambientGain, and len>=1 will be fully panned using Gain). */
+ ambientGain = minf(sqrtf(2.0f/Device->NumSpeakers), 1.0f) * Gain;
length = earlyPan[0]*earlyPan[0] + earlyPan[1]*earlyPan[1] + earlyPan[2]*earlyPan[2];
- if(length > 1.0f)
+ if(length > FLT_EPSILON)
{
- length = 1.0f / sqrtf(length);
- earlyPan[0] *= length;
- earlyPan[1] *= length;
- earlyPan[2] *= length;
+ length = sqrtf(length);
+
+ invlen = 1.0f / length;
+ earlyPan[0] *= invlen;
+ earlyPan[1] *= invlen;
+ earlyPan[2] *= invlen;
+
+ earlyLen = minf(1.0f, length);
+ ComputeDirectionalGains(Device, earlyPan, Gain, State->Early.PanGain);
}
+
length = latePan[0]*latePan[0] + latePan[1]*latePan[1] + latePan[2]*latePan[2];
- if(length > 1.0f)
+ if(length > FLT_EPSILON)
{
- length = 1.0f / sqrtf(length);
- latePan[0] *= length;
- latePan[1] *= length;
- latePan[2] *= length;
- }
+ length = sqrtf(length);
- dirGain = sqrtf(earlyPan[0]*earlyPan[0] + earlyPan[2]*earlyPan[2]);
- ComputeAngleGains(Device, atan2f(earlyPan[0], earlyPan[2]), (1.0f-dirGain)*F_PI,
- lerp(ambientGain, 1.0f, dirGain) * Gain, State->Early.PanGain);
+ invlen = 1.0f / length;
+ latePan[0] *= invlen;
+ latePan[1] *= invlen;
+ latePan[2] *= invlen;
- dirGain = sqrtf(latePan[0]*latePan[0] + latePan[2]*latePan[2]);
- ComputeAngleGains(Device, atan2f(latePan[0], latePan[2]), (1.0f-dirGain)*F_PI,
- lerp(ambientGain, 1.0f, dirGain) * Gain, State->Late.PanGain);
+ lateLen = minf(1.0f, length);
+ ComputeDirectionalGains(Device, latePan, Gain, State->Late.PanGain);
+ }
+
+ for(i = 0;i < Device->NumSpeakers;i++)
+ {
+ enum Channel chan = Device->Speaker[i].ChanName;
+ State->Early.PanGain[chan] = lerp(ambientGain, State->Early.PanGain[chan], earlyLen);
+ State->Late.PanGain[chan] = lerp(ambientGain, State->Late.PanGain[chan], lateLen);
+ }
}
static ALvoid ALreverbState_update(ALreverbState *State, ALCdevice *Device, const ALeffectslot *Slot)
diff --git a/Alc/panning.c b/Alc/panning.c
index d0c89071..d775b746 100644
--- a/Alc/panning.c
+++ b/Alc/panning.c
@@ -81,200 +81,14 @@ static inline void Set3rdOrder(ALfloat coeffs[16], ALfloat w, ALfloat x, ALfloat
}
-void ComputeAngleGains(const ALCdevice *device, ALfloat angle, ALfloat hwidth, ALfloat ingain, ALfloat gains[MaxChannels])
+void ComputeAngleGains(const ALCdevice *device, ALfloat angle, ALfloat elevation, ALfloat ingain, ALfloat gains[MaxChannels])
{
- ALfloat tmpgains[MaxChannels] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f };
- enum Channel Speaker2Chan[MaxChannels];
- ALfloat SpeakerAngle[MaxChannels];
- ALfloat langle, rangle;
- ALfloat a;
- ALuint i;
-
- for(i = 0;i < device->NumSpeakers;i++)
- Speaker2Chan[i] = device->Speaker[i].ChanName;
- for(i = 0;i < device->NumSpeakers;i++)
- SpeakerAngle[i] = device->Speaker[i].Angle;
-
- for(i = 0;i < MaxChannels;i++)
- gains[i] = 0.0f;
-
- /* Some easy special-cases first... */
- if(device->NumSpeakers <= 1 || hwidth >= F_PI)
- {
- /* Full coverage for all speakers. */
- for(i = 0;i < device->NumSpeakers;i++)
- {
- enum Channel chan = Speaker2Chan[i];
- gains[chan] = ingain;
- }
- return;
- }
- if(hwidth <= 0.0f)
- {
- /* Infinitely small sound point. */
- for(i = 0;i < device->NumSpeakers-1;i++)
- {
- if(angle >= SpeakerAngle[i] && angle < SpeakerAngle[i+1])
- {
- /* Sound is between speakers i and i+1 */
- a = (angle-SpeakerAngle[i]) /
- (SpeakerAngle[i+1]-SpeakerAngle[i]);
- gains[Speaker2Chan[i]] = sqrtf(1.0f-a) * ingain;
- gains[Speaker2Chan[i+1]] = sqrtf( a) * ingain;
- return;
- }
- }
- /* Sound is between last and first speakers */
- if(angle < SpeakerAngle[0])
- angle += F_2PI;
- a = (angle-SpeakerAngle[i]) /
- (F_2PI + SpeakerAngle[0]-SpeakerAngle[i]);
- gains[Speaker2Chan[i]] = sqrtf(1.0f-a) * ingain;
- gains[Speaker2Chan[0]] = sqrtf( a) * ingain;
- return;
- }
-
- if(fabsf(angle)+hwidth > F_PI)
- {
- /* The coverage area would go outside of -pi...+pi. Instead, rotate the
- * speaker angles so it would be as if angle=0, and keep them wrapped
- * within -pi...+pi. */
- if(angle > 0.0f)
- {
- ALuint done;
- ALuint i = 0;
- while(i < device->NumSpeakers && device->Speaker[i].Angle-angle < -F_PI)
- i++;
- for(done = 0;i < device->NumSpeakers;done++)
- {
- SpeakerAngle[done] = device->Speaker[i].Angle-angle;
- Speaker2Chan[done] = device->Speaker[i].ChanName;
- i++;
- }
- for(i = 0;done < device->NumSpeakers;i++)
- {
- SpeakerAngle[done] = device->Speaker[i].Angle-angle + F_2PI;
- Speaker2Chan[done] = device->Speaker[i].ChanName;
- done++;
- }
- }
- else
- {
- /* NOTE: '< device->NumChan' on the iterators is correct here since
- * we need to handle index 0. Because the iterators are unsigned,
- * they'll underflow and wrap to become 0xFFFFFFFF, which will
- * break as expected. */
- ALuint done;
- ALuint i = device->NumSpeakers-1;
- while(i < device->NumSpeakers && device->Speaker[i].Angle-angle > F_PI)
- i--;
- for(done = device->NumSpeakers-1;i < device->NumSpeakers;done--)
- {
- SpeakerAngle[done] = device->Speaker[i].Angle-angle;
- Speaker2Chan[done] = device->Speaker[i].ChanName;
- i--;
- }
- for(i = device->NumSpeakers-1;done < device->NumSpeakers;i--)
- {
- SpeakerAngle[done] = device->Speaker[i].Angle-angle - F_2PI;
- Speaker2Chan[done] = device->Speaker[i].ChanName;
- done--;
- }
- }
- angle = 0.0f;
- }
- langle = angle - hwidth;
- rangle = angle + hwidth;
-
- /* First speaker */
- i = 0;
- do {
- ALuint last = device->NumSpeakers-1;
- enum Channel chan = Speaker2Chan[i];
-
- if(SpeakerAngle[i] >= langle && SpeakerAngle[i] <= rangle)
- {
- tmpgains[chan] = 1.0f;
- continue;
- }
-
- if(SpeakerAngle[i] < langle && SpeakerAngle[i+1] > langle)
- {
- a = (langle-SpeakerAngle[i]) /
- (SpeakerAngle[i+1]-SpeakerAngle[i]);
- tmpgains[chan] = lerp(tmpgains[chan], 1.0f, 1.0f-a);
- }
- if(SpeakerAngle[i] > rangle)
- {
- a = (F_2PI + rangle-SpeakerAngle[last]) /
- (F_2PI + SpeakerAngle[i]-SpeakerAngle[last]);
- tmpgains[chan] = lerp(tmpgains[chan], 1.0f, a);
- }
- else if(SpeakerAngle[last] < rangle)
- {
- a = (rangle-SpeakerAngle[last]) /
- (F_2PI + SpeakerAngle[i]-SpeakerAngle[last]);
- tmpgains[chan] = lerp(tmpgains[chan], 1.0f, a);
- }
- } while(0);
-
- for(i = 1;i < device->NumSpeakers-1;i++)
- {
- enum Channel chan = Speaker2Chan[i];
- if(SpeakerAngle[i] >= langle && SpeakerAngle[i] <= rangle)
- {
- tmpgains[chan] = 1.0f;
- continue;
- }
-
- if(SpeakerAngle[i] < langle && SpeakerAngle[i+1] > langle)
- {
- a = (langle-SpeakerAngle[i]) /
- (SpeakerAngle[i+1]-SpeakerAngle[i]);
- tmpgains[chan] = lerp(tmpgains[chan], 1.0f, 1.0f-a);
- }
- if(SpeakerAngle[i] > rangle && SpeakerAngle[i-1] < rangle)
- {
- a = (rangle-SpeakerAngle[i-1]) /
- (SpeakerAngle[i]-SpeakerAngle[i-1]);
- tmpgains[chan] = lerp(tmpgains[chan], 1.0f, a);
- }
- }
-
- /* Last speaker */
- i = device->NumSpeakers-1;
- do {
- enum Channel chan = Speaker2Chan[i];
- if(SpeakerAngle[i] >= langle && SpeakerAngle[i] <= rangle)
- {
- tmpgains[Speaker2Chan[i]] = 1.0f;
- continue;
- }
- if(SpeakerAngle[i] > rangle && SpeakerAngle[i-1] < rangle)
- {
- a = (rangle-SpeakerAngle[i-1]) /
- (SpeakerAngle[i]-SpeakerAngle[i-1]);
- tmpgains[chan] = lerp(tmpgains[chan], 1.0f, a);
- }
- if(SpeakerAngle[i] < langle)
- {
- a = (langle-SpeakerAngle[i]) /
- (F_2PI + SpeakerAngle[0]-SpeakerAngle[i]);
- tmpgains[chan] = lerp(tmpgains[chan], 1.0f, 1.0f-a);
- }
- else if(SpeakerAngle[0] > langle)
- {
- a = (F_2PI + langle-SpeakerAngle[i]) /
- (F_2PI + SpeakerAngle[0]-SpeakerAngle[i]);
- tmpgains[chan] = lerp(tmpgains[chan], 1.0f, 1.0f-a);
- }
- } while(0);
-
- for(i = 0;i < device->NumSpeakers;i++)
- {
- enum Channel chan = device->Speaker[i].ChanName;
- gains[chan] = sqrtf(tmpgains[chan]) * ingain;
- }
+ ALfloat dir[3] = {
+ -sinf(angle) * cosf(elevation),
+ sinf(elevation),
+ -cosf(angle) * cosf(elevation)
+ };
+ ComputeDirectionalGains(device, dir, ingain, gains);
}
void ComputeDirectionalGains(const ALCdevice *device, const ALfloat dir[3], ALfloat ingain, ALfloat gains[MaxChannels])
@@ -323,6 +137,7 @@ ALvoid aluInitPanning(ALCdevice *device)
device->NumSpeakers = 1;
device->Speaker[0].ChanName = FrontCenter;
device->Speaker[0].Angle = DEG2RAD(0.0f);
+ device->Speaker[0].Elevation = DEG2RAD(0.0f);
Set0thOrder(device->Speaker[0].Coeff, 1.4142f);
break;
@@ -332,6 +147,8 @@ ALvoid aluInitPanning(ALCdevice *device)
device->Speaker[1].ChanName = FrontRight;
device->Speaker[0].Angle = DEG2RAD(-90.0f);
device->Speaker[1].Angle = DEG2RAD( 90.0f);
+ device->Speaker[0].Elevation = DEG2RAD(0.0f);
+ device->Speaker[1].Elevation = DEG2RAD(0.0f);
Set1stOrder(device->Speaker[0].Coeff, 0.7071f, -0.5f, 0.0f, 0.0f);
Set1stOrder(device->Speaker[1].Coeff, 0.7071f, 0.5f, 0.0f, 0.0f);
break;
@@ -346,6 +163,10 @@ ALvoid aluInitPanning(ALCdevice *device)
device->Speaker[1].Angle = DEG2RAD( -45.0f);
device->Speaker[2].Angle = DEG2RAD( 45.0f);
device->Speaker[3].Angle = DEG2RAD( 135.0f);
+ device->Speaker[0].Elevation = DEG2RAD(0.0f);
+ device->Speaker[1].Elevation = DEG2RAD(0.0f);
+ device->Speaker[2].Elevation = DEG2RAD(0.0f);
+ device->Speaker[3].Elevation = DEG2RAD(0.0f);
Set2ndOrder(device->Speaker[0].Coeff, 0.353543f, -0.306192f, 0.306181f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -0.117193f);
Set2ndOrder(device->Speaker[1].Coeff, 0.353558f, 0.306181f, 0.306192f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.117183f);
Set2ndOrder(device->Speaker[2].Coeff, 0.353543f, 0.306181f, -0.306192f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -0.117193f);
@@ -364,6 +185,11 @@ ALvoid aluInitPanning(ALCdevice *device)
device->Speaker[2].Angle = DEG2RAD( 0.0f);
device->Speaker[3].Angle = DEG2RAD( 30.0f);
device->Speaker[4].Angle = DEG2RAD( 110.0f);
+ device->Speaker[0].Elevation = DEG2RAD(0.0f);
+ device->Speaker[1].Elevation = DEG2RAD(0.0f);
+ device->Speaker[2].Elevation = DEG2RAD(0.0f);
+ device->Speaker[3].Elevation = DEG2RAD(0.0f);
+ device->Speaker[4].Elevation = DEG2RAD(0.0f);
Set3rdOrder(device->Speaker[0].Coeff, 0.470934f, -0.369630f, 0.349383f, 0.0f, 0.0f, 0.0f, 0.0f, -0.031379f, -0.058143f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -0.007116f, -0.043968f);
Set3rdOrder(device->Speaker[1].Coeff, 0.208954f, 0.212846f, 0.238350f, 0.0f, 0.0f, 0.0f, 0.0f, -0.017738f, 0.204014f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -0.051023f, 0.047490f);
Set3rdOrder(device->Speaker[2].Coeff, 0.109403f, 0.179490f, -0.000002f, 0.0f, 0.0f, 0.0f, 0.0f, 0.142031f, -0.000002f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.072024f, -0.000001f);
@@ -383,6 +209,11 @@ ALvoid aluInitPanning(ALCdevice *device)
device->Speaker[2].Angle = DEG2RAD( 0.0f);
device->Speaker[3].Angle = DEG2RAD( 30.0f);
device->Speaker[4].Angle = DEG2RAD( 90.0f);
+ device->Speaker[0].Elevation = DEG2RAD(0.0f);
+ device->Speaker[1].Elevation = DEG2RAD(0.0f);
+ device->Speaker[2].Elevation = DEG2RAD(0.0f);
+ device->Speaker[3].Elevation = DEG2RAD(0.0f);
+ device->Speaker[4].Elevation = DEG2RAD(0.0f);
Set3rdOrder(device->Speaker[0].Coeff, 0.289151f, -0.081301f, 0.401292f, 0.0f, 0.0f, 0.0f, 0.0f, -0.188208f, -0.071420f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.010099f, -0.032897f);
Set3rdOrder(device->Speaker[1].Coeff, 0.167065f, 0.200583f, 0.172695f, 0.0f, 0.0f, 0.0f, 0.0f, 0.029855f, 0.186407f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -0.039241f, 0.068910f);
Set3rdOrder(device->Speaker[2].Coeff, 0.109403f, 0.179490f, -0.000002f, 0.0f, 0.0f, 0.0f, 0.0f, 0.142031f, -0.000002f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.072024f, -0.000001f);
@@ -404,6 +235,12 @@ ALvoid aluInitPanning(ALCdevice *device)
device->Speaker[3].Angle = DEG2RAD( 30.0f);
device->Speaker[4].Angle = DEG2RAD( 90.0f);
device->Speaker[5].Angle = DEG2RAD(180.0f);
+ device->Speaker[0].Elevation = DEG2RAD(0.0f);
+ device->Speaker[1].Elevation = DEG2RAD(0.0f);
+ device->Speaker[2].Elevation = DEG2RAD(0.0f);
+ device->Speaker[3].Elevation = DEG2RAD(0.0f);
+ device->Speaker[4].Elevation = DEG2RAD(0.0f);
+ device->Speaker[5].Elevation = DEG2RAD(0.0f);
Set3rdOrder(device->Speaker[0].Coeff, 0.289151f, -0.081301f, 0.401292f, 0.0f, 0.0f, 0.0f, 0.0f, -0.188208f, -0.071420f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.010099f, -0.032897f);
Set3rdOrder(device->Speaker[1].Coeff, 0.167065f, 0.200583f, 0.172695f, 0.0f, 0.0f, 0.0f, 0.0f, 0.029855f, 0.186407f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -0.039241f, 0.068910f);
Set3rdOrder(device->Speaker[2].Coeff, 0.109403f, 0.179490f, -0.000002f, 0.0f, 0.0f, 0.0f, 0.0f, 0.142031f, -0.000002f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.072024f, -0.000001f);
@@ -428,6 +265,13 @@ ALvoid aluInitPanning(ALCdevice *device)
device->Speaker[4].Angle = DEG2RAD( 30.0f);
device->Speaker[5].Angle = DEG2RAD( 90.0f);
device->Speaker[6].Angle = DEG2RAD( 150.0f);
+ device->Speaker[0].Elevation = DEG2RAD(0.0f);
+ device->Speaker[1].Elevation = DEG2RAD(0.0f);
+ device->Speaker[2].Elevation = DEG2RAD(0.0f);
+ device->Speaker[3].Elevation = DEG2RAD(0.0f);
+ device->Speaker[4].Elevation = DEG2RAD(0.0f);
+ device->Speaker[5].Elevation = DEG2RAD(0.0f);
+ device->Speaker[6].Elevation = DEG2RAD(0.0f);
Set3rdOrder(device->Speaker[0].Coeff, 0.224752f, -0.295009f, 0.170325f, 0.0f, 0.0f, 0.0f, 0.0f, 0.105349f, -0.182473f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -0.000000f, 0.065799f);
Set3rdOrder(device->Speaker[1].Coeff, 0.224739f, 0.000002f, 0.340644f, 0.0f, 0.0f, 0.0f, 0.0f, -0.210697f, 0.000002f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -0.000000f, -0.065795f);
Set3rdOrder(device->Speaker[2].Coeff, 0.167065f, 0.200583f, 0.172695f, 0.0f, 0.0f, 0.0f, 0.0f, 0.029855f, 0.186407f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -0.039241f, 0.068910f);
diff --git a/OpenAL32/Include/alMain.h b/OpenAL32/Include/alMain.h
index a658227b..62bb0328 100644
--- a/OpenAL32/Include/alMain.h
+++ b/OpenAL32/Include/alMain.h
@@ -656,6 +656,7 @@ struct ALCdevice_struct
struct {
enum Channel ChanName;
ALfloat Angle;
+ ALfloat Elevation;
ALfloat Coeff[MAX_AMBI_COEFFS];
} Speaker[MaxChannels];
ALuint NumSpeakers;
diff --git a/OpenAL32/Include/alu.h b/OpenAL32/Include/alu.h
index bf5de4fe..fb16d143 100644
--- a/OpenAL32/Include/alu.h
+++ b/OpenAL32/Include/alu.h
@@ -204,18 +204,18 @@ ALvoid aluInitPanning(ALCdevice *Device);
/**
* ComputeDirectionalGains
*
- * Sets channel gains based on the given source's direction. The direction must
- * be a 3-component vector no longer than 1 unit.
+ * Sets channel gains based on a direction. The direction must be a 3-component
+ * vector no longer than 1 unit.
*/
void ComputeDirectionalGains(const ALCdevice *device, const ALfloat dir[3], ALfloat ingain, ALfloat gains[MaxChannels]);
/**
* ComputeAngleGains
*
- * Sets channel gains based on a given source's angle and its half-width. The
- * angle and hwidth parameters are in radians.
+ * Sets channel gains based on angle and elevation. The angle and elevation
+ * parameters are in radians, going right and up respectively.
*/
-void ComputeAngleGains(const ALCdevice *device, ALfloat angle, ALfloat hwidth, ALfloat ingain, ALfloat gains[MaxChannels]);
+void ComputeAngleGains(const ALCdevice *device, ALfloat angle, ALfloat elevation, ALfloat ingain, ALfloat gains[MaxChannels]);
/**
* SetGains