Add an option for pair-wise stereo panning

This commit is contained in:
Chris Robinson
2016-02-26 21:48:03 -08:00
parent ac91083ceb
commit 99f685d20d
4 changed files with 81 additions and 26 deletions
+25 -9
View File
@@ -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;
+41 -12
View File
@@ -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++)
{
+7 -5
View File
@@ -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;
+8
View File
@@ -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