aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Robinson <[email protected]>2016-02-26 21:48:03 -0800
committerChris Robinson <[email protected]>2016-02-26 21:48:03 -0800
commit99f685d20d0e9bece99a6019a98d8cb3aecef227 (patch)
treea000504d28b7228402b95d48700b1bf339148ca2
parentac91083ceb27892ce1d474a578634bff580b56d3 (diff)
Add an option for pair-wise stereo panning
-rw-r--r--Alc/ALc.c34
-rw-r--r--Alc/ALu.c53
-rw-r--r--OpenAL32/Include/alMain.h12
-rw-r--r--alsoftrc.sample8
4 files changed, 81 insertions, 26 deletions
diff --git a/Alc/ALc.c b/Alc/ALc.c
index 01fc8a34..fd44ed28 100644
--- a/Alc/ALc.c
+++ b/Alc/ALc.c
@@ -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;
diff --git a/Alc/ALu.c b/Alc/ALu.c
index 41d9a3fb..38a4ef71 100644
--- a/Alc/ALu.c
+++ b/Alc/ALu.c
@@ -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++)
{
diff --git a/OpenAL32/Include/alMain.h b/OpenAL32/Include/alMain.h
index f9532727..8c75cb83 100644
--- a/OpenAL32/Include/alMain.h
+++ b/OpenAL32/Include/alMain.h
@@ -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;
diff --git a/alsoftrc.sample b/alsoftrc.sample
index 7d73b7c6..255f82d0 100644
--- a/alsoftrc.sample
+++ b/alsoftrc.sample
@@ -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