196 lines
6.8 KiB
C++
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;
|
|
}
|
|
}
|
|
}
|