openal-soft/Alc/mixer/hrtf_inc.cpp
2018-12-31 23:33:04 -08:00

196 lines
6.8 KiB
C++

#include "config.h"
#include "alMain.h"
#include "alSource.h"
#include "hrtf.h"
#include "alu.h"
#include "defs.h"
static inline void ApplyCoeffs(ALsizei Offset, ALfloat (&Values)[HRIR_LENGTH][2],
const ALsizei irSize, const ALfloat (&Coeffs)[HRIR_LENGTH][2],
const ALfloat left, const ALfloat right);
void MixHrtf(ALfloat *RESTRICT LeftOut, ALfloat *RESTRICT RightOut,
const ALfloat *data, ALsizei Offset, const ALsizei OutPos,
const ALsizei IrSize, MixHrtfParams *hrtfparams, HrtfState *hrtfstate,
const ALsizei BufferSize)
{
ASSUME(OutPos >= 0);
ASSUME(IrSize >= 4);
ASSUME(BufferSize > 0);
const ALfloat (&Coeffs)[HRIR_LENGTH][2] = *hrtfparams->Coeffs;
const ALfloat gainstep{hrtfparams->GainStep};
const ALfloat gain{hrtfparams->Gain};
ALfloat stepcount{0.0f};
ALsizei HistOffset{Offset&HRTF_HISTORY_MASK};
ALsizei Delay[2]{
(HistOffset-hrtfparams->Delay[0])&HRTF_HISTORY_MASK,
(HistOffset-hrtfparams->Delay[1])&HRTF_HISTORY_MASK };
Offset &= HRIR_MASK;
ALsizei HeadOffset{(Offset+IrSize-1)&HRIR_MASK};
LeftOut += OutPos;
RightOut += OutPos;
for(ALsizei i{0};i < BufferSize;)
{
/* Calculate the number of samples we can do until one of the indices
* wraps on its buffer, or we reach the end.
*/
const ALsizei todo_hist{HRTF_HISTORY_LENGTH - maxi(maxi(HistOffset, Delay[0]), Delay[1])};
const ALsizei todo_hrir{HRIR_LENGTH - maxi(HeadOffset, Offset)};
const ALsizei todo{mini(BufferSize-i, mini(todo_hist, todo_hrir)) + i};
ASSUME(todo > i);
for(;i < todo;++i)
{
hrtfstate->Values[HeadOffset][0] = 0.0f;
hrtfstate->Values[HeadOffset][1] = 0.0f;
++HeadOffset;
hrtfstate->History[HistOffset++] = *(data++);
const ALfloat g{gain + gainstep*stepcount};
const ALfloat left{hrtfstate->History[Delay[0]++] * g};
const ALfloat right{hrtfstate->History[Delay[1]++] * g};
ApplyCoeffs(Offset, hrtfstate->Values, IrSize, Coeffs, left, right);
*(LeftOut++) += hrtfstate->Values[Offset][0];
*(RightOut++) += hrtfstate->Values[Offset][1];
++Offset;
stepcount += 1.0f;
}
HeadOffset &= HRIR_MASK;
HistOffset &= HRTF_HISTORY_MASK;
Delay[0] &= HRTF_HISTORY_MASK;
Delay[1] &= HRTF_HISTORY_MASK;
Offset &= HRIR_MASK;
}
hrtfparams->Gain = gain + gainstep*stepcount;
}
void MixHrtfBlend(ALfloat *RESTRICT LeftOut, ALfloat *RESTRICT RightOut,
const ALfloat *data, ALsizei Offset, const ALsizei OutPos,
const ALsizei IrSize, const HrtfParams *oldparams,
MixHrtfParams *newparams, HrtfState *hrtfstate,
const ALsizei BufferSize)
{
const ALfloat (&OldCoeffs)[HRIR_LENGTH][2] = oldparams->Coeffs;
const ALfloat oldGain{oldparams->Gain};
const ALfloat oldGainStep{-oldGain / (ALfloat)BufferSize};
const ALfloat (&NewCoeffs)[HRIR_LENGTH][2] = *newparams->Coeffs;
const ALfloat newGainStep{newparams->GainStep};
ALfloat stepcount{0.0f};
ASSUME(OutPos >= 0);
ASSUME(IrSize >= 4);
ASSUME(BufferSize > 0);
ALsizei HistOffset{Offset&HRTF_HISTORY_MASK};
ALsizei OldDelay[2]{
(HistOffset-oldparams->Delay[0])&HRTF_HISTORY_MASK,
(HistOffset-oldparams->Delay[1])&HRTF_HISTORY_MASK };
ALsizei NewDelay[2]{
(HistOffset-newparams->Delay[0])&HRTF_HISTORY_MASK,
(HistOffset-newparams->Delay[1])&HRTF_HISTORY_MASK };
Offset &= HRIR_MASK;
ALsizei HeadOffset{(Offset+IrSize-1)&HRIR_MASK};
LeftOut += OutPos;
RightOut += OutPos;
for(ALsizei i{0};i < BufferSize;)
{
const ALsizei todo_hist{HRTF_HISTORY_LENGTH -
maxi(maxi(maxi(maxi(HistOffset, OldDelay[0]), OldDelay[1]), NewDelay[0]), NewDelay[1])
};
const ALsizei todo_hrir{HRIR_LENGTH - maxi(HeadOffset, Offset)};
const ALsizei todo{mini(BufferSize-i, mini(todo_hist, todo_hrir)) + i};
ASSUME(todo > i);
for(;i < todo;++i)
{
hrtfstate->Values[HeadOffset][0] = 0.0f;
hrtfstate->Values[HeadOffset][1] = 0.0f;
++HeadOffset;
hrtfstate->History[HistOffset++] = *(data++);
ALfloat g{oldGain + oldGainStep*stepcount};
ALfloat left{hrtfstate->History[OldDelay[0]++] * g};
ALfloat right{hrtfstate->History[OldDelay[1]++] * g};
ApplyCoeffs(Offset, hrtfstate->Values, IrSize, OldCoeffs, left, right);
g = newGainStep*stepcount;
left = hrtfstate->History[NewDelay[0]++] * g;
right = hrtfstate->History[NewDelay[1]++] * g;
ApplyCoeffs(Offset, hrtfstate->Values, IrSize, NewCoeffs, left, right);
*(LeftOut++) += hrtfstate->Values[Offset][0];
*(RightOut++) += hrtfstate->Values[Offset][1];
++Offset;
stepcount += 1.0f;
}
HeadOffset &= HRIR_MASK;
HistOffset &= HRTF_HISTORY_MASK;
OldDelay[0] &= HRTF_HISTORY_MASK;
OldDelay[1] &= HRTF_HISTORY_MASK;
NewDelay[0] &= HRTF_HISTORY_MASK;
NewDelay[1] &= HRTF_HISTORY_MASK;
Offset &= HRIR_MASK;
}
newparams->Gain = newGainStep*stepcount;
}
void MixDirectHrtf(ALfloat *RESTRICT LeftOut, ALfloat *RESTRICT RightOut,
const ALfloat (*data)[BUFFERSIZE], DirectHrtfState *State,
const ALsizei NumChans, const ALsizei BufferSize)
{
ASSUME(NumChans >= 0);
ASSUME(BufferSize > 0);
const ALsizei IrSize{State->IrSize};
ASSUME(IrSize >= 4);
for(ALsizei c{0};c < NumChans;++c)
{
const ALfloat (&input)[BUFFERSIZE] = data[c];
const ALfloat (&Coeffs)[HRIR_LENGTH][2] = State->Chan[c].Coeffs;
ALfloat (&Values)[HRIR_LENGTH][2] = State->Chan[c].Values;
ALsizei Offset{State->Offset&HRIR_MASK};
ALsizei HeadOffset{(Offset+IrSize-1)&HRIR_MASK};
for(ALsizei i{0};i < BufferSize;)
{
const ALsizei todo_hrir{HRIR_LENGTH - maxi(HeadOffset, Offset)};
const ALsizei todo{mini(BufferSize-i, todo_hrir) + i};
ASSUME(todo > i);
for(;i < todo;++i)
{
Values[HeadOffset][0] = 0.0f;
Values[HeadOffset][1] = 0.0f;
++HeadOffset;
const ALfloat insample{input[i]};
ApplyCoeffs(Offset, Values, IrSize, Coeffs, insample, insample);
LeftOut[i] += Values[Offset][0];
RightOut[i] += Values[Offset][1];
++Offset;
}
HeadOffset &= HRIR_MASK;
Offset &= HRIR_MASK;
}
}
}