aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Robinson <[email protected]>2015-09-29 18:27:11 -0700
committerChris Robinson <[email protected]>2015-09-29 20:39:12 -0700
commitdc10e56babf61b62c6cc779414103d7183100c58 (patch)
tree302dd43223b8c3678cbc726655de628bf5b617fb
parente13d553aefe68f63c1c7d479df80c44f4ab70a0f (diff)
Implement a 6-point sinc-lanczos filter
-rw-r--r--Alc/ALc.c4
-rw-r--r--Alc/ALu.c1
-rw-r--r--Alc/mixer.c38
-rw-r--r--Alc/mixer_c.c3
-rw-r--r--Alc/mixer_defs.h1
-rw-r--r--Alc/mixer_sse2.c8
-rw-r--r--Alc/mixer_sse41.c8
-rw-r--r--ChangeLog4
-rw-r--r--OpenAL32/Include/alMain.h1
-rw-r--r--OpenAL32/Include/alu.h13
-rw-r--r--OpenAL32/alSource.c2
-rw-r--r--alsoftrc.sample1
-rw-r--r--utils/alsoft-config/mainwindow.cpp5
13 files changed, 63 insertions, 26 deletions
diff --git a/Alc/ALc.c b/Alc/ALc.c
index fcb6504b..b9c01128 100644
--- a/Alc/ALc.c
+++ b/Alc/ALc.c
@@ -1011,9 +1011,11 @@ static void alc_initconfig(void)
DefaultResampler = LinearResampler;
else if(strcasecmp(str, "sinc4") == 0)
DefaultResampler = FIR4Resampler;
+ else if(strcasecmp(str, "sinc6") == 0)
+ DefaultResampler = FIR6Resampler;
else if(strcasecmp(str, "cubic") == 0)
{
- ERR("Resampler option \"cubic\" is deprecated, using sinc4\n");
+ WARN("Resampler option \"cubic\" is deprecated, using sinc4\n");
DefaultResampler = FIR4Resampler;
}
else
diff --git a/Alc/ALu.c b/Alc/ALu.c
index 3ffe2e63..d8d41e2b 100644
--- a/Alc/ALu.c
+++ b/Alc/ALu.c
@@ -80,6 +80,7 @@ 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, ALuint frac);
+extern inline ALfloat resample_fir6(ALfloat val0, ALfloat val1, ALfloat val2, ALfloat val3, ALfloat val4, ALfloat val5, ALuint frac);
extern inline void aluVectorSet(aluVector *restrict vector, ALfloat x, ALfloat y, ALfloat z, ALfloat w);
diff --git a/Alc/mixer.c b/Alc/mixer.c
index b2bd1dce..dedcb5b9 100644
--- a/Alc/mixer.c
+++ b/Alc/mixer.c
@@ -43,7 +43,7 @@ static_assert((INT_MAX>>FRACTIONBITS)/MAX_PITCH > BUFFERSIZE,
extern inline void InitiatePositionArrays(ALuint frac, ALuint increment, ALuint *frac_arr, ALuint *pos_arr, ALuint size);
-alignas(16) ALfloat ResampleCoeffs[FRACTIONONE][4];
+alignas(16) union ResamplerCoeffs ResampleCoeffs;
static HrtfMixerFunc MixHrtfSamples = MixHrtf_C;
@@ -104,6 +104,8 @@ static inline ResamplerFunc SelectResampler(enum Resampler resampler)
return Resample_fir4_32_SSE2;
#endif
return Resample_fir4_32_C;
+ case FIR6Resampler:
+ return Resample_fir6_32_C;
case ResamplerMax:
/* Shouldn't happen */
break;
@@ -113,27 +115,39 @@ static inline ResamplerFunc SelectResampler(enum Resampler resampler)
}
-static float lanc2(float x)
+static float lanc(float r, float x)
{
if(x == 0.0f)
return 1.0f;
- if(fabsf(x) >= 2.0f)
+ if(fabsf(x) >= r)
return 0.0f;
- return 2.0f*sinf(x*F_PI)*sinf(x*F_PI/2.0f) /
+ return r*sinf(x*F_PI)*sinf(x*F_PI/r) /
(F_PI*F_PI * x*x);
}
void aluInitMixer(void)
{
ALuint i;
- for(i = 0;i < FRACTIONONE;i++)
- {
- ALfloat mu = (ALfloat)i / FRACTIONONE;
- ResampleCoeffs[i][0] = lanc2(mu - -1.0f);
- ResampleCoeffs[i][1] = lanc2(mu - 0.0f);
- ResampleCoeffs[i][2] = lanc2(mu - 1.0f);
- ResampleCoeffs[i][3] = lanc2(mu - 2.0f);
- }
+ if(DefaultResampler == FIR6Resampler)
+ for(i = 0;i < FRACTIONONE;i++)
+ {
+ ALfloat mu = (ALfloat)i / FRACTIONONE;
+ ResampleCoeffs.FIR6[i][0] = lanc(3.0f, mu - -2.0f);
+ ResampleCoeffs.FIR6[i][1] = lanc(3.0f, mu - -1.0f);
+ ResampleCoeffs.FIR6[i][2] = lanc(3.0f, mu - 0.0f);
+ ResampleCoeffs.FIR6[i][3] = lanc(3.0f, mu - 1.0f);
+ ResampleCoeffs.FIR6[i][4] = lanc(3.0f, mu - 2.0f);
+ ResampleCoeffs.FIR6[i][5] = lanc(3.0f, mu - 3.0f);
+ }
+ else if(DefaultResampler == FIR4Resampler)
+ for(i = 0;i < FRACTIONONE;i++)
+ {
+ ALfloat mu = (ALfloat)i / FRACTIONONE;
+ ResampleCoeffs.FIR4[i][0] = lanc(2.0f, mu - -1.0f);
+ ResampleCoeffs.FIR4[i][1] = lanc(2.0f, mu - 0.0f);
+ ResampleCoeffs.FIR4[i][2] = lanc(2.0f, mu - 1.0f);
+ ResampleCoeffs.FIR4[i][3] = lanc(2.0f, mu - 2.0f);
+ }
MixHrtfSamples = SelectHrtfMixer();
MixSamples = SelectMixer();
diff --git a/Alc/mixer_c.c b/Alc/mixer_c.c
index 6164eb00..59ee5ebf 100644
--- a/Alc/mixer_c.c
+++ b/Alc/mixer_c.c
@@ -14,6 +14,8 @@ static inline ALfloat lerp32(const ALfloat *vals, ALuint frac)
{ return lerp(vals[0], vals[1], frac * (1.0f/FRACTIONONE)); }
static inline ALfloat fir4_32(const ALfloat *vals, ALuint frac)
{ return resample_fir4(vals[-1], vals[0], vals[1], vals[2], frac); }
+static inline ALfloat fir6_32(const ALfloat *vals, ALuint frac)
+{ return resample_fir6(vals[-2], vals[-1], vals[0], vals[1], vals[2], vals[3], frac); }
const ALfloat *Resample_copy32_C(const ALfloat *src, ALuint UNUSED(frac),
ALuint UNUSED(increment), ALfloat *restrict dst, ALuint numsamples)
@@ -46,6 +48,7 @@ const ALfloat *Resample_##Sampler##_C(const ALfloat *src, ALuint frac, \
DECL_TEMPLATE(point32)
DECL_TEMPLATE(lerp32)
DECL_TEMPLATE(fir4_32)
+DECL_TEMPLATE(fir6_32)
#undef DECL_TEMPLATE
diff --git a/Alc/mixer_defs.h b/Alc/mixer_defs.h
index e577fafc..4c94954f 100644
--- a/Alc/mixer_defs.h
+++ b/Alc/mixer_defs.h
@@ -16,6 +16,7 @@ const ALfloat *Resample_copy32_C(const ALfloat *src, ALuint frac, ALuint increme
const ALfloat *Resample_point32_C(const ALfloat *src, ALuint frac, ALuint increment, ALfloat *restrict dst, ALuint dstlen);
const ALfloat *Resample_lerp32_C(const ALfloat *src, ALuint frac, ALuint increment, ALfloat *restrict dst, ALuint dstlen);
const ALfloat *Resample_fir4_32_C(const ALfloat *src, ALuint frac, ALuint increment, ALfloat *restrict dst, ALuint dstlen);
+const ALfloat *Resample_fir6_32_C(const ALfloat *src, ALuint frac, ALuint increment, ALfloat *restrict dst, ALuint dstlen);
/* C mixers */
diff --git a/Alc/mixer_sse2.c b/Alc/mixer_sse2.c
index 09a797c3..a6f2bb4e 100644
--- a/Alc/mixer_sse2.c
+++ b/Alc/mixer_sse2.c
@@ -100,10 +100,10 @@ const ALfloat *Resample_fir4_32_SSE2(const ALfloat *src, ALuint frac, ALuint inc
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(ResampleCoeffs[frac_.i[0]]);
- __m128 k1 = _mm_load_ps(ResampleCoeffs[frac_.i[1]]);
- __m128 k2 = _mm_load_ps(ResampleCoeffs[frac_.i[2]]);
- __m128 k3 = _mm_load_ps(ResampleCoeffs[frac_.i[3]]);
+ __m128 k0 = _mm_load_ps(ResampleCoeffs.FIR4[frac_.i[0]]);
+ __m128 k1 = _mm_load_ps(ResampleCoeffs.FIR4[frac_.i[1]]);
+ __m128 k2 = _mm_load_ps(ResampleCoeffs.FIR4[frac_.i[2]]);
+ __m128 k3 = _mm_load_ps(ResampleCoeffs.FIR4[frac_.i[3]]);
__m128 out;
k0 = _mm_mul_ps(k0, val0);
diff --git a/Alc/mixer_sse41.c b/Alc/mixer_sse41.c
index c85a733d..b9ef608a 100644
--- a/Alc/mixer_sse41.c
+++ b/Alc/mixer_sse41.c
@@ -104,10 +104,10 @@ const ALfloat *Resample_fir4_32_SSE41(const ALfloat *src, ALuint frac, ALuint in
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(ResampleCoeffs[frac_.i[0]]);
- __m128 k1 = _mm_load_ps(ResampleCoeffs[frac_.i[1]]);
- __m128 k2 = _mm_load_ps(ResampleCoeffs[frac_.i[2]]);
- __m128 k3 = _mm_load_ps(ResampleCoeffs[frac_.i[3]]);
+ __m128 k0 = _mm_load_ps(ResampleCoeffs.FIR4[frac_.i[0]]);
+ __m128 k1 = _mm_load_ps(ResampleCoeffs.FIR4[frac_.i[1]]);
+ __m128 k2 = _mm_load_ps(ResampleCoeffs.FIR4[frac_.i[2]]);
+ __m128 k3 = _mm_load_ps(ResampleCoeffs.FIR4[frac_.i[3]]);
__m128 out;
k0 = _mm_mul_ps(k0, val0);
diff --git a/ChangeLog b/ChangeLog
index fb35d599..eacfeba0 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -6,7 +6,9 @@ openal-soft-1.17.0:
Implemented the ALC_SOFT_HRTF extension.
- Implemented C, SSE2, and SSE4.1 based Sinc-Lanczos 4-point resamplers.
+ Implemented C, SSE2, and SSE4.1 based 4-point Sinc-Lanczos resamplers.
+
+ Implemented a C based 6-point Sinc-Lanczos resampler.
Implemented B-Format output support for the wave file writer. This creates
FuMa-style first-order Ambisonics wave files (AMB format).
diff --git a/OpenAL32/Include/alMain.h b/OpenAL32/Include/alMain.h
index 7d508721..9703a9cf 100644
--- a/OpenAL32/Include/alMain.h
+++ b/OpenAL32/Include/alMain.h
@@ -529,6 +529,7 @@ enum Resampler {
PointResampler,
LinearResampler,
FIR4Resampler,
+ FIR6Resampler,
ResamplerMax,
};
diff --git a/OpenAL32/Include/alu.h b/OpenAL32/Include/alu.h
index 16b3e1ab..c37ebb9f 100644
--- a/OpenAL32/Include/alu.h
+++ b/OpenAL32/Include/alu.h
@@ -202,7 +202,11 @@ inline ALuint64 clampu64(ALuint64 val, ALuint64 min, ALuint64 max)
{ return minu64(max, maxu64(min, val)); }
-extern alignas(16) ALfloat ResampleCoeffs[FRACTIONONE][4];
+union ResamplerCoeffs {
+ ALfloat FIR4[FRACTIONONE][4];
+ ALfloat FIR6[FRACTIONONE][6];
+};
+extern alignas(16) union ResamplerCoeffs ResampleCoeffs;
inline ALfloat lerp(ALfloat val1, ALfloat val2, ALfloat mu)
@@ -211,9 +215,14 @@ inline ALfloat lerp(ALfloat val1, ALfloat val2, ALfloat mu)
}
inline ALfloat resample_fir4(ALfloat val0, ALfloat val1, ALfloat val2, ALfloat val3, ALuint frac)
{
- const ALfloat *k = ResampleCoeffs[frac];
+ const ALfloat *k = ResampleCoeffs.FIR4[frac];
return k[0]*val0 + k[1]*val1 + k[2]*val2 + k[3]*val3;
}
+inline ALfloat resample_fir6(ALfloat val0, ALfloat val1, ALfloat val2, ALfloat val3, ALfloat val4, ALfloat val5, ALuint frac)
+{
+ const ALfloat *k = ResampleCoeffs.FIR6[frac];
+ return k[0]*val0 + k[1]*val1 + k[2]*val2 + k[3]*val3 + k[4]*val4 + k[5]*val5;
+}
void aluInitMixer(void);
diff --git a/OpenAL32/alSource.c b/OpenAL32/alSource.c
index aff82b5f..24e5874d 100644
--- a/OpenAL32/alSource.c
+++ b/OpenAL32/alSource.c
@@ -43,11 +43,13 @@ const ALsizei ResamplerPadding[ResamplerMax] = {
0, /* Point */
1, /* Linear */
2, /* FIR4 */
+ 3, /* FIR6 */
};
const ALsizei ResamplerPrePadding[ResamplerMax] = {
0, /* Point */
0, /* Linear */
1, /* FIR4 */
+ 2, /* FIR6 */
};
diff --git a/alsoftrc.sample b/alsoftrc.sample
index c05841b4..e1ab22e4 100644
--- a/alsoftrc.sample
+++ b/alsoftrc.sample
@@ -130,6 +130,7 @@
# point - nearest sample, no interpolation
# linear - extrapolates samples using a linear slope between samples
# sinc4 - extrapolates samples using a 4-point Sinc-Lanczos filter
+# sinc6 - extrapolates samples using a 6-point Sinc-Lanczos filter
# Specifying other values will result in using the default (linear).
#resampler = linear
diff --git a/utils/alsoft-config/mainwindow.cpp b/utils/alsoft-config/mainwindow.cpp
index 310d9260..24372688 100644
--- a/utils/alsoft-config/mainwindow.cpp
+++ b/utils/alsoft-config/mainwindow.cpp
@@ -35,7 +35,7 @@ static const struct {
};
static const struct {
- const char name[32];
+ const char name[48];
const char value[16];
} speakerModeList[] = {
{ "Autodetect", "" },
@@ -63,7 +63,8 @@ static const struct {
{ "Default", "" },
{ "Point (low quality, fast)", "point" },
{ "Linear (basic quality, fast)", "linear" },
- { "Sinc-Lanczos (good quality)", "sinc4" },
+ { "Sinc-Lanczos 4pt (good quality)", "sinc4" },
+ { "Sinc-Lanczos 6pt (high quality, slow)", "sinc6" },
{ "", "" }
}, stereoModeList[] = {