Browse code

Some template cleanup:

* Move the ToIntegral function from NCSF specifically to the framework in general, so it can be used in the base framework's code too.
* Use type traits a bit more.
* Move convertTo into the ConvertFuncs class.

Naram Qashat authored on 2021/04/05 21:47:28
Showing 1 changed files
... ...
@@ -18,6 +18,7 @@
18 18
 #include <cstdint>
19 19
 #include "common.h"
20 20
 #include "consts.h"
21
+#include "convert.h"
21 22
 
22 23
 struct SWAV;
23 24
 struct Track;
... ...
@@ -179,7 +180,7 @@ struct Channel
179 180
 	std::uint8_t prio;
180 181
 	bool manualSweep;
181 182
 
182
-	std::bitset<ToIntegral(ChannelFlag::Bits)> flags;
183
+	std::bitset<ConvertFuncs::ToIntegral(ChannelFlag::Bits)> flags;
183 184
 	std::int8_t pan; // -64 .. 63
184 185
 	std::int16_t extAmpl;
185 186
 
Browse code

Silence various Visual Studio warnings:

* Fix the ones in my code where I could use a proper type or valid casts.
* Ignore the designer-time and compiler-time warnings in vendor code or in my code where I am unable to suppress them via casting.
(Most of these were ignored already before introducing the CMake scripts, because they were in vendor code or were annoying to deal with.)

Naram Qashat authored on 2021/03/29 00:10:11
Showing 1 changed files
... ...
@@ -106,11 +106,11 @@ template<std::size_t N> struct RingBuffer
106 106
 
107 107
 	RingBuffer() : bufferPos(N / 2), getPos(N / 2)
108 108
 	{
109
-		std::fill_n(&this->buffer[0], N * 2, 0);
109
+		std::fill_n(&this->buffer[0], N * 2, static_cast<std::int16_t>(0));
110 110
 	}
111 111
 	void Clear()
112 112
 	{
113
-		std::fill_n(&this->buffer[0], N * 2, 0);
113
+		std::fill_n(&this->buffer[0], N * 2, static_cast<std::int16_t>(0));
114 114
 		this->bufferPos = this->getPos = N / 2;
115 115
 	}
116 116
 	void PushSample(std::int16_t sample)
Browse code

Various changes:

* Use enum class instead of enum (except for the enums for the resource IDs, not really necessary there).
* For NCSF specifically, included a function to convert an enum class to its underlying integral type (as this is needed for use with the std::bitset class).
* Cleanup headers so all the ones needed in a file are explicitly included even if they may possibly be included in another header.
* Used forward declarations in a few spots.
* Explicitly namespaced all (u)int*_t uses (this might seem like overkill, but it helps me see when the standard types are being used with a simple search for std::).
* Made sure it all builds with MinGW-w64 as well (both gcc and clang).
* Removed some std::move from DialogBuilder.cpp based on clang's warnings for that.
* Replaced use of std::copy_n on strings in DialogBuilder.cpp with my CopyToString functions that use wcscpy.
* Replaced CHAR_MIN/CHAR_MAX in eqstr.h and ltstr.h with std::numeric_limits<char>::min/max().

Naram Qashat authored on 2021/03/21 03:16:45
Showing 1 changed files
... ...
@@ -14,9 +14,13 @@
14 14
 
15 15
 #include <algorithm>
16 16
 #include <bitset>
17
+#include <cstddef>
17 18
 #include <cstdint>
18
-#include "SWAV.h"
19
-#include "Track.h"
19
+#include "common.h"
20
+#include "consts.h"
21
+
22
+struct SWAV;
23
+struct Track;
20 24
 
21 25
 /*
22 26
  * This structure is meant to be similar to what is stored in the actual
... ...
@@ -27,41 +31,41 @@
27 31
 struct NDSSoundRegister
28 32
 {
29 33
 	// Control Register
30
-	uint8_t volumeMul;
31
-	uint8_t volumeDiv;
32
-	uint8_t panning;
33
-	uint8_t waveDuty;
34
-	uint8_t repeatMode;
35
-	uint8_t format;
34
+	std::uint8_t volumeMul;
35
+	std::uint8_t volumeDiv;
36
+	std::uint8_t panning;
37
+	std::uint8_t waveDuty;
38
+	std::uint8_t repeatMode;
39
+	std::uint8_t format;
36 40
 	bool enable;
37 41
 
38 42
 	// Data Source Register
39 43
 	const SWAV *source;
40 44
 
41 45
 	// Timer Register
42
-	uint16_t timer;
46
+	std::uint16_t timer;
43 47
 
44 48
 	// PSG Handling, not a DS register
45
-	uint16_t psgX;
46
-	int16_t psgLast;
47
-	uint32_t psgLastCount;
49
+	std::uint16_t psgX;
50
+	std::int16_t psgLast;
51
+	std::uint32_t psgLastCount;
48 52
 
49 53
 	// The following are taken from DeSmuME
50 54
 	double samplePosition;
51 55
 	double sampleIncrease;
52 56
 
53 57
 	// Loopstart Register
54
-	uint32_t loopStart;
58
+	std::uint32_t loopStart;
55 59
 
56 60
 	// Length Register
57
-	uint32_t length;
61
+	std::uint32_t length;
58 62
 
59
-	uint32_t totalLength;
63
+	std::uint32_t totalLength;
60 64
 
61 65
 	NDSSoundRegister();
62 66
 
63 67
 	void ClearControlRegister();
64
-	void SetControlRegister(uint32_t reg);
68
+	void SetControlRegister(std::uint32_t reg);
65 69
 };
66 70
 
67 71
 /*
... ...
@@ -72,10 +76,10 @@ struct NDSSoundRegister
72 76
  */
73 77
 struct TempSndReg
74 78
 {
75
-	uint32_t CR;
79
+	std::uint32_t CR;
76 80
 	const SWAV *SOURCE;
77
-	uint16_t TIMER;
78
-	uint32_t REPEAT_POINT, LENGTH;
81
+	std::uint16_t TIMER;
82
+	std::uint32_t REPEAT_POINT, LENGTH;
79 83
 
80 84
 	TempSndReg();
81 85
 };
... ...
@@ -95,10 +99,10 @@ struct Player;
95 99
  * accessing the SWAVs samples and also doesn't use 0s before the
96 100
  * start of the SWAV or use 0s after the end of a non-looping SWAV.
97 101
  */
98
-template<size_t N> struct RingBuffer
102
+template<std::size_t N> struct RingBuffer
99 103
 {
100
-	int16_t buffer[N * 2];
101
-	size_t bufferPos, getPos;
104
+	std::int16_t buffer[N * 2];
105
+	std::size_t bufferPos, getPos;
102 106
 
103 107
 	RingBuffer() : bufferPos(N / 2), getPos(N / 2)
104 108
 	{
... ...
@@ -109,7 +113,7 @@ template<size_t N> struct RingBuffer
109 113
 		std::fill_n(&this->buffer[0], N * 2, 0);
110 114
 		this->bufferPos = this->getPos = N / 2;
111 115
 	}
112
-	void PushSample(int16_t sample)
116
+	void PushSample(std::int16_t sample)
113 117
 	{
114 118
 		this->buffer[this->bufferPos] = sample;
115 119
 		if (this->bufferPos >= N)
... ...
@@ -120,23 +124,23 @@ template<size_t N> struct RingBuffer
120 124
 		if (this->bufferPos >= N * 3 / 2)
121 125
 			this->bufferPos -= N;
122 126
 	}
123
-	void PushSamples(const int16_t *samples, size_t size)
127
+	void PushSamples(const std::int16_t *samples, std::size_t size)
124 128
 	{
125 129
 		if (this->bufferPos + size > N * 3 / 2)
126 130
 		{
127
-			size_t free = N * 3 / 2 - this->bufferPos;
131
+			std::size_t free = N * 3 / 2 - this->bufferPos;
128 132
 			std::copy_n(&samples[0], free, &this->buffer[this->bufferPos]);
129 133
 			std::copy(&samples[free], &samples[size], &this->buffer[N / 2]);
130 134
 		}
131 135
 		else
132 136
 			std::copy_n(&samples[0], size, &this->buffer[this->bufferPos]);
133
-		size_t rightFree = this->bufferPos < N ? N - this->bufferPos : 0;
137
+		std::size_t rightFree = this->bufferPos < N ? N - this->bufferPos : 0;
134 138
 		if (rightFree < size)
135 139
 		{
136 140
 			if (!rightFree)
137 141
 			{
138
-				size_t leftStart = this->bufferPos - N;
139
-				size_t leftSize = std::min(N / 2 - leftStart, size);
142
+				std::size_t leftStart = this->bufferPos - N;
143
+				std::size_t leftSize = std::min(N / 2 - leftStart, size);
140 144
 				std::copy_n(&samples[0], leftSize, &this->buffer[leftStart]);
141 145
 				if (leftSize < size)
142 146
 					std::copy(&samples[leftSize], &samples[size], &this->buffer[N * 3 / 2]);
... ...
@@ -153,7 +157,7 @@ template<size_t N> struct RingBuffer
153 157
 		if (this->bufferPos >= N * 3 / 2)
154 158
 			this->bufferPos -= N;
155 159
 	}
156
-	const int16_t *GetBuffer() const
160
+	const std::int16_t *GetBuffer() const
157 161
 	{
158 162
 		return &this->buffer[this->getPos];
159 163
 	}
... ...
@@ -167,35 +171,35 @@ template<size_t N> struct RingBuffer
167 171
 
168 172
 struct Channel
169 173
 {
170
-	int8_t chnId;
174
+	std::int8_t chnId;
171 175
 
172 176
 	TempSndReg tempReg;
173
-	uint8_t state;
174
-	int8_t trackId; // -1 = none
175
-	uint8_t prio;
177
+	ChannelState state;
178
+	std::int8_t trackId; // -1 = none
179
+	std::uint8_t prio;
176 180
 	bool manualSweep;
177 181
 
178
-	std::bitset<CF_BITS> flags;
179
-	int8_t pan; // -64 .. 63
180
-	int16_t extAmpl;
182
+	std::bitset<ToIntegral(ChannelFlag::Bits)> flags;
183
+	std::int8_t pan; // -64 .. 63
184
+	std::int16_t extAmpl;
181 185
 
182
-	int16_t velocity;
183
-	int8_t extPan;
184
-	uint8_t key;
186
+	std::int16_t velocity;
187
+	std::int8_t extPan;
188
+	std::uint8_t key;
185 189
 
186 190
 	int ampl; // 7 fractionary bits
187 191
 	int extTune; // in 64ths of a semitone
188 192
 
189
-	uint8_t orgKey;
193
+	std::uint8_t orgKey;
190 194
 
191
-	uint8_t modType, modSpeed, modDepth, modRange;
192
-	uint16_t modDelay, modDelayCnt, modCounter;
195
+	std::uint8_t modType, modSpeed, modDepth, modRange;
196
+	std::uint16_t modDelay, modDelayCnt, modCounter;
193 197
 
194
-	uint32_t sweepLen, sweepCnt;
195
-	int16_t sweepPitch;
198
+	std::uint32_t sweepLen, sweepCnt;
199
+	std::int16_t sweepPitch;
196 200
 
197
-	uint8_t attackLvl, sustainLvl;
198
-	uint16_t decayRate, releaseRate;
201
+	std::uint8_t attackLvl, sustainLvl;
202
+	std::uint16_t decayRate, releaseRate;
199 203
 
200 204
 	/*
201 205
 	 * These were originally global variables in FeOS Sound System, but
... ...
@@ -203,7 +207,7 @@ struct Channel
203 207
 	 * into this class.
204 208
 	 */
205 209
 	int noteLength;
206
-	uint16_t vol;
210
+	std::uint16_t vol;
207 211
 
208 212
 	const Player *ply;
209 213
 	NDSSoundRegister reg;
... ...
@@ -234,7 +238,7 @@ struct Channel
234 238
 	void Kill();
235 239
 	void UpdateTrack();
236 240
 	void Update();
237
-	int32_t Interpolate();
238
-	int32_t GenerateSample();
241
+	std::int32_t Interpolate();
242
+	std::int32_t GenerateSample();
239 243
 	void IncrementSample();
240 244
 };
Browse code

Remove last modification date from files.

(I never remember to update these and besides, GitHub history can show when they were last modified.)

Naram Qashat authored on 2021/03/19 10:58:12
Showing 1 changed files
... ...
@@ -1,7 +1,6 @@
1 1
 /*
2 2
  * SSEQ Player - Channel structures
3 3
  * By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com]
4
- * Last modification on 2014-10-27
5 4
  *
6 5
  * Adapted from source code of FeOS Sound System
7 6
  * By fincs
Browse code

Various updates:

* Fix build with Visual Studio, updating projects to Visual Studio 2019 (as that is what I have installed).
* Changed C++ language standard to C++ 17.
* Add files for in_2sf's spu from Coda's recent commit.
* Add files for zlib now that it is being included as a submodule (removes the need for the zlib DLL as well).
* Remove common.props (due to the aforementioned zlib inclusion as well as the winamp headers also being in the project now).
* Minor NCSF file in the SSEQ player, the check for when to process tracks should've been >=, not >.

Naram Qashat authored on 2021/03/15 22:34:25
Showing 1 changed files
... ...
@@ -21,7 +21,7 @@
21 21
 
22 22
 /*
23 23
  * This structure is meant to be similar to what is stored in the actual
24
- * Nintendo DS's sound registers.  Items that were not being used by this
24
+ * Nintendo DS's sound registers. Items that were not being used by this
25 25
  * player have been removed, and items which help the simulated registers
26 26
  * have been added.
27 27
  */
... ...
@@ -67,7 +67,7 @@ struct NDSSoundRegister
67 67
 
68 68
 /*
69 69
  * From FeOS Sound System, this is temporary storage of what will go into
70
- * the Nintendo DS sound registers.  It is kept separate as the original code
70
+ * the Nintendo DS sound registers. It is kept separate as the original code
71 71
  * from FeOS Sound System utilized this to hold data prior to passing it into
72 72
  * the DS's registers.
73 73
  */
... ...
@@ -88,7 +88,7 @@ struct Player;
88 88
  * data, duplicated. The way it is duplicated is done as follows:
89 89
  * the samples are stored in the center of the buffer, and on both
90 90
  * sides is half of the data, the first half being after the data
91
- * and the second half before before the data. This in essense
91
+ * and the second half begin before the data. This in essence
92 92
  * mirrors the data while allowing a pointer to always be retrieved
93 93
  * and no extra copies of the buffer are created. Part of the idea
94 94
  * for this came from kode54's original buffer implementation, but
Browse code

[NCSF] Applied sinc modification from kode54:

Sinc mode should not scale the window, just the sinc pulse.

Naram Qashat authored on 2014/10/27 04:15:11
Showing 1 changed files
... ...
@@ -1,7 +1,7 @@
1 1
 /*
2 2
  * SSEQ Player - Channel structures
3 3
  * By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com]
4
- * Last modification on 2014-09-17
4
+ * Last modification on 2014-10-27
5 5
  *
6 6
  * Adapted from source code of FeOS Sound System
7 7
  * By fincs
... ...
@@ -220,6 +220,7 @@ struct Channel
220 220
 	static const unsigned SINC_WIDTH = 8;
221 221
 	static const unsigned SINC_SAMPLES = SINC_RESOLUTION * SINC_WIDTH;
222 222
 	static double sinc_lut[SINC_SAMPLES + 1];
223
+	static double window_lut[SINC_SAMPLES + 1];
223 224
 
224 225
 	RingBuffer<SINC_WIDTH * 2> ringBuffer;
225 226
 
Browse code

[NCSF] Very minor cleanups.

Naram Qashat authored on 2014/10/24 19:58:46
Showing 1 changed files
... ...
@@ -210,7 +210,7 @@ struct Channel
210 210
 	NDSSoundRegister reg;
211 211
 
212 212
 	/*
213
-	 * Lookup tables for the cosine and Lanczos Sinc interpolations, to
213
+	 * Lookup tables for the Sinc interpolation, to
214 214
 	 * avoid the need to call the sin/cos functions all the time.
215 215
 	 * These are static as they will not change between channels or runs
216 216
 	 * of the program.
Browse code

[NCSF] Interpolation changes:

* Removed Cosine, 4-Point B-Spline, 6-Point B-Spline, and 6-point
Osculating.
* Added 4-Point Legrange and 6-Point Legrange.
* Changed wording of the Sinc interpolation to mention that it is
16-point.

Naram Qashat authored on 2014/09/28 00:07:18
Showing 1 changed files
... ...
@@ -216,11 +216,9 @@ struct Channel
216 216
 	 * of the program.
217 217
 	 */
218 218
 	static bool initializedLUTs;
219
-	static const unsigned COSINE_RESOLUTION = 8192;
220 219
 	static const unsigned SINC_RESOLUTION = 8192;
221 220
 	static const unsigned SINC_WIDTH = 8;
222 221
 	static const unsigned SINC_SAMPLES = SINC_RESOLUTION * SINC_WIDTH;
223
-	static double cosine_lut[COSINE_RESOLUTION];
224 222
 	static double sinc_lut[SINC_SAMPLES + 1];
225 223
 
226 224
 	RingBuffer<SINC_WIDTH * 2> ringBuffer;
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
... ...
@@ -1,7 +1,7 @@
1 1
 /*
2 2
  * SSEQ Player - Channel structures
3 3
  * By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com]
4
- * Last modification on 2014-09-08
4
+ * Last modification on 2014-09-17
5 5
  *
6 6
  * Adapted from source code of FeOS Sound System
7 7
  * By fincs
... ...
@@ -13,6 +13,7 @@
13 13
 
14 14
 #pragma once
15 15
 
16
+#include <algorithm>
16 17
 #include <bitset>
17 18
 #include <cstdint>
18 19
 #include "SWAV.h"
... ...
@@ -153,7 +154,7 @@ template<size_t N> struct RingBuffer
153 154
 		if (this->bufferPos >= N * 3 / 2)
154 155
 			this->bufferPos -= N;
155 156
 	}
156
-	const int16_t *const GetBuffer() const
157
+	const int16_t *GetBuffer() const
157 158
 	{
158 159
 		return &this->buffer[this->getPos];
159 160
 	}
Browse code

Use std::copy_n/std::fill_n instead of std::copy/std::fill where possible.

Naram Qashat authored on 2014/09/08 16:52:49
Showing 1 changed files
... ...
@@ -102,11 +102,11 @@ template<size_t N> struct RingBuffer
102 102
 
103 103
 	RingBuffer() : bufferPos(N / 2), getPos(N / 2)
104 104
 	{
105
-		std::fill(&this->buffer[0], &this->buffer[N * 2], 0);
105
+		std::fill_n(&this->buffer[0], N * 2, 0);
106 106
 	}
107 107
 	void Clear()
108 108
 	{
109
-		std::fill(&this->buffer[0], &this->buffer[N * 2], 0);
109
+		std::fill_n(&this->buffer[0], N * 2, 0);
110 110
 		this->bufferPos = this->getPos = N / 2;
111 111
 	}
112 112
 	void PushSample(int16_t sample)
... ...
@@ -125,11 +125,11 @@ template<size_t N> struct RingBuffer
125 125
 		if (this->bufferPos + size > N * 3 / 2)
126 126
 		{
127 127
 			size_t free = N * 3 / 2 - this->bufferPos;
128
-			std::copy(&samples[0], &samples[free], &this->buffer[this->bufferPos]);
128
+			std::copy_n(&samples[0], free, &this->buffer[this->bufferPos]);
129 129
 			std::copy(&samples[free], &samples[size], &this->buffer[N / 2]);
130 130
 		}
131 131
 		else
132
-			std::copy(&samples[0], &samples[size], &this->buffer[this->bufferPos]);
132
+			std::copy_n(&samples[0], size, &this->buffer[this->bufferPos]);
133 133
 		size_t rightFree = this->bufferPos < N ? N - this->bufferPos : 0;
134 134
 		if (rightFree < size)
135 135
 		{
... ...
@@ -137,18 +137,18 @@ template<size_t N> struct RingBuffer
137 137
 			{
138 138
 				size_t leftStart = this->bufferPos - N;
139 139
 				size_t leftSize = std::min(N / 2 - leftStart, size);
140
-				std::copy(&samples[0], &samples[leftSize], &this->buffer[leftStart]);
140
+				std::copy_n(&samples[0], leftSize, &this->buffer[leftStart]);
141 141
 				if (leftSize < size)
142 142
 					std::copy(&samples[leftSize], &samples[size], &this->buffer[N * 3 / 2]);
143 143
 			}
144 144
 			else
145 145
 			{
146
-				std::copy(&samples[0], &samples[rightFree], &this->buffer[this->bufferPos + N]);
146
+				std::copy_n(&samples[0], rightFree, &this->buffer[this->bufferPos + N]);
147 147
 				std::copy(&samples[rightFree], &samples[size], &this->buffer[0]);
148 148
 			}
149 149
 		}
150 150
 		else
151
-			std::copy(&samples[0], &samples[size], &this->buffer[this->bufferPos + N]);
151
+			std::copy_n(&samples[0], size, &this->buffer[this->bufferPos + N]);
152 152
 		this->bufferPos += size;
153 153
 		if (this->bufferPos >= N * 3 / 2)
154 154
 			this->bufferPos -= N;
Browse code

Use #pragma once instead of include guards.

Naram Qashat authored on 2014/09/08 14:47:36
Showing 1 changed files
... ...
@@ -1,7 +1,7 @@
1 1
 /*
2 2
  * SSEQ Player - Channel structures
3 3
  * By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com]
4
- * Last modification on 2013-05-07
4
+ * Last modification on 2014-09-08
5 5
  *
6 6
  * Adapted from source code of FeOS Sound System
7 7
  * By fincs
... ...
@@ -11,8 +11,7 @@
11 11
  * http://desmume.org/
12 12
  */
13 13
 
14
-#ifndef SSEQPLAYER_CHANNEL_H
15
-#define SSEQPLAYER_CHANNEL_H
14
+#pragma once
16 15
 
17 16
 #include <bitset>
18 17
 #include <cstdint>
... ...
@@ -240,5 +239,3 @@ struct Channel
240 239
 	int32_t GenerateSample();
241 240
 	void IncrementSample();
242 241
 };
243
-
244
-#endif
Browse code

* Replaced Lanczos window with Hann window for the windowed sinc function in the NCSF plugin. * Added a ring buffer specifically designed for working with SWAVs to replace the one provided by kode54, still have to give him thanks for the original though. * Fixed clipping issue caused by invalid clamping values. * Minor fix to using the min()/max() functions of numeric_limits because Winamp's out.h includes windows.h without my specific wrapper to redefine things.

Naram Qashat authored on 2013/05/07 05:42:46
Showing 1 changed files
... ...
@@ -1,7 +1,7 @@
1 1
 /*
2 2
  * SSEQ Player - Channel structures
3 3
  * By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com]
4
- * Last modification on 2013-04-26
4
+ * Last modification on 2013-05-07
5 5
  *
6 6
  * Adapted from source code of FeOS Sound System
7 7
  * By fincs
... ...
@@ -83,6 +83,89 @@ struct TempSndReg
83 83
 
84 84
 struct Player;
85 85
 
86
+/*
87
+ * This creates a ring buffer, which will store N samples of SWAV
88
+ * data, duplicated. The way it is duplicated is done as follows:
89
+ * the samples are stored in the center of the buffer, and on both
90
+ * sides is half of the data, the first half being after the data
91
+ * and the second half before before the data. This in essense
92
+ * mirrors the data while allowing a pointer to always be retrieved
93
+ * and no extra copies of the buffer are created. Part of the idea
94
+ * for this came from kode54's original buffer implementation, but
95
+ * this has been designed to make sure that there are no delays in
96
+ * accessing the SWAVs samples and also doesn't use 0s before the
97
+ * start of the SWAV or use 0s after the end of a non-looping SWAV.
98
+ */
99
+template<size_t N> struct RingBuffer
100
+{
101
+	int16_t buffer[N * 2];
102
+	size_t bufferPos, getPos;
103
+
104
+	RingBuffer() : bufferPos(N / 2), getPos(N / 2)
105
+	{
106
+		std::fill(&this->buffer[0], &this->buffer[N * 2], 0);
107
+	}
108
+	void Clear()
109
+	{
110
+		std::fill(&this->buffer[0], &this->buffer[N * 2], 0);
111
+		this->bufferPos = this->getPos = N / 2;
112
+	}
113
+	void PushSample(int16_t sample)
114
+	{
115
+		this->buffer[this->bufferPos] = sample;
116
+		if (this->bufferPos >= N)
117
+			this->buffer[this->bufferPos - N] = sample;
118
+		else
119
+			this->buffer[this->bufferPos + N] = sample;
120
+		++this->bufferPos;
121
+		if (this->bufferPos >= N * 3 / 2)
122
+			this->bufferPos -= N;
123
+	}
124
+	void PushSamples(const int16_t *samples, size_t size)
125
+	{
126
+		if (this->bufferPos + size > N * 3 / 2)
127
+		{
128
+			size_t free = N * 3 / 2 - this->bufferPos;
129
+			std::copy(&samples[0], &samples[free], &this->buffer[this->bufferPos]);
130
+			std::copy(&samples[free], &samples[size], &this->buffer[N / 2]);
131
+		}
132
+		else
133
+			std::copy(&samples[0], &samples[size], &this->buffer[this->bufferPos]);
134
+		size_t rightFree = this->bufferPos < N ? N - this->bufferPos : 0;
135
+		if (rightFree < size)
136
+		{
137
+			if (!rightFree)
138
+			{
139
+				size_t leftStart = this->bufferPos - N;
140
+				size_t leftSize = std::min(N / 2 - leftStart, size);
141
+				std::copy(&samples[0], &samples[leftSize], &this->buffer[leftStart]);
142
+				if (leftSize < size)
143
+					std::copy(&samples[leftSize], &samples[size], &this->buffer[N * 3 / 2]);
144
+			}
145
+			else
146
+			{
147
+				std::copy(&samples[0], &samples[rightFree], &this->buffer[this->bufferPos + N]);
148
+				std::copy(&samples[rightFree], &samples[size], &this->buffer[0]);
149
+			}
150
+		}
151
+		else
152
+			std::copy(&samples[0], &samples[size], &this->buffer[this->bufferPos + N]);
153
+		this->bufferPos += size;
154
+		if (this->bufferPos >= N * 3 / 2)
155
+			this->bufferPos -= N;
156
+	}
157
+	const int16_t *const GetBuffer() const
158
+	{
159
+		return &this->buffer[this->getPos];
160
+	}
161
+	void NextSample()
162
+	{
163
+		++this->getPos;
164
+		if (this->getPos >= N * 3 / 2)
165
+			this->getPos -= N;
166
+	}
167
+};
168
+
86 169
 struct Channel
87 170
 {
88 171
 	int8_t chnId;
... ...
@@ -126,14 +209,6 @@ struct Channel
126 209
 	const Player *ply;
127 210
 	NDSSoundRegister reg;
128 211
 
129
-	/*
130
-	 * Interpolation history buffer, which contains the maximum number of
131
-	 * samples required for any given interpolation mode. Doubled to
132
-	 * simplify the case of wrapping. Thanks to kode54 for providing this.
133
-	 */
134
-	uint32_t sampleHistoryPtr;
135
-	int16_t sampleHistory[64];
136
-
137 212
 	/*
138 213
 	 * Lookup tables for the cosine and Lanczos Sinc interpolations, to
139 214
 	 * avoid the need to call the sin/cos functions all the time.
... ...
@@ -142,11 +217,13 @@ struct Channel
142 217
 	 */
143 218
 	static bool initializedLUTs;
144 219
 	static const unsigned COSINE_RESOLUTION = 8192;
145
-	static const unsigned LANCZOS_RESOLUTION = 8192;
146
-	static const unsigned LANCZOS_WIDTH = 8;
147
-	static const unsigned LANCZOS_SAMPLES = LANCZOS_RESOLUTION * LANCZOS_WIDTH;
220
+	static const unsigned SINC_RESOLUTION = 8192;
221
+	static const unsigned SINC_WIDTH = 8;
222
+	static const unsigned SINC_SAMPLES = SINC_RESOLUTION * SINC_WIDTH;
148 223
 	static double cosine_lut[COSINE_RESOLUTION];
149
-	static double lanczos_lut[LANCZOS_SAMPLES + 1];
224
+	static double sinc_lut[SINC_SAMPLES + 1];
225
+
226
+	RingBuffer<SINC_WIDTH * 2> ringBuffer;
150 227
 
151 228
 	Channel();
152 229
 
... ...
@@ -162,7 +239,6 @@ struct Channel
162 239
 	int32_t Interpolate();
163 240
 	int32_t GenerateSample();
164 241
 	void IncrementSample();
165
-	void clearHistory();
166 242
 };
167 243
 
168 244
 #endif
Browse code

Fixed up the Lanczos interpolation in NCSF (thanks to kode54), also allowed the NCSF plugin to use 32-bit samples in it's GenerateSamples function.

Naram Qashat authored on 2013/04/26 00:54:28
Showing 1 changed files
... ...
@@ -1,7 +1,7 @@
1 1
 /*
2 2
  * SSEQ Player - Channel structures
3 3
  * By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com]
4
- * Last modification on 2013-04-23
4
+ * Last modification on 2013-04-26
5 5
  *
6 6
  * Adapted from source code of FeOS Sound System
7 7
  * By fincs
... ...
@@ -132,7 +132,7 @@ struct Channel
132 132
 	 * simplify the case of wrapping. Thanks to kode54 for providing this.
133 133
 	 */
134 134
 	uint32_t sampleHistoryPtr;
135
-	int16_t sampleHistory[16];
135
+	int16_t sampleHistory[64];
136 136
 
137 137
 	/*
138 138
 	 * Lookup tables for the cosine and Lanczos Sinc interpolations, to
... ...
@@ -143,10 +143,10 @@ struct Channel
143 143
 	static bool initializedLUTs;
144 144
 	static const unsigned COSINE_RESOLUTION = 8192;
145 145
 	static const unsigned LANCZOS_RESOLUTION = 8192;
146
-	static const unsigned LANCZOS_WIDTH = 3;
146
+	static const unsigned LANCZOS_WIDTH = 8;
147 147
 	static const unsigned LANCZOS_SAMPLES = LANCZOS_RESOLUTION * LANCZOS_WIDTH;
148 148
 	static double cosine_lut[COSINE_RESOLUTION];
149
-	static double lanczos_lut[LANCZOS_SAMPLES];
149
+	static double lanczos_lut[LANCZOS_SAMPLES + 1];
150 150
 
151 151
 	Channel();
152 152
 
Browse code

Added Lanczos interpolation to the NCSF plugin, and cleaned up a bit of the other code, as well as removing pstdint.h since it's no longer needed.

Naram Qashat authored on 2013/04/23 20:29:21
Showing 1 changed files
... ...
@@ -1,7 +1,7 @@
1 1
 /*
2 2
  * SSEQ Player - Channel structures
3 3
  * By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com]
4
- * Last modification on 2013-04-18
4
+ * Last modification on 2013-04-23
5 5
  *
6 6
  * Adapted from source code of FeOS Sound System
7 7
  * By fincs
... ...
@@ -15,10 +15,9 @@
15 15
 #define SSEQPLAYER_CHANNEL_H
16 16
 
17 17
 #include <bitset>
18
-#include <tuple>
18
+#include <cstdint>
19 19
 #include "SWAV.h"
20 20
 #include "Track.h"
21
-#include "pstdint.h"
22 21
 
23 22
 /*
24 23
  * This structure is meant to be similar to what is stored in the actual
... ...
@@ -135,6 +134,20 @@ struct Channel
135 134
 	uint32_t sampleHistoryPtr;
136 135
 	int16_t sampleHistory[16];
137 136
 
137
+	/*
138
+	 * Lookup tables for the cosine and Lanczos Sinc interpolations, to
139
+	 * avoid the need to call the sin/cos functions all the time.
140
+	 * These are static as they will not change between channels or runs
141
+	 * of the program.
142
+	 */
143
+	static bool initializedLUTs;
144
+	static const unsigned COSINE_RESOLUTION = 8192;
145
+	static const unsigned LANCZOS_RESOLUTION = 8192;
146
+	static const unsigned LANCZOS_WIDTH = 3;
147
+	static const unsigned LANCZOS_SAMPLES = LANCZOS_RESOLUTION * LANCZOS_WIDTH;
148
+	static double cosine_lut[COSINE_RESOLUTION];
149
+	static double lanczos_lut[LANCZOS_SAMPLES];
150
+
138 151
 	Channel();
139 152
 
140 153
 	void UpdateVol(const Track &trk);
Browse code

Implemented circular interpolation buffer to fix interpolation, thanks to kode54 for the code.

Naram Qashat authored on 2013/04/18 20:43:31
Showing 1 changed files
... ...
@@ -1,7 +1,7 @@
1 1
 /*
2 2
  * SSEQ Player - Channel structures
3 3
  * By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com]
4
- * Last modification on 2013-04-02
4
+ * Last modification on 2013-04-18
5 5
  *
6 6
  * Adapted from source code of FeOS Sound System
7 7
  * By fincs
... ...
@@ -127,6 +127,14 @@ struct Channel
127 127
 	const Player *ply;
128 128
 	NDSSoundRegister reg;
129 129
 
130
+	/*
131
+	 * Interpolation history buffer, which contains the maximum number of
132
+	 * samples required for any given interpolation mode. Doubled to
133
+	 * simplify the case of wrapping. Thanks to kode54 for providing this.
134
+	 */
135
+	uint32_t sampleHistoryPtr;
136
+	int16_t sampleHistory[16];
137
+
130 138
 	Channel();
131 139
 
132 140
 	void UpdateVol(const Track &trk);
... ...
@@ -141,6 +149,7 @@ struct Channel
141 149
 	int32_t Interpolate();
142 150
 	int32_t GenerateSample();
143 151
 	void IncrementSample();
152
+	void clearHistory();
144 153
 };
145 154
 
146 155
 #endif
Browse code

Utilize SSEQ's volume from it's INFO section, plus some minor optimizations.

Naram Qashat authored on 2013/04/07 16:39:00
Showing 1 changed files
... ...
@@ -58,6 +58,8 @@ struct NDSSoundRegister
58 58
 	// Length Register
59 59
 	uint32_t length;
60 60
 
61
+	uint32_t totalLength;
62
+
61 63
 	NDSSoundRegister();
62 64
 
63 65
 	void ClearControlRegister();
Browse code

Added new interpolation methods, added version number in plugin description.

Naram Qashat authored on 2013/04/02 22:40:32
Showing 1 changed files
... ...
@@ -1,7 +1,7 @@
1 1
 /*
2 2
  * SSEQ Player - Channel structures
3 3
  * By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com]
4
- * Last modification on 2013-03-21
4
+ * Last modification on 2013-04-02
5 5
  *
6 6
  * Adapted from source code of FeOS Sound System
7 7
  * By fincs
... ...
@@ -15,6 +15,7 @@
15 15
 #define SSEQPLAYER_CHANNEL_H
16 16
 
17 17
 #include <bitset>
18
+#include <tuple>
18 19
 #include "SWAV.h"
19 20
 #include "Track.h"
20 21
 #include "pstdint.h"
... ...
@@ -135,7 +136,7 @@ struct Channel
135 136
 	void Kill();
136 137
 	void UpdateTrack();
137 138
 	void Update();
138
-	int32_t Interpolate(int32_t a, int32_t b, double ratio);
139
+	int32_t Interpolate();
139 140
 	int32_t GenerateSample();
140 141
 	void IncrementSample();
141 142
 };
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,143 @@
1
+/*
2
+ * SSEQ Player - Channel structures
3
+ * By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com]
4
+ * Last modification on 2013-03-21
5
+ *
6
+ * Adapted from source code of FeOS Sound System
7
+ * By fincs
8
+ * https://github.com/fincs/FSS
9
+ *
10
+ * Some code/concepts from DeSmuME
11
+ * http://desmume.org/
12
+ */
13
+
14
+#ifndef SSEQPLAYER_CHANNEL_H
15
+#define SSEQPLAYER_CHANNEL_H
16
+
17
+#include <bitset>
18
+#include "SWAV.h"
19
+#include "Track.h"
20
+#include "pstdint.h"
21
+
22
+/*
23
+ * This structure is meant to be similar to what is stored in the actual
24
+ * Nintendo DS's sound registers.  Items that were not being used by this
25
+ * player have been removed, and items which help the simulated registers
26
+ * have been added.
27
+ */
28
+struct NDSSoundRegister
29
+{
30
+	// Control Register
31
+	uint8_t volumeMul;
32
+	uint8_t volumeDiv;
33
+	uint8_t panning;
34
+	uint8_t waveDuty;
35
+	uint8_t repeatMode;
36
+	uint8_t format;
37
+	bool enable;
38
+
39
+	// Data Source Register
40
+	const SWAV *source;
41
+
42
+	// Timer Register
43
+	uint16_t timer;
44
+
45
+	// PSG Handling, not a DS register
46
+	uint16_t psgX;
47
+	int16_t psgLast;
48
+	uint32_t psgLastCount;
49
+
50
+	// The following are taken from DeSmuME
51
+	double samplePosition;
52
+	double sampleIncrease;
53
+
54
+	// Loopstart Register
55
+	uint32_t loopStart;
56
+
57
+	// Length Register
58
+	uint32_t length;
59
+
60
+	NDSSoundRegister();
61
+
62
+	void ClearControlRegister();
63
+	void SetControlRegister(uint32_t reg);
64
+};
65
+
66
+/*
67
+ * From FeOS Sound System, this is temporary storage of what will go into
68
+ * the Nintendo DS sound registers.  It is kept separate as the original code
69
+ * from FeOS Sound System utilized this to hold data prior to passing it into
70
+ * the DS's registers.
71
+ */
72
+struct TempSndReg
73
+{
74
+	uint32_t CR;
75
+	const SWAV *SOURCE;
76
+	uint16_t TIMER;
77
+	uint32_t REPEAT_POINT, LENGTH;
78
+
79
+	TempSndReg();
80
+};
81
+
82
+struct Player;
83
+
84
+struct Channel
85
+{
86
+	int8_t chnId;
87
+
88
+	TempSndReg tempReg;
89
+	uint8_t state;
90
+	int8_t trackId; // -1 = none
91
+	uint8_t prio;
92
+	bool manualSweep;
93
+
94
+	std::bitset<CF_BITS> flags;
95
+	int8_t pan; // -64 .. 63
96
+	int16_t extAmpl;
97
+
98
+	int16_t velocity;
99
+	int8_t extPan;
100
+	uint8_t key;
101
+
102
+	int ampl; // 7 fractionary bits
103
+	int extTune; // in 64ths of a semitone
104
+
105
+	uint8_t orgKey;
106
+
107
+	uint8_t modType, modSpeed, modDepth, modRange;
108
+	uint16_t modDelay, modDelayCnt, modCounter;
109
+
110
+	uint32_t sweepLen, sweepCnt;
111
+	int16_t sweepPitch;
112
+
113
+	uint8_t attackLvl, sustainLvl;
114
+	uint16_t decayRate, releaseRate;
115
+
116
+	/*
117
+	 * These were originally global variables in FeOS Sound System, but
118
+	 * since they were linked to a certain channel anyways, I moved them
119
+	 * into this class.
120
+	 */
121
+	int noteLength;
122
+	uint16_t vol;
123
+
124
+	const Player *ply;
125
+	NDSSoundRegister reg;
126
+
127
+	Channel();
128
+
129
+	void UpdateVol(const Track &trk);
130
+	void UpdatePan(const Track &trk);
131
+	void UpdateTune(const Track &trk);
132
+	void UpdateMod(const Track &trk);
133
+	void UpdatePorta(const Track &trk);
134
+	void Release();
135
+	void Kill();
136
+	void UpdateTrack();
137
+	void Update();
138
+	int32_t Interpolate(int32_t a, int32_t b, double ratio);
139
+	int32_t GenerateSample();
140
+	void IncrementSample();
141
+};
142
+
143
+#endif