ref: eff0f2541daf739f21bb0662345915f4fa60354f
parent: 92fea5b475e37c39b28b88ab28b0dfbd8c899adf
author: Chris Moeller <[email protected]>
date: Mon Jan 11 04:02:22 EST 2010
{12/17/2009 2:02:04 AM}Failed sinc interpolation for future review git-tfs-id: [http://localhost:8080/tfs/DefaultCollection/]$/foobar2000/files/plugins.root;C364
--- a/dumb/include/dumb.h
+++ b/dumb/include/dumb.h
@@ -641,7 +641,8 @@
#define DUMB_RQ_ALIASING 0
#define DUMB_RQ_LINEAR 1
#define DUMB_RQ_CUBIC 2
-#define DUMB_RQ_N_LEVELS 3
+#define DUMB_RQ_SINC 3
+#define DUMB_RQ_N_LEVELS 4
extern int dumb_resampling_quality;
typedef struct DUMB_RESAMPLER DUMB_RESAMPLER;
@@ -662,9 +663,9 @@
int quality;
/* Everything below this point is internal: do not use. */
union {
- sample_t x24[3*2];
- short x16[3*2];
- signed char x8[3*2];
+ sample_t x24[7*2];
+ short x16[7*2];
+ signed char x8[7*2];
} x;
int overshot;
};
--- a/dumb/src/helpers/resamp2.inc
+++ b/dumb/src/helpers/resamp2.inc
@@ -52,7 +52,7 @@
if (resampler->overshot < 0) {
resampler->overshot = 0;
dumb_resample(resampler, NULL, 2, MONO_DEST_VOLUME_ZEROS, 1.0f); /* Doesn't matter which SUFFIX3. */
- COPYSRC(resampler->X, 0, resampler->X, 1);
+ //COPYSRC(resampler->X, 0, resampler->X, 1);
}
for (;;) {
@@ -59,14 +59,22 @@
SRCTYPE *src = resampler->src;
if (resampler->dir < 0) {
- if (resampler->overshot >= 3 && resampler->pos+3 >= resampler->start) COPYSRC(resampler->X, 0, src, resampler->pos+3);
- if (resampler->overshot >= 2 && resampler->pos+2 >= resampler->start) COPYSRC(resampler->X, 1, src, resampler->pos+2);
- if (resampler->overshot >= 1 && resampler->pos+1 >= resampler->start) COPYSRC(resampler->X, 2, src, resampler->pos+1);
+ if (resampler->overshot >= 7 && resampler->pos+7 >= resampler->start) COPYSRC(resampler->X, 0, src, resampler->pos+7);
+ if (resampler->overshot >= 6 && resampler->pos+6 >= resampler->start) COPYSRC(resampler->X, 1, src, resampler->pos+6);
+ if (resampler->overshot >= 5 && resampler->pos+5 >= resampler->start) COPYSRC(resampler->X, 2, src, resampler->pos+5);
+ if (resampler->overshot >= 4 && resampler->pos+4 >= resampler->start) COPYSRC(resampler->X, 3, src, resampler->pos+4);
+ if (resampler->overshot >= 3 && resampler->pos+3 >= resampler->start) COPYSRC(resampler->X, 4, src, resampler->pos+3);
+ if (resampler->overshot >= 2 && resampler->pos+2 >= resampler->start) COPYSRC(resampler->X, 5, src, resampler->pos+2);
+ if (resampler->overshot >= 1 && resampler->pos+1 >= resampler->start) COPYSRC(resampler->X, 6, src, resampler->pos+1);
resampler->overshot = resampler->start - resampler->pos - 1;
} else {
- if (resampler->overshot >= 3 && resampler->pos-3 < resampler->end) COPYSRC(resampler->X, 0, src, resampler->pos-3);
- if (resampler->overshot >= 2 && resampler->pos-2 < resampler->end) COPYSRC(resampler->X, 1, src, resampler->pos-2);
- if (resampler->overshot >= 1 && resampler->pos-1 < resampler->end) COPYSRC(resampler->X, 2, src, resampler->pos-1);
+ if (resampler->overshot >= 7 && resampler->pos-7 < resampler->end) COPYSRC(resampler->X, 0, src, resampler->pos-7);
+ if (resampler->overshot >= 6 && resampler->pos-6 < resampler->end) COPYSRC(resampler->X, 1, src, resampler->pos-6);
+ if (resampler->overshot >= 5 && resampler->pos-5 < resampler->end) COPYSRC(resampler->X, 2, src, resampler->pos-5);
+ if (resampler->overshot >= 4 && resampler->pos-4 < resampler->end) COPYSRC(resampler->X, 3, src, resampler->pos-4);
+ if (resampler->overshot >= 3 && resampler->pos-3 < resampler->end) COPYSRC(resampler->X, 4, src, resampler->pos-3);
+ if (resampler->overshot >= 2 && resampler->pos-2 < resampler->end) COPYSRC(resampler->X, 5, src, resampler->pos-2);
+ if (resampler->overshot >= 1 && resampler->pos-1 < resampler->end) COPYSRC(resampler->X, 6, src, resampler->pos-1);
resampler->overshot = resampler->pos - resampler->end;
}
@@ -97,6 +105,7 @@
#define MIX_ALIAS(op, upd, offset) MONO_DEST_MIX_ALIAS(op, upd, offset)
#define MIX_LINEAR(op, upd, o0, o1) MONO_DEST_MIX_LINEAR(op, upd, o0, o1)
#define MIX_CUBIC(op, upd, x0, x3, o0, o1, o2, o3) MONO_DEST_MIX_CUBIC(op, upd, x0, x3, o0, o1, o2, o3)
+#define MIX_SINC(op, upd, x0, x7, o0, o1, o2, o3, o4, o5, o6, o7) MONO_DEST_MIX_SINC(op, upd, x0, x7, o0, o1, o2, o3, o4, o5, o6, o7)
#define MIX_ZEROS(op) *dst++ op 0
#include "resamp3.inc"
@@ -136,11 +145,14 @@
#define MIX_ALIAS(op, upd, offset) STEREO_DEST_MIX_ALIAS(op, upd, offset)
#define MIX_LINEAR(op, upd, o0, o1) STEREO_DEST_MIX_LINEAR(op, upd, o0, o1)
#define MIX_CUBIC(op, upd, x0, x3, o0, o1, o2, o3) STEREO_DEST_MIX_CUBIC(op, upd, x0, x3, o0, o1, o2, o3)
+#define MIX_SINC(op, upd, x0, x7, o0, o1, o2, o3, o4, o5, o6, o7) STEREO_DEST_MIX_SINC(op, upd, x0, x7, o0, o1, o2, o3, o4, o5, o6, o7)
#define MIX_ZEROS(op) { *dst++ op 0; *dst++ op 0; }
#include "resamp3.inc"
+#undef STEREO_DEST_MIX_SINC
+#undef MONO_DEST_MIX_SINC
#undef STEREO_DEST_MIX_CUBIC
#undef MONO_DEST_MIX_CUBIC
#undef STEREO_DEST_MIX_LINEAR
--- a/dumb/src/helpers/resamp3.inc
+++ b/dumb/src/helpers/resamp3.inc
@@ -64,6 +64,7 @@
if (VOLUMES_ARE_ZERO) dst = NULL;
init_cubic();
+ init_sinc();
quality = resampler->quality;
@@ -107,8 +108,8 @@
SRCTYPE xbuf[2*SRC_CHANNELS];
SRCTYPE *x = &xbuf[0];
SRCTYPE *xstart;
- COPYSRC(xbuf, 0, resampler->X, 1);
- COPYSRC(xbuf, 1, resampler->X, 2);
+ COPYSRC(xbuf, 0, resampler->X, 5);
+ COPYSRC(xbuf, 1, resampler->X, 6);
while (todo && x < &xbuf[2*SRC_CHANNELS]) {
// TODO: check what happens when multiple tempo slides occur per row
HEAVYASSERT(pos >= resampler->start);
@@ -131,8 +132,8 @@
/* Linear interpolation, backwards */
SRCTYPE xbuf[3*SRC_CHANNELS];
SRCTYPE *x = &xbuf[1*SRC_CHANNELS];
- COPYSRC(xbuf, 0, resampler->X, 1);
- COPYSRC(xbuf, 1, resampler->X, 2);
+ COPYSRC(xbuf, 0, resampler->X, 5);
+ COPYSRC(xbuf, 1, resampler->X, 6);
COPYSRC(xbuf, 2, src, pos);
while (todo && x < &xbuf[3*SRC_CHANNELS]) {
HEAVYASSERT(pos >= resampler->start);
@@ -153,13 +154,13 @@
x += (subpos >> 16) * SRC_CHANNELS;
subpos &= 65535;
);
- } else {
+ } else if (quality <= DUMB_RQ_CUBIC) {
/* Cubic interpolation, backwards */
SRCTYPE xbuf[6*SRC_CHANNELS];
SRCTYPE *x = &xbuf[3*SRC_CHANNELS];
- COPYSRC(xbuf, 0, resampler->X, 0);
- COPYSRC(xbuf, 1, resampler->X, 1);
- COPYSRC(xbuf, 2, resampler->X, 2);
+ COPYSRC(xbuf, 0, resampler->X, 4);
+ COPYSRC(xbuf, 1, resampler->X, 5);
+ COPYSRC(xbuf, 2, resampler->X, 6);
COPYSRC(xbuf, 3, src, pos);
if (pos-1 >= resampler->start) COPYSRC(xbuf, 4, src, pos-1);
if (pos-2 >= resampler->start) COPYSRC(xbuf, 5, src, pos-2);
@@ -181,21 +182,101 @@
x += (subpos >> 16) * SRC_CHANNELS;
subpos &= 65535;
);
+ } else {
+ /* Sinc interpolation, backwards */
+ SRCTYPE xbuf[14*SRC_CHANNELS];
+ SRCTYPE *x = &xbuf[7*SRC_CHANNELS];
+ COPYSRC(xbuf, 0, resampler->X, 0);
+ COPYSRC(xbuf, 1, resampler->X, 1);
+ COPYSRC(xbuf, 2, resampler->X, 2);
+ COPYSRC(xbuf, 3, resampler->X, 3);
+ COPYSRC(xbuf, 4, resampler->X, 4);
+ COPYSRC(xbuf, 5, resampler->X, 5);
+ COPYSRC(xbuf, 6, resampler->X, 6);
+ COPYSRC(xbuf, 7, src, pos);
+ if (pos-1 >= resampler->start) COPYSRC(xbuf, 8, src, pos-1);
+ if (pos-2 >= resampler->start) COPYSRC(xbuf, 9, src, pos-2);
+ if (pos-3 >= resampler->start) COPYSRC(xbuf, 10, src, pos-3);
+ if (pos-4 >= resampler->start) COPYSRC(xbuf, 11, src, pos-4);
+ if (pos-5 >= resampler->start) COPYSRC(xbuf, 12, src, pos-5);
+ if (pos-6 >= resampler->start) COPYSRC(xbuf, 13, src, pos-6);
+ while (todo && x < &xbuf[14*SRC_CHANNELS]) {
+ HEAVYASSERT(pos >= resampler->start);
+ MIX_SINC(+=, 1, x, x, 0, -1, -2, -3, -4, -5, -6, -7);
+ subpos += dt;
+ pos += subpos >> 16;
+ x -= (subpos >> 16) * SRC_CHANNELS;
+ subpos &= 65535;
+ todo--;
+ }
+ x = &src[pos*SRC_CHANNELS];
+ LOOP4(todo,
+ HEAVYASSERT(pos >= resampler->start);
+ MIX_SINC(+=, 1, x, x, 0, 1, 2, 3, 4, 5, 6, 7);
+ subpos += dt;
+ pos += subpos >> 16;
+ x += (subpos >> 16) * SRC_CHANNELS;
+ subpos &= 65535;
+ );
}
diff = diff - pos;
overshot = resampler->start - pos - 1;
- if (diff >= 3) {
- COPYSRC2(resampler->X, 0, overshot < 3, src, pos+3);
- COPYSRC2(resampler->X, 1, overshot < 2, src, pos+2);
- COPYSRC2(resampler->X, 2, overshot < 1, src, pos+1);
+ if (diff >= 7) {
+ COPYSRC2(resampler->X, 0, overshot < 7, src, pos+7);
+ COPYSRC2(resampler->X, 1, overshot < 6, src, pos+6);
+ COPYSRC2(resampler->X, 2, overshot < 5, src, pos+5);
+ COPYSRC2(resampler->X, 3, overshot < 4, src, pos+4);
+ COPYSRC2(resampler->X, 4, overshot < 3, src, pos+3);
+ COPYSRC2(resampler->X, 5, overshot < 2, src, pos+2);
+ COPYSRC2(resampler->X, 6, overshot < 1, src, pos+1);
+ } else if (diff >= 6) {
+ COPYSRC(resampler->X, 0, resampler->X, 1);
+ COPYSRC2(resampler->X, 1, overshot < 6, src, pos+6);
+ COPYSRC2(resampler->X, 2, overshot < 5, src, pos+5);
+ COPYSRC2(resampler->X, 3, overshot < 4, src, pos+4);
+ COPYSRC2(resampler->X, 4, overshot < 3, src, pos+3);
+ COPYSRC2(resampler->X, 5, overshot < 2, src, pos+2);
+ COPYSRC2(resampler->X, 6, overshot < 1, src, pos+1);
+ } else if (diff >= 5) {
+ COPYSRC(resampler->X, 0, resampler->X, 1);
+ COPYSRC(resampler->X, 1, resampler->X, 2);
+ COPYSRC2(resampler->X, 2, overshot < 5, src, pos+5);
+ COPYSRC2(resampler->X, 3, overshot < 4, src, pos+4);
+ COPYSRC2(resampler->X, 4, overshot < 3, src, pos+3);
+ COPYSRC2(resampler->X, 5, overshot < 2, src, pos+2);
+ COPYSRC2(resampler->X, 6, overshot < 1, src, pos+1);
+ } else if (diff >= 4) {
+ COPYSRC(resampler->X, 0, resampler->X, 1);
+ COPYSRC(resampler->X, 1, resampler->X, 2);
+ COPYSRC(resampler->X, 2, resampler->X, 3);
+ COPYSRC2(resampler->X, 3, overshot < 4, src, pos+4);
+ COPYSRC2(resampler->X, 4, overshot < 3, src, pos+3);
+ COPYSRC2(resampler->X, 5, overshot < 2, src, pos+2);
+ COPYSRC2(resampler->X, 6, overshot < 1, src, pos+1);
+ } else if (diff >= 3) {
+ COPYSRC(resampler->X, 0, resampler->X, 1);
+ COPYSRC(resampler->X, 1, resampler->X, 2);
+ COPYSRC(resampler->X, 2, resampler->X, 3);
+ COPYSRC(resampler->X, 3, resampler->X, 4);
+ COPYSRC2(resampler->X, 4, overshot < 3, src, pos+3);
+ COPYSRC2(resampler->X, 5, overshot < 2, src, pos+2);
+ COPYSRC2(resampler->X, 6, overshot < 1, src, pos+1);
} else if (diff >= 2) {
- COPYSRC(resampler->X, 0, resampler->X, 2);
- COPYSRC2(resampler->X, 1, overshot < 2, src, pos+2);
- COPYSRC2(resampler->X, 2, overshot < 1, src, pos+1);
+ COPYSRC(resampler->X, 0, resampler->X, 1);
+ COPYSRC(resampler->X, 1, resampler->X, 2);
+ COPYSRC(resampler->X, 2, resampler->X, 3);
+ COPYSRC(resampler->X, 3, resampler->X, 4);
+ COPYSRC(resampler->X, 4, resampler->X, 5);
+ COPYSRC2(resampler->X, 5, overshot < 2, src, pos+2);
+ COPYSRC2(resampler->X, 6, overshot < 1, src, pos+1);
} else if (diff >= 1) {
COPYSRC(resampler->X, 0, resampler->X, 1);
COPYSRC(resampler->X, 1, resampler->X, 2);
- COPYSRC2(resampler->X, 2, overshot < 1, src, pos+1);
+ COPYSRC(resampler->X, 2, resampler->X, 3);
+ COPYSRC(resampler->X, 3, resampler->X, 4);
+ COPYSRC(resampler->X, 4, resampler->X, 5);
+ COPYSRC(resampler->X, 5, resampler->X, 6);
+ COPYSRC2(resampler->X, 6, overshot < 1, src, pos+1);
}
} else {
if (!dst) {
@@ -208,8 +289,8 @@
SRCTYPE xbuf[2*SRC_CHANNELS];
SRCTYPE *x = &xbuf[0];
SRCTYPE *xstart;
- COPYSRC(xbuf, 0, resampler->X, 1);
- COPYSRC(xbuf, 1, resampler->X, 2);
+ COPYSRC(xbuf, 0, resampler->X, 5);
+ COPYSRC(xbuf, 1, resampler->X, 6);
while (todo && x < &xbuf[2*SRC_CHANNELS]) {
HEAVYASSERT(pos < resampler->end);
MIX_ALIAS(+=, 1, 0);
@@ -231,8 +312,8 @@
/* Linear interpolation, forwards */
SRCTYPE xbuf[3*SRC_CHANNELS];
SRCTYPE *x = &xbuf[1*SRC_CHANNELS];
- COPYSRC(xbuf, 0, resampler->X, 1);
- COPYSRC(xbuf, 1, resampler->X, 2);
+ COPYSRC(xbuf, 0, resampler->X, 5);
+ COPYSRC(xbuf, 1, resampler->X, 6);
COPYSRC(xbuf, 2, src, pos);
while (todo && x < &xbuf[3*SRC_CHANNELS]) {
HEAVYASSERT(pos < resampler->end);
@@ -252,13 +333,13 @@
x += (subpos >> 16) * SRC_CHANNELS;
subpos &= 65535;
);
- } else {
+ } else if (quality <= DUMB_RQ_CUBIC) {
/* Cubic interpolation, forwards */
SRCTYPE xbuf[6*SRC_CHANNELS];
SRCTYPE *x = &xbuf[3*SRC_CHANNELS];
- COPYSRC(xbuf, 0, resampler->X, 0);
- COPYSRC(xbuf, 1, resampler->X, 1);
- COPYSRC(xbuf, 2, resampler->X, 2);
+ COPYSRC(xbuf, 0, resampler->X, 4);
+ COPYSRC(xbuf, 1, resampler->X, 5);
+ COPYSRC(xbuf, 2, resampler->X, 6);
COPYSRC(xbuf, 3, src, pos);
if (pos+1 < resampler->end) COPYSRC(xbuf, 4, src, pos+1);
if (pos+2 < resampler->end) COPYSRC(xbuf, 5, src, pos+2);
@@ -280,21 +361,101 @@
x += (subpos >> 16) * SRC_CHANNELS;
subpos &= 65535;
);
+ } else {
+ /* Sinc interpolation, forwards */
+ SRCTYPE xbuf[14*SRC_CHANNELS];
+ SRCTYPE *x = &xbuf[7*SRC_CHANNELS];
+ COPYSRC(xbuf, 0, resampler->X, 0);
+ COPYSRC(xbuf, 1, resampler->X, 1);
+ COPYSRC(xbuf, 2, resampler->X, 2);
+ COPYSRC(xbuf, 3, resampler->X, 3);
+ COPYSRC(xbuf, 4, resampler->X, 4);
+ COPYSRC(xbuf, 5, resampler->X, 5);
+ COPYSRC(xbuf, 6, resampler->X, 6);
+ COPYSRC(xbuf, 7, src, pos);
+ if (pos+1 < resampler->end) COPYSRC(xbuf, 8, src, pos+1);
+ if (pos+2 < resampler->end) COPYSRC(xbuf, 9, src, pos+2);
+ if (pos+3 < resampler->end) COPYSRC(xbuf, 10, src, pos+3);
+ if (pos+4 < resampler->end) COPYSRC(xbuf, 11, src, pos+4);
+ if (pos+5 < resampler->end) COPYSRC(xbuf, 12, src, pos+5);
+ if (pos+6 < resampler->end) COPYSRC(xbuf, 13, src, pos+6);
+ while (todo && x < &xbuf[14*SRC_CHANNELS]) {
+ HEAVYASSERT(pos < resampler->end);
+ MIX_SINC(+=, 1, x, x, -7, -6, -5, -4, -3, -2, -1, 0);
+ subpos += dt;
+ pos += subpos >> 16;
+ x += (subpos >> 16) * SRC_CHANNELS;
+ subpos &= 65535;
+ todo--;
+ }
+ x = &src[pos*SRC_CHANNELS];
+ LOOP4(todo,
+ HEAVYASSERT(pos < resampler->end);
+ MIX_SINC(+=, 1, x, x, -7, -6, -5, -4, -3, -2, -1, 0);
+ subpos += dt;
+ pos += subpos >> 16;
+ x += (subpos >> 16) * SRC_CHANNELS;
+ subpos &= 65535;
+ );
}
diff = pos - diff;
overshot = pos - resampler->end;
- if (diff >= 3) {
- COPYSRC2(resampler->X, 0, overshot < 3, src, pos-3);
- COPYSRC2(resampler->X, 1, overshot < 2, src, pos-2);
- COPYSRC2(resampler->X, 2, overshot < 1, src, pos-1);
+ if (diff >= 7) {
+ COPYSRC2(resampler->X, 0, overshot < 7, src, pos-7);
+ COPYSRC2(resampler->X, 1, overshot < 6, src, pos-6);
+ COPYSRC2(resampler->X, 2, overshot < 5, src, pos-5);
+ COPYSRC2(resampler->X, 3, overshot < 4, src, pos-4);
+ COPYSRC2(resampler->X, 4, overshot < 3, src, pos-3);
+ COPYSRC2(resampler->X, 5, overshot < 2, src, pos-2);
+ COPYSRC2(resampler->X, 6, overshot < 1, src, pos-1);
+ } else if (diff >= 6) {
+ COPYSRC(resampler->X, 0, resampler->X, 1);
+ COPYSRC2(resampler->X, 1, overshot < 6, src, pos-6);
+ COPYSRC2(resampler->X, 2, overshot < 5, src, pos-5);
+ COPYSRC2(resampler->X, 3, overshot < 4, src, pos-4);
+ COPYSRC2(resampler->X, 4, overshot < 3, src, pos-3);
+ COPYSRC2(resampler->X, 5, overshot < 2, src, pos-2);
+ COPYSRC2(resampler->X, 6, overshot < 1, src, pos-1);
+ } else if (diff >= 5) {
+ COPYSRC(resampler->X, 0, resampler->X, 1);
+ COPYSRC(resampler->X, 1, resampler->X, 2);
+ COPYSRC2(resampler->X, 2, overshot < 5, src, pos-5);
+ COPYSRC2(resampler->X, 3, overshot < 4, src, pos-4);
+ COPYSRC2(resampler->X, 4, overshot < 3, src, pos-3);
+ COPYSRC2(resampler->X, 5, overshot < 2, src, pos-2);
+ COPYSRC2(resampler->X, 6, overshot < 1, src, pos-1);
+ } else if (diff >= 4) {
+ COPYSRC(resampler->X, 0, resampler->X, 1);
+ COPYSRC(resampler->X, 1, resampler->X, 2);
+ COPYSRC(resampler->X, 2, resampler->X, 3);
+ COPYSRC2(resampler->X, 3, overshot < 4, src, pos-4);
+ COPYSRC2(resampler->X, 4, overshot < 3, src, pos-3);
+ COPYSRC2(resampler->X, 5, overshot < 2, src, pos-2);
+ COPYSRC2(resampler->X, 6, overshot < 1, src, pos-1);
+ } else if (diff >= 3) {
+ COPYSRC(resampler->X, 0, resampler->X, 1);
+ COPYSRC(resampler->X, 1, resampler->X, 2);
+ COPYSRC(resampler->X, 2, resampler->X, 3);
+ COPYSRC(resampler->X, 3, resampler->X, 4);
+ COPYSRC2(resampler->X, 4, overshot < 3, src, pos-3);
+ COPYSRC2(resampler->X, 5, overshot < 2, src, pos-2);
+ COPYSRC2(resampler->X, 6, overshot < 1, src, pos-1);
} else if (diff >= 2) {
- COPYSRC(resampler->X, 0, resampler->X, 2);
- COPYSRC2(resampler->X, 1, overshot < 2, src, pos-2);
- COPYSRC2(resampler->X, 2, overshot < 1, src, pos-1);
+ COPYSRC(resampler->X, 0, resampler->X, 1);
+ COPYSRC(resampler->X, 1, resampler->X, 2);
+ COPYSRC(resampler->X, 2, resampler->X, 3);
+ COPYSRC(resampler->X, 3, resampler->X, 4);
+ COPYSRC(resampler->X, 4, resampler->X, 5);
+ COPYSRC2(resampler->X, 5, overshot < 2, src, pos-2);
+ COPYSRC2(resampler->X, 6, overshot < 1, src, pos-1);
} else if (diff >= 1) {
COPYSRC(resampler->X, 0, resampler->X, 1);
COPYSRC(resampler->X, 1, resampler->X, 2);
- COPYSRC2(resampler->X, 2, overshot < 1, src, pos-1);
+ COPYSRC(resampler->X, 2, resampler->X, 3);
+ COPYSRC(resampler->X, 3, resampler->X, 4);
+ COPYSRC(resampler->X, 4, resampler->X, 5);
+ COPYSRC(resampler->X, 5, resampler->X, 6);
+ COPYSRC2(resampler->X, 6, overshot < 1, src, pos-1);
}
}
resampler->pos = pos;
@@ -327,6 +488,7 @@
if (VOLUMES_ARE_ZERO) { MIX_ZEROS(=); return; }
init_cubic();
+ init_sinc();
quality = resampler->quality;
@@ -337,27 +499,33 @@
if (resampler->dir < 0) {
HEAVYASSERT(pos >= resampler->start);
- if (dumb_resampling_quality <= DUMB_RQ_ALIASING) {
+ if (quality <= DUMB_RQ_ALIASING) {
/* Aliasing, backwards */
MIX_ALIAS(=, 0, 1);
} else if (quality <= DUMB_RQ_LINEAR) {
/* Linear interpolation, backwards */
MIX_LINEAR(=, 0, 2, 1);
- } else {
+ } else if (quality <= DUMB_RQ_CUBIC) {
/* Cubic interpolation, backwards */
MIX_CUBIC(=, 0, src, x, pos, 2, 1, 0);
+ } else {
+ /* Sinc interpolation, backwards */
+ MIX_SINC(=, 0, src, x, pos, 6, 5, 4, 3, 2, 1, 0);
}
} else {
HEAVYASSERT(pos < resampler->end);
- if (dumb_resampling_quality <= DUMB_RQ_ALIASING) {
+ if (quality <= DUMB_RQ_ALIASING) {
/* Aliasing */
MIX_ALIAS(=, 0, 1);
- } else if (dumb_resampling_quality <= DUMB_RQ_LINEAR) {
+ } else if (quality <= DUMB_RQ_LINEAR) {
/* Linear interpolation, forwards */
MIX_LINEAR(=, 0, 1, 2);
- } else {
+ } else if (quality <= DUMB_RQ_CUBIC) {
/* Cubic interpolation, forwards */
MIX_CUBIC(=, 0, x, src, 0, 1, 2, pos);
+ } else {
+ /* Sinc interpolation, forwards */
+ MIX_SINC(=, 0, x, src, 0, 1, 2, 3, 4, 5, 6, pos);
}
}
}
@@ -365,6 +533,7 @@
#undef MIX_ZEROS
+#undef MIX_SINC
#undef MIX_CUBIC
#undef MIX_LINEAR
#undef MIX_ALIAS
--- a/dumb/src/helpers/resample.c
+++ b/dumb/src/helpers/resample.c
@@ -71,9 +71,10 @@
*
* 0 - DUMB_RQ_ALIASING - fastest
* 1 - DUMB_RQ_LINEAR
- * 2 - DUMB_RQ_CUBIC - nicest
+ * 2 - DUMB_RQ_CUBIC
+ * 3 - DUMB_RQ_SINC - nicest
*
- * Values outside the range 0-2 will behave the same as the nearest
+ * Values outside the range 0-3 will behave the same as the nearest
* value within the range.
*/
int dumb_resampling_quality = DUMB_RQ_CUBIC;
@@ -161,8 +162,144 @@
}
}
+static short sinc[8192];
+#define WFIR_QUANTBITS 14
+#define WFIR_QUANTSCALE (1L<<WFIR_QUANTBITS)
+#define WFIR_8SHIFT (WFIR_QUANTBITS-8)
+#define WFIR_16BITSHIFT (WFIR_QUANTBITS)
+// log2(number)-1 of precalculated taps range is [4..12]
+#define WFIR_FRACBITS 9
+#define WFIR_LUTLEN ((1L<<(WFIR_FRACBITS+1))/*+1*/)
+// number of samples in window
+#define WFIR_LOG2WIDTH 3
+#define WFIR_WIDTH (1L<<WFIR_LOG2WIDTH)
+#define WFIR_SMPSPERWING ((WFIR_WIDTH-1)>>1)
+// cutoff (1.0 == pi/2)
+#define WFIR_CUTOFF 0.95f
+// wfir type
+#define WFIR_HANN 0
+#define WFIR_HAMMING 1
+#define WFIR_BLACKMANEXACT 2
+#define WFIR_BLACKMAN3T61 3
+#define WFIR_BLACKMAN3T67 4
+#define WFIR_BLACKMAN4T92 5
+#define WFIR_BLACKMAN4T74 6
+#define WFIR_KAISER4T 7
+#define WFIR_TYPE WFIR_HANN
+// wfir help
+#ifndef M_zPI
+#define M_zPI 3.1415926535897932384626433832795
+#endif
+#define M_zEPS 1e-8
+#define M_zBESSELEPS 1e-21
+static float sinc_coef( int _PCnr, float _POfs, float _PCut, int _PWidth, int _PType ) //float _PPos, float _PFc, int _PLen )
+{
+ double _LWidthM1 = _PWidth-1;
+ double _LWidthM1Half = 0.5*_LWidthM1;
+ double _LPosU = ((double)_PCnr - _POfs);
+ double _LPos = _LPosU-_LWidthM1Half;
+ double _LPIdl = 2.0*M_zPI/_LWidthM1;
+ double _LWc,_LSi;
+ if( fabs(_LPos)<M_zEPS )
+ {
+ _LWc = 1.0;
+ _LSi = _PCut;
+ }
+ else
+ {
+ switch( _PType )
+ {
+ case WFIR_HANN:
+ _LWc = 0.50 - 0.50 * cos(_LPIdl*_LPosU);
+ break;
+ case WFIR_HAMMING:
+ _LWc = 0.54 - 0.46 * cos(_LPIdl*_LPosU);
+ break;
+ case WFIR_BLACKMANEXACT:
+ _LWc = 0.42 - 0.50 * cos(_LPIdl*_LPosU) + 0.08 * cos(2.0*_LPIdl*_LPosU);
+ break;
+ case WFIR_BLACKMAN3T61:
+ _LWc = 0.44959 - 0.49364 * cos(_LPIdl*_LPosU) + 0.05677 * cos(2.0*_LPIdl*_LPosU);
+ break;
+ case WFIR_BLACKMAN3T67:
+ _LWc = 0.42323 - 0.49755 * cos(_LPIdl*_LPosU) + 0.07922 * cos(2.0*_LPIdl*_LPosU);
+ break;
+ case WFIR_BLACKMAN4T92:
+ _LWc = 0.35875 - 0.48829 * cos(_LPIdl*_LPosU) + 0.14128 * cos(2.0*_LPIdl*_LPosU) - 0.01168 * cos(3.0*_LPIdl*_LPosU);
+ break;
+ case WFIR_BLACKMAN4T74:
+ _LWc = 0.40217 - 0.49703 * cos(_LPIdl*_LPosU) + 0.09392 * cos(2.0*_LPIdl*_LPosU) - 0.00183 * cos(3.0*_LPIdl*_LPosU);
+ break;
+ case WFIR_KAISER4T:
+ _LWc = 0.40243 - 0.49804 * cos(_LPIdl*_LPosU) + 0.09831 * cos(2.0*_LPIdl*_LPosU) - 0.00122 * cos(3.0*_LPIdl*_LPosU);
+ break;
+ default:
+ _LWc = 1.0;
+ break;
+ }
+ _LPos *= M_zPI;
+ _LSi = sin(_PCut*_LPos)/_LPos;
+ }
+ return (float)(_LWc*_LSi);
+}
+
+/*static*/ void init_sinc(void)
+{
+ int _LPcl;
+ float _LPcllen;
+ float _LNorm;
+ float _LCut;
+ float _LScale;
+ float _LGain,_LCoefs[WFIR_WIDTH];
+ static int done = 0;
+ if (done) return;
+ done = 1;
+ _LPcllen = (float)(1L<<WFIR_FRACBITS); // number of precalculated lines for 0..1 (-1..0)
+ _LNorm = 1.0f / (float)(2.0f * _LPcllen);
+ _LCut = WFIR_CUTOFF;
+ _LScale = (float)WFIR_QUANTSCALE;
+ for( _LPcl=0;_LPcl<WFIR_LUTLEN;_LPcl++ )
+ {
+ float _LOfs = ((float)_LPcl-_LPcllen)*_LNorm;
+ int _LCc,_LIdx = _LPcl<<WFIR_LOG2WIDTH;
+ for( _LCc=0,_LGain=0.0f;_LCc<WFIR_WIDTH;_LCc++ )
+ {
+ _LGain += (_LCoefs[_LCc] = sinc_coef( _LCc, _LOfs, _LCut, WFIR_WIDTH, WFIR_TYPE ));
+ }
+ _LGain = 1.0f/_LGain;
+ for( _LCc=0;_LCc<WFIR_WIDTH;_LCc++ )
+ {
+ float _LCoef = (float)floor( 0.5 + _LScale*_LCoefs[_LCc]*_LGain );
+ sinc[_LIdx+_LCc] = (signed short)( (_LCoef<-_LScale)?-_LScale:((_LCoef>_LScale)?_LScale:_LCoef) );
+ }
+ }
+}
+
+#undef WFIR_QUANTBITS
+#undef WFIR_QUANTSCALE
+#undef WFIR_8SHIFT
+#undef WFIR_16BITSHIFT
+#undef WFIR_FRACBITS
+#undef WFIR_LUTLEN
+#undef WFIR_LOG2WIDTH
+#undef WFIR_WIDTH
+#undef WFIR_SMPSPERWING
+#undef WFIR_CUTOFF
+#undef WFIR_HANN
+#undef WFIR_HAMMING
+#undef WFIR_BLACKMANEXACT
+#undef WFIR_BLACKMAN3T61
+#undef WFIR_BLACKMAN3T67
+#undef WFIR_BLACKMAN4T92
+#undef WFIR_BLACKMAN4T74
+#undef WFIR_KAISER4T
+#undef WFIR_TYPE
+#undef M_zPI
+#undef M_zEPS
+#undef M_zBESSELEPS
+
/* Create resamplers for 24-in-32-bit source samples. */
/* #define SUFFIX
@@ -192,6 +329,16 @@
MULSC(x2, cubicA1[1 + (subpos >> 6 ^ 1023)] << 2) + \
MULSC(x3, cubicA0[1 + (subpos >> 6 ^ 1023)] << 2))
#define CUBICVOL(x, vol) MULSC(x, vol)
+#define SINC(x0, x1, x2, x3, x4, x5, x6, x7) ( \
+ MULSC(x0, sinc[(subpos >> 3) & 0x1FF8] << 2) + \
+ MULSC(x1, sinc[((subpos >> 3) & 0x1FF8) + 1] << 2) + \
+ MULSC(x2, sinc[((subpos >> 3) & 0x1FF8) + 2] << 2) + \
+ MULSC(x3, sinc[((subpos >> 3) & 0x1FF8) + 3] << 2) + \
+ MULSC(x4, sinc[((subpos >> 3) & 0x1FF8) + 4] << 2) + \
+ MULSC(x5, sinc[((subpos >> 3) & 0x1FF8) + 5] << 2) + \
+ MULSC(x6, sinc[((subpos >> 3) & 0x1FF8) + 6] << 2) + \
+ MULSC(x7, sinc[((subpos >> 3) & 0x1FF8) + 7] << 2))
+#define SINCVOL(x, vol) MULSC(x, vol)
#include "resample.inc"
/* Undefine the simplified macros. */
@@ -228,6 +375,16 @@
x2 * cubicA1[1 + (subpos >> 6 ^ 1023)] + \
x3 * cubicA0[1 + (subpos >> 6 ^ 1023)])
#define CUBICVOL(x, vol) (int)((LONG_LONG)(x) * (vol << 10) >> 32)
+#define SINC(x0, x1, x2, x3, x4, x5, x6, x7) ( \
+ x0 * sinc[(subpos >> 3) & 0x1FF8] + \
+ x1 * sinc[((subpos >> 3) & 0x1FF8) + 1] + \
+ x2 * sinc[((subpos >> 3) & 0x1FF8) + 2] + \
+ x3 * sinc[((subpos >> 3) & 0x1FF8) + 3] + \
+ x4 * sinc[((subpos >> 3) & 0x1FF8) + 4] + \
+ x5 * sinc[((subpos >> 3) & 0x1FF8) + 5] + \
+ x6 * sinc[((subpos >> 3) & 0x1FF8) + 6] + \
+ x7 * sinc[((subpos >> 3) & 0x1FF8) + 7])
+#define SINCVOL(x, vol) (int)((LONG_LONG)(x) * (vol << 10) >> 32)
#include "resample.inc"
/* Create resamplers for 8-bit source samples. */
@@ -250,6 +407,16 @@
x2 * cubicA1[1 + (subpos >> 6 ^ 1023)] + \
x3 * cubicA0[1 + (subpos >> 6 ^ 1023)]) << 6)
#define CUBICVOL(x, vol) (int)((LONG_LONG)(x) * (vol << 12) >> 32)
+#define SINC(x0, x1, x2, x3, x4, x5, x6, x7) (( \
+ x0 * sinc[(subpos >> 3) & 0x1FF8] + \
+ x1 * sinc[((subpos >> 3) & 0x1FF8) + 1] + \
+ x2 * sinc[((subpos >> 3) & 0x1FF8) + 2] + \
+ x3 * sinc[((subpos >> 3) & 0x1FF8) + 3] + \
+ x4 * sinc[((subpos >> 3) & 0x1FF8) + 4] + \
+ x5 * sinc[((subpos >> 3) & 0x1FF8) + 5] + \
+ x6 * sinc[((subpos >> 3) & 0x1FF8) + 6] + \
+ x7 * sinc[((subpos >> 3) & 0x1FF8) + 7]) << 6)
+#define SINCVOL(x, vol) (int)((LONG_LONG)(x) * (vol << 12) >> 32)
#include "resample.inc"
--- a/dumb/src/helpers/resample.inc
+++ b/dumb/src/helpers/resample.inc
@@ -67,7 +67,7 @@
{
resampler->quality = quality;
}
- for (i = 0; i < src_channels*3; i++) resampler->X[i] = 0;
+ for (i = 0; i < src_channels*7; i++) resampler->X[i] = 0;
resampler->overshot = -1;
}
@@ -156,6 +156,17 @@
if ( upd ) UPDATE_VOLUME( volume_left, lvol ); \
if ( upd ) UPDATE_VOLUME( volume_right, rvol ); \
}
+#define MONO_DEST_MIX_SINC(op, upd, x0, x7, o0, o1, o2, o3, o4, o5, o6, o7) { \
+ *dst++ op SINCVOL(SINC(x0[o0], x[o1], x[o2], x[o3], x[o4], x[o5], x[o6], x7[o7]), vol); \
+ if ( upd ) UPDATE_VOLUME( volume, vol ); \
+}
+#define STEREO_DEST_MIX_SINC(op, upd, x0, x7, o0, o1, o2, o3, o4, o5, o6, o7) { \
+ int xm = SINC(x0[o0], x[o1], x[o2], x[o3], x[o4], x[o5], x[o6], x7[o7]); \
+ *dst++ op SINCVOL(xm, lvol); \
+ *dst++ op SINCVOL(xm, rvol); \
+ if ( upd ) UPDATE_VOLUME( volume_left, lvol ); \
+ if ( upd ) UPDATE_VOLUME( volume_right, rvol ); \
+}
#include "resamp2.inc"
/* Create stereo source resampler. */
@@ -243,6 +254,19 @@
if ( upd ) UPDATE_VOLUME( volume_left, lvol ); \
if ( upd ) UPDATE_VOLUME( volume_right, rvol ); \
}
+#define MONO_DEST_MIX_SINC(op, upd, x0, x7, o0, o1, o2, o3, o4, o5, o6, o7) { \
+ *dst++ op \
+ SINCVOL(SINC(x0[(o0)*2], x[(o1)*2], x[(o2)*2], x[(o3)*2], x[(o4)*2], x[(o5)*2], x[(o6)*2], x7[(o7)*2]), lvol) + \
+ SINCVOL(SINC(x0[(o0)*2+1], x[(o1)*2+1], x[(o2)*2+1], x[(o3)*2+1], x[(o4)*2+1], x[(o5)*2+1], x[(o6)*2+1], x7[(o7)*2+1]), rvol); \
+ if ( upd ) UPDATE_VOLUME( volume_left, lvol ); \
+ if ( upd ) UPDATE_VOLUME( volume_right, rvol ); \
+}
+#define STEREO_DEST_MIX_SINC(op, upd, x0, x7, o0, o1, o2, o3, o4, o5, o6, o7) { \
+ *dst++ op SINCVOL(SINC(x0[(o0)*2], x[(o1)*2], x[(o2)*2], x[(o3)*2], x[(o4)*2], x[(o5)*2], x[(o6)*2], x7[(o7)*2]), lvol); \
+ *dst++ op SINCVOL(SINC(x0[(o0)*2+1], x[(o1)*2+1], x[(o2)*2+1], x[(o3)*2+1], x[(o4)*2+1], x[(o5)*2+1], x[(o6)*2+1], x7[(o7)*2+1]), rvol); \
+ if ( upd ) UPDATE_VOLUME( volume_left, lvol ); \
+ if ( upd ) UPDATE_VOLUME( volume_right, rvol ); \
+}
#include "resamp2.inc"
@@ -255,6 +279,8 @@
+#undef SINCVOL
+#undef SINC
#undef CUBICVOL
#undef CUBIC
#undef LINEAR