Use a temporary buffer for HRTF filter accumulation
Similar to the history buffer, to avoid using the state buffer as a ring buffer.
This commit is contained in:
parent
fe7918465e
commit
cc91490b61
@ -134,8 +134,8 @@ void ProcessHrtf(ALCdevice *device, const ALsizei SamplesToDo)
|
|||||||
ALfloat *RightOut{device->RealOut.Buffer[ridx]};
|
ALfloat *RightOut{device->RealOut.Buffer[ridx]};
|
||||||
|
|
||||||
DirectHrtfState *state{device->mHrtfState.get()};
|
DirectHrtfState *state{device->mHrtfState.get()};
|
||||||
MixDirectHrtf(LeftOut, RightOut, device->Dry.Buffer, state, device->Dry.NumChannels,
|
MixDirectHrtf(LeftOut, RightOut, device->Dry.Buffer, device->HrtfAccumData, state,
|
||||||
SamplesToDo);
|
device->Dry.NumChannels, SamplesToDo);
|
||||||
state->Offset += SamplesToDo;
|
state->Offset += SamplesToDo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,6 +60,8 @@ struct EnumeratedHrtf {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
using float2 = std::array<float,2>;
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
using HrirArray = std::array<std::array<T,2>,HRIR_LENGTH>;
|
using HrirArray = std::array<std::array<T,2>,HRIR_LENGTH>;
|
||||||
|
|
||||||
|
@ -35,11 +35,11 @@ template<typename InstTag>
|
|||||||
void MixRow_(ALfloat *OutBuffer, const ALfloat *Gains, const ALfloat (*data)[BUFFERSIZE], const ALsizei InChans, const ALsizei InPos, const ALsizei BufferSize);
|
void MixRow_(ALfloat *OutBuffer, const ALfloat *Gains, const ALfloat (*data)[BUFFERSIZE], const ALsizei InChans, const ALsizei InPos, const ALsizei BufferSize);
|
||||||
|
|
||||||
template<typename InstTag>
|
template<typename InstTag>
|
||||||
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);
|
void MixHrtf_(ALfloat *RESTRICT LeftOut, ALfloat *RESTRICT RightOut, const ALfloat *data, float2 *RESTRICT AccumSamples, const ALsizei OutPos, const ALsizei IrSize, MixHrtfParams *hrtfparams, const ALsizei BufferSize);
|
||||||
template<typename InstTag>
|
template<typename InstTag>
|
||||||
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);
|
void MixHrtfBlend_(ALfloat *RESTRICT LeftOut, ALfloat *RESTRICT RightOut, const ALfloat *data, float2 *RESTRICT AccumSamples, const ALsizei OutPos, const ALsizei IrSize, const HrtfParams *oldparams, MixHrtfParams *newparams, const ALsizei BufferSize);
|
||||||
template<typename InstTag>
|
template<typename InstTag>
|
||||||
void MixDirectHrtf_(ALfloat *RESTRICT LeftOut, ALfloat *RESTRICT RightOut, const ALfloat (*data)[BUFFERSIZE], DirectHrtfState *State, const ALsizei NumChans, const ALsizei BufferSize);
|
void MixDirectHrtf_(ALfloat *RESTRICT LeftOut, ALfloat *RESTRICT RightOut, const ALfloat (*data)[BUFFERSIZE], float2 *RESTRICT AccumSamples, DirectHrtfState *State, const ALsizei NumChans, const ALsizei BufferSize);
|
||||||
|
|
||||||
/* Vectorized resampler helpers */
|
/* Vectorized resampler helpers */
|
||||||
inline void InitiatePositionArrays(ALsizei frac, ALint increment, ALsizei *RESTRICT frac_arr, ALsizei *RESTRICT pos_arr, ALsizei size)
|
inline void InitiatePositionArrays(ALsizei frac, ALint increment, ALsizei *RESTRICT frac_arr, ALsizei *RESTRICT pos_arr, ALsizei size)
|
||||||
|
@ -1,18 +1,20 @@
|
|||||||
#ifndef MIXER_HRTFBASE_H
|
#ifndef MIXER_HRTFBASE_H
|
||||||
#define MIXER_HRTFBASE_H
|
#define MIXER_HRTFBASE_H
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
#include "alu.h"
|
#include "alu.h"
|
||||||
#include "../hrtf.h"
|
#include "../hrtf.h"
|
||||||
#include "opthelpers.h"
|
#include "opthelpers.h"
|
||||||
|
|
||||||
|
|
||||||
using ApplyCoeffsT = void(ALsizei Offset, HrirArray<ALfloat> &Values, const ALsizei irSize,
|
using ApplyCoeffsT = void(ALsizei Offset, float2 *RESTRICT Values, const ALsizei irSize,
|
||||||
const HrirArray<ALfloat> &Coeffs, const ALfloat left, const ALfloat right);
|
const HrirArray<ALfloat> &Coeffs, const ALfloat left, const ALfloat right);
|
||||||
|
|
||||||
template<ApplyCoeffsT &ApplyCoeffs>
|
template<ApplyCoeffsT &ApplyCoeffs>
|
||||||
inline void MixHrtfBase(ALfloat *RESTRICT LeftOut, ALfloat *RESTRICT RightOut, const ALfloat *data,
|
inline void MixHrtfBase(ALfloat *RESTRICT LeftOut, ALfloat *RESTRICT RightOut, const ALfloat *data,
|
||||||
ALsizei Offset, const ALsizei OutPos, const ALsizei IrSize, MixHrtfParams *hrtfparams,
|
float2 *RESTRICT AccumSamples, const ALsizei OutPos, const ALsizei IrSize,
|
||||||
HrtfState *hrtfstate, const ALsizei BufferSize)
|
MixHrtfParams *hrtfparams, const ALsizei BufferSize)
|
||||||
{
|
{
|
||||||
ASSUME(OutPos >= 0);
|
ASSUME(OutPos >= 0);
|
||||||
ASSUME(IrSize >= 4);
|
ASSUME(IrSize >= 4);
|
||||||
@ -28,49 +30,27 @@ inline void MixHrtfBase(ALfloat *RESTRICT LeftOut, ALfloat *RESTRICT RightOut, c
|
|||||||
HRTF_HISTORY_LENGTH - hrtfparams->Delay[1] };
|
HRTF_HISTORY_LENGTH - hrtfparams->Delay[1] };
|
||||||
ASSUME(Delay[0] >= 0 && Delay[1] >= 0);
|
ASSUME(Delay[0] >= 0 && Delay[1] >= 0);
|
||||||
|
|
||||||
Offset &= HRIR_MASK;
|
for(ALsizei i{0};i < BufferSize;++i)
|
||||||
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_hrir{HRIR_LENGTH - maxi(HeadOffset, Offset)};
|
|
||||||
const ALsizei todo{mini(BufferSize-i, todo_hrir) + i};
|
|
||||||
ASSUME(todo > i);
|
|
||||||
|
|
||||||
for(;i < todo;++i)
|
|
||||||
{
|
|
||||||
hrtfstate->Values[HeadOffset][0] = 0.0f;
|
|
||||||
hrtfstate->Values[HeadOffset][1] = 0.0f;
|
|
||||||
++HeadOffset;
|
|
||||||
|
|
||||||
const ALfloat g{gain + gainstep*stepcount};
|
const ALfloat g{gain + gainstep*stepcount};
|
||||||
const ALfloat left{data[Delay[0]++] * g};
|
const ALfloat left{data[Delay[0]++] * g};
|
||||||
const ALfloat right{data[Delay[1]++] * g};
|
const ALfloat right{data[Delay[1]++] * g};
|
||||||
ApplyCoeffs(Offset, hrtfstate->Values, IrSize, Coeffs, left, right);
|
ApplyCoeffs(i, AccumSamples+i, IrSize, Coeffs, left, right);
|
||||||
|
|
||||||
*(LeftOut++) += hrtfstate->Values[Offset][0];
|
|
||||||
*(RightOut++) += hrtfstate->Values[Offset][1];
|
|
||||||
++Offset;
|
|
||||||
|
|
||||||
stepcount += 1.0f;
|
stepcount += 1.0f;
|
||||||
}
|
}
|
||||||
|
for(ALsizei i{0};i < BufferSize;++i)
|
||||||
|
LeftOut[OutPos+i] += AccumSamples[i][0];
|
||||||
|
for(ALsizei i{0};i < BufferSize;++i)
|
||||||
|
RightOut[OutPos+i] += AccumSamples[i][1];
|
||||||
|
|
||||||
HeadOffset &= HRIR_MASK;
|
|
||||||
Offset &= HRIR_MASK;
|
|
||||||
}
|
|
||||||
hrtfparams->Gain = gain + gainstep*stepcount;
|
hrtfparams->Gain = gain + gainstep*stepcount;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<ApplyCoeffsT &ApplyCoeffs>
|
template<ApplyCoeffsT &ApplyCoeffs>
|
||||||
inline void MixHrtfBlendBase(ALfloat *RESTRICT LeftOut, ALfloat *RESTRICT RightOut,
|
inline void MixHrtfBlendBase(ALfloat *RESTRICT LeftOut, ALfloat *RESTRICT RightOut,
|
||||||
const ALfloat *data, ALsizei Offset, const ALsizei OutPos, const ALsizei IrSize,
|
const ALfloat *data, float2 *RESTRICT AccumSamples, const ALsizei OutPos, const ALsizei IrSize,
|
||||||
const HrtfParams *oldparams, MixHrtfParams *newparams, HrtfState *hrtfstate,
|
const HrtfParams *oldparams, MixHrtfParams *newparams, const ALsizei BufferSize)
|
||||||
const ALsizei BufferSize)
|
|
||||||
{
|
{
|
||||||
const auto &OldCoeffs = oldparams->Coeffs;
|
const auto &OldCoeffs = oldparams->Coeffs;
|
||||||
const ALfloat oldGain{oldparams->Gain};
|
const ALfloat oldGain{oldparams->Gain};
|
||||||
@ -92,50 +72,32 @@ inline void MixHrtfBlendBase(ALfloat *RESTRICT LeftOut, ALfloat *RESTRICT RightO
|
|||||||
HRTF_HISTORY_LENGTH - newparams->Delay[1] };
|
HRTF_HISTORY_LENGTH - newparams->Delay[1] };
|
||||||
ASSUME(NewDelay[0] >= 0 && NewDelay[1] >= 0);
|
ASSUME(NewDelay[0] >= 0 && NewDelay[1] >= 0);
|
||||||
|
|
||||||
Offset &= HRIR_MASK;
|
for(ALsizei i{0};i < BufferSize;++i)
|
||||||
ALsizei HeadOffset{(Offset+IrSize-1)&HRIR_MASK};
|
|
||||||
|
|
||||||
LeftOut += OutPos;
|
|
||||||
RightOut += OutPos;
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
hrtfstate->Values[HeadOffset][0] = 0.0f;
|
|
||||||
hrtfstate->Values[HeadOffset][1] = 0.0f;
|
|
||||||
++HeadOffset;
|
|
||||||
|
|
||||||
ALfloat g{oldGain + oldGainStep*stepcount};
|
ALfloat g{oldGain + oldGainStep*stepcount};
|
||||||
ALfloat left{data[OldDelay[0]++] * g};
|
ALfloat left{data[OldDelay[0]++] * g};
|
||||||
ALfloat right{data[OldDelay[1]++] * g};
|
ALfloat right{data[OldDelay[1]++] * g};
|
||||||
ApplyCoeffs(Offset, hrtfstate->Values, IrSize, OldCoeffs, left, right);
|
ApplyCoeffs(i, AccumSamples+i, IrSize, OldCoeffs, left, right);
|
||||||
|
|
||||||
g = newGainStep*stepcount;
|
g = newGainStep*stepcount;
|
||||||
left = data[NewDelay[0]++] * g;
|
left = data[NewDelay[0]++] * g;
|
||||||
right = data[NewDelay[1]++] * g;
|
right = data[NewDelay[1]++] * g;
|
||||||
ApplyCoeffs(Offset, hrtfstate->Values, IrSize, NewCoeffs, left, right);
|
ApplyCoeffs(i, AccumSamples+i, IrSize, NewCoeffs, left, right);
|
||||||
|
|
||||||
*(LeftOut++) += hrtfstate->Values[Offset][0];
|
|
||||||
*(RightOut++) += hrtfstate->Values[Offset][1];
|
|
||||||
++Offset;
|
|
||||||
|
|
||||||
stepcount += 1.0f;
|
stepcount += 1.0f;
|
||||||
}
|
}
|
||||||
|
for(ALsizei i{0};i < BufferSize;++i)
|
||||||
|
LeftOut[OutPos+i] += AccumSamples[i][0];
|
||||||
|
for(ALsizei i{0};i < BufferSize;++i)
|
||||||
|
RightOut[OutPos+i] += AccumSamples[i][1];
|
||||||
|
|
||||||
HeadOffset &= HRIR_MASK;
|
|
||||||
Offset &= HRIR_MASK;
|
|
||||||
}
|
|
||||||
newparams->Gain = newGainStep*stepcount;
|
newparams->Gain = newGainStep*stepcount;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<ApplyCoeffsT &ApplyCoeffs>
|
template<ApplyCoeffsT &ApplyCoeffs>
|
||||||
inline void MixDirectHrtfBase(ALfloat *RESTRICT LeftOut, ALfloat *RESTRICT RightOut,
|
inline void MixDirectHrtfBase(ALfloat *RESTRICT LeftOut, ALfloat *RESTRICT RightOut,
|
||||||
const ALfloat (*data)[BUFFERSIZE], DirectHrtfState *State, const ALsizei NumChans,
|
const ALfloat (*data)[BUFFERSIZE], float2 *RESTRICT AccumSamples, DirectHrtfState *State,
|
||||||
const ALsizei BufferSize)
|
const ALsizei NumChans, const ALsizei BufferSize)
|
||||||
{
|
{
|
||||||
ASSUME(NumChans > 0);
|
ASSUME(NumChans > 0);
|
||||||
ASSUME(BufferSize > 0);
|
ASSUME(BufferSize > 0);
|
||||||
@ -147,32 +109,23 @@ inline void MixDirectHrtfBase(ALfloat *RESTRICT LeftOut, ALfloat *RESTRICT Right
|
|||||||
{
|
{
|
||||||
const ALfloat (&input)[BUFFERSIZE] = data[c];
|
const ALfloat (&input)[BUFFERSIZE] = data[c];
|
||||||
const auto &Coeffs = State->Chan[c].Coeffs;
|
const auto &Coeffs = State->Chan[c].Coeffs;
|
||||||
auto &Values = State->Chan[c].Values;
|
|
||||||
ALsizei Offset{State->Offset&HRIR_MASK};
|
|
||||||
|
|
||||||
ALsizei HeadOffset{(Offset+IrSize-1)&HRIR_MASK};
|
auto accum_iter = std::copy_n(State->Chan[c].Values.begin(),
|
||||||
for(ALsizei i{0};i < BufferSize;)
|
State->Chan[c].Values.size(), AccumSamples);
|
||||||
|
std::fill_n(accum_iter, BufferSize, float2{});
|
||||||
|
|
||||||
|
for(ALsizei i{0};i < BufferSize;++i)
|
||||||
{
|
{
|
||||||
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]};
|
const ALfloat insample{input[i]};
|
||||||
ApplyCoeffs(Offset, Values, IrSize, Coeffs, insample, insample);
|
ApplyCoeffs(i, AccumSamples+i, IrSize, Coeffs, insample, insample);
|
||||||
|
}
|
||||||
|
for(ALsizei i{0};i < BufferSize;++i)
|
||||||
|
LeftOut[i] += AccumSamples[i][0];
|
||||||
|
for(ALsizei i{0};i < BufferSize;++i)
|
||||||
|
RightOut[i] += AccumSamples[i][1];
|
||||||
|
|
||||||
LeftOut[i] += Values[Offset][0];
|
std::copy_n(AccumSamples + BufferSize, State->Chan[c].Values.size(),
|
||||||
RightOut[i] += Values[Offset][1];
|
State->Chan[c].Values.begin());
|
||||||
++Offset;
|
|
||||||
}
|
|
||||||
HeadOffset &= HRIR_MASK;
|
|
||||||
Offset &= HRIR_MASK;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -103,54 +103,43 @@ const ALfloat *Resample_<BSincTag,CTag>(const InterpState *state, const ALfloat
|
|||||||
{ return DoResample<do_bsinc>(state, src-state->bsinc.l, frac, increment, dst, dstlen); }
|
{ return DoResample<do_bsinc>(state, src-state->bsinc.l, frac, increment, dst, dstlen); }
|
||||||
|
|
||||||
|
|
||||||
static inline void ApplyCoeffs(ALsizei Offset, HrirArray<ALfloat> &Values, const ALsizei IrSize,
|
static inline void ApplyCoeffs(ALsizei /*Offset*/, float2 *RESTRICT Values, const ALsizei IrSize,
|
||||||
const HrirArray<ALfloat> &Coeffs, const ALfloat left, const ALfloat right)
|
const HrirArray<ALfloat> &Coeffs, const ALfloat left, const ALfloat right)
|
||||||
{
|
{
|
||||||
ASSUME(Offset >= 0 && Offset < HRIR_LENGTH);
|
|
||||||
ASSUME(IrSize >= 2);
|
ASSUME(IrSize >= 2);
|
||||||
ASSUME(&Values != &Coeffs);
|
for(ALsizei c{0};c < IrSize;++c)
|
||||||
|
|
||||||
ALsizei count{mini(IrSize, HRIR_LENGTH - Offset)};
|
|
||||||
ASSUME(count > 0);
|
|
||||||
for(ALsizei c{0};;)
|
|
||||||
{
|
{
|
||||||
for(;c < count;++c)
|
Values[c][0] += Coeffs[c][0] * left;
|
||||||
{
|
Values[c][1] += Coeffs[c][1] * right;
|
||||||
Values[Offset][0] += Coeffs[c][0] * left;
|
|
||||||
Values[Offset][1] += Coeffs[c][1] * right;
|
|
||||||
++Offset;
|
|
||||||
}
|
|
||||||
if(c >= IrSize)
|
|
||||||
break;
|
|
||||||
Offset = 0;
|
|
||||||
count = IrSize;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
void MixHrtf_<CTag>(ALfloat *RESTRICT LeftOut, ALfloat *RESTRICT RightOut, const ALfloat *data,
|
void MixHrtf_<CTag>(ALfloat *RESTRICT LeftOut, ALfloat *RESTRICT RightOut, const ALfloat *data,
|
||||||
ALsizei Offset, const ALsizei OutPos, const ALsizei IrSize, MixHrtfParams *hrtfparams,
|
float2 *RESTRICT AccumSamples, const ALsizei OutPos, const ALsizei IrSize,
|
||||||
HrtfState *hrtfstate, const ALsizei BufferSize)
|
MixHrtfParams *hrtfparams, const ALsizei BufferSize)
|
||||||
{
|
{
|
||||||
MixHrtfBase<ApplyCoeffs>(LeftOut, RightOut, data, Offset, OutPos, IrSize, hrtfparams,
|
MixHrtfBase<ApplyCoeffs>(LeftOut, RightOut, data, AccumSamples, OutPos, IrSize, hrtfparams,
|
||||||
hrtfstate, BufferSize);
|
BufferSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
void MixHrtfBlend_<CTag>(ALfloat *RESTRICT LeftOut, ALfloat *RESTRICT RightOut,
|
void MixHrtfBlend_<CTag>(ALfloat *RESTRICT LeftOut, ALfloat *RESTRICT RightOut,
|
||||||
const ALfloat *data, ALsizei Offset, const ALsizei OutPos, const ALsizei IrSize,
|
const ALfloat *data, float2 *RESTRICT AccumSamples, const ALsizei OutPos, const ALsizei IrSize,
|
||||||
const HrtfParams *oldparams, MixHrtfParams *newparams, HrtfState *hrtfstate,
|
const HrtfParams *oldparams, MixHrtfParams *newparams, const ALsizei BufferSize)
|
||||||
const ALsizei BufferSize)
|
|
||||||
{
|
{
|
||||||
MixHrtfBlendBase<ApplyCoeffs>(LeftOut, RightOut, data, Offset, OutPos, IrSize, oldparams,
|
MixHrtfBlendBase<ApplyCoeffs>(LeftOut, RightOut, data, AccumSamples, OutPos, IrSize, oldparams,
|
||||||
newparams, hrtfstate, BufferSize);
|
newparams, BufferSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
void MixDirectHrtf_<CTag>(ALfloat *RESTRICT LeftOut, ALfloat *RESTRICT RightOut,
|
void MixDirectHrtf_<CTag>(ALfloat *RESTRICT LeftOut, ALfloat *RESTRICT RightOut,
|
||||||
const ALfloat (*data)[BUFFERSIZE], DirectHrtfState *State, const ALsizei NumChans,
|
const ALfloat (*data)[BUFFERSIZE], float2 *RESTRICT AccumSamples, DirectHrtfState *State,
|
||||||
const ALsizei BufferSize)
|
const ALsizei NumChans, const ALsizei BufferSize)
|
||||||
{ MixDirectHrtfBase<ApplyCoeffs>(LeftOut, RightOut, data, State, NumChans, BufferSize); }
|
{
|
||||||
|
MixDirectHrtfBase<ApplyCoeffs>(LeftOut, RightOut, data, AccumSamples, State, NumChans,
|
||||||
|
BufferSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
|
@ -136,11 +136,10 @@ const ALfloat *Resample_<BSincTag,NEONTag>(const InterpState *state, const ALflo
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static inline void ApplyCoeffs(ALsizei Offset, HrirArray<ALfloat> &Values, const ALsizei IrSize,
|
static inline void ApplyCoeffs(ALsizei /*Offset*/, float2 *RESTRICT Values, const ALsizei IrSize,
|
||||||
const HrirArray<ALfloat> &Coeffs, const ALfloat left, const ALfloat right)
|
const HrirArray<ALfloat> &Coeffs, const ALfloat left, const ALfloat right)
|
||||||
{
|
{
|
||||||
ASSUME(IrSize >= 2);
|
ASSUME(IrSize >= 2);
|
||||||
ASSUME(&Values != &Coeffs);
|
|
||||||
|
|
||||||
float32x4_t leftright4;
|
float32x4_t leftright4;
|
||||||
{
|
{
|
||||||
@ -152,43 +151,43 @@ static inline void ApplyCoeffs(ALsizei Offset, HrirArray<ALfloat> &Values, const
|
|||||||
|
|
||||||
for(ALsizei c{0};c < IrSize;c += 2)
|
for(ALsizei c{0};c < IrSize;c += 2)
|
||||||
{
|
{
|
||||||
const ALsizei o0 = (Offset+c)&HRIR_MASK;
|
float32x4_t vals = vcombine_f32(vld1_f32((float32_t*)&Values[c ][0]),
|
||||||
const ALsizei o1 = (o0+1)&HRIR_MASK;
|
vld1_f32((float32_t*)&Values[c+1][0]));
|
||||||
float32x4_t vals = vcombine_f32(vld1_f32((float32_t*)&Values[o0][0]),
|
|
||||||
vld1_f32((float32_t*)&Values[o1][0]));
|
|
||||||
float32x4_t coefs = vld1q_f32((float32_t*)&Coeffs[c][0]);
|
float32x4_t coefs = vld1q_f32((float32_t*)&Coeffs[c][0]);
|
||||||
|
|
||||||
vals = vmlaq_f32(vals, coefs, leftright4);
|
vals = vmlaq_f32(vals, coefs, leftright4);
|
||||||
|
|
||||||
vst1_f32((float32_t*)&Values[o0][0], vget_low_f32(vals));
|
vst1_f32((float32_t*)&Values[c ][0], vget_low_f32(vals));
|
||||||
vst1_f32((float32_t*)&Values[o1][0], vget_high_f32(vals));
|
vst1_f32((float32_t*)&Values[c+1][0], vget_high_f32(vals));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
void MixHrtf_<NEONTag>(ALfloat *RESTRICT LeftOut, ALfloat *RESTRICT RightOut, const ALfloat *data,
|
void MixHrtf_<NEONTag>(ALfloat *RESTRICT LeftOut, ALfloat *RESTRICT RightOut, const ALfloat *data,
|
||||||
ALsizei Offset, const ALsizei OutPos, const ALsizei IrSize, MixHrtfParams *hrtfparams,
|
float2 *RESTRICT AccumSamples, const ALsizei OutPos, const ALsizei IrSize,
|
||||||
HrtfState *hrtfstate, const ALsizei BufferSize)
|
MixHrtfParams *hrtfparams, const ALsizei BufferSize)
|
||||||
{
|
{
|
||||||
MixHrtfBase<ApplyCoeffs>(LeftOut, RightOut, data, Offset, OutPos, IrSize, hrtfparams,
|
MixHrtfBase<ApplyCoeffs>(LeftOut, RightOut, data, AccumSamples, OutPos, IrSize, hrtfparams,
|
||||||
hrtfstate, BufferSize);
|
BufferSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
void MixHrtfBlend_<NEONTag>(ALfloat *RESTRICT LeftOut, ALfloat *RESTRICT RightOut,
|
void MixHrtfBlend_<NEONTag>(ALfloat *RESTRICT LeftOut, ALfloat *RESTRICT RightOut,
|
||||||
const ALfloat *data, ALsizei Offset, const ALsizei OutPos, const ALsizei IrSize,
|
const ALfloat *data, float2 *RESTRICT AccumSamples, const ALsizei OutPos, const ALsizei IrSize,
|
||||||
const HrtfParams *oldparams, MixHrtfParams *newparams, HrtfState *hrtfstate,
|
const HrtfParams *oldparams, MixHrtfParams *newparams, const ALsizei BufferSize)
|
||||||
const ALsizei BufferSize)
|
|
||||||
{
|
{
|
||||||
MixHrtfBlendBase<ApplyCoeffs>(LeftOut, RightOut, data, Offset, OutPos, IrSize, oldparams,
|
MixHrtfBlendBase<ApplyCoeffs>(LeftOut, RightOut, data, AccumSamples, OutPos, IrSize, oldparams,
|
||||||
newparams, hrtfstate, BufferSize);
|
newparams, BufferSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
void MixDirectHrtf_<NEONTag>(ALfloat *RESTRICT LeftOut, ALfloat *RESTRICT RightOut,
|
void MixDirectHrtf_<NEONTag>(ALfloat *RESTRICT LeftOut, ALfloat *RESTRICT RightOut,
|
||||||
const ALfloat (*data)[BUFFERSIZE], DirectHrtfState *State, const ALsizei NumChans,
|
const ALfloat (*data)[BUFFERSIZE], float2 *RESTRICT AccumSamples, DirectHrtfState *State,
|
||||||
const ALsizei BufferSize)
|
const ALsizei NumChans, const ALsizei BufferSize)
|
||||||
{ MixDirectHrtfBase<ApplyCoeffs>(LeftOut, RightOut, data, State, NumChans, BufferSize); }
|
{
|
||||||
|
MixDirectHrtfBase<ApplyCoeffs>(LeftOut, RightOut, data, AccumSamples, State, NumChans,
|
||||||
|
BufferSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
|
@ -76,97 +76,75 @@ const ALfloat *Resample_<BSincTag,SSETag>(const InterpState *state, const ALfloa
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static inline void ApplyCoeffs(ALsizei Offset, HrirArray<ALfloat> &Values, const ALsizei IrSize,
|
static inline void ApplyCoeffs(ALsizei Offset, float2 *RESTRICT Values, const ALsizei IrSize,
|
||||||
const HrirArray<ALfloat> &Coeffs, const ALfloat left, const ALfloat right)
|
const HrirArray<ALfloat> &Coeffs, const ALfloat left, const ALfloat right)
|
||||||
{
|
{
|
||||||
const __m128 lrlr{_mm_setr_ps(left, right, left, right)};
|
const __m128 lrlr{_mm_setr_ps(left, right, left, right)};
|
||||||
|
|
||||||
ASSUME(IrSize >= 2);
|
ASSUME(IrSize >= 2);
|
||||||
ASSUME(&Values != &Coeffs);
|
|
||||||
|
|
||||||
ASSUME(Offset >= 0 && Offset < HRIR_LENGTH);
|
|
||||||
if((Offset&1))
|
if((Offset&1))
|
||||||
{
|
{
|
||||||
ALsizei count{mini(IrSize-1, HRIR_LENGTH - Offset)};
|
|
||||||
ASSUME(count >= 1);
|
|
||||||
|
|
||||||
__m128 imp0, imp1;
|
__m128 imp0, imp1;
|
||||||
__m128 coeffs{_mm_load_ps(&Coeffs[0][0])};
|
__m128 coeffs{_mm_load_ps(&Coeffs[0][0])};
|
||||||
__m128 vals{_mm_loadl_pi(_mm_setzero_ps(), reinterpret_cast<__m64*>(&Values[Offset][0]))};
|
__m128 vals{_mm_loadl_pi(_mm_setzero_ps(), reinterpret_cast<__m64*>(&Values[0][0]))};
|
||||||
imp0 = _mm_mul_ps(lrlr, coeffs);
|
imp0 = _mm_mul_ps(lrlr, coeffs);
|
||||||
vals = _mm_add_ps(imp0, vals);
|
vals = _mm_add_ps(imp0, vals);
|
||||||
_mm_storel_pi(reinterpret_cast<__m64*>(&Values[Offset][0]), vals);
|
_mm_storel_pi(reinterpret_cast<__m64*>(&Values[0][0]), vals);
|
||||||
++Offset;
|
ALsizei i{1};
|
||||||
for(ALsizei i{1};;)
|
for(;i < IrSize-1;i += 2)
|
||||||
{
|
|
||||||
for(;i < count;i += 2)
|
|
||||||
{
|
{
|
||||||
coeffs = _mm_load_ps(&Coeffs[i+1][0]);
|
coeffs = _mm_load_ps(&Coeffs[i+1][0]);
|
||||||
vals = _mm_load_ps(&Values[Offset][0]);
|
vals = _mm_load_ps(&Values[i][0]);
|
||||||
imp1 = _mm_mul_ps(lrlr, coeffs);
|
imp1 = _mm_mul_ps(lrlr, coeffs);
|
||||||
imp0 = _mm_shuffle_ps(imp0, imp1, _MM_SHUFFLE(1, 0, 3, 2));
|
imp0 = _mm_shuffle_ps(imp0, imp1, _MM_SHUFFLE(1, 0, 3, 2));
|
||||||
vals = _mm_add_ps(imp0, vals);
|
vals = _mm_add_ps(imp0, vals);
|
||||||
_mm_store_ps(&Values[Offset][0], vals);
|
_mm_store_ps(&Values[i][0], vals);
|
||||||
imp0 = imp1;
|
imp0 = imp1;
|
||||||
Offset += 2;
|
|
||||||
}
|
}
|
||||||
Offset &= HRIR_MASK;
|
vals = _mm_loadl_pi(vals, reinterpret_cast<__m64*>(&Values[i][0]));
|
||||||
if(i >= IrSize-1)
|
|
||||||
break;
|
|
||||||
count = IrSize-1;
|
|
||||||
}
|
|
||||||
vals = _mm_loadl_pi(vals, reinterpret_cast<__m64*>(&Values[Offset][0]));
|
|
||||||
imp0 = _mm_movehl_ps(imp0, imp0);
|
imp0 = _mm_movehl_ps(imp0, imp0);
|
||||||
vals = _mm_add_ps(imp0, vals);
|
vals = _mm_add_ps(imp0, vals);
|
||||||
_mm_storel_pi(reinterpret_cast<__m64*>(&Values[Offset][0]), vals);
|
_mm_storel_pi(reinterpret_cast<__m64*>(&Values[i][0]), vals);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ALsizei count{mini(IrSize, HRIR_LENGTH - Offset)};
|
for(ALsizei i{0};i < IrSize;i += 2)
|
||||||
ASSUME(count >= 2);
|
|
||||||
|
|
||||||
for(ALsizei i{0};;)
|
|
||||||
{
|
|
||||||
for(;i < count;i += 2)
|
|
||||||
{
|
{
|
||||||
__m128 coeffs{_mm_load_ps(&Coeffs[i][0])};
|
__m128 coeffs{_mm_load_ps(&Coeffs[i][0])};
|
||||||
__m128 vals{_mm_load_ps(&Values[Offset][0])};
|
__m128 vals{_mm_load_ps(&Values[i][0])};
|
||||||
vals = _mm_add_ps(vals, _mm_mul_ps(lrlr, coeffs));
|
vals = _mm_add_ps(vals, _mm_mul_ps(lrlr, coeffs));
|
||||||
_mm_store_ps(&Values[Offset][0], vals);
|
_mm_store_ps(&Values[i][0], vals);
|
||||||
Offset += 2;
|
|
||||||
}
|
|
||||||
if(i >= IrSize)
|
|
||||||
break;
|
|
||||||
Offset = 0;
|
|
||||||
count = IrSize;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
void MixHrtf_<SSETag>(ALfloat *RESTRICT LeftOut, ALfloat *RESTRICT RightOut, const ALfloat *data,
|
void MixHrtf_<SSETag>(ALfloat *RESTRICT LeftOut, ALfloat *RESTRICT RightOut, const ALfloat *data,
|
||||||
ALsizei Offset, const ALsizei OutPos, const ALsizei IrSize, MixHrtfParams *hrtfparams,
|
float2 *RESTRICT AccumSamples, const ALsizei OutPos, const ALsizei IrSize,
|
||||||
HrtfState *hrtfstate, const ALsizei BufferSize)
|
MixHrtfParams *hrtfparams, const ALsizei BufferSize)
|
||||||
{
|
{
|
||||||
MixHrtfBase<ApplyCoeffs>(LeftOut, RightOut, data, Offset, OutPos, IrSize, hrtfparams,
|
MixHrtfBase<ApplyCoeffs>(LeftOut, RightOut, data, AccumSamples, OutPos, IrSize, hrtfparams,
|
||||||
hrtfstate, BufferSize);
|
BufferSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
void MixHrtfBlend_<SSETag>(ALfloat *RESTRICT LeftOut, ALfloat *RESTRICT RightOut,
|
void MixHrtfBlend_<SSETag>(ALfloat *RESTRICT LeftOut, ALfloat *RESTRICT RightOut,
|
||||||
const ALfloat *data, ALsizei Offset, const ALsizei OutPos, const ALsizei IrSize,
|
const ALfloat *data, float2 *RESTRICT AccumSamples, const ALsizei OutPos, const ALsizei IrSize,
|
||||||
const HrtfParams *oldparams, MixHrtfParams *newparams, HrtfState *hrtfstate,
|
const HrtfParams *oldparams, MixHrtfParams *newparams, const ALsizei BufferSize)
|
||||||
const ALsizei BufferSize)
|
|
||||||
{
|
{
|
||||||
MixHrtfBlendBase<ApplyCoeffs>(LeftOut, RightOut, data, Offset, OutPos, IrSize, oldparams,
|
MixHrtfBlendBase<ApplyCoeffs>(LeftOut, RightOut, data, AccumSamples, OutPos, IrSize, oldparams,
|
||||||
newparams, hrtfstate, BufferSize);
|
newparams, BufferSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
void MixDirectHrtf_<SSETag>(ALfloat *RESTRICT LeftOut, ALfloat *RESTRICT RightOut,
|
void MixDirectHrtf_<SSETag>(ALfloat *RESTRICT LeftOut, ALfloat *RESTRICT RightOut,
|
||||||
const ALfloat (*data)[BUFFERSIZE], DirectHrtfState *State, const ALsizei NumChans,
|
const ALfloat (*data)[BUFFERSIZE], float2 *RESTRICT AccumSamples, DirectHrtfState *State,
|
||||||
const ALsizei BufferSize)
|
const ALsizei NumChans, const ALsizei BufferSize)
|
||||||
{ MixDirectHrtfBase<ApplyCoeffs>(LeftOut, RightOut, data, State, NumChans, BufferSize); }
|
{
|
||||||
|
MixDirectHrtfBase<ApplyCoeffs>(LeftOut, RightOut, data, AccumSamples, State, NumChans,
|
||||||
|
BufferSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
|
@ -625,6 +625,7 @@ void MixVoice(ALvoice *voice, ALvoice::State vstate, const ALuint SourceID, ALCc
|
|||||||
if((voice->mFlags&VOICE_HAS_HRTF))
|
if((voice->mFlags&VOICE_HAS_HRTF))
|
||||||
{
|
{
|
||||||
auto &HrtfSamples = Device->HrtfSourceData;
|
auto &HrtfSamples = Device->HrtfSourceData;
|
||||||
|
auto &AccumSamples = Device->HrtfAccumData;
|
||||||
const ALfloat TargetGain{UNLIKELY(vstate == ALvoice::Stopping) ? 0.0f :
|
const ALfloat TargetGain{UNLIKELY(vstate == ALvoice::Stopping) ? 0.0f :
|
||||||
parms.Hrtf.Target.Gain};
|
parms.Hrtf.Target.Gain};
|
||||||
ALsizei fademix{0};
|
ALsizei fademix{0};
|
||||||
@ -641,12 +642,24 @@ void MixVoice(ALvoice *voice, ALvoice::State vstate, const ALuint SourceID, ALCc
|
|||||||
std::copy_n(std::begin(HrtfSamples) + DstBufferSize,
|
std::copy_n(std::begin(HrtfSamples) + DstBufferSize,
|
||||||
parms.Hrtf.State.History.size(), parms.Hrtf.State.History.begin());
|
parms.Hrtf.State.History.size(), parms.Hrtf.State.History.begin());
|
||||||
|
|
||||||
|
/* Copy the current filtered values being accumulated into
|
||||||
|
* the temp buffer.
|
||||||
|
*/
|
||||||
|
auto accum_iter = std::copy_n(parms.Hrtf.State.Values.begin(),
|
||||||
|
parms.Hrtf.State.Values.size(), std::begin(AccumSamples));
|
||||||
|
|
||||||
/* If fading, the old gain is not silence, and this is the
|
/* If fading, the old gain is not silence, and this is the
|
||||||
* first mixing pass, fade between the IRs.
|
* first mixing pass, fade between the IRs.
|
||||||
*/
|
*/
|
||||||
if(Counter && (parms.Hrtf.Old.Gain > GAIN_SILENCE_THRESHOLD) && OutPos == 0)
|
if(Counter && (parms.Hrtf.Old.Gain > GAIN_SILENCE_THRESHOLD) && OutPos == 0)
|
||||||
{
|
{
|
||||||
fademix = mini(DstBufferSize, 128);
|
fademix = mini(DstBufferSize, 128);
|
||||||
|
|
||||||
|
/* Clear the accumulation buffer that will start
|
||||||
|
* getting filled in.
|
||||||
|
*/
|
||||||
|
std::fill_n(accum_iter, fademix, float2{});
|
||||||
|
|
||||||
ALfloat gain{TargetGain};
|
ALfloat gain{TargetGain};
|
||||||
|
|
||||||
/* The new coefficients need to fade in completely
|
/* The new coefficients need to fade in completely
|
||||||
@ -670,19 +683,32 @@ void MixVoice(ALvoice *voice, ALvoice::State vstate, const ALuint SourceID, ALCc
|
|||||||
|
|
||||||
MixHrtfBlendSamples(
|
MixHrtfBlendSamples(
|
||||||
voice->mDirect.Buffer[OutLIdx], voice->mDirect.Buffer[OutRIdx],
|
voice->mDirect.Buffer[OutLIdx], voice->mDirect.Buffer[OutRIdx],
|
||||||
HrtfSamples, voice->mOffset, OutPos, IrSize, &parms.Hrtf.Old,
|
HrtfSamples, AccumSamples, OutPos, IrSize, &parms.Hrtf.Old,
|
||||||
&hrtfparams, &parms.Hrtf.State, fademix);
|
&hrtfparams, fademix);
|
||||||
/* Update the old parameters with the result. */
|
/* Update the old parameters with the result. */
|
||||||
parms.Hrtf.Old = parms.Hrtf.Target;
|
parms.Hrtf.Old = parms.Hrtf.Target;
|
||||||
if(fademix < Counter)
|
if(fademix < Counter)
|
||||||
parms.Hrtf.Old.Gain = hrtfparams.Gain;
|
parms.Hrtf.Old.Gain = hrtfparams.Gain;
|
||||||
else
|
else
|
||||||
parms.Hrtf.Old.Gain = TargetGain;
|
parms.Hrtf.Old.Gain = TargetGain;
|
||||||
|
|
||||||
|
/* Copy the new in-progress accumulation values to the
|
||||||
|
* front of the temp buffer for the following mix.
|
||||||
|
*/
|
||||||
|
accum_iter = std::copy(std::begin(AccumSamples) + fademix,
|
||||||
|
std::begin(AccumSamples) + fademix + HRIR_LENGTH,
|
||||||
|
std::begin(AccumSamples));
|
||||||
}
|
}
|
||||||
|
|
||||||
if(fademix < DstBufferSize)
|
if(LIKELY(fademix < DstBufferSize))
|
||||||
{
|
{
|
||||||
const ALsizei todo{DstBufferSize - fademix};
|
const ALsizei todo{DstBufferSize - fademix};
|
||||||
|
|
||||||
|
/* Clear the accumulation buffer that will start
|
||||||
|
* getting filled in.
|
||||||
|
*/
|
||||||
|
std::fill_n(accum_iter, todo, float2{});
|
||||||
|
|
||||||
ALfloat gain{TargetGain};
|
ALfloat gain{TargetGain};
|
||||||
|
|
||||||
/* Interpolate the target gain if the gain fading lasts
|
/* Interpolate the target gain if the gain fading lasts
|
||||||
@ -704,8 +730,8 @@ void MixVoice(ALvoice *voice, ALvoice::State vstate, const ALuint SourceID, ALCc
|
|||||||
static_cast<ALfloat>(todo);
|
static_cast<ALfloat>(todo);
|
||||||
MixHrtfSamples(
|
MixHrtfSamples(
|
||||||
voice->mDirect.Buffer[OutLIdx], voice->mDirect.Buffer[OutRIdx],
|
voice->mDirect.Buffer[OutLIdx], voice->mDirect.Buffer[OutRIdx],
|
||||||
HrtfSamples+fademix, voice->mOffset+fademix, OutPos+fademix, IrSize,
|
HrtfSamples+fademix, AccumSamples, OutPos+fademix, IrSize, &hrtfparams,
|
||||||
&hrtfparams, &parms.Hrtf.State, todo);
|
todo);
|
||||||
/* Store the interpolated gain or the final target gain
|
/* Store the interpolated gain or the final target gain
|
||||||
* depending if the fade is done.
|
* depending if the fade is done.
|
||||||
*/
|
*/
|
||||||
@ -714,6 +740,12 @@ void MixVoice(ALvoice *voice, ALvoice::State vstate, const ALuint SourceID, ALCc
|
|||||||
else
|
else
|
||||||
parms.Hrtf.Old.Gain = TargetGain;
|
parms.Hrtf.Old.Gain = TargetGain;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Copy the new in-progress accumulation values back for
|
||||||
|
* the next mix.
|
||||||
|
*/
|
||||||
|
std::copy_n(std::begin(AccumSamples) + DstBufferSize,
|
||||||
|
parms.Hrtf.State.Values.size(), parms.Hrtf.State.Values.begin());
|
||||||
}
|
}
|
||||||
else if((voice->mFlags&VOICE_HAS_NFC))
|
else if((voice->mFlags&VOICE_HAS_NFC))
|
||||||
{
|
{
|
||||||
|
@ -407,6 +407,7 @@ struct ALCdevice {
|
|||||||
alignas(16) ALfloat HrtfSourceData[BUFFERSIZE + HRTF_HISTORY_LENGTH];
|
alignas(16) ALfloat HrtfSourceData[BUFFERSIZE + HRTF_HISTORY_LENGTH];
|
||||||
alignas(16) ALfloat NfcSampleData[BUFFERSIZE];
|
alignas(16) ALfloat NfcSampleData[BUFFERSIZE];
|
||||||
};
|
};
|
||||||
|
alignas(16) float2 HrtfAccumData[BUFFERSIZE + HRIR_LENGTH];
|
||||||
|
|
||||||
/* Mixing buffer used by the Dry mix and Real output. */
|
/* Mixing buffer used by the Dry mix and Real output. */
|
||||||
al::vector<std::array<ALfloat,BUFFERSIZE>, 16> MixBuffer;
|
al::vector<std::array<ALfloat,BUFFERSIZE>, 16> MixBuffer;
|
||||||
|
@ -298,15 +298,14 @@ using RowMixerFunc = void(*)(ALfloat *OutBuffer, const ALfloat *gains,
|
|||||||
const ALfloat (*data)[BUFFERSIZE], const ALsizei InChans, const ALsizei InPos,
|
const ALfloat (*data)[BUFFERSIZE], const ALsizei InChans, const ALsizei InPos,
|
||||||
const ALsizei BufferSize);
|
const ALsizei BufferSize);
|
||||||
using HrtfMixerFunc = void(*)(ALfloat *RESTRICT LeftOut, ALfloat *RESTRICT RightOut,
|
using HrtfMixerFunc = void(*)(ALfloat *RESTRICT LeftOut, ALfloat *RESTRICT RightOut,
|
||||||
const ALfloat *data, ALsizei Offset, const ALsizei OutPos, const ALsizei IrSize,
|
const ALfloat *data, float2 *RESTRICT AccumSamples, const ALsizei OutPos, const ALsizei IrSize,
|
||||||
MixHrtfParams *hrtfparams, HrtfState *hrtfstate, const ALsizei BufferSize);
|
MixHrtfParams *hrtfparams, const ALsizei BufferSize);
|
||||||
using HrtfMixerBlendFunc = void(*)(ALfloat *RESTRICT LeftOut, ALfloat *RESTRICT RightOut,
|
using HrtfMixerBlendFunc = void(*)(ALfloat *RESTRICT LeftOut, ALfloat *RESTRICT RightOut,
|
||||||
const ALfloat *data, ALsizei Offset, const ALsizei OutPos, const ALsizei IrSize,
|
const ALfloat *data, float2 *RESTRICT AccumSamples, const ALsizei OutPos, const ALsizei IrSize,
|
||||||
const HrtfParams *oldparams, MixHrtfParams *newparams, HrtfState *hrtfstate,
|
const HrtfParams *oldparams, MixHrtfParams *newparams, const ALsizei BufferSize);
|
||||||
const ALsizei BufferSize);
|
|
||||||
using HrtfDirectMixerFunc = void(*)(ALfloat *RESTRICT LeftOut, ALfloat *RESTRICT RightOut,
|
using HrtfDirectMixerFunc = void(*)(ALfloat *RESTRICT LeftOut, ALfloat *RESTRICT RightOut,
|
||||||
const ALfloat (*data)[BUFFERSIZE], DirectHrtfState *State, const ALsizei NumChans,
|
const ALfloat (*data)[BUFFERSIZE], float2 *RESTRICT AccumSamples, DirectHrtfState *State,
|
||||||
const ALsizei BufferSize);
|
const ALsizei NumChans, const ALsizei BufferSize);
|
||||||
|
|
||||||
|
|
||||||
#define GAIN_MIX_MAX (1000.0f) /* +60dB */
|
#define GAIN_MIX_MAX (1000.0f) /* +60dB */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user