aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Alc/mixer.c63
-rw-r--r--OpenAL32/Include/alSource.h1
-rw-r--r--alsoftrc.sample1
3 files changed, 59 insertions, 6 deletions
diff --git a/Alc/mixer.c b/Alc/mixer.c
index ff5c669d..f31d7985 100644
--- a/Alc/mixer.c
+++ b/Alc/mixer.c
@@ -42,21 +42,38 @@ static __inline ALdouble lerp(ALdouble val1, ALdouble val2, ALint frac)
val1 += ((val2-val1) * (frac * (1.0/(1<<FRACTIONBITS))));
return val1;
}
+static __inline ALdouble cubic(ALdouble val0, ALdouble val1, ALdouble val2, ALdouble val3, ALint frac)
+{
+ ALdouble mu = frac * (1.0/(1<<FRACTIONBITS));
+ ALdouble mu2 = mu*mu;
+ ALdouble a0 = -0.5*val0 + 1.5*val1 + -1.5*val2 + 0.5*val3;
+ ALdouble a1 = val0 + -2.5*val1 + 2.0*val2 + -0.5*val3;
+ ALdouble a2 = -0.5*val0 + 0.5*val2;
+ ALdouble a3 = val1;
+
+ return a0*mu*mu2 + a1*mu2 + a2*mu + a3;
+}
-static __inline ALdouble point32(const ALfloat *vals, ALuint step, ALint frac)
+static __inline ALdouble point32(const ALfloat *vals, ALint step, ALint frac)
{ return vals[0]; (void)step; (void)frac; }
-static __inline ALdouble lerp32(const ALfloat *vals, ALuint step, ALint frac)
+static __inline ALdouble lerp32(const ALfloat *vals, ALint step, ALint frac)
{ return lerp(vals[0], vals[step], frac); }
+static __inline ALdouble cubic32(const ALfloat *vals, ALint step, ALint frac)
+{ return cubic(vals[-step], vals[0], vals[step], vals[step+step], frac); }
-static __inline ALdouble point16(const ALshort *vals, ALuint step, ALint frac)
+static __inline ALdouble point16(const ALshort *vals, ALint step, ALint frac)
{ return vals[0] / 32767.0; (void)step; (void)frac; }
-static __inline ALdouble lerp16(const ALshort *vals, ALuint step, ALint frac)
+static __inline ALdouble lerp16(const ALshort *vals, ALint step, ALint frac)
{ return lerp(vals[0], vals[step], frac) / 32767.0; }
+static __inline ALdouble cubic16(const ALshort *vals, ALint step, ALint frac)
+{ return cubic(vals[-step], vals[0], vals[step], vals[step+step], frac) / 32767.0; }
-static __inline ALdouble point8(const ALubyte *vals, ALuint step, ALint frac)
+static __inline ALdouble point8(const ALubyte *vals, ALint step, ALint frac)
{ return (vals[0]-128.0) / 127.0; (void)step; (void)frac; }
-static __inline ALdouble lerp8(const ALubyte *vals, ALuint step, ALint frac)
+static __inline ALdouble lerp8(const ALubyte *vals, ALint step, ALint frac)
{ return (lerp(vals[0], vals[step], frac)-128.0) / 127.0; }
+static __inline ALdouble cubic8(const ALubyte *vals, ALint step, ALint frac)
+{ return (cubic(vals[-step], vals[0], vals[step], vals[step+step], frac)-128.0) / 127.0; }
#define DECL_TEMPLATE(T, sampler) \
@@ -193,12 +210,15 @@ static void Mix_##T##_Mono_##sampler(ALsource *Source, ALCdevice *Device, \
DECL_TEMPLATE(ALfloat, point32)
DECL_TEMPLATE(ALfloat, lerp32)
+DECL_TEMPLATE(ALfloat, cubic32)
DECL_TEMPLATE(ALshort, point16)
DECL_TEMPLATE(ALshort, lerp16)
+DECL_TEMPLATE(ALshort, cubic16)
DECL_TEMPLATE(ALubyte, point8)
DECL_TEMPLATE(ALubyte, lerp8)
+DECL_TEMPLATE(ALubyte, cubic8)
#undef DECL_TEMPLATE
@@ -343,12 +363,15 @@ static void Mix_##T##_Stereo_##sampler(ALsource *Source, ALCdevice *Device, \
DECL_TEMPLATE(ALfloat, point32)
DECL_TEMPLATE(ALfloat, lerp32)
+DECL_TEMPLATE(ALfloat, cubic32)
DECL_TEMPLATE(ALshort, point16)
DECL_TEMPLATE(ALshort, lerp16)
+DECL_TEMPLATE(ALshort, cubic16)
DECL_TEMPLATE(ALubyte, point8)
DECL_TEMPLATE(ALubyte, lerp8)
+DECL_TEMPLATE(ALubyte, cubic8)
#undef DECL_TEMPLATE
@@ -484,12 +507,15 @@ static const Channel QuadChans[] = { FRONT_LEFT, FRONT_RIGHT,
BACK_LEFT, BACK_RIGHT };
DECL_TEMPLATE(ALfloat, QuadChans, point32)
DECL_TEMPLATE(ALfloat, QuadChans, lerp32)
+DECL_TEMPLATE(ALfloat, QuadChans, cubic32)
DECL_TEMPLATE(ALshort, QuadChans, point16)
DECL_TEMPLATE(ALshort, QuadChans, lerp16)
+DECL_TEMPLATE(ALshort, QuadChans, cubic16)
DECL_TEMPLATE(ALubyte, QuadChans, point8)
DECL_TEMPLATE(ALubyte, QuadChans, lerp8)
+DECL_TEMPLATE(ALubyte, QuadChans, cubic8)
static const Channel X51Chans[] = { FRONT_LEFT, FRONT_RIGHT,
@@ -497,12 +523,15 @@ static const Channel X51Chans[] = { FRONT_LEFT, FRONT_RIGHT,
BACK_LEFT, BACK_RIGHT };
DECL_TEMPLATE(ALfloat, X51Chans, point32)
DECL_TEMPLATE(ALfloat, X51Chans, lerp32)
+DECL_TEMPLATE(ALfloat, X51Chans, cubic32)
DECL_TEMPLATE(ALshort, X51Chans, point16)
DECL_TEMPLATE(ALshort, X51Chans, lerp16)
+DECL_TEMPLATE(ALshort, X51Chans, cubic16)
DECL_TEMPLATE(ALubyte, X51Chans, point8)
DECL_TEMPLATE(ALubyte, X51Chans, lerp8)
+DECL_TEMPLATE(ALubyte, X51Chans, cubic8)
static const Channel X61Chans[] = { FRONT_LEFT, FRONT_RIGHT,
@@ -511,12 +540,15 @@ static const Channel X61Chans[] = { FRONT_LEFT, FRONT_RIGHT,
SIDE_LEFT, SIDE_RIGHT };
DECL_TEMPLATE(ALfloat, X61Chans, point32)
DECL_TEMPLATE(ALfloat, X61Chans, lerp32)
+DECL_TEMPLATE(ALfloat, X61Chans, cubic32)
DECL_TEMPLATE(ALshort, X61Chans, point16)
DECL_TEMPLATE(ALshort, X61Chans, lerp16)
+DECL_TEMPLATE(ALshort, X61Chans, cubic16)
DECL_TEMPLATE(ALubyte, X61Chans, point8)
DECL_TEMPLATE(ALubyte, X61Chans, lerp8)
+DECL_TEMPLATE(ALubyte, X61Chans, cubic8)
static const Channel X71Chans[] = { FRONT_LEFT, FRONT_RIGHT,
@@ -525,12 +557,15 @@ static const Channel X71Chans[] = { FRONT_LEFT, FRONT_RIGHT,
SIDE_LEFT, SIDE_RIGHT };
DECL_TEMPLATE(ALfloat, X71Chans, point32)
DECL_TEMPLATE(ALfloat, X71Chans, lerp32)
+DECL_TEMPLATE(ALfloat, X71Chans, cubic32)
DECL_TEMPLATE(ALshort, X71Chans, point16)
DECL_TEMPLATE(ALshort, X71Chans, lerp16)
+DECL_TEMPLATE(ALshort, X71Chans, cubic16)
DECL_TEMPLATE(ALubyte, X71Chans, point8)
DECL_TEMPLATE(ALubyte, X71Chans, lerp8)
+DECL_TEMPLATE(ALubyte, X71Chans, cubic8)
#undef DECL_TEMPLATE
@@ -577,12 +612,15 @@ static void Mix_##T##_##sampler(ALsource *Source, ALCdevice *Device, ALuint Chan
DECL_TEMPLATE(ALfloat, point32)
DECL_TEMPLATE(ALfloat, lerp32)
+DECL_TEMPLATE(ALfloat, cubic32)
DECL_TEMPLATE(ALshort, point16)
DECL_TEMPLATE(ALshort, lerp16)
+DECL_TEMPLATE(ALshort, cubic16)
DECL_TEMPLATE(ALubyte, point8)
DECL_TEMPLATE(ALubyte, lerp8)
+DECL_TEMPLATE(ALubyte, cubic8)
#undef DECL_TEMPLATE
@@ -869,6 +907,19 @@ ALvoid MixSource(ALsource *Source, ALCdevice *Device, ALuint SamplesToDo)
Mix_ALubyte_lerp8(Source, Device, Channels,
SrcData, &DataPosInt, &DataPosFrac,
j, SamplesToDo, BufferSize);
+ case CUBIC_RESAMPLER:
+ if(Bytes == 4)
+ Mix_ALfloat_cubic32(Source, Device, Channels,
+ SrcData, &DataPosInt, &DataPosFrac,
+ j, SamplesToDo, BufferSize);
+ else if(Bytes == 2)
+ Mix_ALshort_cubic16(Source, Device, Channels,
+ SrcData, &DataPosInt, &DataPosFrac,
+ j, SamplesToDo, BufferSize);
+ else if(Bytes == 1)
+ Mix_ALubyte_cubic8(Source, Device, Channels,
+ SrcData, &DataPosInt, &DataPosFrac,
+ j, SamplesToDo, BufferSize);
break;
case RESAMPLER_MIN:
case RESAMPLER_MAX:
diff --git a/OpenAL32/Include/alSource.h b/OpenAL32/Include/alSource.h
index 96e5393c..e2452279 100644
--- a/OpenAL32/Include/alSource.h
+++ b/OpenAL32/Include/alSource.h
@@ -14,6 +14,7 @@ extern "C" {
typedef enum {
POINT_RESAMPLER = 0,
LINEAR_RESAMPLER,
+ CUBIC_RESAMPLER,
RESAMPLER_MAX,
RESAMPLER_MIN = -1,
diff --git a/alsoftrc.sample b/alsoftrc.sample
index dacaf0d7..0ac27619 100644
--- a/alsoftrc.sample
+++ b/alsoftrc.sample
@@ -64,6 +64,7 @@
# Selects the resampler used when mixing sources. Valid values are:
# 0 - None (nearest sample, no interpolation)
# 1 - Linear (extrapolates samples using a linear slope between samples)
+# 2 - Cubic (extrapolates samples using a Catmull-Rom spline)
# Specifying other values will result in using the default (linear).
#resampler = 1