Use a function pointer for applying the dry mix post-process

This commit is contained in:
Chris Robinson 2018-02-10 15:50:05 -08:00
parent ee3d53a673
commit 5b11129eaa
4 changed files with 106 additions and 70 deletions

View File

@ -2216,6 +2216,8 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
}
TRACE("Output limiter %s\n", device->Limiter ? "enabled" : "disabled");
aluSelectPostProcess(device);
/* Need to delay returning failure until replacement Send arrays have been
* allocated with the appropriate size.
*/

165
Alc/ALu.c
View File

@ -208,6 +208,98 @@ void aluInit(void)
MixDirectHrtf = SelectHrtfMixer();
}
static void ProcessHrtf(ALCdevice *device, ALsizei SamplesToDo)
{
DirectHrtfState *state;
int lidx, ridx;
ALsizei c;
if(device->AmbiUp)
ambiup_process(device->AmbiUp,
device->Dry.Buffer, device->Dry.NumChannels, device->FOAOut.Buffer,
SamplesToDo
);
lidx = GetChannelIdxByName(&device->RealOut, FrontLeft);
ridx = GetChannelIdxByName(&device->RealOut, FrontRight);
assert(lidx != -1 && ridx != -1);
state = device->Hrtf;
for(c = 0;c < device->Dry.NumChannels;c++)
{
MixDirectHrtf(device->RealOut.Buffer[lidx], device->RealOut.Buffer[ridx],
device->Dry.Buffer[c], state->Offset, state->IrSize,
state->Chan[c].Coeffs, state->Chan[c].Values, SamplesToDo
);
}
state->Offset += SamplesToDo;
}
static void ProcessAmbiDec(ALCdevice *device, ALsizei SamplesToDo)
{
if(device->Dry.Buffer != device->FOAOut.Buffer)
bformatdec_upSample(device->AmbiDecoder,
device->Dry.Buffer, device->FOAOut.Buffer, device->FOAOut.NumChannels,
SamplesToDo
);
bformatdec_process(device->AmbiDecoder,
device->RealOut.Buffer, device->RealOut.NumChannels, device->Dry.Buffer,
SamplesToDo
);
}
static void ProcessAmbiUp(ALCdevice *device, ALsizei SamplesToDo)
{
ambiup_process(device->AmbiUp,
device->RealOut.Buffer, device->RealOut.NumChannels, device->FOAOut.Buffer,
SamplesToDo
);
}
static void ProcessUhj(ALCdevice *device, ALsizei SamplesToDo)
{
int lidx = GetChannelIdxByName(&device->RealOut, FrontLeft);
int ridx = GetChannelIdxByName(&device->RealOut, FrontRight);
if(LIKELY(lidx != -1 && ridx != -1))
{
/* Encode to stereo-compatible 2-channel UHJ output. */
EncodeUhj2(device->Uhj_Encoder,
device->RealOut.Buffer[lidx], device->RealOut.Buffer[ridx],
device->Dry.Buffer, SamplesToDo
);
}
}
static void ProcessBs2b(ALCdevice *device, ALsizei SamplesToDo)
{
int lidx = GetChannelIdxByName(&device->RealOut, FrontLeft);
int ridx = GetChannelIdxByName(&device->RealOut, FrontRight);
if(LIKELY(lidx != -1 && ridx != -1))
{
/* Apply binaural/crossfeed filter */
bs2b_cross_feed(device->Bs2b, device->RealOut.Buffer[lidx],
device->RealOut.Buffer[ridx], SamplesToDo);
}
}
void aluSelectPostProcess(ALCdevice *device)
{
if(device->HrtfHandle)
device->PostProcess = ProcessHrtf;
else if(device->AmbiDecoder)
device->PostProcess = ProcessAmbiDec;
else if(device->AmbiUp)
device->PostProcess = ProcessAmbiUp;
else if(device->Uhj_Encoder)
device->PostProcess = ProcessUhj;
else if(device->Bs2b)
device->PostProcess = ProcessBs2b;
else
device->PostProcess = NULL;
}
/* Prepares the interpolator for a given rate (determined by increment). A
* result of AL_FALSE indicates that the filter output will completely cut
* the input signal.
@ -1723,74 +1815,11 @@ void aluMixData(ALCdevice *device, ALvoid *OutBuffer, ALsizei NumSamples)
device->SamplesDone %= device->Frequency;
IncrementRef(&device->MixCount);
if(device->HrtfHandle)
{
DirectHrtfState *state;
int lidx, ridx;
if(device->AmbiUp)
ambiup_process(device->AmbiUp,
device->Dry.Buffer, device->Dry.NumChannels, device->FOAOut.Buffer,
SamplesToDo
);
lidx = GetChannelIdxByName(&device->RealOut, FrontLeft);
ridx = GetChannelIdxByName(&device->RealOut, FrontRight);
assert(lidx != -1 && ridx != -1);
state = device->Hrtf;
for(c = 0;c < device->Dry.NumChannels;c++)
{
MixDirectHrtf(device->RealOut.Buffer[lidx], device->RealOut.Buffer[ridx],
device->Dry.Buffer[c], state->Offset, state->IrSize,
state->Chan[c].Coeffs, state->Chan[c].Values, SamplesToDo
);
}
state->Offset += SamplesToDo;
}
else if(device->AmbiDecoder)
{
if(device->Dry.Buffer != device->FOAOut.Buffer)
bformatdec_upSample(device->AmbiDecoder,
device->Dry.Buffer, device->FOAOut.Buffer, device->FOAOut.NumChannels,
SamplesToDo
);
bformatdec_process(device->AmbiDecoder,
device->RealOut.Buffer, device->RealOut.NumChannels, device->Dry.Buffer,
SamplesToDo
);
}
else if(device->AmbiUp)
{
ambiup_process(device->AmbiUp,
device->RealOut.Buffer, device->RealOut.NumChannels, device->FOAOut.Buffer,
SamplesToDo
);
}
else if(device->Uhj_Encoder)
{
int lidx = GetChannelIdxByName(&device->RealOut, FrontLeft);
int ridx = GetChannelIdxByName(&device->RealOut, FrontRight);
if(lidx != -1 && ridx != -1)
{
/* Encode to stereo-compatible 2-channel UHJ output. */
EncodeUhj2(device->Uhj_Encoder,
device->RealOut.Buffer[lidx], device->RealOut.Buffer[ridx],
device->Dry.Buffer, SamplesToDo
);
}
}
else if(device->Bs2b)
{
int lidx = GetChannelIdxByName(&device->RealOut, FrontLeft);
int ridx = GetChannelIdxByName(&device->RealOut, FrontRight);
if(lidx != -1 && ridx != -1)
{
/* Apply binaural/crossfeed filter */
bs2b_cross_feed(device->Bs2b, device->RealOut.Buffer[lidx],
device->RealOut.Buffer[ridx], SamplesToDo);
}
}
/* Apply post-process for finalizing the Dry mix to the RealOut
* (Ambisonic decode, UHJ encode, etc).
*/
if(LIKELY(device->PostProcess))
device->PostProcess(device, SamplesToDo);
if(OutBuffer)
{

View File

@ -462,8 +462,9 @@ typedef struct RealMixParams {
ALsizei NumChannels;
} RealMixParams;
struct ALCdevice_struct
{
typedef void (*POSTPROCESS)(ALCdevice *device, ALsizei SamplesToDo);
struct ALCdevice_struct {
RefCount ref;
ATOMIC(ALenum) Connected;
@ -507,6 +508,8 @@ struct ALCdevice_struct
vector_FilterSubList FilterList;
almtx_t FilterLock;
POSTPROCESS PostProcess;
/* HRTF state and info */
struct DirectHrtfState *Hrtf;
al_string HrtfName;

View File

@ -429,6 +429,8 @@ void aluInitRenderer(ALCdevice *device, ALint hrtf_id, enum HrtfRequestMode hrtf
void aluInitEffectPanning(struct ALeffectslot *slot);
void aluSelectPostProcess(ALCdevice *device);
/**
* CalcDirectionCoeffs
*