Calculate the multi-channel panning in a separate function
This commit is contained in:
parent
14b23c2502
commit
23bf3d3959
524
Alc/ALu.c
524
Alc/ALu.c
@ -349,137 +349,76 @@ static ALboolean CalcEffectSlotParams(ALeffectslot *slot, ALCdevice *device)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void CalcNonAttnSourceParams(ALvoice *voice, const struct ALvoiceProps *props, const ALbuffer *ALBuffer, const ALCcontext *ALContext)
|
static const struct ChanMap MonoMap[1] = {
|
||||||
{
|
{ FrontCenter, 0.0f, 0.0f }
|
||||||
static const struct ChanMap MonoMap[1] = {
|
}, RearMap[2] = {
|
||||||
{ FrontCenter, 0.0f, 0.0f }
|
{ BackLeft, DEG2RAD(-150.0f), DEG2RAD(0.0f) },
|
||||||
}, RearMap[2] = {
|
{ BackRight, DEG2RAD( 150.0f), DEG2RAD(0.0f) }
|
||||||
{ BackLeft, DEG2RAD(-150.0f), DEG2RAD(0.0f) },
|
}, QuadMap[4] = {
|
||||||
{ BackRight, DEG2RAD( 150.0f), DEG2RAD(0.0f) }
|
{ FrontLeft, DEG2RAD( -45.0f), DEG2RAD(0.0f) },
|
||||||
}, QuadMap[4] = {
|
{ FrontRight, DEG2RAD( 45.0f), DEG2RAD(0.0f) },
|
||||||
{ FrontLeft, DEG2RAD( -45.0f), DEG2RAD(0.0f) },
|
{ BackLeft, DEG2RAD(-135.0f), DEG2RAD(0.0f) },
|
||||||
{ FrontRight, DEG2RAD( 45.0f), DEG2RAD(0.0f) },
|
{ BackRight, DEG2RAD( 135.0f), DEG2RAD(0.0f) }
|
||||||
{ BackLeft, DEG2RAD(-135.0f), DEG2RAD(0.0f) },
|
}, X51Map[6] = {
|
||||||
{ BackRight, DEG2RAD( 135.0f), DEG2RAD(0.0f) }
|
{ FrontLeft, DEG2RAD( -30.0f), DEG2RAD(0.0f) },
|
||||||
}, X51Map[6] = {
|
{ FrontRight, DEG2RAD( 30.0f), DEG2RAD(0.0f) },
|
||||||
{ FrontLeft, DEG2RAD( -30.0f), DEG2RAD(0.0f) },
|
{ FrontCenter, DEG2RAD( 0.0f), DEG2RAD(0.0f) },
|
||||||
{ FrontRight, DEG2RAD( 30.0f), DEG2RAD(0.0f) },
|
{ LFE, 0.0f, 0.0f },
|
||||||
{ FrontCenter, DEG2RAD( 0.0f), DEG2RAD(0.0f) },
|
{ SideLeft, DEG2RAD(-110.0f), DEG2RAD(0.0f) },
|
||||||
{ LFE, 0.0f, 0.0f },
|
{ SideRight, DEG2RAD( 110.0f), DEG2RAD(0.0f) }
|
||||||
{ SideLeft, DEG2RAD(-110.0f), DEG2RAD(0.0f) },
|
}, X61Map[7] = {
|
||||||
{ SideRight, DEG2RAD( 110.0f), DEG2RAD(0.0f) }
|
{ FrontLeft, DEG2RAD(-30.0f), DEG2RAD(0.0f) },
|
||||||
}, X61Map[7] = {
|
{ FrontRight, DEG2RAD( 30.0f), DEG2RAD(0.0f) },
|
||||||
{ FrontLeft, DEG2RAD(-30.0f), DEG2RAD(0.0f) },
|
{ FrontCenter, DEG2RAD( 0.0f), DEG2RAD(0.0f) },
|
||||||
{ FrontRight, DEG2RAD( 30.0f), DEG2RAD(0.0f) },
|
{ LFE, 0.0f, 0.0f },
|
||||||
{ FrontCenter, DEG2RAD( 0.0f), DEG2RAD(0.0f) },
|
{ BackCenter, DEG2RAD(180.0f), DEG2RAD(0.0f) },
|
||||||
{ LFE, 0.0f, 0.0f },
|
{ SideLeft, DEG2RAD(-90.0f), DEG2RAD(0.0f) },
|
||||||
{ BackCenter, DEG2RAD(180.0f), DEG2RAD(0.0f) },
|
{ SideRight, DEG2RAD( 90.0f), DEG2RAD(0.0f) }
|
||||||
{ SideLeft, DEG2RAD(-90.0f), DEG2RAD(0.0f) },
|
}, X71Map[8] = {
|
||||||
{ SideRight, DEG2RAD( 90.0f), DEG2RAD(0.0f) }
|
{ FrontLeft, DEG2RAD( -30.0f), DEG2RAD(0.0f) },
|
||||||
}, X71Map[8] = {
|
{ FrontRight, DEG2RAD( 30.0f), DEG2RAD(0.0f) },
|
||||||
{ FrontLeft, DEG2RAD( -30.0f), DEG2RAD(0.0f) },
|
{ FrontCenter, DEG2RAD( 0.0f), DEG2RAD(0.0f) },
|
||||||
{ FrontRight, DEG2RAD( 30.0f), DEG2RAD(0.0f) },
|
{ LFE, 0.0f, 0.0f },
|
||||||
{ FrontCenter, DEG2RAD( 0.0f), DEG2RAD(0.0f) },
|
{ BackLeft, DEG2RAD(-150.0f), DEG2RAD(0.0f) },
|
||||||
{ LFE, 0.0f, 0.0f },
|
{ BackRight, DEG2RAD( 150.0f), DEG2RAD(0.0f) },
|
||||||
{ BackLeft, DEG2RAD(-150.0f), DEG2RAD(0.0f) },
|
{ SideLeft, DEG2RAD( -90.0f), DEG2RAD(0.0f) },
|
||||||
{ BackRight, DEG2RAD( 150.0f), DEG2RAD(0.0f) },
|
{ SideRight, DEG2RAD( 90.0f), DEG2RAD(0.0f) }
|
||||||
{ SideLeft, DEG2RAD( -90.0f), DEG2RAD(0.0f) },
|
};
|
||||||
{ SideRight, DEG2RAD( 90.0f), DEG2RAD(0.0f) }
|
|
||||||
};
|
|
||||||
|
|
||||||
const ALCdevice *Device = ALContext->Device;
|
static void CalcPanningAndFilters(ALvoice *voice,
|
||||||
const ALlistener *Listener = ALContext->Listener;
|
const ALfloat DryGain, const ALfloat DryGainHF,
|
||||||
ALfloat SourceVolume,ListenerGain,MinVolume,MaxVolume;
|
const ALfloat DryGainLF, const ALfloat *WetGain,
|
||||||
ALfloat DryGain, DryGainHF, DryGainLF;
|
const ALfloat *WetGainLF, const ALfloat *WetGainHF,
|
||||||
ALfloat WetGain[MAX_SENDS];
|
ALeffectslot **SendSlots, const ALbuffer *Buffer,
|
||||||
ALfloat WetGainHF[MAX_SENDS];
|
const struct ALvoiceProps *props, const ALlistener *Listener,
|
||||||
ALfloat WetGainLF[MAX_SENDS];
|
const ALCdevice *Device)
|
||||||
ALeffectslot *SendSlots[MAX_SENDS];
|
{
|
||||||
ALfloat HFScale, LFScale;
|
|
||||||
ALuint NumSends, Frequency;
|
|
||||||
ALboolean Relative;
|
|
||||||
const struct ChanMap *chans = NULL;
|
|
||||||
struct ChanMap StereoMap[2] = {
|
struct ChanMap StereoMap[2] = {
|
||||||
{ FrontLeft, DEG2RAD(-30.0f), DEG2RAD(0.0f) },
|
{ FrontLeft, DEG2RAD(-30.0f), DEG2RAD(0.0f) },
|
||||||
{ FrontRight, DEG2RAD( 30.0f), DEG2RAD(0.0f) }
|
{ FrontRight, DEG2RAD( 30.0f), DEG2RAD(0.0f) }
|
||||||
};
|
};
|
||||||
ALuint num_channels = 0;
|
bool DirectChannels = props->DirectChannels;
|
||||||
ALboolean DirectChannels;
|
const ALsizei NumSends = Device->NumAuxSends;
|
||||||
ALboolean isbformat = AL_FALSE;
|
const ALuint Frequency = Device->Frequency;
|
||||||
ALfloat Pitch;
|
const struct ChanMap *chans = NULL;
|
||||||
ALuint i, j, c;
|
ALsizei num_channels = 0;
|
||||||
|
bool isbformat = false;
|
||||||
|
ALsizei c, i, j;
|
||||||
|
|
||||||
/* Get device properties */
|
switch(Buffer->FmtChannels)
|
||||||
NumSends = Device->NumAuxSends;
|
|
||||||
Frequency = Device->Frequency;
|
|
||||||
|
|
||||||
/* Get listener properties */
|
|
||||||
ListenerGain = Listener->Params.Gain;
|
|
||||||
|
|
||||||
/* Get source properties */
|
|
||||||
SourceVolume = props->Gain;
|
|
||||||
MinVolume = props->MinGain;
|
|
||||||
MaxVolume = props->MaxGain;
|
|
||||||
Pitch = props->Pitch;
|
|
||||||
Relative = props->HeadRelative;
|
|
||||||
DirectChannels = props->DirectChannels;
|
|
||||||
|
|
||||||
/* Convert counter-clockwise to clockwise. */
|
|
||||||
StereoMap[0].angle = -props->StereoPan[0];
|
|
||||||
StereoMap[1].angle = -props->StereoPan[1];
|
|
||||||
|
|
||||||
voice->Direct.Buffer = Device->Dry.Buffer;
|
|
||||||
voice->Direct.Channels = Device->Dry.NumChannels;
|
|
||||||
for(i = 0;i < NumSends;i++)
|
|
||||||
{
|
|
||||||
SendSlots[i] = props->Send[i].Slot;
|
|
||||||
if(!SendSlots[i] && i == 0)
|
|
||||||
SendSlots[i] = Device->DefaultSlot;
|
|
||||||
if(!SendSlots[i] || SendSlots[i]->Params.EffectType == AL_EFFECT_NULL)
|
|
||||||
{
|
|
||||||
SendSlots[i] = NULL;
|
|
||||||
voice->Send[i].Buffer = NULL;
|
|
||||||
voice->Send[i].Channels = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
voice->Send[i].Buffer = SendSlots[i]->WetBuffer;
|
|
||||||
voice->Send[i].Channels = SendSlots[i]->NumChannels;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Calculate the stepping value */
|
|
||||||
Pitch *= (ALfloat)ALBuffer->Frequency / Frequency;
|
|
||||||
if(Pitch > (ALfloat)MAX_PITCH)
|
|
||||||
voice->Step = MAX_PITCH<<FRACTIONBITS;
|
|
||||||
else
|
|
||||||
voice->Step = maxi(fastf2i(Pitch*FRACTIONONE + 0.5f), 1);
|
|
||||||
BsincPrepare(voice->Step, &voice->ResampleState.bsinc);
|
|
||||||
voice->Resampler = SelectResampler(props->Resampler);
|
|
||||||
|
|
||||||
/* Calculate gains */
|
|
||||||
DryGain = clampf(SourceVolume, MinVolume, MaxVolume);
|
|
||||||
DryGain *= props->Direct.Gain * ListenerGain;
|
|
||||||
DryGain = minf(DryGain, GAIN_MIX_MAX);
|
|
||||||
DryGainHF = props->Direct.GainHF;
|
|
||||||
DryGainLF = props->Direct.GainLF;
|
|
||||||
for(i = 0;i < NumSends;i++)
|
|
||||||
{
|
|
||||||
WetGain[i] = clampf(SourceVolume, MinVolume, MaxVolume);
|
|
||||||
WetGain[i] *= props->Send[i].Gain * ListenerGain;
|
|
||||||
WetGain[i] = minf(WetGain[i], GAIN_MIX_MAX);
|
|
||||||
WetGainHF[i] = props->Send[i].GainHF;
|
|
||||||
WetGainLF[i] = props->Send[i].GainLF;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch(ALBuffer->FmtChannels)
|
|
||||||
{
|
{
|
||||||
case FmtMono:
|
case FmtMono:
|
||||||
chans = MonoMap;
|
chans = MonoMap;
|
||||||
num_channels = 1;
|
num_channels = 1;
|
||||||
|
/* Mono buffers are never played direct. */
|
||||||
|
DirectChannels = false;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FmtStereo:
|
case FmtStereo:
|
||||||
|
/* Convert counter-clockwise to clockwise. */
|
||||||
|
StereoMap[0].angle = -props->StereoPan[0];
|
||||||
|
StereoMap[1].angle = -props->StereoPan[1];
|
||||||
|
|
||||||
chans = StereoMap;
|
chans = StereoMap;
|
||||||
num_channels = 2;
|
num_channels = 2;
|
||||||
break;
|
break;
|
||||||
@ -511,14 +450,14 @@ static void CalcNonAttnSourceParams(ALvoice *voice, const struct ALvoiceProps *p
|
|||||||
|
|
||||||
case FmtBFormat2D:
|
case FmtBFormat2D:
|
||||||
num_channels = 3;
|
num_channels = 3;
|
||||||
isbformat = AL_TRUE;
|
isbformat = true;
|
||||||
DirectChannels = AL_FALSE;
|
DirectChannels = false;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FmtBFormat3D:
|
case FmtBFormat3D:
|
||||||
num_channels = 4;
|
num_channels = 4;
|
||||||
isbformat = AL_TRUE;
|
isbformat = true;
|
||||||
DirectChannels = AL_FALSE;
|
DirectChannels = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -538,7 +477,7 @@ static void CalcNonAttnSourceParams(ALvoice *voice, const struct ALvoiceProps *p
|
|||||||
V[1] = props->Orientation[1][1];
|
V[1] = props->Orientation[1][1];
|
||||||
V[2] = props->Orientation[1][2];
|
V[2] = props->Orientation[1][2];
|
||||||
aluNormalize(V);
|
aluNormalize(V);
|
||||||
if(!Relative)
|
if(!props->HeadRelative)
|
||||||
{
|
{
|
||||||
const aluMatrixf *lmatrix = &Listener->Params.Matrix;
|
const aluMatrixf *lmatrix = &Listener->Params.Matrix;
|
||||||
aluMatrixfFloat3(N, 0.0f, lmatrix);
|
aluMatrixfFloat3(N, 0.0f, lmatrix);
|
||||||
@ -592,189 +531,250 @@ static void CalcNonAttnSourceParams(ALvoice *voice, const struct ALvoiceProps *p
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if(DirectChannels)
|
||||||
|
{
|
||||||
|
/* Skip the virtual channels and write inputs to the real output. */
|
||||||
|
voice->Direct.Buffer = Device->RealOut.Buffer;
|
||||||
|
voice->Direct.Channels = Device->RealOut.NumChannels;
|
||||||
|
for(c = 0;c < num_channels;c++)
|
||||||
|
{
|
||||||
|
int idx;
|
||||||
|
for(j = 0;j < MAX_OUTPUT_CHANNELS;j++)
|
||||||
|
voice->Direct.Params[c].Gains.Target[j] = 0.0f;
|
||||||
|
if((idx=GetChannelIdxByName(Device->RealOut, chans[c].channel)) != -1)
|
||||||
|
voice->Direct.Params[c].Gains.Target[idx] = DryGain;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Auxiliary sends still use normal panning since they mix to B-Format,
|
||||||
|
* which can't channel-match.
|
||||||
|
*/
|
||||||
|
for(c = 0;c < num_channels;c++)
|
||||||
|
{
|
||||||
|
ALfloat coeffs[MAX_AMBI_COEFFS];
|
||||||
|
CalcAngleCoeffs(chans[c].angle, chans[c].elevation, 0.0f, coeffs);
|
||||||
|
|
||||||
|
for(i = 0;i < NumSends;i++)
|
||||||
|
{
|
||||||
|
const ALeffectslot *Slot = SendSlots[i];
|
||||||
|
if(Slot)
|
||||||
|
ComputePanningGainsBF(Slot->ChanMap, Slot->NumChannels,
|
||||||
|
coeffs, WetGain[i], voice->Send[i].Params[c].Gains.Target
|
||||||
|
);
|
||||||
|
else
|
||||||
|
for(j = 0;j < MAX_EFFECT_CHANNELS;j++)
|
||||||
|
voice->Send[i].Params[c].Gains.Target[j] = 0.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(Device->Render_Mode == HrtfRender)
|
||||||
|
{
|
||||||
|
/* Full HRTF rendering. Skip the virtual channels and render each input
|
||||||
|
* channel to the real outputs.
|
||||||
|
*/
|
||||||
|
voice->Direct.Buffer = Device->RealOut.Buffer;
|
||||||
|
voice->Direct.Channels = Device->RealOut.NumChannels;
|
||||||
|
for(c = 0;c < num_channels;c++)
|
||||||
|
{
|
||||||
|
ALfloat coeffs[MAX_AMBI_COEFFS];
|
||||||
|
|
||||||
|
if(chans[c].channel == LFE)
|
||||||
|
{
|
||||||
|
/* Skip LFE */
|
||||||
|
voice->Direct.Params[c].Hrtf.Target.Delay[0] = 0;
|
||||||
|
voice->Direct.Params[c].Hrtf.Target.Delay[1] = 0;
|
||||||
|
for(i = 0;i < HRIR_LENGTH;i++)
|
||||||
|
{
|
||||||
|
voice->Direct.Params[c].Hrtf.Target.Coeffs[i][0] = 0.0f;
|
||||||
|
voice->Direct.Params[c].Hrtf.Target.Coeffs[i][1] = 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(i = 0;i < NumSends;i++)
|
||||||
|
{
|
||||||
|
for(j = 0;j < MAX_EFFECT_CHANNELS;j++)
|
||||||
|
voice->Send[i].Params[c].Gains.Target[j] = 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the static HRIR coefficients and delays for this channel. */
|
||||||
|
GetHrtfCoeffs(Device->HrtfHandle,
|
||||||
|
chans[c].elevation, chans[c].angle, 0.0f,
|
||||||
|
voice->Direct.Params[c].Hrtf.Target.Coeffs,
|
||||||
|
voice->Direct.Params[c].Hrtf.Target.Delay
|
||||||
|
);
|
||||||
|
voice->Direct.Params[c].Hrtf.Target.Gain = DryGain;
|
||||||
|
|
||||||
|
/* Normal panning for auxiliary sends. */
|
||||||
|
CalcAngleCoeffs(chans[c].angle, chans[c].elevation, 0.0f, coeffs);
|
||||||
|
|
||||||
|
for(i = 0;i < NumSends;i++)
|
||||||
|
{
|
||||||
|
const ALeffectslot *Slot = SendSlots[i];
|
||||||
|
if(Slot)
|
||||||
|
ComputePanningGainsBF(Slot->ChanMap, Slot->NumChannels,
|
||||||
|
coeffs, WetGain[i], voice->Send[i].Params[c].Gains.Target
|
||||||
|
);
|
||||||
|
else
|
||||||
|
for(j = 0;j < MAX_EFFECT_CHANNELS;j++)
|
||||||
|
voice->Send[i].Params[c].Gains.Target[j] = 0.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
voice->Flags |= VOICE_HAS_HRTF;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ALfloat coeffs[MAX_AMBI_COEFFS];
|
/* Non-HRTF rendering. Use normal panning to the output. */
|
||||||
|
for(c = 0;c < num_channels;c++)
|
||||||
if(DirectChannels)
|
|
||||||
{
|
{
|
||||||
/* Skip the virtual channels and write inputs to the real output. */
|
ALfloat coeffs[MAX_AMBI_COEFFS];
|
||||||
voice->Direct.Buffer = Device->RealOut.Buffer;
|
|
||||||
voice->Direct.Channels = Device->RealOut.NumChannels;
|
/* Special-case LFE */
|
||||||
for(c = 0;c < num_channels;c++)
|
if(chans[c].channel == LFE)
|
||||||
{
|
{
|
||||||
int idx;
|
|
||||||
for(j = 0;j < MAX_OUTPUT_CHANNELS;j++)
|
for(j = 0;j < MAX_OUTPUT_CHANNELS;j++)
|
||||||
voice->Direct.Params[c].Gains.Target[j] = 0.0f;
|
voice->Direct.Params[c].Gains.Target[j] = 0.0f;
|
||||||
if((idx=GetChannelIdxByName(Device->RealOut, chans[c].channel)) != -1)
|
if(Device->Dry.Buffer == Device->RealOut.Buffer)
|
||||||
voice->Direct.Params[c].Gains.Target[idx] = DryGain;
|
{
|
||||||
}
|
int idx;
|
||||||
|
if((idx=GetChannelIdxByName(Device->RealOut, chans[c].channel)) != -1)
|
||||||
/* Auxiliary sends still use normal panning since they mix to B-Format, which can't
|
voice->Direct.Params[c].Gains.Target[idx] = DryGain;
|
||||||
* channel-match. */
|
}
|
||||||
for(c = 0;c < num_channels;c++)
|
|
||||||
{
|
|
||||||
CalcAngleCoeffs(chans[c].angle, chans[c].elevation, 0.0f, coeffs);
|
|
||||||
|
|
||||||
for(i = 0;i < NumSends;i++)
|
for(i = 0;i < NumSends;i++)
|
||||||
{
|
{
|
||||||
const ALeffectslot *Slot = SendSlots[i];
|
for(j = 0;j < MAX_EFFECT_CHANNELS;j++)
|
||||||
if(Slot)
|
|
||||||
ComputePanningGainsBF(Slot->ChanMap, Slot->NumChannels,
|
|
||||||
coeffs, WetGain[i], voice->Send[i].Params[c].Gains.Target
|
|
||||||
);
|
|
||||||
else
|
|
||||||
for(j = 0;j < MAX_EFFECT_CHANNELS;j++)
|
|
||||||
voice->Send[i].Params[c].Gains.Target[j] = 0.0f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if(Device->Render_Mode == HrtfRender)
|
|
||||||
{
|
|
||||||
/* Full HRTF rendering. Skip the virtual channels and render each
|
|
||||||
* input channel to the real outputs.
|
|
||||||
*/
|
|
||||||
voice->Direct.Buffer = Device->RealOut.Buffer;
|
|
||||||
voice->Direct.Channels = Device->RealOut.NumChannels;
|
|
||||||
for(c = 0;c < num_channels;c++)
|
|
||||||
{
|
|
||||||
if(chans[c].channel == LFE)
|
|
||||||
{
|
|
||||||
/* Skip LFE */
|
|
||||||
voice->Direct.Params[c].Hrtf.Target.Delay[0] = 0;
|
|
||||||
voice->Direct.Params[c].Hrtf.Target.Delay[1] = 0;
|
|
||||||
for(i = 0;i < HRIR_LENGTH;i++)
|
|
||||||
{
|
|
||||||
voice->Direct.Params[c].Hrtf.Target.Coeffs[i][0] = 0.0f;
|
|
||||||
voice->Direct.Params[c].Hrtf.Target.Coeffs[i][1] = 0.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
for(i = 0;i < NumSends;i++)
|
|
||||||
{
|
|
||||||
for(j = 0;j < MAX_EFFECT_CHANNELS;j++)
|
|
||||||
voice->Send[i].Params[c].Gains.Target[j] = 0.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get the static HRIR coefficients and delays for this channel. */
|
|
||||||
GetHrtfCoeffs(Device->HrtfHandle,
|
|
||||||
chans[c].elevation, chans[c].angle, 0.0f,
|
|
||||||
voice->Direct.Params[c].Hrtf.Target.Coeffs,
|
|
||||||
voice->Direct.Params[c].Hrtf.Target.Delay
|
|
||||||
);
|
|
||||||
voice->Direct.Params[c].Hrtf.Target.Gain = DryGain;
|
|
||||||
|
|
||||||
/* Normal panning for auxiliary sends. */
|
|
||||||
CalcAngleCoeffs(chans[c].angle, chans[c].elevation, 0.0f, coeffs);
|
|
||||||
|
|
||||||
for(i = 0;i < NumSends;i++)
|
|
||||||
{
|
|
||||||
const ALeffectslot *Slot = SendSlots[i];
|
|
||||||
if(Slot)
|
|
||||||
ComputePanningGainsBF(Slot->ChanMap, Slot->NumChannels,
|
|
||||||
coeffs, WetGain[i], voice->Send[i].Params[c].Gains.Target
|
|
||||||
);
|
|
||||||
else
|
|
||||||
for(j = 0;j < MAX_EFFECT_CHANNELS;j++)
|
|
||||||
voice->Send[i].Params[c].Gains.Target[j] = 0.0f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
voice->Flags |= VOICE_HAS_HRTF;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Non-HRTF rendering. Use normal panning to the output. */
|
|
||||||
for(c = 0;c < num_channels;c++)
|
|
||||||
{
|
|
||||||
/* Special-case LFE */
|
|
||||||
if(chans[c].channel == LFE)
|
|
||||||
{
|
|
||||||
for(j = 0;j < MAX_OUTPUT_CHANNELS;j++)
|
|
||||||
voice->Direct.Params[c].Gains.Target[j] = 0.0f;
|
voice->Direct.Params[c].Gains.Target[j] = 0.0f;
|
||||||
if(Device->Dry.Buffer == Device->RealOut.Buffer)
|
|
||||||
{
|
|
||||||
int idx;
|
|
||||||
if((idx=GetChannelIdxByName(Device->RealOut, chans[c].channel)) != -1)
|
|
||||||
voice->Direct.Params[c].Gains.Target[idx] = DryGain;
|
|
||||||
}
|
|
||||||
|
|
||||||
for(i = 0;i < NumSends;i++)
|
|
||||||
{
|
|
||||||
for(j = 0;j < MAX_EFFECT_CHANNELS;j++)
|
|
||||||
voice->Direct.Params[c].Gains.Target[j] = 0.0f;
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if(Device->Render_Mode == StereoPair)
|
if(Device->Render_Mode == StereoPair)
|
||||||
CalcAnglePairwiseCoeffs(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
|
||||||
|
);
|
||||||
|
|
||||||
|
for(i = 0;i < NumSends;i++)
|
||||||
|
{
|
||||||
|
const ALeffectslot *Slot = SendSlots[i];
|
||||||
|
if(Slot)
|
||||||
|
ComputePanningGainsBF(Slot->ChanMap, Slot->NumChannels,
|
||||||
|
coeffs, WetGain[i], voice->Send[i].Params[c].Gains.Target
|
||||||
|
);
|
||||||
else
|
else
|
||||||
CalcAngleCoeffs(chans[c].angle, chans[c].elevation, 0.0f, coeffs);
|
for(j = 0;j < MAX_EFFECT_CHANNELS;j++)
|
||||||
ComputePanningGains(Device->Dry,
|
voice->Send[i].Params[c].Gains.Target[j] = 0.0f;
|
||||||
coeffs, DryGain, voice->Direct.Params[c].Gains.Target
|
|
||||||
);
|
|
||||||
|
|
||||||
for(i = 0;i < NumSends;i++)
|
|
||||||
{
|
|
||||||
const ALeffectslot *Slot = SendSlots[i];
|
|
||||||
if(Slot)
|
|
||||||
ComputePanningGainsBF(Slot->ChanMap, Slot->NumChannels,
|
|
||||||
coeffs, WetGain[i], voice->Send[i].Params[c].Gains.Target
|
|
||||||
);
|
|
||||||
else
|
|
||||||
for(j = 0;j < MAX_EFFECT_CHANNELS;j++)
|
|
||||||
voice->Send[i].Params[c].Gains.Target[j] = 0.0f;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
HFScale = props->Direct.HFReference / Frequency;
|
ALfloat hfScale = props->Direct.HFReference / Frequency;
|
||||||
LFScale = props->Direct.LFReference / Frequency;
|
ALfloat lfScale = props->Direct.LFReference / Frequency;
|
||||||
DryGainHF = maxf(DryGainHF, 0.0625f); /* Limit -24dB */
|
ALfloat gainHF = maxf(DryGainHF, 0.0625f); /* Limit -24dB */
|
||||||
DryGainLF = maxf(DryGainLF, 0.0625f);
|
ALfloat gainLF = maxf(DryGainLF, 0.0625f);
|
||||||
for(c = 0;c < num_channels;c++)
|
for(c = 0;c < num_channels;c++)
|
||||||
{
|
{
|
||||||
voice->Direct.Params[c].FilterType = AF_None;
|
voice->Direct.Params[c].FilterType = AF_None;
|
||||||
if(DryGainHF != 1.0f) voice->Direct.Params[c].FilterType |= AF_LowPass;
|
if(gainHF != 1.0f) voice->Direct.Params[c].FilterType |= AF_LowPass;
|
||||||
if(DryGainLF != 1.0f) voice->Direct.Params[c].FilterType |= AF_HighPass;
|
if(gainLF != 1.0f) voice->Direct.Params[c].FilterType |= AF_HighPass;
|
||||||
ALfilterState_setParams(
|
ALfilterState_setParams(
|
||||||
&voice->Direct.Params[c].LowPass, ALfilterType_HighShelf,
|
&voice->Direct.Params[c].LowPass, ALfilterType_HighShelf,
|
||||||
DryGainHF, HFScale, calc_rcpQ_from_slope(DryGainHF, 1.0f)
|
gainHF, hfScale, calc_rcpQ_from_slope(gainHF, 1.0f)
|
||||||
);
|
);
|
||||||
ALfilterState_setParams(
|
ALfilterState_setParams(
|
||||||
&voice->Direct.Params[c].HighPass, ALfilterType_LowShelf,
|
&voice->Direct.Params[c].HighPass, ALfilterType_LowShelf,
|
||||||
DryGainLF, LFScale, calc_rcpQ_from_slope(DryGainLF, 1.0f)
|
gainLF, lfScale, calc_rcpQ_from_slope(gainLF, 1.0f)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for(i = 0;i < NumSends;i++)
|
for(i = 0;i < NumSends;i++)
|
||||||
{
|
{
|
||||||
HFScale = props->Send[i].HFReference / Frequency;
|
ALfloat hfScale = props->Send[i].HFReference / Frequency;
|
||||||
LFScale = props->Send[i].LFReference / Frequency;
|
ALfloat lfScale = props->Send[i].LFReference / Frequency;
|
||||||
WetGainHF[i] = maxf(WetGainHF[i], 0.0625f);
|
ALfloat gainHF = maxf(WetGainHF[i], 0.0625f);
|
||||||
WetGainLF[i] = maxf(WetGainLF[i], 0.0625f);
|
ALfloat gainLF = maxf(WetGainLF[i], 0.0625f);
|
||||||
for(c = 0;c < num_channels;c++)
|
for(c = 0;c < num_channels;c++)
|
||||||
{
|
{
|
||||||
voice->Send[i].Params[c].FilterType = AF_None;
|
voice->Send[i].Params[c].FilterType = AF_None;
|
||||||
if(WetGainHF[i] != 1.0f) voice->Send[i].Params[c].FilterType |= AF_LowPass;
|
if(gainHF != 1.0f) voice->Send[i].Params[c].FilterType |= AF_LowPass;
|
||||||
if(WetGainLF[i] != 1.0f) voice->Send[i].Params[c].FilterType |= AF_HighPass;
|
if(gainLF != 1.0f) voice->Send[i].Params[c].FilterType |= AF_HighPass;
|
||||||
ALfilterState_setParams(
|
ALfilterState_setParams(
|
||||||
&voice->Send[i].Params[c].LowPass, ALfilterType_HighShelf,
|
&voice->Send[i].Params[c].LowPass, ALfilterType_HighShelf,
|
||||||
WetGainHF[i], HFScale, calc_rcpQ_from_slope(WetGainHF[i], 1.0f)
|
gainHF, hfScale, calc_rcpQ_from_slope(gainHF, 1.0f)
|
||||||
);
|
);
|
||||||
ALfilterState_setParams(
|
ALfilterState_setParams(
|
||||||
&voice->Send[i].Params[c].HighPass, ALfilterType_LowShelf,
|
&voice->Send[i].Params[c].HighPass, ALfilterType_LowShelf,
|
||||||
WetGainLF[i], LFScale, calc_rcpQ_from_slope(WetGainLF[i], 1.0f)
|
gainLF, lfScale, calc_rcpQ_from_slope(gainLF, 1.0f)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void CalcNonAttnSourceParams(ALvoice *voice, const struct ALvoiceProps *props, const ALbuffer *ALBuffer, const ALCcontext *ALContext)
|
||||||
|
{
|
||||||
|
const ALCdevice *Device = ALContext->Device;
|
||||||
|
const ALlistener *Listener = ALContext->Listener;
|
||||||
|
ALfloat DryGain, DryGainHF, DryGainLF;
|
||||||
|
ALfloat WetGain[MAX_SENDS];
|
||||||
|
ALfloat WetGainHF[MAX_SENDS];
|
||||||
|
ALfloat WetGainLF[MAX_SENDS];
|
||||||
|
ALeffectslot *SendSlots[MAX_SENDS];
|
||||||
|
ALfloat Pitch;
|
||||||
|
ALsizei i;
|
||||||
|
|
||||||
|
voice->Direct.Buffer = Device->Dry.Buffer;
|
||||||
|
voice->Direct.Channels = Device->Dry.NumChannels;
|
||||||
|
for(i = 0;i < Device->NumAuxSends;i++)
|
||||||
|
{
|
||||||
|
SendSlots[i] = props->Send[i].Slot;
|
||||||
|
if(!SendSlots[i] && i == 0)
|
||||||
|
SendSlots[i] = Device->DefaultSlot;
|
||||||
|
if(!SendSlots[i] || SendSlots[i]->Params.EffectType == AL_EFFECT_NULL)
|
||||||
|
{
|
||||||
|
SendSlots[i] = NULL;
|
||||||
|
voice->Send[i].Buffer = NULL;
|
||||||
|
voice->Send[i].Channels = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
voice->Send[i].Buffer = SendSlots[i]->WetBuffer;
|
||||||
|
voice->Send[i].Channels = SendSlots[i]->NumChannels;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Calculate the stepping value */
|
||||||
|
Pitch = (ALfloat)ALBuffer->Frequency/(ALfloat)Device->Frequency * props->Pitch;
|
||||||
|
if(Pitch > (ALfloat)MAX_PITCH)
|
||||||
|
voice->Step = MAX_PITCH<<FRACTIONBITS;
|
||||||
|
else
|
||||||
|
voice->Step = maxi(fastf2i(Pitch*FRACTIONONE + 0.5f), 1);
|
||||||
|
BsincPrepare(voice->Step, &voice->ResampleState.bsinc);
|
||||||
|
voice->Resampler = SelectResampler(props->Resampler);
|
||||||
|
|
||||||
|
/* Calculate gains */
|
||||||
|
DryGain = clampf(props->Gain, props->MinGain, props->MaxGain);
|
||||||
|
DryGain *= props->Direct.Gain * Listener->Params.Gain;
|
||||||
|
DryGain = minf(DryGain, GAIN_MIX_MAX);
|
||||||
|
DryGainHF = props->Direct.GainHF;
|
||||||
|
DryGainLF = props->Direct.GainLF;
|
||||||
|
for(i = 0;i < Device->NumAuxSends;i++)
|
||||||
|
{
|
||||||
|
WetGain[i] = clampf(props->Gain, props->MinGain, props->MaxGain);
|
||||||
|
WetGain[i] *= props->Send[i].Gain * Listener->Params.Gain;
|
||||||
|
WetGain[i] = minf(WetGain[i], GAIN_MIX_MAX);
|
||||||
|
WetGainHF[i] = props->Send[i].GainHF;
|
||||||
|
WetGainLF[i] = props->Send[i].GainLF;
|
||||||
|
}
|
||||||
|
|
||||||
|
CalcPanningAndFilters(voice, DryGain, DryGainHF, DryGainLF, WetGain, WetGainLF, WetGainHF,
|
||||||
|
SendSlots, ALBuffer, props, Listener, Device);
|
||||||
|
}
|
||||||
|
|
||||||
static void CalcAttnSourceParams(ALvoice *voice, const struct ALvoiceProps *props, const ALbuffer *ALBuffer, const ALCcontext *ALContext)
|
static void CalcAttnSourceParams(ALvoice *voice, const struct ALvoiceProps *props, const ALbuffer *ALBuffer, const ALCcontext *ALContext)
|
||||||
{
|
{
|
||||||
const ALCdevice *Device = ALContext->Device;
|
const ALCdevice *Device = ALContext->Device;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user