shithub: dumb

Download patch

ref: eff0f2541daf739f21bb0662345915f4fa60354f
parent: 92fea5b475e37c39b28b88ab28b0dfbd8c899adf
author: Chris Moeller <kode54@gmail.com>
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