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,42 +1,193 @@
1
-/* Simple resampler based on bsnes's ruby audio library */
1
+/*****************************************************************************\
2
+  Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
3
+                This file is licensed under the Snes9x License.
4
+   For further information, consult the LICENSE file in the root directory.
5
+\*****************************************************************************/
2 6
 
3 7
 #pragma once
4 8
 
5
-#include "ring_buffer.h"
9
+#include <algorithm>
10
+#include <limits>
11
+#include <memory>
12
+#include <cstdint>
13
+#include <cmath>
14
+#include "XSFCommon.h"
6 15
 
7
-class Resampler : public ring_buffer
16
+class Resampler
8 17
 {
9 18
 public:
10
-	virtual void clear() = 0;
11
-	virtual void time_ratio(double) = 0;
12
-	virtual void read(short *, int) = 0;
13
-	virtual int avail() = 0;
19
+	int size;
20
+	int buffer_size;
21
+	int start;
22
+	std::unique_ptr<int16_t[]> buffer;
14 23
 
15
-	Resampler(int num_samples) : ring_buffer(num_samples << 1)
24
+	float r_step;
25
+	float r_frac;
26
+	int   r_left[4], r_right[4];
27
+
28
+	static float hermite(float mu1, float a, float b, float c, float d)
29
+	{
30
+		float mu2 = mu1 * mu1;
31
+		float mu3 = mu2 * mu1;
32
+
33
+		float m0 = (c - a) * 0.5;
34
+		float m1 = (d - b) * 0.5;
35
+
36
+		float a0 = +2 * mu3 - 3 * mu2 + 1;
37
+		float a1 = mu3 - 2 * mu2 + mu1;
38
+		float a2 = mu3 - mu2;
39
+		float a3 = -2 * mu3 + 3 * mu2;
40
+
41
+		return (a0 * b) + (a1 * m0) + (a2 * m1) + (a3 * c);
42
+	}
43
+
44
+	Resampler(int num_samples)
45
+	{
46
+		this->buffer_size = num_samples;
47
+		this->buffer.reset(new int16_t[this->buffer_size]);
48
+		this->r_step = 1.0;
49
+		this->clear();
50
+	}
51
+
52
+	void time_ratio(double ratio)
16 53
 	{
54
+		this->r_step = ratio;
17 55
 	}
18 56
 
19
-	virtual ~Resampler()
57
+	void clear()
20 58
 	{
59
+		this->start = 0;
60
+		this->size = 0;
61
+		std::fill_n(&this->buffer[0], this->buffer_size, 0);
62
+
63
+		this->r_frac = 0.0;
64
+		this->r_left[0] = this->r_left[1] = this->r_left[2] = this->r_left[3] = 0;
65
+		this->r_right[0] = this->r_right[1] = this->r_right[2] = this->r_right[3] = 0;
21 66
 	}
22 67
 
23
-	bool push(short *src, int num_samples)
68
+	bool pull(int16_t *dst, int num_samples)
24 69
 	{
25
-		if (this->max_write() < num_samples)
70
+		if (this->space_filled() < num_samples)
26 71
 			return false;
27 72
 
28
-		!num_samples || ring_buffer::push(reinterpret_cast<unsigned char *>(src), num_samples << 1);
73
+		std::copy_n(&this->buffer[start], std::min(num_samples, this->buffer_size - this->start), &dst[0]);
74
+
75
+		if (num_samples > this->buffer_size - this->start)
76
+			std::copy_n(&this->buffer[0], num_samples - (this->buffer_size - this->start), &dst[this->buffer_size - this->start]);
77
+
78
+		this->start = (this->start + num_samples) % this->buffer_size;
79
+		this->size -= num_samples;
29 80
 
30 81
 		return true;
31 82
 	}
32 83
 
33
-	int max_write()
84
+	void push_sample(int16_t l, int16_t r)
85
+	{
86
+		if (this->space_empty() >= 2)
87
+		{
88
+			int end = this->start + this->size;
89
+			if (end >= this->buffer_size)
90
+				end -= this->buffer_size;
91
+			this->buffer[end] = l;
92
+			this->buffer[end + 1] = r;
93
+			this->size += 2;
94
+		}
95
+	}
96
+
97
+	bool push(int16_t *src, int num_samples)
34 98
 	{
35
-		return this->space_empty () >> 1;
99
+		if (this->space_empty() < num_samples)
100
+			return false;
101
+
102
+		int end = this->start + this->size;
103
+		if (end > this->buffer_size)
104
+			end -= this->buffer_size;
105
+		int first_write_size = std::min(num_samples, this->buffer_size - end);
106
+
107
+		std::copy_n(&src[0], first_write_size, &this->buffer[end]);
108
+
109
+		if (num_samples > first_write_size)
110
+			std::copy_n(&src[first_write_size], num_samples - first_write_size, &this->buffer[0]);
111
+
112
+		this->size += num_samples;
113
+
114
+		return true;
115
+	}
116
+
117
+	void read(int16_t *data, int num_samples)
118
+	{
119
+		// If we are outputting the exact same ratio as the input, pull directly from the input buffer
120
+		if (fEqual(this->r_step, 1.0f))
121
+		{
122
+			this->pull(data, num_samples);
123
+			return;
124
+		}
125
+
126
+		int o_position = 0;
127
+
128
+		while (o_position < num_samples && this->size > 0)
129
+		{
130
+			int s_left = this->buffer[start];
131
+			int s_right = this->buffer[start + 1];
132
+			int hermite_val[2];
133
+
134
+			while (this->r_frac <= 1.0 && o_position < num_samples)
135
+			{
136
+				hermite_val[0] = static_cast<int>(hermite(this->r_frac, this->r_left[0], this->r_left[1], this->r_left[2], this->r_left[3]));
137
+				hermite_val[1] = static_cast<int>(hermite(this->r_frac, this->r_right[0], this->r_right[1], this->r_right[2], this->r_right[3]));
138
+				data[o_position] = static_cast<int16_t>(std::clamp<int>(hermite_val[0], std::numeric_limits<int16_t>::min(), std::numeric_limits<int16_t>::max()));
139
+				data[o_position + 1] = static_cast<int16_t>(std::clamp<int>(hermite_val[1], std::numeric_limits<int16_t>::min(), std::numeric_limits<int16_t>::max()));
140
+
141
+				o_position += 2;
142
+
143
+				this->r_frac += this->r_step;
144
+			}
145
+
146
+			if (this->r_frac > 1.0)
147
+			{
148
+				this->r_left[0] = this->r_left[1];
149
+				this->r_left[1] = this->r_left[2];
150
+				this->r_left[2] = this->r_left[3];
151
+				this->r_left[3] = s_left;
152
+
153
+				this->r_right[0] = this->r_right[1];
154
+				this->r_right[1] = this->r_right[2];
155
+				this->r_right[2] = this->r_right[3];
156
+				this->r_right[3] = s_right;
157
+
158
+				--this->r_frac;
159
+
160
+				this->start += 2;
161
+				if (this->start >= this->buffer_size)
162
+					this->start -= this->buffer_size;
163
+				this->size -= 2;
164
+			}
165
+		}
166
+	}
167
+
168
+	int space_empty() const
169
+	{
170
+		return this->buffer_size - this->size;
171
+	}
172
+
173
+	int space_filled() const
174
+	{
175
+		return this->size;
176
+	}
177
+
178
+	int avail()
179
+	{
180
+		// If we are outputting the exact same ratio as the input, find out directly from the input buffer
181
+		if (fEqual(this->r_step, 1.0f))
182
+			return this->size;
183
+
184
+		return static_cast<int>(std::trunc(((this->size >> 1) - this->r_frac) / this->r_step)) * 2;
36 185
 	}
37 186
 
38 187
 	void resize(int num_samples)
39 188
 	{
40
-		ring_buffer::resize(num_samples << 1);
189
+		this->buffer_size = num_samples;
190
+		this->buffer.reset(new int16_t[this->buffer_size]);
191
+		this->clear();
41 192
 	}
42 193
 };
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 __RESAMPLER_H
4
-#define __RESAMPLER_H
3
+#pragma once
5 4
 
6 5
 #include "ring_buffer.h"
7 6
 
... ...
@@ -41,5 +40,3 @@ public:
41 40
 		ring_buffer::resize(num_samples << 1);
42 41
 	}
43 42
 };
44
-
45
-#endif /* __RESAMPLER_H */
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
... ...
@@ -7,54 +7,39 @@
7 7
 
8 8
 class Resampler : public ring_buffer
9 9
 {
10
-    public:
11
-        virtual void clear()        = 0;
12
-        virtual void time_ratio (double) = 0;
13
-        virtual void read (short *, int) = 0;
14
-        virtual int  avail()        = 0;
15
-    
16
-        Resampler (int num_samples) : ring_buffer (num_samples << 1)
17
-        {
18
-        }
19
-
20
-        ~Resampler ()
21
-        {
22
-        }
23
-
24
-        inline bool
25
-        push (short *src, int num_samples)
26
-        {
27
-            if (max_write () < num_samples)
28
-                return false;
29
-
30
-            !num_samples || ring_buffer::push ((unsigned char *) src, num_samples << 1);
31
-
32
-            return true;
33
-        }
34
-
35
-        inline int
36
-        space_empty()
37
-        {
38
-            return buffer_size - size;
39
-        }
40
-    
41
-        inline int
42
-        space_filled()
43
-        {
44
-            return size;
45
-        }
46
-        
47
-        inline int
48
-        max_write()
49
-        {
50
-            return space_empty () >> 1;
51
-        }
52
-
53
-        inline void
54
-        resize (int num_samples)
55
-        {
56
-            ring_buffer::resize (num_samples << 1);
57
-        }
10
+public:
11
+	virtual void clear() = 0;
12
+	virtual void time_ratio(double) = 0;
13
+	virtual void read(short *, int) = 0;
14
+	virtual int avail() = 0;
15
+
16
+	Resampler(int num_samples) : ring_buffer(num_samples << 1)
17
+	{
18
+	}
19
+
20
+	virtual ~Resampler()
21
+	{
22
+	}
23
+
24
+	bool push(short *src, int num_samples)
25
+	{
26
+		if (this->max_write() < num_samples)
27
+			return false;
28
+
29
+		!num_samples || ring_buffer::push(reinterpret_cast<unsigned char *>(src), num_samples << 1);
30
+
31
+		return true;
32
+	}
33
+
34
+	int max_write()
35
+	{
36
+		return this->space_empty () >> 1;
37
+	}
38
+
39
+	void resize(int num_samples)
40
+	{
41
+		ring_buffer::resize(num_samples << 1);
42
+	}
58 43
 };
59 44
 
60 45
 #endif /* __RESAMPLER_H */
Browse code

Import actual code.

Naram Qashat authored on 2013/03/26 02:41:19
Showing 1 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,60 @@
1
+/* Simple resampler based on bsnes's ruby audio library */
2
+
3
+#ifndef __RESAMPLER_H
4
+#define __RESAMPLER_H
5
+
6
+#include "ring_buffer.h"
7
+
8
+class Resampler : public ring_buffer
9
+{
10
+    public:
11
+        virtual void clear()        = 0;
12
+        virtual void time_ratio (double) = 0;
13
+        virtual void read (short *, int) = 0;
14
+        virtual int  avail()        = 0;
15
+    
16
+        Resampler (int num_samples) : ring_buffer (num_samples << 1)
17
+        {
18
+        }
19
+
20
+        ~Resampler ()
21
+        {
22
+        }
23
+
24
+        inline bool
25
+        push (short *src, int num_samples)
26
+        {
27
+            if (max_write () < num_samples)
28
+                return false;
29
+
30
+            !num_samples || ring_buffer::push ((unsigned char *) src, num_samples << 1);
31
+
32
+            return true;
33
+        }
34
+
35
+        inline int
36
+        space_empty()
37
+        {
38
+            return buffer_size - size;
39
+        }
40
+    
41
+        inline int
42
+        space_filled()
43
+        {
44
+            return size;
45
+        }
46
+        
47
+        inline int
48
+        max_write()
49
+        {
50
+            return space_empty () >> 1;
51
+        }
52
+
53
+        inline void
54
+        resize (int num_samples)
55
+        {
56
+            ring_buffer::resize (num_samples << 1);
57
+        }
58
+};
59
+
60
+#endif /* __RESAMPLER_H */