Store the sinc4 table in the filter state

Also rename the resampler functions to remove the unnecessary '32' token.
This commit is contained in:
Chris Robinson
2017-08-16 18:09:53 -07:00
parent f9c09cc845
commit 5008024e73
11 changed files with 123 additions and 92 deletions
+11 -3
View File
@@ -69,7 +69,9 @@ extern inline ALuint64 maxu64(ALuint64 a, ALuint64 b);
extern inline ALuint64 clampu64(ALuint64 val, ALuint64 min, ALuint64 max);
extern inline ALfloat lerp(ALfloat val1, ALfloat val2, ALfloat mu);
extern inline ALfloat resample_fir4(ALfloat val0, ALfloat val1, ALfloat val2, ALfloat val3, ALsizei frac);
extern inline ALfloat resample_fir4(const ALfloat (*restrict filter)[4],
ALfloat val0, ALfloat val1, ALfloat val2, ALfloat val3,
ALsizei frac);
extern inline void aluVectorSet(aluVector *restrict vector, ALfloat x, ALfloat y, ALfloat z, ALfloat w);
@@ -1037,7 +1039,10 @@ static void CalcNonAttnSourceParams(ALvoice *voice, const struct ALvoiceProps *p
voice->Step = MAX_PITCH<<FRACTIONBITS;
else
voice->Step = maxi(fastf2i(Pitch*FRACTIONONE + 0.5f), 1);
BsincPrepare(voice->Step, &voice->ResampleState.bsinc);
if(props->Resampler == BSincResampler)
BsincPrepare(voice->Step, &voice->ResampleState.bsinc);
else
voice->ResampleState.sinc4.filter = sinc4Tab;
voice->Resampler = SelectResampler(props->Resampler);
/* Calculate gains */
@@ -1380,7 +1385,10 @@ static void CalcAttnSourceParams(ALvoice *voice, const struct ALvoiceProps *prop
voice->Step = MAX_PITCH<<FRACTIONBITS;
else
voice->Step = maxi(fastf2i(Pitch*FRACTIONONE + 0.5f), 1);
BsincPrepare(voice->Step, &voice->ResampleState.bsinc);
if(props->Resampler == BSincResampler)
BsincPrepare(voice->Step, &voice->ResampleState.bsinc);
else
voice->ResampleState.sinc4.filter = sinc4Tab;
voice->Resampler = SelectResampler(props->Resampler);
if(Distance > FLT_EPSILON)
+1 -1
View File
@@ -29,7 +29,7 @@ SampleConverter *CreateSampleConverter(enum DevFmtType srcType, enum DevFmtType
step = fastf2i(minf((ALdouble)srcRate / dstRate, MAX_PITCH)*FRACTIONONE + 0.5f);
converter->mIncrement = maxi(step, 1);
if(converter->mIncrement == FRACTIONONE)
converter->mResample = Resample_copy32_C;
converter->mResample = Resample_copy_C;
else
{
/* TODO: Allow other resamplers. */
+14 -14
View File
@@ -112,48 +112,48 @@ ResamplerFunc SelectResampler(enum Resampler resampler)
switch(resampler)
{
case PointResampler:
return Resample_point32_C;
return Resample_point_C;
case LinearResampler:
#ifdef HAVE_NEON
if((CPUCapFlags&CPU_CAP_NEON))
return Resample_lerp32_Neon;
return Resample_lerp_Neon;
#endif
#ifdef HAVE_SSE4_1
if((CPUCapFlags&CPU_CAP_SSE4_1))
return Resample_lerp32_SSE41;
return Resample_lerp_SSE41;
#endif
#ifdef HAVE_SSE2
if((CPUCapFlags&CPU_CAP_SSE2))
return Resample_lerp32_SSE2;
return Resample_lerp_SSE2;
#endif
return Resample_lerp32_C;
return Resample_lerp_C;
case FIR4Resampler:
#ifdef HAVE_NEON
if((CPUCapFlags&CPU_CAP_NEON))
return Resample_fir4_32_Neon;
return Resample_fir4_Neon;
#endif
#ifdef HAVE_SSE4_1
if((CPUCapFlags&CPU_CAP_SSE4_1))
return Resample_fir4_32_SSE41;
return Resample_fir4_SSE41;
#endif
#ifdef HAVE_SSE3
if((CPUCapFlags&CPU_CAP_SSE3))
return Resample_fir4_32_SSE3;
return Resample_fir4_SSE3;
#endif
return Resample_fir4_32_C;
return Resample_fir4_C;
case BSincResampler:
#ifdef HAVE_NEON
if((CPUCapFlags&CPU_CAP_NEON))
return Resample_bsinc32_Neon;
return Resample_bsinc_Neon;
#endif
#ifdef HAVE_SSE
if((CPUCapFlags&CPU_CAP_SSE))
return Resample_bsinc32_SSE;
return Resample_bsinc_SSE;
#endif
return Resample_bsinc32_C;
return Resample_bsinc_C;
}
return Resample_point32_C;
return Resample_point_C;
}
@@ -312,7 +312,7 @@ ALboolean MixSource(ALvoice *voice, ALsource *Source, ALCdevice *Device, ALsizei
IrSize = (Device->HrtfHandle ? Device->HrtfHandle->irSize : 0);
Resample = ((increment == FRACTIONONE && DataPosFrac == 0) ?
Resample_copy32_C : voice->Resampler);
Resample_copy_C : voice->Resampler);
Counter = (voice->Flags&VOICE_IS_FADING) ? SamplesToDo : 0;
firstpass = true;
+29 -13
View File
@@ -8,15 +8,13 @@
#include "alAuxEffectSlot.h"
static inline ALfloat point32(const ALfloat *restrict vals, ALsizei UNUSED(frac))
static inline ALfloat do_point(const ALfloat *restrict vals, ALsizei UNUSED(frac))
{ return vals[0]; }
static inline ALfloat lerp32(const ALfloat *restrict vals, ALsizei frac)
static inline ALfloat do_lerp(const ALfloat *restrict vals, ALsizei frac)
{ return lerp(vals[0], vals[1], frac * (1.0f/FRACTIONONE)); }
static inline ALfloat fir4_32(const ALfloat *restrict vals, ALsizei frac)
{ return resample_fir4(vals[-1], vals[0], vals[1], vals[2], frac); }
const ALfloat *Resample_copy32_C(const InterpState* UNUSED(state),
const ALfloat *Resample_copy_C(const InterpState* UNUSED(state),
const ALfloat *restrict src, ALsizei UNUSED(frac), ALint UNUSED(increment),
ALfloat *restrict dst, ALsizei numsamples)
{
@@ -29,8 +27,8 @@ const ALfloat *Resample_copy32_C(const InterpState* UNUSED(state),
return dst;
}
#define DECL_TEMPLATE(Sampler) \
const ALfloat *Resample_##Sampler##_C(const InterpState* UNUSED(state), \
#define DECL_TEMPLATE(Tag, Sampler) \
const ALfloat *Resample_##Tag##_C(const InterpState* UNUSED(state), \
const ALfloat *restrict src, ALsizei frac, ALint increment, \
ALfloat *restrict dst, ALsizei numsamples) \
{ \
@@ -46,15 +44,33 @@ const ALfloat *Resample_##Sampler##_C(const InterpState* UNUSED(state), \
return dst; \
}
DECL_TEMPLATE(point32)
DECL_TEMPLATE(lerp32)
DECL_TEMPLATE(fir4_32)
DECL_TEMPLATE(point, do_point)
DECL_TEMPLATE(lerp, do_lerp)
#undef DECL_TEMPLATE
const ALfloat *Resample_bsinc32_C(const InterpState *state, const ALfloat *restrict src,
ALsizei frac, ALint increment, ALfloat *restrict dst,
ALsizei dstlen)
const ALfloat *Resample_fir4_C(const InterpState *state, const ALfloat *restrict src,
ALsizei frac, ALint increment, ALfloat *restrict dst,
ALsizei numsamples)
{
const ALfloat (*restrict filter)[4] = ASSUME_ALIGNED(state->sinc4.filter, 16);
ALsizei i;
src -= 1;
for(i = 0;i < numsamples;i++)
{
dst[i] = resample_fir4(filter, src[0], src[1], src[2], src[3], frac);
frac += increment;
src += frac>>FRACTIONBITS;
frac &= FRACTIONMASK;
}
return dst;
}
const ALfloat *Resample_bsinc_C(const InterpState *state, const ALfloat *restrict src,
ALsizei frac, ALint increment, ALfloat *restrict dst,
ALsizei dstlen)
{
const ALfloat *fil, *scd, *phd, *spd;
const ALfloat *filter = state->bsinc.filter;
+29 -29
View File
@@ -12,11 +12,11 @@ struct MixHrtfParams;
struct HrtfState;
/* C resamplers */
const ALfloat *Resample_copy32_C(const InterpState *state, const ALfloat *restrict src, ALsizei frac, ALint increment, ALfloat *restrict dst, ALsizei dstlen);
const ALfloat *Resample_point32_C(const InterpState *state, const ALfloat *restrict src, ALsizei frac, ALint increment, ALfloat *restrict dst, ALsizei dstlen);
const ALfloat *Resample_lerp32_C(const InterpState *state, const ALfloat *restrict src, ALsizei frac, ALint increment, ALfloat *restrict dst, ALsizei dstlen);
const ALfloat *Resample_fir4_32_C(const InterpState *state, const ALfloat *restrict src, ALsizei frac, ALint increment, ALfloat *restrict dst, ALsizei dstlen);
const ALfloat *Resample_bsinc32_C(const InterpState *state, const ALfloat *restrict src, ALsizei frac, ALint increment, ALfloat *restrict dst, ALsizei dstlen);
const ALfloat *Resample_copy_C(const InterpState *state, const ALfloat *restrict src, ALsizei frac, ALint increment, ALfloat *restrict dst, ALsizei dstlen);
const ALfloat *Resample_point_C(const InterpState *state, const ALfloat *restrict src, ALsizei frac, ALint increment, ALfloat *restrict dst, ALsizei dstlen);
const ALfloat *Resample_lerp_C(const InterpState *state, const ALfloat *restrict src, ALsizei frac, ALint increment, ALfloat *restrict dst, ALsizei dstlen);
const ALfloat *Resample_fir4_C(const InterpState *state, const ALfloat *restrict src, ALsizei frac, ALint increment, ALfloat *restrict dst, ALsizei dstlen);
const ALfloat *Resample_bsinc_C(const InterpState *state, const ALfloat *restrict src, ALsizei frac, ALint increment, ALfloat *restrict dst, ALsizei dstlen);
/* C mixers */
@@ -76,23 +76,23 @@ inline void InitiatePositionArrays(ALsizei frac, ALint increment, ALsizei *restr
}
}
const ALfloat *Resample_lerp32_SSE2(const InterpState *state, const ALfloat *restrict src,
ALsizei frac, ALint increment, ALfloat *restrict dst,
ALsizei numsamples);
const ALfloat *Resample_lerp32_SSE41(const InterpState *state, const ALfloat *restrict src,
ALsizei frac, ALint increment, ALfloat *restrict dst,
ALsizei numsamples);
const ALfloat *Resample_lerp_SSE2(const InterpState *state, const ALfloat *restrict src,
ALsizei frac, ALint increment, ALfloat *restrict dst,
ALsizei numsamples);
const ALfloat *Resample_lerp_SSE41(const InterpState *state, const ALfloat *restrict src,
ALsizei frac, ALint increment, ALfloat *restrict dst,
ALsizei numsamples);
const ALfloat *Resample_fir4_32_SSE3(const InterpState *state, const ALfloat *restrict src,
ALsizei frac, ALint increment, ALfloat *restrict dst,
ALsizei numsamples);
const ALfloat *Resample_fir4_32_SSE41(const InterpState *state, const ALfloat *restrict src,
ALsizei frac, ALint increment, ALfloat *restrict dst,
ALsizei numsamples);
const ALfloat *Resample_fir4_SSE3(const InterpState *state, const ALfloat *restrict src,
ALsizei frac, ALint increment, ALfloat *restrict dst,
ALsizei numsamples);
const ALfloat *Resample_fir4_SSE41(const InterpState *state, const ALfloat *restrict src,
ALsizei frac, ALint increment, ALfloat *restrict dst,
ALsizei numsamples);
const ALfloat *Resample_bsinc32_SSE(const InterpState *state, const ALfloat *restrict src,
ALsizei frac, ALint increment, ALfloat *restrict dst,
ALsizei dstlen);
const ALfloat *Resample_bsinc_SSE(const InterpState *state, const ALfloat *restrict src,
ALsizei frac, ALint increment, ALfloat *restrict dst,
ALsizei dstlen);
/* Neon mixers */
void MixHrtf_Neon(ALfloat *restrict LeftOut, ALfloat *restrict RightOut,
@@ -116,14 +116,14 @@ void MixRow_Neon(ALfloat *OutBuffer, const ALfloat *Gains,
ALsizei InPos, ALsizei BufferSize);
/* Neon resamplers */
const ALfloat *Resample_lerp32_Neon(const InterpState *state, const ALfloat *restrict src,
ALsizei frac, ALint increment, ALfloat *restrict dst,
ALsizei numsamples);
const ALfloat *Resample_fir4_32_Neon(const InterpState *state, const ALfloat *restrict src,
ALsizei frac, ALint increment, ALfloat *restrict dst,
ALsizei numsamples);
const ALfloat *Resample_bsinc32_Neon(const InterpState *state, const ALfloat *restrict src,
ALsizei frac, ALint increment, ALfloat *restrict dst,
ALsizei dstlen);
const ALfloat *Resample_lerp_Neon(const InterpState *state, const ALfloat *restrict src,
ALsizei frac, ALint increment, ALfloat *restrict dst,
ALsizei numsamples);
const ALfloat *Resample_fir4_Neon(const InterpState *state, const ALfloat *restrict src,
ALsizei frac, ALint increment, ALfloat *restrict dst,
ALsizei numsamples);
const ALfloat *Resample_bsinc_Neon(const InterpState *state, const ALfloat *restrict src,
ALsizei frac, ALint increment, ALfloat *restrict dst,
ALsizei dstlen);
#endif /* MIXER_DEFS_H */
+9 -8
View File
@@ -10,7 +10,7 @@
#include "mixer_defs.h"
const ALfloat *Resample_lerp32_Neon(const InterpState* UNUSED(state),
const ALfloat *Resample_lerp_Neon(const InterpState* UNUSED(state),
const ALfloat *restrict src, ALsizei frac, ALint increment,
ALfloat *restrict dst, ALsizei numsamples)
{
@@ -66,10 +66,11 @@ const ALfloat *Resample_lerp32_Neon(const InterpState* UNUSED(state),
return dst;
}
const ALfloat *Resample_fir4_32_Neon(const InterpState* UNUSED(state),
const ALfloat *Resample_fir4_Neon(const InterpState *state,
const ALfloat *restrict src, ALsizei frac, ALint increment,
ALfloat *restrict dst, ALsizei numsamples)
{
const ALfloat (*restrict filter)[4] = ASSUME_ALIGNED(state->sinc4.filter, 16);
const int32x4_t increment4 = vdupq_n_s32(increment*4);
const int32x4_t fracMask4 = vdupq_n_s32(FRACTIONMASK);
alignas(16) ALint pos_[4];
@@ -90,10 +91,10 @@ const ALfloat *Resample_fir4_32_Neon(const InterpState* UNUSED(state),
const float32x4_t val1 = vld1q_f32(&src[pos_[1]]);
const float32x4_t val2 = vld1q_f32(&src[pos_[2]]);
const float32x4_t val3 = vld1q_f32(&src[pos_[3]]);
float32x4_t k0 = vld1q_f32(sinc4Tab[frac_[0]]);
float32x4_t k1 = vld1q_f32(sinc4Tab[frac_[1]]);
float32x4_t k2 = vld1q_f32(sinc4Tab[frac_[2]]);
float32x4_t k3 = vld1q_f32(sinc4Tab[frac_[3]]);
float32x4_t k0 = vld1q_f32(filter[frac_[0]]);
float32x4_t k1 = vld1q_f32(filter[frac_[1]]);
float32x4_t k2 = vld1q_f32(filter[frac_[2]]);
float32x4_t k3 = vld1q_f32(filter[frac_[3]]);
float32x4_t out;
k0 = vmulq_f32(k0, val0);
@@ -126,7 +127,7 @@ const ALfloat *Resample_fir4_32_Neon(const InterpState* UNUSED(state),
ALint pos = pos_[0];
frac = frac_[0];
do {
dst[i] = resample_fir4(src[pos], src[pos+1], src[pos+2], src[pos+3], frac);
dst[i] = resample_fir4(filter, src[pos], src[pos+1], src[pos+2], src[pos+3], frac);
frac += increment;
pos += frac>>FRACTIONBITS;
@@ -136,7 +137,7 @@ const ALfloat *Resample_fir4_32_Neon(const InterpState* UNUSED(state),
return dst;
}
const ALfloat *Resample_bsinc32_Neon(const InterpState *state,
const ALfloat *Resample_bsinc_Neon(const InterpState *state,
const ALfloat *restrict src, ALsizei frac, ALint increment,
ALfloat *restrict dst, ALsizei dstlen)
{
+3 -3
View File
@@ -12,9 +12,9 @@
#include "mixer_defs.h"
const ALfloat *Resample_bsinc32_SSE(const InterpState *state, const ALfloat *restrict src,
ALsizei frac, ALint increment, ALfloat *restrict dst,
ALsizei dstlen)
const ALfloat *Resample_bsinc_SSE(const InterpState *state, const ALfloat *restrict src,
ALsizei frac, ALint increment, ALfloat *restrict dst,
ALsizei dstlen)
{
const ALfloat *filter = state->bsinc.filter;
const __m128 sf4 = _mm_set1_ps(state->bsinc.sf);
+1 -1
View File
@@ -27,7 +27,7 @@
#include "mixer_defs.h"
const ALfloat *Resample_lerp32_SSE2(const InterpState* UNUSED(state),
const ALfloat *Resample_lerp_SSE2(const InterpState* UNUSED(state),
const ALfloat *restrict src, ALsizei frac, ALint increment,
ALfloat *restrict dst, ALsizei numsamples)
{
+7 -6
View File
@@ -31,10 +31,11 @@
#include "mixer_defs.h"
const ALfloat *Resample_fir4_32_SSE3(const InterpState* UNUSED(state),
const ALfloat *Resample_fir4_SSE3(const InterpState *state,
const ALfloat *restrict src, ALsizei frac, ALint increment,
ALfloat *restrict dst, ALsizei numsamples)
{
const ALfloat (*restrict filter)[4] = ASSUME_ALIGNED(state->sinc4.filter, 16);
const __m128i increment4 = _mm_set1_epi32(increment*4);
const __m128i fracMask4 = _mm_set1_epi32(FRACTIONMASK);
union { alignas(16) ALint i[4]; float f[4]; } pos_;
@@ -55,10 +56,10 @@ const ALfloat *Resample_fir4_32_SSE3(const InterpState* UNUSED(state),
const __m128 val1 = _mm_loadu_ps(&src[pos_.i[1]]);
const __m128 val2 = _mm_loadu_ps(&src[pos_.i[2]]);
const __m128 val3 = _mm_loadu_ps(&src[pos_.i[3]]);
__m128 k0 = _mm_load_ps(sinc4Tab[frac_.i[0]]);
__m128 k1 = _mm_load_ps(sinc4Tab[frac_.i[1]]);
__m128 k2 = _mm_load_ps(sinc4Tab[frac_.i[2]]);
__m128 k3 = _mm_load_ps(sinc4Tab[frac_.i[3]]);
__m128 k0 = _mm_load_ps(filter[frac_.i[0]]);
__m128 k1 = _mm_load_ps(filter[frac_.i[1]]);
__m128 k2 = _mm_load_ps(filter[frac_.i[2]]);
__m128 k3 = _mm_load_ps(filter[frac_.i[3]]);
__m128 out;
k0 = _mm_mul_ps(k0, val0);
@@ -87,7 +88,7 @@ const ALfloat *Resample_fir4_32_SSE3(const InterpState* UNUSED(state),
for(;i < numsamples;i++)
{
dst[i] = resample_fir4(src[pos], src[pos+1], src[pos+2], src[pos+3], frac);
dst[i] = resample_fir4(filter, src[pos], src[pos+1], src[pos+2], src[pos+3], frac);
frac += increment;
pos += frac>>FRACTIONBITS;
+8 -7
View File
@@ -28,7 +28,7 @@
#include "mixer_defs.h"
const ALfloat *Resample_lerp32_SSE41(const InterpState* UNUSED(state),
const ALfloat *Resample_lerp_SSE41(const InterpState* UNUSED(state),
const ALfloat *restrict src, ALsizei frac, ALint increment,
ALfloat *restrict dst, ALsizei numsamples)
{
@@ -85,10 +85,11 @@ const ALfloat *Resample_lerp32_SSE41(const InterpState* UNUSED(state),
return dst;
}
const ALfloat *Resample_fir4_32_SSE41(const InterpState* UNUSED(state),
const ALfloat *Resample_fir4_SSE41(const InterpState *state,
const ALfloat *restrict src, ALsizei frac, ALint increment,
ALfloat *restrict dst, ALsizei numsamples)
{
const ALfloat (*restrict filter)[4] = ASSUME_ALIGNED(state->sinc4.filter, 16);
const __m128i increment4 = _mm_set1_epi32(increment*4);
const __m128i fracMask4 = _mm_set1_epi32(FRACTIONMASK);
union { alignas(16) ALint i[4]; float f[4]; } pos_;
@@ -109,10 +110,10 @@ const ALfloat *Resample_fir4_32_SSE41(const InterpState* UNUSED(state),
const __m128 val1 = _mm_loadu_ps(&src[pos_.i[1]]);
const __m128 val2 = _mm_loadu_ps(&src[pos_.i[2]]);
const __m128 val3 = _mm_loadu_ps(&src[pos_.i[3]]);
__m128 k0 = _mm_load_ps(sinc4Tab[frac_.i[0]]);
__m128 k1 = _mm_load_ps(sinc4Tab[frac_.i[1]]);
__m128 k2 = _mm_load_ps(sinc4Tab[frac_.i[2]]);
__m128 k3 = _mm_load_ps(sinc4Tab[frac_.i[3]]);
__m128 k0 = _mm_load_ps(filter[frac_.i[0]]);
__m128 k1 = _mm_load_ps(filter[frac_.i[1]]);
__m128 k2 = _mm_load_ps(filter[frac_.i[2]]);
__m128 k3 = _mm_load_ps(filter[frac_.i[3]]);
__m128 out;
k0 = _mm_mul_ps(k0, val0);
@@ -144,7 +145,7 @@ const ALfloat *Resample_fir4_32_SSE41(const InterpState* UNUSED(state),
for(;i < numsamples;i++)
{
dst[i] = resample_fir4(src[pos], src[pos+1], src[pos+2], src[pos+3], frac);
dst[i] = resample_fir4(filter, src[pos], src[pos+1], src[pos+2], src[pos+3], frac);
frac += increment;
pos += frac>>FRACTIONBITS;
+11 -7
View File
@@ -59,7 +59,9 @@ enum Resampler {
};
extern enum Resampler ResamplerDefault;
/* The number of distinct scale and phase intervals within the filter table. */
/* The number of distinct scale and phase intervals within the bsinc filter
* table.
*/
#define BSINC_SCALE_BITS 4
#define BSINC_SCALE_COUNT (1<<BSINC_SCALE_BITS)
#define BSINC_PHASE_BITS 4
@@ -80,8 +82,13 @@ typedef struct BsincState {
const ALfloat *filter;
} BsincState;
typedef struct Sinc4State {
const ALfloat (*filter)[4];
} Sinc4State;
typedef union InterpState {
BsincState bsinc;
Sinc4State sinc4;
} InterpState;
ALboolean BsincPrepare(const ALuint increment, BsincState *state);
@@ -381,17 +388,14 @@ inline ALuint64 clampu64(ALuint64 val, ALuint64 min, ALuint64 max)
{ return minu64(max, maxu64(min, val)); }
extern alignas(16) const ALfloat sinc4Tab[FRACTIONONE][4];
inline ALfloat lerp(ALfloat val1, ALfloat val2, ALfloat mu)
{
return val1 + (val2-val1)*mu;
}
inline ALfloat resample_fir4(ALfloat val0, ALfloat val1, ALfloat val2, ALfloat val3, ALsizei frac)
inline ALfloat resample_fir4(const ALfloat (*restrict filter)[4], ALfloat val0, ALfloat val1, ALfloat val2, ALfloat val3, ALsizei frac)
{
return sinc4Tab[frac][0]*val0 + sinc4Tab[frac][1]*val1 +
sinc4Tab[frac][2]*val2 + sinc4Tab[frac][3]*val3;
return filter[frac][0]*val0 + filter[frac][1]*val1 +
filter[frac][2]*val2 + filter[frac][3]*val3;
}