Browse code

For in_snsf, replaced the B-spline interpolation with the 6-point, 5th-order version, and replaced the Optimal interpolation with 6-point, 5th-order 2nd-order Osculating.

Naram Qashat authored on 2013/04/12 13:36:31
Showing 5 changed files
... ...
@@ -1,7 +1,7 @@
1 1
 /*
2 2
  * xSF - SNSF configuration
3 3
  * By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com]
4
- * Last modification on 2013-03-25
4
+ * Last modification on 2013-04-12
5 5
  *
6 6
  * Partially based on the vio*sf framework
7 7
  *
... ...
@@ -97,7 +97,7 @@ INT_PTR CALLBACK XSFConfig_SNSF::ConfigDialogProc(HWND hwndDlg, UINT uMsg, WPARA
97 97
 			SendMessageW(GetDlgItem(hwndDlg, idResampler), CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(L"Linear Resampler"));
98 98
 			SendMessageW(GetDlgItem(hwndDlg, idResampler), CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(L"Hermite Resampler"));
99 99
 			SendMessageW(GetDlgItem(hwndDlg, idResampler), CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(L"Bspline Resampler"));
100
-			SendMessageW(GetDlgItem(hwndDlg, idResampler), CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(L"Optimal Resampler"));
100
+			SendMessageW(GetDlgItem(hwndDlg, idResampler), CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(L"Osculating Resampler"));
101 101
 			SendMessageW(GetDlgItem(hwndDlg, idResampler), CB_SETCURSEL, this->resampler, 0);
102 102
 			// Mutes
103 103
 			for (int x = 0, numMutes = this->mutes.size(); x < numMutes; ++x)
... ...
@@ -25,7 +25,7 @@
25 25
 #include "snes9x/apu/linear_resampler.h"
26 26
 #include "snes9x/apu/hermite_resampler.h"
27 27
 #include "snes9x/apu/bspline_resampler.h"
28
-#include "snes9x/apu/optimal_resampler.h"
28
+#include "snes9x/apu/osculating_resampler.h"
29 29
 #include "snes9x/memmap.h"
30 30
 
31 31
 class XSFPlayer_SNSF : public XSFPlayer
... ...
@@ -231,7 +231,7 @@ bool XSFPlayer_SNSF::Load()
231 231
 	S9xInitAPU();
232 232
 	XSFConfig_SNSF *xSFConfig_SNSF = dynamic_cast<XSFConfig_SNSF *>(xSFConfig);
233 233
 	if (xSFConfig_SNSF->resampler == 3)
234
-		S9xInitSound<OptimalResampler>(10, 0);
234
+		S9xInitSound<OsculatingResampler>(10, 0);
235 235
 	if (xSFConfig_SNSF->resampler == 2)
236 236
 		S9xInitSound<BsplineResampler>(10, 0);
237 237
 	else if (xSFConfig_SNSF->resampler == 1)
... ...
@@ -183,7 +183,7 @@
183 183
 #include "linear_resampler.h"
184 184
 #include "hermite_resampler.h"
185 185
 #include "bspline_resampler.h"
186
-#include "optimal_resampler.h"
186
+#include "osculating_resampler.h"
187 187
 
188 188
 #define APU_DEFAULT_INPUT_RATE		32000
189 189
 #define APU_MINIMUM_SAMPLE_COUNT	512
... ...
@@ -478,7 +478,7 @@ template<class ResamplerClass> bool S9xInitSound (int buffer_ms, int lag_ms)
478 478
 template bool S9xInitSound<LinearResampler>(int, int);
479 479
 template bool S9xInitSound<HermiteResampler>(int, int);
480 480
 template bool S9xInitSound<BsplineResampler>(int, int);
481
-template bool S9xInitSound<OptimalResampler>(int, int);
481
+template bool S9xInitSound<OsculatingResampler>(int, int);
482 482
 
483 483
 void S9xSetSoundControl (uint8_t voice_switch)
484 484
 {
... ...
@@ -16,16 +16,20 @@ class BsplineResampler : public Resampler
16 16
 protected:
17 17
 	double r_step;
18 18
 	double r_frac;
19
-	int r_left[4], r_right[4];
19
+	int r_left[6], r_right[6];
20 20
 
21
-	double bspline(double x, double a, double b, double c, double d)
21
+	double bspline(double x, double a, double b, double c, double d, double e, double f)
22 22
 	{
23
-		double ym1py1 = a + c;
24
-		double c0 = 1 / 6.0 * ym1py1 + 2 / 3.0 * b;
25
-		double c1 = 0.5 * (c - a);
26
-		double c2 = 0.5 * ym1py1 - b;
27
-		double c3 = 0.5 * (b - c) + 1 / 6.0 * (d - a);
28
-		return ((c3 * x + c2) * x + c1) * x + c0;
23
+		float ym2py2 = a + e, ym1py1 = b + d;
24
+		float y2mym2 = e - a, y1mym1 = d - b;
25
+		float sixthym1py1 = 1 / 6.0 * ym1py1;
26
+		float c0 = 1 / 120.0 * ym2py2 + 13 / 60.0 * ym1py1 + 0.55 * c;
27
+		float c1 = 1 / 24.0 * y2mym2 + 5 / 12.0 * y1mym1;
28
+		float c2 = 1 / 12.0 * ym2py2 + sixthym1py1 - 0.5 * c;
29
+		float c3 = 1 / 12.0 * y2mym2 - 1 / 6.0 * y1mym1;
30
+		float c4 = 1 / 24.0 * ym2py2 - sixthym1py1 + 0.25 * c;
31
+		float c5 = 1 / 120.0 * (f - a) + 1 / 24.0 * (b - e) + 1 / 12.0 * (d - c);
32
+		return ((((c5 * x + c4) * x + c3) * x + c2) * x + c1) * x + c0;
29 33
 	}
30 34
 
31 35
 public:
... ...
@@ -44,8 +48,8 @@ public:
44 48
 	{
45 49
 		ring_buffer::clear ();
46 50
 		this->r_frac = 1.0;
47
-		this->r_left[0] = this->r_left[1] = this->r_left[2] = this->r_left[3] = 0;
48
-		this->r_right[0] = this->r_right[1] = this->r_right[2] = this->r_right[3] = 0;
51
+		this->r_left[0] = this->r_left[1] = this->r_left[2] = this->r_left[3] = this->r_left[4] = this->r_left[5] = 0;
52
+		this->r_right[0] = this->r_right[1] = this->r_right[2] = this->r_right[3] = this->r_right[4] = this->r_right[5] = 0;
49 53
 	}
50 54
 
51 55
 	void read(short *data, int num_samples)
... ...
@@ -78,8 +82,8 @@ public:
78 82
 
79 83
 			while (this->r_frac <= 1.0 && o_position < num_samples)
80 84
 			{
81
-				data[o_position] = SHORT_CLAMP(bspline(this->r_frac, this->r_left[0], this->r_left[1], this->r_left[2], this->r_left[3]));
82
-				data[o_position + 1] = SHORT_CLAMP(bspline(this->r_frac, this->r_right[0], this->r_right[1], this->r_right[2], this->r_right[3]));
85
+				data[o_position] = SHORT_CLAMP(bspline(this->r_frac, this->r_left[0], this->r_left[1], this->r_left[2], this->r_left[3], this->r_left[4], this->r_left[5]));
86
+				data[o_position + 1] = SHORT_CLAMP(bspline(this->r_frac, this->r_right[0], this->r_right[1], this->r_right[2], this->r_right[3], this->r_right[4], this->r_right[5]));
83 87
 
84 88
 				o_position += 2;
85 89
 
... ...
@@ -91,12 +95,16 @@ public:
91 95
 				this->r_left[0] = this->r_left[1];
92 96
 				this->r_left[1] = this->r_left[2];
93 97
 				this->r_left[2] = this->r_left[3];
94
-				this->r_left[3] = s_left;
98
+				this->r_left[3] = this->r_left[4];
99
+				this->r_left[4] = this->r_left[5];
100
+				this->r_left[5] = s_left;
95 101
 
96 102
 				this->r_right[0] = this->r_right[1];
97 103
 				this->r_right[1] = this->r_right[2];
98 104
 				this->r_right[2] = this->r_right[3];
99
-				this->r_right[3] = s_right;
105
+				this->r_right[3] = this->r_right[4];
106
+				this->r_right[4] = this->r_right[5];
107
+				this->r_right[5] = s_right;
100 108
 
101 109
 				this->r_frac -= 1.0;
102 110
 
103 111
similarity index 59%
104 112
rename from src/in_snsf/snes9x/apu/optimal_resampler.h
105 113
rename to src/in_snsf/snes9x/apu/osculating_resampler.h
... ...
@@ -1,7 +1,7 @@
1 1
 /* Simple resampler based on bsnes's ruby audio library */
2 2
 
3
-#ifndef __OPTIMAL_RESAMPLER_H
4
-#define __OPTIMAL_RESAMPLER_H
3
+#ifndef __OSCULATING_RESAMPLER_H
4
+#define __OSCULATING_RESAMPLER_H
5 5
 
6 6
 #include <cmath>
7 7
 #include "resampler.h"
... ...
@@ -11,28 +11,30 @@
11 11
 //template<typename T1, typename T2> static inline T1 CLAMP(T1 x, T2 low, T2 high) { return x > high ? high : (x < low ? low : x); }
12 12
 //template<typename T> static inline short SHORT_CLAMP(T n) { return static_cast<short>(CLAMP(n, -32768, 32767)); }
13 13
 
14
-class OptimalResampler : public Resampler
14
+class OsculatingResampler : public Resampler
15 15
 {
16 16
 protected:
17 17
 	double r_step;
18 18
 	double r_frac;
19
-	int r_left[4], r_right[4];
19
+	int r_left[6], r_right[6];
20 20
 
21
-	double optimal(double x, double a, double b, double c, double d)
21
+	double osculating(double x, double a, double b, double c, double d, double e, double f)
22 22
 	{
23 23
 		double z = x - 0.5;
24
-		double even1 = c + b, odd1 = c - b;
25
-		double even2 = d + a, odd2 = d - a;
26
-		double c0 = even1 * 0.46822774170144532 + even2 * 0.03177225758005808;
27
-		double c1 = odd1 * 0.55890365706150436 + odd2 * 0.14703258836343669;
28
-		double c2 = even1 * -0.250153411893796031 + even2 * 0.25015343462990891;
29
-		double c3 = odd1 * -0.49800710906733769 + odd2 * 0.16600005174304033;
30
-		double c4 = even1 * 0.00064264050033187 + even2 * -0.00064273459469381;
31
-		return (((c4 * z + c3) * z + c2) * z + c1) * z + c0;
24
+		double even1 = a + f, odd1 = a - f;
25
+		double even2 = b + e, odd2 = b - e;
26
+		double even3 = c + d, odd3 = c - d;
27
+		double c0 = 0.01171875 * even1 - 0.09765625 * even2 + 0.5859375 * even3;
28
+		double c1 = 0.2109375 * odd2 - 281 / 192.0 * odd3 - 13 / 384.0 * odd1;
29
+		double c2 = 0.40625 * even2 - 17 / 48.0 * even3 - 5 / 96.0 * even1;
30
+		double c3 = 0.1875 * odd1 - 53 / 48.0 * odd2 + 2.375 * odd3;
31
+		double c4 = 1 / 48.0*even1 - 0.0625 * even2 + 1 / 24.0 * even3;
32
+		double c5 = 25 / 24.0 * odd2 - 25 / 12.0 * odd3 - 5 / 24.0 * odd1;
33
+		return ((((c5 * z + c4) * z + c3) * z + c2) * z + c1) * z + c0;
32 34
 	}
33 35
 
34 36
 public:
35
-	OptimalResampler(int num_samples) : Resampler(num_samples)
37
+	OsculatingResampler(int num_samples) : Resampler(num_samples)
36 38
 	{
37 39
 		this->clear();
38 40
 	}
... ...
@@ -47,8 +49,8 @@ public:
47 49
 	{
48 50
 		ring_buffer::clear ();
49 51
 		this->r_frac = 1.0;
50
-		this->r_left[0] = this->r_left[1] = this->r_left[2] = this->r_left[3] = 0;
51
-		this->r_right[0] = this->r_right[1] = this->r_right[2] = this->r_right[3] = 0;
52
+		this->r_left[0] = this->r_left[1] = this->r_left[2] = this->r_left[3] = this->r_left[4] = this->r_left[5] = 0;
53
+		this->r_right[0] = this->r_right[1] = this->r_right[2] = this->r_right[3] = this->r_right[4] = this->r_right[5] = 0;
52 54
 	}
53 55
 
54 56
 	void read(short *data, int num_samples)
... ...
@@ -81,8 +83,8 @@ public:
81 83
 
82 84
 			while (this->r_frac <= 1.0 && o_position < num_samples)
83 85
 			{
84
-				data[o_position] = SHORT_CLAMP(optimal(this->r_frac, this->r_left[0], this->r_left[1], this->r_left[2], this->r_left[3]));
85
-				data[o_position + 1] = SHORT_CLAMP(optimal(this->r_frac, this->r_right[0], this->r_right[1], this->r_right[2], this->r_right[3]));
86
+				data[o_position] = SHORT_CLAMP(osculating(this->r_frac, this->r_left[0], this->r_left[1], this->r_left[2], this->r_left[3], this->r_left[4], this->r_left[5]));
87
+				data[o_position + 1] = SHORT_CLAMP(osculating(this->r_frac, this->r_right[0], this->r_right[1], this->r_right[2], this->r_right[3], this->r_right[4], this->r_right[5]));
86 88
 
87 89
 				o_position += 2;
88 90
 
... ...
@@ -94,12 +96,16 @@ public:
94 96
 				this->r_left[0] = this->r_left[1];
95 97
 				this->r_left[1] = this->r_left[2];
96 98
 				this->r_left[2] = this->r_left[3];
97
-				this->r_left[3] = s_left;
99
+				this->r_left[3] = this->r_left[4];
100
+				this->r_left[4] = this->r_left[5];
101
+				this->r_left[5] = s_left;
98 102
 
99 103
 				this->r_right[0] = this->r_right[1];
100 104
 				this->r_right[1] = this->r_right[2];
101 105
 				this->r_right[2] = this->r_right[3];
102
-				this->r_right[3] = s_right;
106
+				this->r_right[3] = this->r_right[4];
107
+				this->r_right[4] = this->r_right[5];
108
+				this->r_right[5] = s_right;
103 109
 
104 110
 				this->r_frac -= 1.0;
105 111
 
... ...
@@ -122,4 +128,4 @@ public:
122 128
 	}
123 129
 };
124 130
 
125
-#endif /* __OPTIMAL_RESAMPLER_H */
131
+#endif /* __OSCULATING_RESAMPLER_H */