aboutsummaryrefslogtreecommitdiffstats
path: root/Alc
diff options
context:
space:
mode:
authorChris Robinson <[email protected]>2016-02-26 16:09:06 -0800
committerChris Robinson <[email protected]>2016-02-26 16:09:06 -0800
commitac91083ceb27892ce1d474a578634bff580b56d3 (patch)
tree91d10d8ab79d17e5b44c6876ccca5cfa2a553639 /Alc
parent67f086d1d4527d1c920d90660124c5592b898354 (diff)
Use 2-channel UHJ for stereo output
Diffstat (limited to 'Alc')
-rw-r--r--Alc/ALc.c33
-rw-r--r--Alc/ALu.c61
-rw-r--r--Alc/effects/reverb.c12
-rw-r--r--Alc/panning.c22
4 files changed, 76 insertions, 52 deletions
diff --git a/Alc/ALc.c b/Alc/ALc.c
index d116650f..01fc8a34 100644
--- a/Alc/ALc.c
+++ b/Alc/ALc.c
@@ -36,6 +36,7 @@
#include "alAuxEffectSlot.h"
#include "alError.h"
#include "bs2b.h"
+#include "uhjfilter.h"
#include "alu.h"
#include "compat.h"
@@ -1846,6 +1847,12 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
if((device->Flags&DEVICE_RUNNING))
return ALC_NO_ERROR;
+ al_free(device->Uhj_Encoder);
+ device->Uhj_Encoder = NULL;
+
+ al_free(device->Bs2b);
+ device->Bs2b = NULL;
+
al_free(device->DryBuffer);
device->DryBuffer = NULL;
@@ -1971,9 +1978,6 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
{
if(hrtf_appreq == Hrtf_Enable)
device->Hrtf_Status = ALC_HRTF_UNSUPPORTED_FORMAT_SOFT;
-
- free(device->Bs2b);
- device->Bs2b = NULL;
}
else
{
@@ -2067,8 +2071,6 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
device->Hrtf_Mode = hrtf_mode;
device->Hrtf_Status = hrtf_status;
TRACE("HRTF enabled, \"%s\"\n", al_string_get_cstr(device->Hrtf_Name));
- free(device->Bs2b);
- device->Bs2b = NULL;
}
else
{
@@ -2080,27 +2082,25 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
ConfigValueInt(al_string_get_cstr(device->DeviceName), NULL, "cf_level", &bs2blevel);
if(bs2blevel > 0 && bs2blevel <= 6)
{
- if(!device->Bs2b)
- {
- device->Bs2b = calloc(1, sizeof(*device->Bs2b));
- bs2b_clear(device->Bs2b);
- }
+ device->Bs2b = al_calloc(16, sizeof(*device->Bs2b));
bs2b_set_params(device->Bs2b, bs2blevel, device->Frequency);
TRACE("BS2B enabled\n");
}
else
{
- free(device->Bs2b);
- device->Bs2b = NULL;
TRACE("BS2B disabled\n");
}
+
+ device->Uhj_Encoder = al_calloc(16, sizeof(Uhj2Encoder));
}
}
aluInitPanning(device);
/* With HRTF, allocate two extra channels for the post-filter output. */
- size = sizeof(device->DryBuffer[0]) * (device->NumChannels + (device->Hrtf ? 2 : 0));
+ size = device->NumChannels * sizeof(device->DryBuffer[0]);
+ if(device->Hrtf || device->Uhj_Encoder)
+ size += 2 * sizeof(device->DryBuffer[0]);
device->DryBuffer = al_calloc(16, size);
if(!device->DryBuffer)
{
@@ -2235,9 +2235,12 @@ static ALCvoid FreeDevice(ALCdevice *device)
AL_STRING_DEINIT(device->Hrtf_Name);
FreeHrtfList(&device->Hrtf_List);
- free(device->Bs2b);
+ al_free(device->Bs2b);
device->Bs2b = NULL;
+ al_free(device->Uhj_Encoder);
+ device->Uhj_Encoder = NULL;
+
AL_STRING_DEINIT(device->DeviceName);
al_free(device->DryBuffer);
@@ -3336,6 +3339,7 @@ ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName)
device->Flags = 0;
device->Bs2b = NULL;
+ device->Uhj_Encoder = NULL;
VECTOR_INIT(device->Hrtf_List);
AL_STRING_INIT(device->Hrtf_Name);
device->Hrtf_Mode = DisabledHrtf;
@@ -3782,6 +3786,7 @@ ALC_API ALCdevice* ALC_APIENTRY alcLoopbackOpenDeviceSOFT(const ALCchar *deviceN
VECTOR_INIT(device->Hrtf_List);
AL_STRING_INIT(device->Hrtf_Name);
device->Bs2b = NULL;
+ device->Uhj_Encoder = NULL;
device->Hrtf_Mode = DisabledHrtf;
AL_STRING_INIT(device->DeviceName);
device->DryBuffer = NULL;
diff --git a/Alc/ALu.c b/Alc/ALu.c
index d4dac1ab..41d9a3fb 100644
--- a/Alc/ALu.c
+++ b/Alc/ALu.c
@@ -34,6 +34,7 @@
#include "alu.h"
#include "bs2b.h"
#include "hrtf.h"
+#include "uhjfilter.h"
#include "static_assert.h"
#include "mixer_defs.h"
@@ -100,19 +101,18 @@ extern inline void aluMatrixdSet(aluMatrixd *matrix,
ALdouble m30, ALdouble m31, ALdouble m32, ALdouble m33);
-/* NOTE: HRTF is set up a bit special in the device. By default, without HRTF,
- * the device's DryBuffer, NumChannels, ChannelName, and Channel fields
- * correspond to the output format, and the DryBuffer is then converted and
- * written to the backend's audio buffer.
+/* NOTE: HRTF and UHJ are set up a bit special in the device. Normally the
+ * device's DryBuffer, NumChannels, ChannelName, and Channel fields correspond
+ * to the output format, and the DryBuffer is then converted and written to the
+ * backend's audio buffer.
*
- * With HRTF, these fields correspond to a virtual format, and the actual
- * output is stored in DryBuffer[NumChannels] for the left channel and
+ * With HRTF or UHJ, these fields correspond to a virtual format, and the
+ * actual output is stored in DryBuffer[NumChannels] for the left channel and
* DryBuffer[NumChannels+1] for the right. As a final output step,
- * the virtual channels will have HRTF applied and written to the actual
- * output. Things like effects and B-Format decoding will want to write to the
- * virtual channels so that they can be mixed with HRTF in full 3D.
+ * the virtual channels will have HRTF filters or UHJ encoding applied and
+ * written to the actual output.
*
- * Sources that get mixed using HRTF directly (or that want to skip HRTF
+ * Sources that get mixed using HRTF directly (or that want to skip HRTF or UHJ
* completely) will need to offset the output buffer so that they skip the
* virtual output and write to the actual output channels. This is the reason
* you'll see
@@ -327,9 +327,6 @@ ALvoid CalcNonAttnSourceParams(ALvoice *voice, const ALsource *ALSource, const A
}, StereoMap[2] = {
{ FrontLeft, DEG2RAD(-30.0f), DEG2RAD(0.0f) },
{ FrontRight, DEG2RAD( 30.0f), DEG2RAD(0.0f) }
- }, StereoWideMap[2] = {
- { FrontLeft, DEG2RAD(-90.0f), DEG2RAD(0.0f) },
- { FrontRight, DEG2RAD( 90.0f), DEG2RAD(0.0f) }
}, RearMap[2] = {
{ BackLeft, DEG2RAD(-150.0f), DEG2RAD(0.0f) },
{ BackRight, DEG2RAD( 150.0f), DEG2RAD(0.0f) }
@@ -459,13 +456,7 @@ ALvoid CalcNonAttnSourceParams(ALvoice *voice, const ALsource *ALSource, const A
break;
case FmtStereo:
- /* 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;
+ chans = StereoMap;
num_channels = 2;
break;
@@ -584,7 +575,7 @@ ALvoid CalcNonAttnSourceParams(ALvoice *voice, const ALsource *ALSource, const A
if(DirectChannels)
{
- if(Device->Hrtf)
+ if(Device->Hrtf || Device->Uhj_Encoder)
{
/* DirectChannels with HRTF enabled. Skip the virtual channels
* and write FrontLeft and FrontRight inputs to the first and
@@ -1384,7 +1375,7 @@ ALvoid aluMixData(ALCdevice *device, ALvoid *buffer, ALsizei size)
SamplesToDo = minu(size, BUFFERSIZE);
for(c = 0;c < OutChannels;c++)
memset(OutBuffer[c], 0, SamplesToDo*sizeof(ALfloat));
- if(device->Hrtf)
+ if(device->Hrtf || device->Uhj_Encoder)
{
/* Set OutBuffer/OutChannels to correspond to the actual output
* with HRTF. Make sure to clear them too. */
@@ -1485,17 +1476,25 @@ ALvoid aluMixData(ALCdevice *device, ALvoid *buffer, ALsizei size)
}
device->Hrtf_Offset += SamplesToDo;
}
- else if(device->Bs2b)
+ else
{
- /* Apply binaural/crossfeed filter */
- for(i = 0;i < SamplesToDo;i++)
+ if(device->Uhj_Encoder)
{
- float samples[2];
- samples[0] = device->DryBuffer[0][i];
- samples[1] = device->DryBuffer[1][i];
- bs2b_cross_feed(device->Bs2b, samples);
- device->DryBuffer[0][i] = samples[0];
- device->DryBuffer[1][i] = samples[1];
+ /* Encode to stereo-compatible 2-channel UHJ output. */
+ EncodeUhj2(device->Uhj_Encoder, OutBuffer, device->DryBuffer, SamplesToDo);
+ }
+ if(device->Bs2b)
+ {
+ /* Apply binaural/crossfeed filter */
+ for(i = 0;i < SamplesToDo;i++)
+ {
+ float samples[2];
+ samples[0] = OutBuffer[0][i];
+ samples[1] = OutBuffer[1][i];
+ bs2b_cross_feed(device->Bs2b, samples);
+ OutBuffer[0][i] = samples[0];
+ OutBuffer[1][i] = samples[1];
+ }
}
}
diff --git a/Alc/effects/reverb.c b/Alc/effects/reverb.c
index 103db906..7bbdb8a7 100644
--- a/Alc/effects/reverb.c
+++ b/Alc/effects/reverb.c
@@ -659,7 +659,7 @@ static ALvoid UpdateEchoLine(ALfloat echoTime, ALfloat decayTime, ALfloat diffus
}
// Update the early and late 3D panning gains.
-static ALvoid UpdateHrtfPanning(const ALCdevice *Device, const ALfloat *ReflectionsPan, const ALfloat *LateReverbPan, ALfloat Gain, ALfloat EarlyGain, ALfloat LateGain, ALreverbState *State)
+static ALvoid UpdateMixedPanning(const ALCdevice *Device, const ALfloat *ReflectionsPan, const ALfloat *LateReverbPan, ALfloat Gain, ALfloat EarlyGain, ALfloat LateGain, ALreverbState *State)
{
ALfloat DirGains[MAX_OUTPUT_CHANNELS];
ALfloat coeffs[MAX_AMBI_COEFFS];
@@ -925,11 +925,11 @@ static ALvoid ALreverbState_update(ALreverbState *State, const ALCdevice *Device
gain = props->Reverb.Gain * Slot->Gain * ReverbBoost;
// Update early and late 3D panning.
- if(Device->Hrtf)
- UpdateHrtfPanning(Device, props->Reverb.ReflectionsPan,
- props->Reverb.LateReverbPan, gain,
- props->Reverb.ReflectionsGain,
- props->Reverb.LateReverbGain, State);
+ if(Device->Hrtf || Device->Uhj_Encoder)
+ UpdateMixedPanning(Device, props->Reverb.ReflectionsPan,
+ props->Reverb.LateReverbPan, gain,
+ props->Reverb.ReflectionsGain,
+ props->Reverb.LateReverbGain, State);
else if(Device->FmtChans == DevFmtBFormat3D)
Update3DPanning(Device, props->Reverb.ReflectionsPan,
props->Reverb.LateReverbPan, gain,
diff --git a/Alc/panning.c b/Alc/panning.c
index 9f1e87d7..b17df007 100644
--- a/Alc/panning.c
+++ b/Alc/panning.c
@@ -484,6 +484,10 @@ ALvoid aluInitPanning(ALCdevice *device)
{ LowerFrontRight, { 0.176776695f, 0.072168784f, -0.072168784f, -0.072168784f } },
{ LowerBackLeft, { 0.176776695f, -0.072168784f, 0.072168784f, -0.072168784f } },
{ LowerBackRight, { 0.176776695f, -0.072168784f, -0.072168784f, -0.072168784f } },
+ }, BFormat2D[3] = {
+ { BFormatW, { 1.0f, 0.0f, 0.0f, 0.0f } },
+ { BFormatX, { 0.0f, 1.0f, 0.0f, 0.0f } },
+ { BFormatY, { 0.0f, 0.0f, 1.0f, 0.0f } },
}, BFormat3D[4] = {
{ BFormatW, { 1.0f, 0.0f, 0.0f, 0.0f } },
{ BFormatX, { 0.0f, 1.0f, 0.0f, 0.0f } },
@@ -493,6 +497,7 @@ ALvoid aluInitPanning(ALCdevice *device)
const ChannelMap *chanmap = NULL;
ALfloat ambiscale = 1.0f;
size_t count = 0;
+ ALuint i;
device->AmbiScale = 1.0f;
memset(device->AmbiCoeffs, 0, sizeof(device->AmbiCoeffs));
@@ -514,7 +519,6 @@ ALvoid aluInitPanning(ALCdevice *device)
{ LowerBackLeft, DEG2RAD(-135.0f), DEG2RAD(-45.0f) },
{ LowerBackRight, DEG2RAD( 135.0f), DEG2RAD(-45.0f) },
};
- ALuint i;
count = COUNTOF(Cube8Cfg);
chanmap = Cube8Cfg;
@@ -536,6 +540,22 @@ ALvoid aluInitPanning(ALCdevice *device)
}
return;
}
+ if(device->Uhj_Encoder)
+ {
+ count = COUNTOF(BFormat2D);
+ chanmap = BFormat2D;
+ ambiscale = FIRST_ORDER_SCALE;
+
+ for(i = 0;i < count;i++)
+ device->ChannelName[i] = chanmap[i].ChanName;
+ for(;i < MAX_OUTPUT_CHANNELS;i++)
+ device->ChannelName[i] = InvalidChannel;
+ SetChannelMap(device->ChannelName, device->AmbiCoeffs, chanmap, count,
+ &device->NumChannels, AL_TRUE);
+ device->AmbiScale = ambiscale;
+
+ return;
+ }
if(LoadChannelSetup(device))
return;