Add an option for pair-wise stereo panning
This commit is contained in:
@@ -1972,8 +1972,8 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
|
||||
}
|
||||
|
||||
device->Hrtf = NULL;
|
||||
device->Hrtf_Mode = DisabledHrtf;
|
||||
al_string_clear(&device->Hrtf_Name);
|
||||
device->Render_Mode = NormalRender;
|
||||
if(device->FmtChans != DevFmtStereo)
|
||||
{
|
||||
if(hrtf_appreq == Hrtf_Enable)
|
||||
@@ -1982,7 +1982,7 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
|
||||
else
|
||||
{
|
||||
bool headphones = device->IsHeadphones;
|
||||
enum HrtfMode hrtf_mode = FullHrtf;
|
||||
enum RenderMode render_mode = HrtfRender;
|
||||
ALCenum hrtf_status = device->Hrtf_Status;
|
||||
const char *mode;
|
||||
int bs2blevel;
|
||||
@@ -2003,9 +2003,9 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
|
||||
if(ConfigValueStr(al_string_get_cstr(device->DeviceName), NULL, "hrtf-mode", &mode))
|
||||
{
|
||||
if(strcasecmp(mode, "full") == 0)
|
||||
hrtf_mode = FullHrtf;
|
||||
render_mode = HrtfRender;
|
||||
else if(strcasecmp(mode, "basic") == 0)
|
||||
hrtf_mode = BasicHrtf;
|
||||
render_mode = NormalRender;
|
||||
else
|
||||
ERR("Unexpected hrtf-mode: %s\n", mode);
|
||||
}
|
||||
@@ -2068,8 +2068,8 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
|
||||
}
|
||||
if(device->Hrtf)
|
||||
{
|
||||
device->Hrtf_Mode = hrtf_mode;
|
||||
device->Hrtf_Status = hrtf_status;
|
||||
device->Render_Mode = render_mode;
|
||||
TRACE("HRTF enabled, \"%s\"\n", al_string_get_cstr(device->Hrtf_Name));
|
||||
}
|
||||
else
|
||||
@@ -2084,14 +2084,30 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
|
||||
{
|
||||
device->Bs2b = al_calloc(16, sizeof(*device->Bs2b));
|
||||
bs2b_set_params(device->Bs2b, bs2blevel, device->Frequency);
|
||||
device->Render_Mode = StereoPair;
|
||||
TRACE("BS2B enabled\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
TRACE("BS2B disabled\n");
|
||||
}
|
||||
|
||||
device->Uhj_Encoder = al_calloc(16, sizeof(Uhj2Encoder));
|
||||
render_mode = NormalRender;
|
||||
if(ConfigValueStr(al_string_get_cstr(device->DeviceName), NULL, "stereo-panning", &mode))
|
||||
{
|
||||
if(strcasecmp(mode, "paired") == 0)
|
||||
render_mode = StereoPair;
|
||||
else if(strcasecmp(mode, "uhj") != 0)
|
||||
ERR("Unexpected stereo-panning: %s\n", mode);
|
||||
}
|
||||
device->Render_Mode = render_mode;
|
||||
if(render_mode == NormalRender)
|
||||
{
|
||||
device->Uhj_Encoder = al_calloc(16, sizeof(Uhj2Encoder));
|
||||
TRACE("UHJ enabled\n");
|
||||
}
|
||||
else
|
||||
TRACE("UHJ disabled\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3342,7 +3358,7 @@ ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName)
|
||||
device->Uhj_Encoder = NULL;
|
||||
VECTOR_INIT(device->Hrtf_List);
|
||||
AL_STRING_INIT(device->Hrtf_Name);
|
||||
device->Hrtf_Mode = DisabledHrtf;
|
||||
device->Render_Mode = NormalRender;
|
||||
AL_STRING_INIT(device->DeviceName);
|
||||
device->DryBuffer = NULL;
|
||||
|
||||
@@ -3787,7 +3803,7 @@ ALC_API ALCdevice* ALC_APIENTRY alcLoopbackOpenDeviceSOFT(const ALCchar *deviceN
|
||||
AL_STRING_INIT(device->Hrtf_Name);
|
||||
device->Bs2b = NULL;
|
||||
device->Uhj_Encoder = NULL;
|
||||
device->Hrtf_Mode = DisabledHrtf;
|
||||
device->Render_Mode = NormalRender;
|
||||
AL_STRING_INIT(device->DeviceName);
|
||||
device->DryBuffer = NULL;
|
||||
|
||||
|
||||
@@ -577,9 +577,9 @@ ALvoid CalcNonAttnSourceParams(ALvoice *voice, const ALsource *ALSource, const A
|
||||
{
|
||||
if(Device->Hrtf || Device->Uhj_Encoder)
|
||||
{
|
||||
/* DirectChannels with HRTF enabled. Skip the virtual channels
|
||||
* and write FrontLeft and FrontRight inputs to the first and
|
||||
* second outputs.
|
||||
/* DirectChannels with HRTF or UHJ enabled. Skip the virtual
|
||||
* channels and write FrontLeft and FrontRight inputs to the
|
||||
* first and second outputs.
|
||||
*/
|
||||
voice->Direct.OutBuffer += voice->Direct.OutChannels;
|
||||
voice->Direct.OutChannels = 2;
|
||||
@@ -627,7 +627,7 @@ ALvoid CalcNonAttnSourceParams(ALvoice *voice, const ALsource *ALSource, const A
|
||||
|
||||
voice->IsHrtf = AL_FALSE;
|
||||
}
|
||||
else if(Device->Hrtf_Mode == FullHrtf)
|
||||
else if(Device->Render_Mode == HrtfRender)
|
||||
{
|
||||
/* Full HRTF rendering. Skip the virtual channels and render each
|
||||
* input channel to the real outputs.
|
||||
@@ -686,7 +686,7 @@ ALvoid CalcNonAttnSourceParams(ALvoice *voice, const ALsource *ALSource, const A
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Basic or no HRTF rendering. Use normal panning to the output. */
|
||||
/* Non-HRTF rendering. Use normal panning to the output. */
|
||||
for(c = 0;c < num_channels;c++)
|
||||
{
|
||||
/* Special-case LFE */
|
||||
@@ -707,9 +707,24 @@ ALvoid CalcNonAttnSourceParams(ALvoice *voice, const ALsource *ALSource, const A
|
||||
continue;
|
||||
}
|
||||
|
||||
CalcAngleCoeffs(chans[c].angle, chans[c].elevation, coeffs);
|
||||
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.5;
|
||||
voice->Direct.Gains[c].Target[0] = coeffs[0] * DryGain;
|
||||
voice->Direct.Gains[c].Target[1] = (1.0f-coeffs[0]) * DryGain;
|
||||
for(j = 2;j < MAX_OUTPUT_CHANNELS;j++)
|
||||
voice->Direct.Gains[c].Target[j] = 0.0f;
|
||||
|
||||
ComputePanningGains(Device->AmbiCoeffs, Device->NumChannels, coeffs, DryGain, voice->Direct.Gains[c].Target);
|
||||
CalcAngleCoeffs(chans[c].angle, chans[c].elevation, coeffs);
|
||||
}
|
||||
else
|
||||
{
|
||||
CalcAngleCoeffs(chans[c].angle, chans[c].elevation, coeffs);
|
||||
ComputePanningGains(Device->AmbiCoeffs, Device->NumChannels, coeffs, DryGain,
|
||||
voice->Direct.Gains[c].Target);
|
||||
}
|
||||
|
||||
for(i = 0;i < NumSends;i++)
|
||||
{
|
||||
@@ -1105,7 +1120,7 @@ ALvoid CalcSourceParams(ALvoice *voice, const ALsource *ALSource, const ALCconte
|
||||
BufferListItem = BufferListItem->next;
|
||||
}
|
||||
|
||||
if(Device->Hrtf_Mode == FullHrtf)
|
||||
if(Device->Render_Mode == HrtfRender)
|
||||
{
|
||||
/* Full HRTF rendering. Skip the virtual channels and render to the
|
||||
* real outputs.
|
||||
@@ -1170,7 +1185,7 @@ ALvoid CalcSourceParams(ALvoice *voice, const ALsource *ALSource, const ALCconte
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Basic or no HRTF rendering. Use normal panning to the output. */
|
||||
/* Non-HRTF rendering. */
|
||||
ALfloat dir[3] = { 0.0f, 0.0f, -1.0f };
|
||||
ALfloat radius = ALSource->Radius;
|
||||
ALfloat coeffs[MAX_AMBI_COEFFS];
|
||||
@@ -1193,10 +1208,24 @@ ALvoid CalcSourceParams(ALvoice *voice, const ALsource *ALSource, const ALCconte
|
||||
dir[1] *= dirfact;
|
||||
dir[2] *= dirfact;
|
||||
}
|
||||
CalcDirectionCoeffs(dir, coeffs);
|
||||
|
||||
ComputePanningGains(Device->AmbiCoeffs, Device->NumChannels, coeffs, DryGain,
|
||||
voice->Direct.Gains[0].Target);
|
||||
if(Device->Render_Mode == StereoPair)
|
||||
{
|
||||
/* Clamp X so it remains within 30 degrees of 0 or 180 degree azimuth. */
|
||||
coeffs[0] = clampf(-dir[0], -0.5f, 0.5f) + 0.5;
|
||||
voice->Direct.Gains[0].Target[0] = coeffs[0] * DryGain;
|
||||
voice->Direct.Gains[0].Target[1] = (1.0f-coeffs[0]) * DryGain;
|
||||
for(i = 2;i < MAX_OUTPUT_CHANNELS;i++)
|
||||
voice->Direct.Gains[0].Target[i] = 0.0f;
|
||||
|
||||
CalcDirectionCoeffs(dir, coeffs);
|
||||
}
|
||||
else
|
||||
{
|
||||
CalcDirectionCoeffs(dir, coeffs);
|
||||
ComputePanningGains(Device->AmbiCoeffs, Device->NumChannels, coeffs, DryGain,
|
||||
voice->Direct.Gains[0].Target);
|
||||
}
|
||||
|
||||
for(i = 0;i < NumSends;i++)
|
||||
{
|
||||
|
||||
@@ -387,10 +387,10 @@ enum DeviceType {
|
||||
};
|
||||
|
||||
|
||||
enum HrtfMode {
|
||||
DisabledHrtf,
|
||||
BasicHrtf,
|
||||
FullHrtf
|
||||
enum RenderMode {
|
||||
NormalRender,
|
||||
StereoPair,
|
||||
HrtfRender
|
||||
};
|
||||
|
||||
|
||||
@@ -465,7 +465,6 @@ struct ALCdevice_struct
|
||||
al_string Hrtf_Name;
|
||||
const struct Hrtf *Hrtf;
|
||||
ALCenum Hrtf_Status;
|
||||
enum HrtfMode Hrtf_Mode;
|
||||
HrtfState Hrtf_State[MAX_OUTPUT_CHANNELS];
|
||||
HrtfParams Hrtf_Params[MAX_OUTPUT_CHANNELS];
|
||||
ALuint Hrtf_Offset;
|
||||
@@ -476,6 +475,9 @@ struct ALCdevice_struct
|
||||
// Stereo-to-binaural filter
|
||||
struct bs2b *Bs2b;
|
||||
|
||||
/* Rendering mode. */
|
||||
enum RenderMode Render_Mode;
|
||||
|
||||
// Device flags
|
||||
ALuint Flags;
|
||||
|
||||
|
||||
@@ -86,6 +86,14 @@
|
||||
# Valid settings are auto, speakers, and headphones.
|
||||
#stereo-mode = auto
|
||||
|
||||
## stereo-panning:
|
||||
# Specifies the panning method for non-HRTF stereo output. uhj (default)
|
||||
# creates stereo-compatible two-channel UHJ output, which encodes some
|
||||
# surround sound information, while paired uses standard pair-wise panning
|
||||
# between -30 and +30 degrees. If crossfeed filters are used, uhj panning is
|
||||
# disabled.
|
||||
#stereo-panning = uhj
|
||||
|
||||
## hrtf:
|
||||
# Controls HRTF processing. These filters provide better spatialization of
|
||||
# sounds while using headphones, but do require a bit more CPU power. The
|
||||
|
||||
Reference in New Issue
Block a user