Make ComputeAngleGains use ComputeDirectionalGains
This commit is contained in:
parent
9377d0f237
commit
95ba18cf4e
119
Alc/ALu.c
119
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];
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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])
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
invlen = 1.0f / length;
|
||||
latePan[0] *= invlen;
|
||||
latePan[1] *= invlen;
|
||||
latePan[2] *= invlen;
|
||||
|
||||
lateLen = minf(1.0f, length);
|
||||
ComputeDirectionalGains(Device, latePan, Gain, State->Late.PanGain);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
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)
|
||||
|
230
Alc/panning.c
230
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);
|
||||
|
@ -656,6 +656,7 @@ struct ALCdevice_struct
|
||||
struct {
|
||||
enum Channel ChanName;
|
||||
ALfloat Angle;
|
||||
ALfloat Elevation;
|
||||
ALfloat Coeff[MAX_AMBI_COEFFS];
|
||||
} Speaker[MaxChannels];
|
||||
ALuint NumSpeakers;
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user