aboutsummaryrefslogtreecommitdiffstats
path: root/Alc/mixer.c
diff options
context:
space:
mode:
authorChris Robinson <[email protected]>2010-11-25 23:05:44 -0800
committerChris Robinson <[email protected]>2010-11-25 23:05:44 -0800
commit30820c1bdeadb49b4eeb44d46e3b472460cdd53a (patch)
tree251a9f0e34d1c769e04419c0e4f790e4c261d9d7 /Alc/mixer.c
parent46b98029027f0f5b397975ad5f77d99fee480d90 (diff)
Add a cubic resampler
Diffstat (limited to 'Alc/mixer.c')
-rw-r--r--Alc/mixer.c63
1 files changed, 57 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: