diff options
author | Chris Robinson <[email protected]> | 2016-02-26 16:09:06 -0800 |
---|---|---|
committer | Chris Robinson <[email protected]> | 2016-02-26 16:09:06 -0800 |
commit | ac91083ceb27892ce1d474a578634bff580b56d3 (patch) | |
tree | 91d10d8ab79d17e5b44c6876ccca5cfa2a553639 /Alc | |
parent | 67f086d1d4527d1c920d90660124c5592b898354 (diff) |
Use 2-channel UHJ for stereo output
Diffstat (limited to 'Alc')
-rw-r--r-- | Alc/ALc.c | 33 | ||||
-rw-r--r-- | Alc/ALu.c | 61 | ||||
-rw-r--r-- | Alc/effects/reverb.c | 12 | ||||
-rw-r--r-- | Alc/panning.c | 22 |
4 files changed, 76 insertions, 52 deletions
@@ -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; @@ -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; |