Browse code

Update snes9x code from 1.53 to 1.6.0.

Notable differences from upstream:
* Did not use the same #include setup for the new byuu apu and instead chose to do things more traditionally, as the latter is also much easier to deal with in Visual Studio than just including .cpp files into other .cpp files...
* MSU1 support not included (I see no need for this in a plugin meant to be used for original SNES music).
* The dynamic rate control on the APU not included (I also see no need for it in this plugin).
* The extra resamplers I added in were removed as the original hermite resampler was folded into a single non-inhertiable resampler.
* Bits of cleanup.

Naram Qashat authored on 2021/04/19 21:20:36
Showing 1 changed files
1 1
deleted file mode 100644
... ...
@@ -1,145 +0,0 @@
1
-/* Simple resampler based on bsnes's ruby audio library */
2
-
3
-#pragma once
4
-
5
-#include <algorithm>
6
-#define _USE_MATH_DEFINES
7
-#include <cmath>
8
-#include "resampler.h"
9
-#include "XSFCommon.h"
10
-
11
-#ifndef M_PI
12
-const double M_PI = 3.14159265358979323846;
13
-#endif
14
-
15
-class SincResampler : public Resampler
16
-{
17
-protected:
18
-	static bool initializedLUTs;
19
-	static const unsigned SINC_RESOLUTION = 8192;
20
-	static const unsigned SINC_WIDTH = 8;
21
-	static const unsigned SINC_SAMPLES = SINC_RESOLUTION * SINC_WIDTH;
22
-	static double sinc_lut[SINC_SAMPLES + 1];
23
-
24
-	double r_step;
25
-	double r_frac;
26
-	int r_left[SINC_WIDTH * 2], r_right[SINC_WIDTH * 2];
27
-
28
-	template<typename T1, typename T2> static T1 CLAMP(T1 x, T2 low, T2 high) { return x > high ? high : (x < low ? low : x); }
29
-	template<typename T> static short SHORT_CLAMP(T n) { return static_cast<short>(CLAMP(n, -32768, 32767)); }
30
-
31
-	static inline double sinc(double x)
32
-	{
33
-		return fEqual(x, 0.0) ? 1.0 : std::sin(x * M_PI) / (x * M_PI);
34
-	}
35
-
36
-	double sinc(const int *data)
37
-	{
38
-		double kernel[SINC_WIDTH * 2], kernel_sum = 0.0;
39
-		int i = SINC_WIDTH, shift = static_cast<int>(std::floor(this->r_frac * SINC_RESOLUTION));
40
-		int step = this->r_step > 1.0 ? static_cast<int>(SINC_RESOLUTION / this->r_step) : SINC_RESOLUTION;
41
-		int shift_adj = shift * step / SINC_RESOLUTION;
42
-		for (; i >= -static_cast<int>(SINC_WIDTH - 1); --i)
43
-		{
44
-			int pos = i * step;
45
-			kernel_sum += kernel[i + SINC_WIDTH - 1] = this->sinc_lut[std::abs(shift_adj - pos)];
46
-		}
47
-		double sum = 0.0;
48
-		for (i = 0; i < static_cast<int>(SINC_WIDTH * 2); ++i)
49
-			sum += data[i] * kernel[i];
50
-		return sum / kernel_sum;
51
-	}
52
-
53
-public:
54
-	SincResampler(int num_samples) : Resampler(num_samples)
55
-	{
56
-		if (!this->initializedLUTs)
57
-		{
58
-			double dx = static_cast<double>(SINC_WIDTH) / SINC_SAMPLES, x = 0.0;
59
-			for (unsigned i = 0; i <= SINC_SAMPLES; ++i, x += dx)
60
-				this->sinc_lut[i] = std::abs(x) < SINC_WIDTH ? sinc(x) * sinc(x / SINC_WIDTH) : 0.0;
61
-			this->initializedLUTs = true;
62
-		}
63
-		this->clear();
64
-	}
65
-
66
-	void time_ratio(double ratio)
67
-	{
68
-		this->r_step = ratio;
69
-		this->clear();
70
-	}
71
-
72
-	void clear()
73
-	{
74
-		ring_buffer::clear();
75
-		this->r_frac = 1.0;
76
-		std::fill_n(&this->r_left[0], SINC_WIDTH * 2, 0);
77
-		std::fill_n(&this->r_right[0], SINC_WIDTH * 2, 0);
78
-	}
79
-
80
-	void read(short *data, int num_samples)
81
-	{
82
-		int i_position = this->start >> 1;
83
-		short *internal_buffer = reinterpret_cast<short *>(&this->buffer[0]);
84
-		int o_position = 0;
85
-		int consumed = 0;
86
-
87
-		while (o_position < num_samples && consumed < this->buffer_size)
88
-		{
89
-			int s_left = internal_buffer[i_position];
90
-			int s_right = internal_buffer[i_position + 1];
91
-			int max_samples = this->buffer_size >> 1;
92
-			static const double margin_of_error = 1.0e-10;
93
-
94
-			if (std::abs(this->r_step - 1.0) < margin_of_error)
95
-			{
96
-				data[o_position] = static_cast<short>(s_left);
97
-				data[o_position + 1] = static_cast<short>(s_right);
98
-
99
-				o_position += 2;
100
-				i_position += 2;
101
-				if (i_position >= max_samples)
102
-					i_position -= max_samples;
103
-				consumed += 2;
104
-
105
-				continue;
106
-			}
107
-
108
-			while (this->r_frac <= 1.0 && o_position < num_samples)
109
-			{
110
-				data[o_position] = SHORT_CLAMP(sinc(this->r_left));
111
-				data[o_position + 1] = SHORT_CLAMP(sinc(this->r_right));
112
-
113
-				o_position += 2;
114
-
115
-				this->r_frac += this->r_step;
116
-			}
117
-
118
-			if (this->r_frac > 1.0)
119
-			{
120
-				std::copy_n(&this->r_left[1], SINC_WIDTH * 2 - 1, &this->r_left[0]);
121
-				this->r_left[SINC_WIDTH * 2 - 1] = s_left;
122
-
123
-				std::copy_n(&this->r_right[1], SINC_WIDTH * 2 - 1, &this->r_right[0]);
124
-				this->r_right[SINC_WIDTH * 2 - 1] = s_right;
125
-
126
-				this->r_frac -= 1.0;
127
-
128
-				i_position += 2;
129
-				if (i_position >= max_samples)
130
-					i_position -= max_samples;
131
-				consumed += 2;
132
-			}
133
-		}
134
-
135
-		this->size -= consumed << 1;
136
-		this->start += consumed << 1;
137
-		if (this->start >= this->buffer_size)
138
-			this->start -= this->buffer_size;
139
-	}
140
-
141
-	int avail()
142
-	{
143
-		return static_cast<int>(std::floor(((this->size >> 2) - this->r_frac) / this->r_step) * 2);
144
-	}
145
-};
Browse code

* Fixes for gcc and clang (while they can compile the code, the DLLs made aren't functional, but oh well).

* [2SF] Used more up-to-date asmjit, despite the ugly looking code.

Naram Qashat authored on 2014/09/17 19:51:45
Showing 1 changed files
... ...
@@ -6,6 +6,7 @@
6 6
 #define _USE_MATH_DEFINES
7 7
 #include <cmath>
8 8
 #include "resampler.h"
9
+#include "XSFCommon.h"
9 10
 
10 11
 #ifndef M_PI
11 12
 const double M_PI = 3.14159265358979323846;
... ...
@@ -27,14 +28,6 @@ protected:
27 28
 	template<typename T1, typename T2> static T1 CLAMP(T1 x, T2 low, T2 high) { return x > high ? high : (x < low ? low : x); }
28 29
 	template<typename T> static short SHORT_CLAMP(T n) { return static_cast<short>(CLAMP(n, -32768, 32767)); }
29 30
 
30
-	// Code from http://learningcppisfun.blogspot.com/2010/04/comparing-floating-point-numbers.html
31
-	template<typename T> static bool fEqual(T x, T y, int N = 1)
32
-	{
33
-		T diff = std::abs(x - y);
34
-		T tolerance = N * std::numeric_limits<T>::epsilon();
35
-		return diff <= tolerance * std::abs(x) && diff <= tolerance * std::abs(y);
36
-	}
37
-
38 31
 	static inline double sinc(double x)
39 32
 	{
40 33
 		return fEqual(x, 0.0) ? 1.0 : std::sin(x * M_PI) / (x * M_PI);
... ...
@@ -87,7 +80,7 @@ public:
87 80
 	void read(short *data, int num_samples)
88 81
 	{
89 82
 		int i_position = this->start >> 1;
90
-		short *internal_buffer = reinterpret_cast<short *>(this->buffer);
83
+		short *internal_buffer = reinterpret_cast<short *>(&this->buffer[0]);
91 84
 		int o_position = 0;
92 85
 		int consumed = 0;
93 86
 
Browse code

A few more cases of using #pragma once instead of include guards.

Naram Qashat authored on 2014/09/08 14:51:19
Showing 1 changed files
... ...
@@ -1,7 +1,6 @@
1 1
 /* Simple resampler based on bsnes's ruby audio library */
2 2
 
3
-#ifndef __SINC_RESAMPLER_H
4
-#define __SINC_RESAMPLER_H
3
+#pragma once
5 4
 
6 5
 #include <algorithm>
7 6
 #define _USE_MATH_DEFINES
... ...
@@ -151,5 +150,3 @@ public:
151 150
 		return static_cast<int>(std::floor(((this->size >> 2) - this->r_frac) / this->r_step) * 2);
152 151
 	}
153 152
 };
154
-
155
-#endif /* __SINC_RESAMPLER_H */
Browse code

[SNSF] Make the SNSF sinc resampler use Lanczos instead.

Naram Qashat authored on 2014/09/08 14:16:54
Showing 1 changed files
... ...
@@ -65,7 +65,7 @@ public:
65 65
 		{
66 66
 			double dx = static_cast<double>(SINC_WIDTH) / SINC_SAMPLES, x = 0.0;
67 67
 			for (unsigned i = 0; i <= SINC_SAMPLES; ++i, x += dx)
68
-				this->sinc_lut[i] = std::abs(x) < SINC_WIDTH ? sinc(x) * (0.5 * (1.0 + std::cos((M_PI * x) / SINC_WIDTH))) : 0.0;
68
+				this->sinc_lut[i] = std::abs(x) < SINC_WIDTH ? sinc(x) * sinc(x / SINC_WIDTH) : 0.0;
69 69
 			this->initializedLUTs = true;
70 70
 		}
71 71
 		this->clear();
Browse code

[SNSF] Replaced most uses of fill/copy with fill_n/copy_n, and a few other minor code cleanups.

Naram Qashat authored on 2013/05/27 22:34:22
Showing 1 changed files
... ...
@@ -81,8 +81,8 @@ public:
81 81
 	{
82 82
 		ring_buffer::clear();
83 83
 		this->r_frac = 1.0;
84
-		std::fill(&this->r_left[0], &this->r_left[SINC_WIDTH * 2], 0);
85
-		std::fill(&this->r_right[0], &this->r_right[SINC_WIDTH * 2], 0);
84
+		std::fill_n(&this->r_left[0], SINC_WIDTH * 2, 0);
85
+		std::fill_n(&this->r_right[0], SINC_WIDTH * 2, 0);
86 86
 	}
87 87
 
88 88
 	void read(short *data, int num_samples)
... ...
@@ -125,10 +125,10 @@ public:
125 125
 
126 126
 			if (this->r_frac > 1.0)
127 127
 			{
128
-				std::copy(&this->r_left[1], &this->r_left[SINC_WIDTH * 2], &this->r_left[0]);
128
+				std::copy_n(&this->r_left[1], SINC_WIDTH * 2 - 1, &this->r_left[0]);
129 129
 				this->r_left[SINC_WIDTH * 2 - 1] = s_left;
130 130
 
131
-				std::copy(&this->r_right[1], &this->r_right[SINC_WIDTH * 2], &this->r_right[0]);
131
+				std::copy_n(&this->r_right[1], SINC_WIDTH * 2 - 1, &this->r_right[0]);
132 132
 				this->r_right[SINC_WIDTH * 2 - 1] = s_right;
133 133
 
134 134
 				this->r_frac -= 1.0;
Browse code

[SNSF] Massive code cleanup, as well as removing as much unused code/variables as possible.

Naram Qashat authored on 2013/05/23 06:02:16
Showing 1 changed files
... ...
@@ -8,9 +8,6 @@
8 8
 #include <cmath>
9 9
 #include "resampler.h"
10 10
 
11
-#undef CLAMP
12
-#undef SHORT_CLAMP
13
-
14 11
 #ifndef M_PI
15 12
 const double M_PI = 3.14159265358979323846;
16 13
 #endif
... ...
@@ -82,7 +79,7 @@ public:
82 79
 
83 80
 	void clear()
84 81
 	{
85
-		ring_buffer::clear ();
82
+		ring_buffer::clear();
86 83
 		this->r_frac = 1.0;
87 84
 		std::fill(&this->r_left[0], &this->r_left[SINC_WIDTH * 2], 0);
88 85
 		std::fill(&this->r_right[0], &this->r_right[SINC_WIDTH * 2], 0);
... ...
@@ -100,7 +97,7 @@ public:
100 97
 			int s_left = internal_buffer[i_position];
101 98
 			int s_right = internal_buffer[i_position + 1];
102 99
 			int max_samples = this->buffer_size >> 1;
103
-			const double margin_of_error = 1.0e-10;
100
+			static const double margin_of_error = 1.0e-10;
104 101
 
105 102
 			if (std::abs(this->r_step - 1.0) < margin_of_error)
106 103
 			{
... ...
@@ -149,7 +146,7 @@ public:
149 146
 			this->start -= this->buffer_size;
150 147
 	}
151 148
 
152
-	inline int avail()
149
+	int avail()
153 150
 	{
154 151
 		return static_cast<int>(std::floor(((this->size >> 2) - this->r_frac) / this->r_step) * 2);
155 152
 	}
Browse code

Added Sinc resampler to SNSF plugin, as well as fixed issue with there being garbage at the start of an SNSF when played after one has finished.

Naram Qashat authored on 2013/05/08 03:42:24
Showing 1 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,158 @@
1
+/* Simple resampler based on bsnes's ruby audio library */
2
+
3
+#ifndef __SINC_RESAMPLER_H
4
+#define __SINC_RESAMPLER_H
5
+
6
+#include <algorithm>
7
+#define _USE_MATH_DEFINES
8
+#include <cmath>
9
+#include "resampler.h"
10
+
11
+#undef CLAMP
12
+#undef SHORT_CLAMP
13
+
14
+#ifndef M_PI
15
+const double M_PI = 3.14159265358979323846;
16
+#endif
17
+
18
+class SincResampler : public Resampler
19
+{
20
+protected:
21
+	static bool initializedLUTs;
22
+	static const unsigned SINC_RESOLUTION = 8192;
23
+	static const unsigned SINC_WIDTH = 8;
24
+	static const unsigned SINC_SAMPLES = SINC_RESOLUTION * SINC_WIDTH;
25
+	static double sinc_lut[SINC_SAMPLES + 1];
26
+
27
+	double r_step;
28
+	double r_frac;
29
+	int r_left[SINC_WIDTH * 2], r_right[SINC_WIDTH * 2];
30
+
31
+	template<typename T1, typename T2> static T1 CLAMP(T1 x, T2 low, T2 high) { return x > high ? high : (x < low ? low : x); }
32
+	template<typename T> static short SHORT_CLAMP(T n) { return static_cast<short>(CLAMP(n, -32768, 32767)); }
33
+
34
+	// Code from http://learningcppisfun.blogspot.com/2010/04/comparing-floating-point-numbers.html
35
+	template<typename T> static bool fEqual(T x, T y, int N = 1)
36
+	{
37
+		T diff = std::abs(x - y);
38
+		T tolerance = N * std::numeric_limits<T>::epsilon();
39
+		return diff <= tolerance * std::abs(x) && diff <= tolerance * std::abs(y);
40
+	}
41
+
42
+	static inline double sinc(double x)
43
+	{
44
+		return fEqual(x, 0.0) ? 1.0 : std::sin(x * M_PI) / (x * M_PI);
45
+	}
46
+
47
+	double sinc(const int *data)
48
+	{
49
+		double kernel[SINC_WIDTH * 2], kernel_sum = 0.0;
50
+		int i = SINC_WIDTH, shift = static_cast<int>(std::floor(this->r_frac * SINC_RESOLUTION));
51
+		int step = this->r_step > 1.0 ? static_cast<int>(SINC_RESOLUTION / this->r_step) : SINC_RESOLUTION;
52
+		int shift_adj = shift * step / SINC_RESOLUTION;
53
+		for (; i >= -static_cast<int>(SINC_WIDTH - 1); --i)
54
+		{
55
+			int pos = i * step;
56
+			kernel_sum += kernel[i + SINC_WIDTH - 1] = this->sinc_lut[std::abs(shift_adj - pos)];
57
+		}
58
+		double sum = 0.0;
59
+		for (i = 0; i < static_cast<int>(SINC_WIDTH * 2); ++i)
60
+			sum += data[i] * kernel[i];
61
+		return sum / kernel_sum;
62
+	}
63
+
64
+public:
65
+	SincResampler(int num_samples) : Resampler(num_samples)
66
+	{
67
+		if (!this->initializedLUTs)
68
+		{
69
+			double dx = static_cast<double>(SINC_WIDTH) / SINC_SAMPLES, x = 0.0;
70
+			for (unsigned i = 0; i <= SINC_SAMPLES; ++i, x += dx)
71
+				this->sinc_lut[i] = std::abs(x) < SINC_WIDTH ? sinc(x) * (0.5 * (1.0 + std::cos((M_PI * x) / SINC_WIDTH))) : 0.0;
72
+			this->initializedLUTs = true;
73
+		}
74
+		this->clear();
75
+	}
76
+
77
+	void time_ratio(double ratio)
78
+	{
79
+		this->r_step = ratio;
80
+		this->clear();
81
+	}
82
+
83
+	void clear()
84
+	{
85
+		ring_buffer::clear ();
86
+		this->r_frac = 1.0;
87
+		std::fill(&this->r_left[0], &this->r_left[SINC_WIDTH * 2], 0);
88
+		std::fill(&this->r_right[0], &this->r_right[SINC_WIDTH * 2], 0);
89
+	}
90
+
91
+	void read(short *data, int num_samples)
92
+	{
93
+		int i_position = this->start >> 1;
94
+		short *internal_buffer = reinterpret_cast<short *>(this->buffer);
95
+		int o_position = 0;
96
+		int consumed = 0;
97
+
98
+		while (o_position < num_samples && consumed < this->buffer_size)
99
+		{
100
+			int s_left = internal_buffer[i_position];
101
+			int s_right = internal_buffer[i_position + 1];
102
+			int max_samples = this->buffer_size >> 1;
103
+			const double margin_of_error = 1.0e-10;
104
+
105
+			if (std::abs(this->r_step - 1.0) < margin_of_error)
106
+			{
107
+				data[o_position] = static_cast<short>(s_left);
108
+				data[o_position + 1] = static_cast<short>(s_right);
109
+
110
+				o_position += 2;
111
+				i_position += 2;
112
+				if (i_position >= max_samples)
113
+					i_position -= max_samples;
114
+				consumed += 2;
115
+
116
+				continue;
117
+			}
118
+
119
+			while (this->r_frac <= 1.0 && o_position < num_samples)
120
+			{
121
+				data[o_position] = SHORT_CLAMP(sinc(this->r_left));
122
+				data[o_position + 1] = SHORT_CLAMP(sinc(this->r_right));
123
+
124
+				o_position += 2;
125
+
126
+				this->r_frac += this->r_step;
127
+			}
128
+
129
+			if (this->r_frac > 1.0)
130
+			{
131
+				std::copy(&this->r_left[1], &this->r_left[SINC_WIDTH * 2], &this->r_left[0]);
132
+				this->r_left[SINC_WIDTH * 2 - 1] = s_left;
133
+
134
+				std::copy(&this->r_right[1], &this->r_right[SINC_WIDTH * 2], &this->r_right[0]);
135
+				this->r_right[SINC_WIDTH * 2 - 1] = s_right;
136
+
137
+				this->r_frac -= 1.0;
138
+
139
+				i_position += 2;
140
+				if (i_position >= max_samples)
141
+					i_position -= max_samples;
142
+				consumed += 2;
143
+			}
144
+		}
145
+
146
+		this->size -= consumed << 1;
147
+		this->start += consumed << 1;
148
+		if (this->start >= this->buffer_size)
149
+			this->start -= this->buffer_size;
150
+	}
151
+
152
+	inline int avail()
153
+	{
154
+		return static_cast<int>(std::floor(((this->size >> 2) - this->r_frac) / this->r_step) * 2);
155
+	}
156
+};
157
+
158
+#endif /* __SINC_RESAMPLER_H */