Browse code

update for C++17 compliance, update to latest 2sf, add WINE cross-compile makefiles

Adam Higerd authored on 2021/02/11 15:36:17
Showing 1 changed files
... ...
@@ -1,4 +1,4 @@
1
-/*  Copyright 2009 DeSmuME team
1
+/*  Copyright 2009-2015 DeSmuME team
2 2
 
3 3
     This file is part of DeSmuME
4 4
 
... ...
@@ -17,474 +17,41 @@
17 17
     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
18 18
 */
19 19
 
20
-#include <queue>
21
-#include <vector>
22
-#include <cmath>
23
-#include "../types.h"
24 20
 #include "metaspu.h"
25 21
 
26
-//for pcsx2 method
27
-//(havent bothered to get it compiling in gcc yet)
28
-#ifdef _MSC_VER
29
-#include "SndOut.h"
30
-#endif
31
-
32
-class ZeromusSynchronizer : public ISynchronizingAudioBuffer
33
-{
34
-public:
35
-	ZeromusSynchronizer() : mixqueue_go(false),
36
-#ifdef NDEBUG
37
-		adjustobuf(200, 1000)
38
-#else
39
-		adjustobuf(22000, 44000)
40
-#endif
41
-	{
42
-	}
43
-
44
-	bool mixqueue_go;
45
-
46
-	virtual void enqueue_samples(int16_t *buf, int samples_provided)
47
-	{
48
-		for (int i = 0; i < samples_provided; ++i)
49
-		{
50
-			int16_t left = *buf++;
51
-			int16_t right = *buf++;
52
-			this->adjustobuf.enqueue(left, right);
53
-		}
54
-	}
55
-
56
-	// returns the number of samples actually supplied, which may not match the number requested
57
-	virtual int output_samples(int16_t *buf, int samples_requested)
58
-	{
59
-		int done = 0;
60
-		if (!this->mixqueue_go)
61
-		{
62
-			if (this->adjustobuf.size > 200)
63
-				this->mixqueue_go = true;
64
-		}
65
-		else
66
-		{
67
-			for (int i = 0; i < samples_requested; ++i)
68
-			{
69
-				if (!this->adjustobuf.size)
70
-				{
71
-					this->mixqueue_go = false;
72
-					break;
73
-				}
74
-				++done;
75
-				int16_t left, right;
76
-				this->adjustobuf.dequeue(left, right);
77
-				*buf++ = left;
78
-				*buf++ = right;
79
-			}
80
-		}
81
-
82
-		return done;
83
-	}
84
-
85
-private:
86
-	class Adjustobuf
87
-	{
88
-	public:
89
-		Adjustobuf(int _minLatency, int _maxLatency) : minLatency(_minLatency), maxLatency(_maxLatency), size(0)
90
-		{
91
-			this->rollingTotalSize = 0;
92
-			this->targetLatency = (this->maxLatency + this->minLatency) / 2;
93
-			this->rate = 1.0f;
94
-			this->cursor = 0.0f;
95
-			this->curr[0] = this->curr[1] = 0;
96
-			this->kAverageSize = 80000;
97
-		}
98
-
99
-		float rate, cursor;
100
-		int minLatency, targetLatency, maxLatency;
101
-		std::queue<int16_t> buffer;
102
-		int size;
103
-		int16_t curr[2];
104
-
105
-		std::queue<int> statsHistory;
106
-
107
-		void enqueue(int16_t left, int16_t right)
108
-		{
109
-			this->buffer.push(left);
110
-			this->buffer.push(right);
111
-			++this->size;
112
-		}
113
-
114
-		int64_t rollingTotalSize;
115
-
116
-		uint32_t kAverageSize;
117
-
118
-		void addStatistic()
119
-		{
120
-			this->statsHistory.push(this->size);
121
-			this->rollingTotalSize += this->size;
122
-			if (this->statsHistory.size() > this->kAverageSize)
123
-			{
124
-				this->rollingTotalSize -= this->statsHistory.front();
125
-				this->statsHistory.pop();
126
-
127
-				float averageSize = rollingTotalSize / kAverageSize;
128
-				//static int ctr=0;  ctr++; if((ctr&127)==0) printf("avg size: %f curr size: %d rate: %f\n",averageSize,size,rate);
129
-				{
130
-					float targetRate;
131
-					if (averageSize < this->targetLatency)
132
-						targetRate = 1.0f - (this->targetLatency - averageSize) / this->kAverageSize;
133
-					else if (averageSize > this->targetLatency)
134
-						targetRate = 1.0f + (averageSize - this->targetLatency) / this->kAverageSize;
135
-					else
136
-						targetRate = 1.0f;
137
-
138
-					//rate = moveValueTowards(rate,targetRate,0.001f);
139
-					this->rate = targetRate;
140
-				}
141
-			}
142
-		}
143
-
144
-		void dequeue(int16_t &left, int16_t &right)
145
-		{
146
-			left = right = 0;
147
-			this->addStatistic();
148
-			if (!this->size)
149
-				return;
150
-			this->cursor += this->rate;
151
-			while (this->cursor > 1.0f)
152
-			{
153
-				this->cursor -= 1.0f;
154
-				if (this->size > 0)
155
-				{
156
-					this->curr[0] = this->buffer.front();
157
-					this->buffer.pop();
158
-					this->curr[1] = this->buffer.front();
159
-					this->buffer.pop();
160
-					--this->size;
161
-				}
162
-			}
163
-			left = this->curr[0];
164
-			right = this->curr[1];
165
-		}
166
-	} adjustobuf;
167
-};
168
-
169
-class NitsujaSynchronizer : public ISynchronizingAudioBuffer
170
-{
171
-private:
172
-	struct ssamp
173
-	{
174
-		int16_t l, r;
175
-		ssamp() { }
176
-		ssamp(int16_t ll, int16_t rr) : l(ll), r(rr) { }
177
-	};
178
-
179
-	std::vector<ssamp> sampleQueue;
180
-
181
-	// returns values going between 0 and y-1 in a saw wave pattern, based on x
182
-	static int pingpong(int x, int y)
183
-	{
184
-		x %= 2 * y;
185
-		if (x >= y)
186
-			x = 2 * y - x - 1;
187
-		return x;
188
-
189
-		// in case we want to switch to odd buffer sizes for more sharpness
190
-		//x %= 2*(y-1);
191
-		//if(x >= y)
192
-		//	x = 2*(y-1) - x;
193
-		//return x;
194
-	}
195
-
196
-	static ssamp crossfade(const ssamp &lhs, const ssamp &rhs, int cur, int start, int end)
197
-	{
198
-		if (cur <= start)
199
-			return lhs;
200
-		if (cur >= end)
201
-			return rhs;
202
-
203
-		// in case we want sine wave interpolation instead of linear here
204
-		//float ang = 3.14159f * (float)(cur - start) / (float)(end - start);
205
-		//cur = start + (int)((1-cosf(ang))*0.5f * (end - start));
206
-
207
-		int inNum = cur - start;
208
-		int outNum = end - cur;
209
-		int denom = end - start;
210
-
211
-		int lrv = (lhs.l * outNum + rhs.l * inNum) / denom;
212
-		int rrv = (lhs.r * outNum + rhs.r * inNum) / denom;
213
-
214
-		return ssamp(lrv, rrv);
215
-	}
216
-
217
-	static void emit_sample(int16_t *&outbuf, const ssamp &sample)
218
-	{
219
-		*outbuf++ = sample.l;
220
-		*outbuf++ = sample.r;
221
-	}
222
-
223
-	static void emit_samples(int16_t *&outbuf, const ssamp *samplebuf, int samples)
224
-	{
225
-		for (int i = 0; i < samples; ++i)
226
-			NitsujaSynchronizer::emit_sample(outbuf, samplebuf[i]);
227
-	}
228
-
229
-public:
230
-	NitsujaSynchronizer() { }
231
-
232
-	virtual void enqueue_samples(int16_t *buf, int samples_provided)
233
-	{
234
-		for (int i = 0; i < samples_provided; ++i)
235
-		{
236
-			this->sampleQueue.push_back(ssamp(buf[0], buf[1]));
237
-			buf += 2;
238
-		}
239
-	}
240
-
241
-	virtual int output_samples(int16_t *buf, int samples_requested)
242
-	{
243
-		int audiosize = samples_requested;
244
-		int queued = this->sampleQueue.size();
245
-
246
-		// I am too lazy to deal with odd numbers
247
-		audiosize &= ~1;
248
-		queued &= ~1;
249
-
250
-		if (queued > 0x200 && audiosize > 0) // is there any work to do?
251
-		{
252
-			// are we going at normal speed?
253
-			// or more precisely, are the input and output queues/buffers of similar size?
254
-			if (queued > 900 || audiosize > queued * 2)
255
-			{
256
-				// not normal speed. we have to resample it somehow in this case.
257
-				if (audiosize <= queued)
258
-				{
259
-					// fast forward speed
260
-					// this is the easy case, just crossfade it and it sounds ok
261
-					for (int i = 0; i < audiosize; ++i)
262
-					{
263
-						int j = i + queued - audiosize;
264
-						ssamp outsamp = this->crossfade(this->sampleQueue[i], this->sampleQueue[j], i, 0, audiosize);
265
-						this->emit_sample(buf, outsamp);
266
-					}
267
-				}
268
-				else
269
-				{
270
-					// slow motion speed
271
-					// here we take a very different approach,
272
-					// instead of crossfading it, we select a single sample from the queue
273
-					// and make sure that the index we use to select a sample is constantly moving
274
-					// and that it starts at the first sample in the queue and ends on the last one.
275
-					//
276
-					// hopefully the index doesn't move discontinuously or we'll get slight crackling
277
-					// (there might still be a minor bug here that causes this occasionally)
278
-					//
279
-					// here's a diagram of how the index we sample from moves:
280
-					//
281
-					// queued (this axis represents the index we sample from. the top means the end of the queue)
282
-					// ^
283
-					// |   --> audiosize (this axis represents the output index we write to, right meaning forward in output time/position)
284
-					// |   A           C       C  end
285
-					//    A A     B   C C     C
286
-					//   A   A   A B C   C   C
287
-					//  A     A A   B     C C
288
-					// A       A           C
289
-					// start
290
-					//
291
-					// yes, this means we are spending some stretches of time playing the sound backwards,
292
-					// but the stretches are short enough that this doesn't sound weird.
293
-					// this lets us avoid most crackling problems due to the endpoints matching up.
294
-
295
-					// first calculate a shorter-than-full window
296
-					// that has minimal slope at the endpoints
297
-					// (to further reduce crackling, especially in sine waves)
298
-					int beststart = 0, extraAtEnd = 0;
299
-					{
300
-						int bestend = queued;
301
-						static const int worstdiff = 99999999;
302
-						int beststartdiff = worstdiff;
303
-						int bestenddiff = worstdiff;
304
-						for(int i = 0; i < 128; i += 2)
305
-						{
306
-							int diff = std::abs(this->sampleQueue[i].l - this->sampleQueue[i + 1].l) + std::abs(this->sampleQueue[i].r - this->sampleQueue[i + 1].r);
307
-							if (diff < beststartdiff)
308
-							{
309
-								beststartdiff = diff;
310
-								beststart = i;
311
-							}
312
-						}
313
-						for (int i = queued - 3; i > queued - 3 - 128; i -= 2)
314
-						{
315
-							int diff = std::abs(this->sampleQueue[i].l - this->sampleQueue[i + 1].l) + std::abs(this->sampleQueue[i].r - this->sampleQueue[i + 1].r);
316
-							if (diff < bestenddiff)
317
-							{
318
-								bestenddiff = diff;
319
-								bestend = i+1;
320
-							}
321
-						}
322
-
323
-						extraAtEnd = queued - bestend;
324
-						queued = bestend - beststart;
325
-
326
-						int oksize = queued;
327
-						while (oksize + queued * 2 + beststart + extraAtEnd <= samples_requested)
328
-							oksize += queued * 2;
329
-						audiosize = oksize;
330
-
331
-						for (int x = 0; x < beststart; ++x)
332
-							this->emit_sample(buf, this->sampleQueue[x]);
333
-						this->sampleQueue.erase(this->sampleQueue.begin(), this->sampleQueue.begin() + beststart);
334
-					}
335
-
336
-					int midpointX = audiosize >> 1;
337
-					int midpointY = queued >> 1;
338
-
339
-					// all we need to do here is calculate the X position of the leftmost "B" in the above diagram.
340
-					// TODO: we should calculate it with a simple equation like
341
-					//   midpointXOffset = min(something,somethingElse);
342
-					// but it's a little difficult to work it out exactly
343
-					// so here's a stupid search for the value for now:
344
-
345
-					int prevA = 999999;
346
-					int midpointXOffset = queued / 2;
347
-					while (true)
348
-					{
349
-						int a = std::abs(this->pingpong(midpointX - midpointXOffset, queued) - midpointY) - midpointXOffset;
350
-						if (((a > 0) != (prevA > 0) || (a < 0) != (prevA < 0)) && prevA != 999999)
351
-						{
352
-							if ((a + prevA) & 1) // there's some sort of off-by-one problem with this search since we're moving diagonally...
353
-								++midpointXOffset; // but this fixes it most of the time...
354
-							break; // found it
355
-						}
356
-						prevA = a;
357
-						--midpointXOffset;
358
-						if (midpointXOffset < 0)
359
-						{
360
-							midpointXOffset = 0;
361
-							break; // failed to find it. the two sides probably meet exactly in the center.
362
-						}
363
-					}
364
-
365
-					int leftMidpointX = midpointX - midpointXOffset;
366
-					int rightMidpointX = midpointX + midpointXOffset;
367
-					int leftMidpointY = pingpong(leftMidpointX, queued);
368
-					int rightMidpointY = (queued - 1) - this->pingpong(audiosize - 1 - rightMidpointX + queued * 2, queued);
369
-
370
-					// output the left almost-half of the sound (section "A")
371
-					for (int x = 0; x < leftMidpointX; ++x)
372
-					{
373
-						int i = this->pingpong(x, queued);
374
-						this->emit_sample(buf, this->sampleQueue[i]);
375
-					}
376
-
377
-					// output the middle stretch (section "B")
378
-					int y = leftMidpointY;
379
-					int dyMidLeft = leftMidpointY < midpointY ? 1 : -1;
380
-					int dyMidRight = rightMidpointY > midpointY ? 1 : -1;
381
-					for (int x = leftMidpointX; x < midpointX; ++x, y += dyMidLeft)
382
-						this->emit_sample(buf, this->sampleQueue[y]);
383
-					for (int x = midpointX; x < rightMidpointX; ++x, y += dyMidRight)
384
-						this->emit_sample(buf, this->sampleQueue[y]);
385
-
386
-					// output the end of the queued sound (section "C")
387
-					for (int x = rightMidpointX; x < audiosize; ++x)
388
-					{
389
-						int i = (queued - 1) - this->pingpong(audiosize - 1 - x + queued * 2, queued);
390
-						this->emit_sample(buf, sampleQueue[i]);
391
-					}
392
-
393
-					for (int x = 0; x < extraAtEnd; ++x)
394
-					{
395
-						int i = queued + x;
396
-						this->emit_sample(buf, this->sampleQueue[i]);
397
-					}
398
-					queued += extraAtEnd;
399
-					audiosize += beststart + extraAtEnd;
400
-				} //end else
401
-
402
-				this->sampleQueue.erase(this->sampleQueue.begin(), this->sampleQueue.begin() + queued);
403
-				return audiosize;
404
-			}
405
-			else
406
-			{
407
-				// normal speed
408
-				// just output the samples straightforwardly.
409
-				//
410
-				// at almost-full speeds (like 50/60 FPS)
411
-				// what will happen is that we rapidly fluctuate between entering this branch
412
-				// and entering the "slow motion speed" branch above.
413
-				// but that's ok! because all of these branches sound similar enough that we can get away with it.
414
-				// so the two cases actually complement each other.
415
-
416
-				if (audiosize >= queued)
417
-				{
418
-					this->emit_samples(buf, &this->sampleQueue[0], queued);
419
-					this->sampleQueue.erase(this->sampleQueue.begin(), this->sampleQueue.begin() + queued);
420
-					return queued;
421
-				}
422
-				else
423
-				{
424
-					this->emit_samples(buf, &this->sampleQueue[0], audiosize);
425
-					this->sampleQueue.erase(this->sampleQueue.begin(), this->sampleQueue.begin() + audiosize);
426
-					return audiosize;
427
-				}
428
-			} //end normal speed
429
-		} //end if there is any work to do
430
-		else
431
-			return 0;
432
-	} //output_samples
433
-}; //NitsujaSynchronizer
22
+#include <queue>
23
+#include <vector>
24
+#include <list>
25
+#include <cstring>
26
+#include <assert.h>
434 27
 
435
-#ifdef _MSC_VER
436
-class PCSX2Synchronizer : public ISynchronizingAudioBuffer
28
+class NullSynchronizer : public ISynchronizingAudioBuffer
437 29
 {
438 30
 public:
439
-	std::queue<int16_t> readySamples;
440
-	PCSX2Synchronizer()
441
-	{
442
-		SndBuffer::Init();
443
-	}
444
-	virtual void enqueue_samples(int16_t *buf, int samples_provided)
445
-	{
446
-		for (int i = 0; i < samples_provided; ++i)
447
-		{
448
-			auto so32 = StereoOut32(buf[0], buf[1]);
449
-			SndBuffer::Write(so32);
450
-			buf += 2;
451
-		}
452
-	}
453
-
454
-	virtual int output_samples(int16_t *buf, int samples_requested)
455
-	{
456
-		for (int i = 0; i < samples_requested; ++i)
457
-		{
458
-			if (!this->readySamples.size())
459
-			{
460
-				//SndOutPacketSize
461
-				StereoOut16 temp[SndOutPacketSize * 2];
462
-				SndBuffer::ReadSamples(temp);
463
-				for (int i = 0; i < SndOutPacketSize; ++i)
464
-				{
465
-					this->readySamples.push(temp[i].Left);
466
-					this->readySamples.push(temp[i].Right);
467
-				}
468
-			}
469
-			*buf++ = this->readySamples.front();
470
-			this->readySamples.pop();
471
-			*buf++ = this->readySamples.front();
472
-			this->readySamples.pop();
473
-		}
474
-		return samples_requested;
475
-	}
31
+  std::queue<uint32_t> buffer;
32
+  NullSynchronizer() {}
33
+
34
+	virtual void enqueue_samples(s16* buf, int samples_provided) {
35
+    for (int i = 0; i < samples_provided * 2; i += 2) {
36
+      uint16_t left = buf[i];
37
+      uint16_t right = buf[i + 1];
38
+      buffer.push(left << 16 | right);
39
+    }
40
+  }
41
+
42
+	virtual int output_samples(s16* buf, int samples_requested) {
43
+    int samples = ((samples_requested < buffer.size()) ? samples_requested : buffer.size()) & ~1;
44
+    for (int offset = 0, i = 0; i < samples; i++) {
45
+      uint32_t sample = buffer.front();
46
+      buffer.pop();
47
+      buf[offset++] = (sample >> 16) & 0xFFFF;
48
+      buf[offset++] = sample & 0xFFFF;
49
+    }
50
+    return samples;
51
+  }
476 52
 };
477
-#endif
478 53
 
479
-ISynchronizingAudioBuffer *metaspu_construct(ESynchMethod method)
54
+ISynchronizingAudioBuffer* metaspu_construct(ESynchMethod method)
480 55
 {
481
-	switch(method)
482
-	{
483
-		case ESynchMethod_N: return new NitsujaSynchronizer();
484
-		case ESynchMethod_Z: return new ZeromusSynchronizer();
485
-#ifdef _MSC_VER
486
-		case ESynchMethod_P: return new PCSX2Synchronizer();
487
-#endif
488
-		default: return nullptr;
489
-	}
56
+	return new NullSynchronizer();
490 57
 }
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
... ...
@@ -19,7 +19,7 @@
19 19
 
20 20
 #include <queue>
21 21
 #include <vector>
22
-#include <cassert>
22
+#include <cmath>
23 23
 #include "../types.h"
24 24
 #include "metaspu.h"
25 25
 
Browse code

Removed a bunch of casts, they seem to be fine without them in most cases.

Naram Qashat authored on 2013/04/18 23:22:54
Showing 1 changed files
... ...
@@ -124,7 +124,7 @@ private:
124 124
 				this->rollingTotalSize -= this->statsHistory.front();
125 125
 				this->statsHistory.pop();
126 126
 
127
-				float averageSize = static_cast<float>(rollingTotalSize / kAverageSize);
127
+				float averageSize = rollingTotalSize / kAverageSize;
128 128
 				//static int ctr=0;  ctr++; if((ctr&127)==0) printf("avg size: %f curr size: %d rate: %f\n",averageSize,size,rate);
129 129
 				{
130 130
 					float targetRate;
... ...
@@ -208,8 +208,8 @@ private:
208 208
 		int outNum = end - cur;
209 209
 		int denom = end - start;
210 210
 
211
-		int lrv = (static_cast<int>(lhs.l) * outNum + static_cast<int>(rhs.l) * inNum) / denom;
212
-		int rrv = (static_cast<int>(lhs.r) * outNum + static_cast<int>(rhs.r) * inNum) / denom;
211
+		int lrv = (lhs.l * outNum + rhs.l * inNum) / denom;
212
+		int rrv = (lhs.r * outNum + rhs.r * inNum) / denom;
213 213
 
214 214
 		return ssamp(lrv, rrv);
215 215
 	}
Browse code

Updating in_2sf to use a newish version of DeSmuME, 0.9.9 from SVN. Somewhat cleaned up as well, but not everything because it's a pain in the ass.

Naram Qashat authored on 2013/04/18 17:22:55
Showing 1 changed files
... ...
@@ -20,7 +20,6 @@
20 20
 #include <queue>
21 21
 #include <vector>
22 22
 #include <cassert>
23
-
24 23
 #include "../types.h"
25 24
 #include "metaspu.h"
26 25
 
... ...
@@ -30,68 +29,51 @@
30 29
 #include "SndOut.h"
31 30
 #endif
32 31
 
33
-/*template<typename T> inline T _abs(T val)
34
-{
35
-	if(val<0) return -val;
36
-	else return val;
37
-}*/
38
-
39
-/*template<typename T> inline T moveValueTowards(T val, T target, T incr)
40
-{
41
-	incr = _abs(incr);
42
-	T delta = _abs(target-val);
43
-	if(val<target) val += incr;
44
-	else if(val>target) val -= incr;
45
-	T newDelta = _abs(target-val);
46
-	if(newDelta >= delta)
47
-		val = target;
48
-	return val;
49
-}*/
50
-
51 32
 class ZeromusSynchronizer : public ISynchronizingAudioBuffer
52 33
 {
53 34
 public:
54
-	ZeromusSynchronizer()
55
-		: mixqueue_go(false)
56
-		,
57
-		#ifdef NDEBUG
58
-		adjustobuf(200,1000)
59
-		#else
60
-		adjustobuf(22000,44000)
61
-		#endif
35
+	ZeromusSynchronizer() : mixqueue_go(false),
36
+#ifdef NDEBUG
37
+		adjustobuf(200, 1000)
38
+#else
39
+		adjustobuf(22000, 44000)
40
+#endif
62 41
 	{
63
-
64 42
 	}
65 43
 
66 44
 	bool mixqueue_go;
67 45
 
68
-	virtual void enqueue_samples(int16_t* buf, int samples_provided)
46
+	virtual void enqueue_samples(int16_t *buf, int samples_provided)
69 47
 	{
70
-		for(int i=0;i<samples_provided;i++) {
48
+		for (int i = 0; i < samples_provided; ++i)
49
+		{
71 50
 			int16_t left = *buf++;
72 51
 			int16_t right = *buf++;
73
-			adjustobuf.enqueue(left,right);
52
+			this->adjustobuf.enqueue(left, right);
74 53
 		}
75 54
 	}
76 55
 
77
-	//returns the number of samples actually supplied, which may not match the number requested
78
-	virtual int output_samples(int16_t* buf, int samples_requested)
56
+	// returns the number of samples actually supplied, which may not match the number requested
57
+	virtual int output_samples(int16_t *buf, int samples_requested)
79 58
 	{
80 59
 		int done = 0;
81
-		if(!mixqueue_go) {
82
-			if(adjustobuf.size > 200)
83
-				mixqueue_go = true;
60
+		if (!this->mixqueue_go)
61
+		{
62
+			if (this->adjustobuf.size > 200)
63
+				this->mixqueue_go = true;
84 64
 		}
85 65
 		else
86 66
 		{
87
-			for(int i=0;i<samples_requested;i++) {
88
-				if(adjustobuf.size==0) {
89
-					mixqueue_go = false;
67
+			for (int i = 0; i < samples_requested; ++i)
68
+			{
69
+				if (!this->adjustobuf.size)
70
+				{
71
+					this->mixqueue_go = false;
90 72
 					break;
91 73
 				}
92
-				done++;
74
+				++done;
93 75
 				int16_t left, right;
94
-				adjustobuf.dequeue(left,right);
76
+				this->adjustobuf.dequeue(left, right);
95 77
 				*buf++ = left;
96 78
 				*buf++ = right;
97 79
 			}
... ...
@@ -104,17 +86,14 @@ private:
104 86
 	class Adjustobuf
105 87
 	{
106 88
 	public:
107
-		Adjustobuf(int _minLatency, int _maxLatency)
108
-			: minLatency(_minLatency)
109
-			, maxLatency(_maxLatency)
110
-			, size(0)
89
+		Adjustobuf(int _minLatency, int _maxLatency) : minLatency(_minLatency), maxLatency(_maxLatency), size(0)
111 90
 		{
112
-			rollingTotalSize = 0;
113
-			targetLatency = (maxLatency + minLatency)/2;
114
-			rate = 1.0f;
115
-			cursor = 0.0f;
116
-			curr[0] = curr[1] = 0;
117
-			kAverageSize = 80000;
91
+			this->rollingTotalSize = 0;
92
+			this->targetLatency = (this->maxLatency + this->minLatency) / 2;
93
+			this->rate = 1.0f;
94
+			this->cursor = 0.0f;
95
+			this->curr[0] = this->curr[1] = 0;
96
+			this->kAverageSize = 80000;
118 97
 		}
119 98
 
120 99
 		float rate, cursor;
... ...
@@ -127,9 +106,9 @@ private:
127 106
 
128 107
 		void enqueue(int16_t left, int16_t right)
129 108
 		{
130
-			buffer.push(left);
131
-			buffer.push(right);
132
-			size++;
109
+			this->buffer.push(left);
110
+			this->buffer.push(right);
111
+			++this->size;
133 112
 		}
134 113
 
135 114
 		int64_t rollingTotalSize;
... ...
@@ -138,50 +117,51 @@ private:
138 117
 
139 118
 		void addStatistic()
140 119
 		{
141
-			statsHistory.push(size);
142
-			rollingTotalSize += size;
143
-			if(statsHistory.size()>kAverageSize)
120
+			this->statsHistory.push(this->size);
121
+			this->rollingTotalSize += this->size;
122
+			if (this->statsHistory.size() > this->kAverageSize)
144 123
 			{
145
-				rollingTotalSize -= statsHistory.front();
146
-				statsHistory.pop();
124
+				this->rollingTotalSize -= this->statsHistory.front();
125
+				this->statsHistory.pop();
147 126
 
148
-				float averageSize = (float)(rollingTotalSize / kAverageSize);
127
+				float averageSize = static_cast<float>(rollingTotalSize / kAverageSize);
149 128
 				//static int ctr=0;  ctr++; if((ctr&127)==0) printf("avg size: %f curr size: %d rate: %f\n",averageSize,size,rate);
150 129
 				{
151 130
 					float targetRate;
152
-					if(averageSize < targetLatency)
153
-					{
154
-						targetRate = 1.0f - (targetLatency-averageSize)/kAverageSize;
155
-					}
156
-					else if(averageSize > targetLatency) {
157
-						targetRate = 1.0f + (averageSize-targetLatency)/kAverageSize;
158
-					} else targetRate = 1.0f;
131
+					if (averageSize < this->targetLatency)
132
+						targetRate = 1.0f - (this->targetLatency - averageSize) / this->kAverageSize;
133
+					else if (averageSize > this->targetLatency)
134
+						targetRate = 1.0f + (averageSize - this->targetLatency) / this->kAverageSize;
135
+					else
136
+						targetRate = 1.0f;
159 137
 
160 138
 					//rate = moveValueTowards(rate,targetRate,0.001f);
161
-					rate = targetRate;
139
+					this->rate = targetRate;
162 140
 				}
163
-
164 141
 			}
165
-
166
-
167 142
 		}
168 143
 
169
-		void dequeue(int16_t& left, int16_t& right)
144
+		void dequeue(int16_t &left, int16_t &right)
170 145
 		{
171 146
 			left = right = 0;
172
-			addStatistic();
173
-			if(size==0) { return; }
174
-			cursor += rate;
175
-			while(cursor>1.0f) {
176
-				cursor -= 1.0f;
177
-				if(size>0) {
178
-					curr[0] = buffer.front(); buffer.pop();
179
-					curr[1] = buffer.front(); buffer.pop();
180
-					size--;
147
+			this->addStatistic();
148
+			if (!this->size)
149
+				return;
150
+			this->cursor += this->rate;
151
+			while (this->cursor > 1.0f)
152
+			{
153
+				this->cursor -= 1.0f;
154
+				if (this->size > 0)
155
+				{
156
+					this->curr[0] = this->buffer.front();
157
+					this->buffer.pop();
158
+					this->curr[1] = this->buffer.front();
159
+					this->buffer.pop();
160
+					--this->size;
181 161
 				}
182 162
 			}
183
-			left = curr[0];
184
-			right = curr[1];
163
+			left = this->curr[0];
164
+			right = this->curr[1];
185 165
 		}
186 166
 	} adjustobuf;
187 167
 };
... ...
@@ -192,18 +172,18 @@ private:
192 172
 	struct ssamp
193 173
 	{
194 174
 		int16_t l, r;
195
-		ssamp() {}
196
-		ssamp(int16_t ll, int16_t rr) : l(ll), r(rr) {}
175
+		ssamp() { }
176
+		ssamp(int16_t ll, int16_t rr) : l(ll), r(rr) { }
197 177
 	};
198 178
 
199 179
 	std::vector<ssamp> sampleQueue;
200 180
 
201 181
 	// returns values going between 0 and y-1 in a saw wave pattern, based on x
202
-	static inline int pingpong(int x, int y)
182
+	static int pingpong(int x, int y)
203 183
 	{
204
-		x %= 2*y;
205
-		if(x >= y)
206
-			x = 2*y - x - 1;
184
+		x %= 2 * y;
185
+		if (x >= y)
186
+			x = 2 * y - x - 1;
207 187
 		return x;
208 188
 
209 189
 		// in case we want to switch to odd buffer sizes for more sharpness
... ...
@@ -213,11 +193,11 @@ private:
213 193
 		//return x;
214 194
 	}
215 195
 
216
-	static inline ssamp crossfade (ssamp lhs, ssamp rhs,  int cur, int start, int end)
196
+	static ssamp crossfade(const ssamp &lhs, const ssamp &rhs, int cur, int start, int end)
217 197
 	{
218
-		if(cur <= start)
198
+		if (cur <= start)
219 199
 			return lhs;
220
-		if(cur >= end)
200
+		if (cur >= end)
221 201
 			return rhs;
222 202
 
223 203
 		// in case we want sine wave interpolation instead of linear here
... ...
@@ -228,62 +208,61 @@ private:
228 208
 		int outNum = end - cur;
229 209
 		int denom = end - start;
230 210
 
231
-		int lrv = ((int)lhs.l * outNum + (int)rhs.l * inNum) / denom;
232
-		int rrv = ((int)lhs.r * outNum + (int)rhs.r * inNum) / denom;
211
+		int lrv = (static_cast<int>(lhs.l) * outNum + static_cast<int>(rhs.l) * inNum) / denom;
212
+		int rrv = (static_cast<int>(lhs.r) * outNum + static_cast<int>(rhs.r) * inNum) / denom;
233 213
 
234
-		return ssamp(lrv,rrv);
214
+		return ssamp(lrv, rrv);
235 215
 	}
236 216
 
237
-	static inline void emit_sample(int16_t*& outbuf, ssamp sample)
217
+	static void emit_sample(int16_t *&outbuf, const ssamp &sample)
238 218
 	{
239 219
 		*outbuf++ = sample.l;
240 220
 		*outbuf++ = sample.r;
241 221
 	}
242 222
 
243
-	static inline void emit_samples(int16_t*& outbuf, const ssamp* samplebuf, int samples)
223
+	static void emit_samples(int16_t *&outbuf, const ssamp *samplebuf, int samples)
244 224
 	{
245
-		for(int i=0;i<samples;i++)
246
-			emit_sample(outbuf,samplebuf[i]);
225
+		for (int i = 0; i < samples; ++i)
226
+			NitsujaSynchronizer::emit_sample(outbuf, samplebuf[i]);
247 227
 	}
248 228
 
249 229
 public:
250
-	NitsujaSynchronizer()
251
-	{}
230
+	NitsujaSynchronizer() { }
252 231
 
253
-	virtual void enqueue_samples(int16_t* buf, int samples_provided)
232
+	virtual void enqueue_samples(int16_t *buf, int samples_provided)
254 233
 	{
255
-		for(int i=0;i<samples_provided;i++)
234
+		for (int i = 0; i < samples_provided; ++i)
256 235
 		{
257
-			sampleQueue.push_back(ssamp(buf[0],buf[1]));
236
+			this->sampleQueue.push_back(ssamp(buf[0], buf[1]));
258 237
 			buf += 2;
259 238
 		}
260 239
 	}
261 240
 
262
-	virtual int output_samples(int16_t* buf, int samples_requested)
241
+	virtual int output_samples(int16_t *buf, int samples_requested)
263 242
 	{
264 243
 		int audiosize = samples_requested;
265
-		int queued = sampleQueue.size();
244
+		int queued = this->sampleQueue.size();
266 245
 
267 246
 		// I am too lazy to deal with odd numbers
268 247
 		audiosize &= ~1;
269 248
 		queued &= ~1;
270 249
 
271
-		if(queued > 0x200 && audiosize > 0) // is there any work to do?
250
+		if (queued > 0x200 && audiosize > 0) // is there any work to do?
272 251
 		{
273 252
 			// are we going at normal speed?
274 253
 			// or more precisely, are the input and output queues/buffers of similar size?
275
-			if(queued > 900 || audiosize > queued * 2)
254
+			if (queued > 900 || audiosize > queued * 2)
276 255
 			{
277 256
 				// not normal speed. we have to resample it somehow in this case.
278
-				if(audiosize <= queued)
257
+				if (audiosize <= queued)
279 258
 				{
280 259
 					// fast forward speed
281 260
 					// this is the easy case, just crossfade it and it sounds ok
282
-					for(int i = 0; i < audiosize; i++)
261
+					for (int i = 0; i < audiosize; ++i)
283 262
 					{
284 263
 						int j = i + queued - audiosize;
285
-						ssamp outsamp = crossfade(sampleQueue[i],sampleQueue[j], i,0,audiosize);
286
-						emit_sample(buf,outsamp);
264
+						ssamp outsamp = this->crossfade(this->sampleQueue[i], this->sampleQueue[j], i, 0, audiosize);
265
+						this->emit_sample(buf, outsamp);
287 266
 					}
288 267
 				}
289 268
 				else
... ...
@@ -322,19 +301,19 @@ public:
322 301
 						static const int worstdiff = 99999999;
323 302
 						int beststartdiff = worstdiff;
324 303
 						int bestenddiff = worstdiff;
325
-						for(int i = 0; i < 128; i+=2)
304
+						for(int i = 0; i < 128; i += 2)
326 305
 						{
327
-							int diff = abs(sampleQueue[i].l - sampleQueue[i+1].l) + abs(sampleQueue[i].r - sampleQueue[i+1].r);
328
-							if(diff < beststartdiff)
306
+							int diff = std::abs(this->sampleQueue[i].l - this->sampleQueue[i + 1].l) + std::abs(this->sampleQueue[i].r - this->sampleQueue[i + 1].r);
307
+							if (diff < beststartdiff)
329 308
 							{
330 309
 								beststartdiff = diff;
331 310
 								beststart = i;
332 311
 							}
333 312
 						}
334
-						for(int i = queued-3; i > queued-3-128; i-=2)
313
+						for (int i = queued - 3; i > queued - 3 - 128; i -= 2)
335 314
 						{
336
-							int diff = abs(sampleQueue[i].l - sampleQueue[i+1].l) + abs(sampleQueue[i].r - sampleQueue[i+1].r);
337
-							if(diff < bestenddiff)
315
+							int diff = std::abs(this->sampleQueue[i].l - this->sampleQueue[i + 1].l) + std::abs(this->sampleQueue[i].r - this->sampleQueue[i + 1].r);
316
+							if (diff < bestenddiff)
338 317
 							{
339 318
 								bestenddiff = diff;
340 319
 								bestend = i+1;
... ...
@@ -345,18 +324,15 @@ public:
345 324
 						queued = bestend - beststart;
346 325
 
347 326
 						int oksize = queued;
348
-						while(oksize + queued*2 + beststart + extraAtEnd <= samples_requested)
349
-							oksize += queued*2;
327
+						while (oksize + queued * 2 + beststart + extraAtEnd <= samples_requested)
328
+							oksize += queued * 2;
350 329
 						audiosize = oksize;
351 330
 
352
-						for(int x = 0; x < beststart; x++)
353
-						{
354
-							emit_sample(buf,sampleQueue[x]);
355
-						}
356
-						sampleQueue.erase(sampleQueue.begin(), sampleQueue.begin() + beststart);
331
+						for (int x = 0; x < beststart; ++x)
332
+							this->emit_sample(buf, this->sampleQueue[x]);
333
+						this->sampleQueue.erase(this->sampleQueue.begin(), this->sampleQueue.begin() + beststart);
357 334
 					}
358 335
 
359
-
360 336
 					int midpointX = audiosize >> 1;
361 337
 					int midpointY = queued >> 1;
362 338
 
... ...
@@ -367,19 +343,19 @@ public:
367 343
 					// so here's a stupid search for the value for now:
368 344
 
369 345
 					int prevA = 999999;
370
-					int midpointXOffset = queued/2;
371
-					while(true)
346
+					int midpointXOffset = queued / 2;
347
+					while (true)
372 348
 					{
373
-						int a = abs(pingpong(midpointX - midpointXOffset, queued) - midpointY) - midpointXOffset;
374
-						if(((a > 0) != (prevA > 0) || (a < 0) != (prevA < 0)) && prevA != 999999)
349
+						int a = std::abs(this->pingpong(midpointX - midpointXOffset, queued) - midpointY) - midpointXOffset;
350
+						if (((a > 0) != (prevA > 0) || (a < 0) != (prevA < 0)) && prevA != 999999)
375 351
 						{
376
-							if((a + prevA)&1) // there's some sort of off-by-one problem with this search since we're moving diagonally...
377
-								midpointXOffset++; // but this fixes it most of the time...
352
+							if ((a + prevA) & 1) // there's some sort of off-by-one problem with this search since we're moving diagonally...
353
+								++midpointXOffset; // but this fixes it most of the time...
378 354
 							break; // found it
379 355
 						}
380 356
 						prevA = a;
381
-						midpointXOffset--;
382
-						if(midpointXOffset < 0)
357
+						--midpointXOffset;
358
+						if (midpointXOffset < 0)
383 359
 						{
384 360
 							midpointXOffset = 0;
385 361
 							break; // failed to find it. the two sides probably meet exactly in the center.
... ...
@@ -389,41 +365,41 @@ public:
389 365
 					int leftMidpointX = midpointX - midpointXOffset;
390 366
 					int rightMidpointX = midpointX + midpointXOffset;
391 367
 					int leftMidpointY = pingpong(leftMidpointX, queued);
392
-					int rightMidpointY = (queued-1) - pingpong((int)audiosize-1 - rightMidpointX + queued*2, queued);
368
+					int rightMidpointY = (queued - 1) - this->pingpong(audiosize - 1 - rightMidpointX + queued * 2, queued);
393 369
 
394 370
 					// output the left almost-half of the sound (section "A")
395
-					for(int x = 0; x < leftMidpointX; x++)
371
+					for (int x = 0; x < leftMidpointX; ++x)
396 372
 					{
397
-						int i = pingpong(x, queued);
398
-						emit_sample(buf,sampleQueue[i]);
373
+						int i = this->pingpong(x, queued);
374
+						this->emit_sample(buf, this->sampleQueue[i]);
399 375
 					}
400 376
 
401 377
 					// output the middle stretch (section "B")
402 378
 					int y = leftMidpointY;
403
-					int dyMidLeft  = (leftMidpointY  < midpointY) ? 1 : -1;
404
-					int dyMidRight = (rightMidpointY > midpointY) ? 1 : -1;
405
-					for(int x = leftMidpointX; x < midpointX; x++, y+=dyMidLeft)
406
-						emit_sample(buf,sampleQueue[y]);
407
-					for(int x = midpointX; x < rightMidpointX; x++, y+=dyMidRight)
408
-						emit_sample(buf,sampleQueue[y]);
379
+					int dyMidLeft = leftMidpointY < midpointY ? 1 : -1;
380
+					int dyMidRight = rightMidpointY > midpointY ? 1 : -1;
381
+					for (int x = leftMidpointX; x < midpointX; ++x, y += dyMidLeft)
382
+						this->emit_sample(buf, this->sampleQueue[y]);
383
+					for (int x = midpointX; x < rightMidpointX; ++x, y += dyMidRight)
384
+						this->emit_sample(buf, this->sampleQueue[y]);
409 385
 
410 386
 					// output the end of the queued sound (section "C")
411
-					for(int x = rightMidpointX; x < audiosize; x++)
387
+					for (int x = rightMidpointX; x < audiosize; ++x)
412 388
 					{
413
-						int i = (queued-1) - pingpong((int)audiosize-1 - x + queued*2, queued);
414
-						emit_sample(buf,sampleQueue[i]);
389
+						int i = (queued - 1) - this->pingpong(audiosize - 1 - x + queued * 2, queued);
390
+						this->emit_sample(buf, sampleQueue[i]);
415 391
 					}
416 392
 
417
-					for(int x = 0; x < extraAtEnd; x++)
393
+					for (int x = 0; x < extraAtEnd; ++x)
418 394
 					{
419 395
 						int i = queued + x;
420
-						emit_sample(buf,sampleQueue[i]);
396
+						this->emit_sample(buf, this->sampleQueue[i]);
421 397
 					}
422 398
 					queued += extraAtEnd;
423 399
 					audiosize += beststart + extraAtEnd;
424 400
 				} //end else
425 401
 
426
-				sampleQueue.erase(sampleQueue.begin(), sampleQueue.begin() + queued);
402
+				this->sampleQueue.erase(this->sampleQueue.begin(), this->sampleQueue.begin() + queued);
427 403
 				return audiosize;
428 404
 			}
429 405
 			else
... ...
@@ -437,31 +413,23 @@ public:
437 413
 				// but that's ok! because all of these branches sound similar enough that we can get away with it.
438 414
 				// so the two cases actually complement each other.
439 415
 
440
-				if(audiosize >= queued)
416
+				if (audiosize >= queued)
441 417
 				{
442
-					emit_samples(buf,&sampleQueue[0],queued);
443
-					sampleQueue.erase(sampleQueue.begin(), sampleQueue.begin() + queued);
418
+					this->emit_samples(buf, &this->sampleQueue[0], queued);
419
+					this->sampleQueue.erase(this->sampleQueue.begin(), this->sampleQueue.begin() + queued);
444 420
 					return queued;
445 421
 				}
446 422
 				else
447 423
 				{
448
-					emit_samples(buf,&sampleQueue[0],audiosize);
449
-					sampleQueue.erase(sampleQueue.begin(), sampleQueue.begin()+audiosize);
424
+					this->emit_samples(buf, &this->sampleQueue[0], audiosize);
425
+					this->sampleQueue.erase(this->sampleQueue.begin(), this->sampleQueue.begin() + audiosize);
450 426
 					return audiosize;
451 427
 				}
452
-
453 428
 			} //end normal speed
454
-
455 429
 		} //end if there is any work to do
456 430
 		else
457
-		{
458 431
 			return 0;
459
-		}
460
-
461 432
 	} //output_samples
462
-
463
-private:
464
-
465 433
 }; //NitsujaSynchronizer
466 434
 
467 435
 #ifdef _MSC_VER
... ...
@@ -473,46 +441,50 @@ public:
473 441
 	{
474 442
 		SndBuffer::Init();
475 443
 	}
476
-	virtual void enqueue_samples(int16_t* buf, int samples_provided)
444
+	virtual void enqueue_samples(int16_t *buf, int samples_provided)
477 445
 	{
478
-		for(int i=0;i<samples_provided;i++)
446
+		for (int i = 0; i < samples_provided; ++i)
479 447
 		{
480
-			StereoOut32 so32(buf[0],buf[1]);
448
+			auto so32 = StereoOut32(buf[0], buf[1]);
481 449
 			SndBuffer::Write(so32);
482
-			buf++;
483
-			buf++;
450
+			buf += 2;
484 451
 		}
485 452
 	}
486 453
 
487
-	virtual int output_samples(int16_t* buf, int samples_requested)
454
+	virtual int output_samples(int16_t *buf, int samples_requested)
488 455
 	{
489
-		for(int i=0;i<samples_requested;i++) {
490
-			if(readySamples.size()==0) {
456
+		for (int i = 0; i < samples_requested; ++i)
457
+		{
458
+			if (!this->readySamples.size())
459
+			{
491 460
 				//SndOutPacketSize
492
-				StereoOut16 temp[SndOutPacketSize*2];
493
-				SndBuffer::ReadSamples( temp );
494
-				for(int i=0;i<SndOutPacketSize;i++) {
495
-					readySamples.push(temp[i].Left);
496
-					readySamples.push(temp[i].Right);
461
+				StereoOut16 temp[SndOutPacketSize * 2];
462
+				SndBuffer::ReadSamples(temp);
463
+				for (int i = 0; i < SndOutPacketSize; ++i)
464
+				{
465
+					this->readySamples.push(temp[i].Left);
466
+					this->readySamples.push(temp[i].Right);
497 467
 				}
498 468
 			}
499
-			*buf++ = readySamples.front(); readySamples.pop();
500
-			*buf++ = readySamples.front(); readySamples.pop();
469
+			*buf++ = this->readySamples.front();
470
+			this->readySamples.pop();
471
+			*buf++ = this->readySamples.front();
472
+			this->readySamples.pop();
501 473
 		}
502 474
 		return samples_requested;
503 475
 	}
504 476
 };
505 477
 #endif
506 478
 
507
-ISynchronizingAudioBuffer* metaspu_construct(ESynchMethod method)
479
+ISynchronizingAudioBuffer *metaspu_construct(ESynchMethod method)
508 480
 {
509 481
 	switch(method)
510 482
 	{
511
-	case ESynchMethod_N: return new NitsujaSynchronizer();
512
-	case ESynchMethod_Z: return new ZeromusSynchronizer();
513
-	#ifdef _MSC_VER
514
-	case ESynchMethod_P: return new PCSX2Synchronizer();
515
-	#endif
516
-	default: return NULL;
483
+		case ESynchMethod_N: return new NitsujaSynchronizer();
484
+		case ESynchMethod_Z: return new ZeromusSynchronizer();
485
+#ifdef _MSC_VER
486
+		case ESynchMethod_P: return new PCSX2Synchronizer();
487
+#endif
488
+		default: return nullptr;
517 489
 	}
518 490
 }
Browse code

Cleanup of some warnings, updating modification dates, using nullptr instead of NULL in some cases.

Naram Qashat authored on 2013/03/30 16:17:42
Showing 1 changed files
... ...
@@ -21,7 +21,7 @@
21 21
 #include <vector>
22 22
 #include <cassert>
23 23
 
24
-#include "types.h"
24
+#include "../types.h"
25 25
 #include "metaspu.h"
26 26
 
27 27
 //for pcsx2 method
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,518 @@
1
+/*  Copyright 2009 DeSmuME team
2
+
3
+    This file is part of DeSmuME
4
+
5
+    DeSmuME is free software; you can redistribute it and/or modify
6
+    it under the terms of the GNU General Public License as published by
7
+    the Free Software Foundation; either version 2 of the License, or
8
+    (at your option) any later version.
9
+
10
+    DeSmuME is distributed in the hope that it will be useful,
11
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
+    GNU General Public License for more details.
14
+
15
+    You should have received a copy of the GNU General Public License
16
+    along with DeSmuME; if not, write to the Free Software
17
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
18
+*/
19
+
20
+#include <queue>
21
+#include <vector>
22
+#include <cassert>
23
+
24
+#include "types.h"
25
+#include "metaspu.h"
26
+
27
+//for pcsx2 method
28
+//(havent bothered to get it compiling in gcc yet)
29
+#ifdef _MSC_VER
30
+#include "SndOut.h"
31
+#endif
32
+
33
+/*template<typename T> inline T _abs(T val)
34
+{
35
+	if(val<0) return -val;
36
+	else return val;
37
+}*/
38
+
39
+/*template<typename T> inline T moveValueTowards(T val, T target, T incr)
40
+{
41
+	incr = _abs(incr);
42
+	T delta = _abs(target-val);
43
+	if(val<target) val += incr;
44
+	else if(val>target) val -= incr;
45
+	T newDelta = _abs(target-val);
46
+	if(newDelta >= delta)
47
+		val = target;
48
+	return val;
49
+}*/
50
+
51
+class ZeromusSynchronizer : public ISynchronizingAudioBuffer
52
+{
53
+public:
54
+	ZeromusSynchronizer()
55
+		: mixqueue_go(false)
56
+		,
57
+		#ifdef NDEBUG
58
+		adjustobuf(200,1000)
59
+		#else
60
+		adjustobuf(22000,44000)
61
+		#endif
62
+	{
63
+
64
+	}
65
+
66
+	bool mixqueue_go;
67
+
68
+	virtual void enqueue_samples(int16_t* buf, int samples_provided)
69
+	{
70
+		for(int i=0;i<samples_provided;i++) {
71
+			int16_t left = *buf++;
72
+			int16_t right = *buf++;
73
+			adjustobuf.enqueue(left,right);
74
+		}
75
+	}
76
+
77
+	//returns the number of samples actually supplied, which may not match the number requested
78
+	virtual int output_samples(int16_t* buf, int samples_requested)
79
+	{
80
+		int done = 0;
81
+		if(!mixqueue_go) {
82
+			if(adjustobuf.size > 200)
83
+				mixqueue_go = true;
84
+		}
85
+		else
86
+		{
87
+			for(int i=0;i<samples_requested;i++) {
88
+				if(adjustobuf.size==0) {
89
+					mixqueue_go = false;
90
+					break;
91
+				}
92
+				done++;
93
+				int16_t left, right;
94
+				adjustobuf.dequeue(left,right);
95
+				*buf++ = left;
96
+				*buf++ = right;
97
+			}
98
+		}
99
+
100
+		return done;
101
+	}
102
+
103
+private:
104
+	class Adjustobuf
105
+	{
106
+	public:
107
+		Adjustobuf(int _minLatency, int _maxLatency)
108
+			: minLatency(_minLatency)
109
+			, maxLatency(_maxLatency)
110
+			, size(0)
111
+		{
112
+			rollingTotalSize = 0;
113
+			targetLatency = (maxLatency + minLatency)/2;
114
+			rate = 1.0f;
115
+			cursor = 0.0f;
116
+			curr[0] = curr[1] = 0;
117
+			kAverageSize = 80000;
118
+		}
119
+
120
+		float rate, cursor;
121
+		int minLatency, targetLatency, maxLatency;
122
+		std::queue<int16_t> buffer;
123
+		int size;
124
+		int16_t curr[2];
125
+
126
+		std::queue<int> statsHistory;
127
+
128
+		void enqueue(int16_t left, int16_t right)
129
+		{
130
+			buffer.push(left);
131
+			buffer.push(right);
132
+			size++;
133
+		}
134
+
135
+		int64_t rollingTotalSize;
136
+
137
+		uint32_t kAverageSize;
138
+
139
+		void addStatistic()
140
+		{
141
+			statsHistory.push(size);
142
+			rollingTotalSize += size;
143
+			if(statsHistory.size()>kAverageSize)
144
+			{
145
+				rollingTotalSize -= statsHistory.front();
146
+				statsHistory.pop();
147
+
148
+				float averageSize = (float)(rollingTotalSize / kAverageSize);
149
+				//static int ctr=0;  ctr++; if((ctr&127)==0) printf("avg size: %f curr size: %d rate: %f\n",averageSize,size,rate);
150
+				{
151
+					float targetRate;
152
+					if(averageSize < targetLatency)
153
+					{
154
+						targetRate = 1.0f - (targetLatency-averageSize)/kAverageSize;
155
+					}
156
+					else if(averageSize > targetLatency) {
157
+						targetRate = 1.0f + (averageSize-targetLatency)/kAverageSize;
158
+					} else targetRate = 1.0f;
159
+
160
+					//rate = moveValueTowards(rate,targetRate,0.001f);
161
+					rate = targetRate;
162
+				}
163
+
164
+			}
165
+
166
+
167
+		}
168
+
169
+		void dequeue(int16_t& left, int16_t& right)
170
+		{
171
+			left = right = 0;
172
+			addStatistic();
173
+			if(size==0) { return; }
174
+			cursor += rate;
175
+			while(cursor>1.0f) {
176
+				cursor -= 1.0f;
177
+				if(size>0) {
178
+					curr[0] = buffer.front(); buffer.pop();
179
+					curr[1] = buffer.front(); buffer.pop();
180
+					size--;
181
+				}
182
+			}
183
+			left = curr[0];
184
+			right = curr[1];
185
+		}
186
+	} adjustobuf;
187
+};
188
+
189
+class NitsujaSynchronizer : public ISynchronizingAudioBuffer
190
+{
191
+private:
192
+	struct ssamp
193
+	{
194
+		int16_t l, r;
195
+		ssamp() {}
196
+		ssamp(int16_t ll, int16_t rr) : l(ll), r(rr) {}
197
+	};
198
+
199
+	std::vector<ssamp> sampleQueue;
200
+
201
+	// returns values going between 0 and y-1 in a saw wave pattern, based on x
202
+	static inline int pingpong(int x, int y)
203
+	{
204
+		x %= 2*y;
205
+		if(x >= y)
206
+			x = 2*y - x - 1;
207
+		return x;
208
+
209
+		// in case we want to switch to odd buffer sizes for more sharpness
210
+		//x %= 2*(y-1);
211
+		//if(x >= y)
212
+		//	x = 2*(y-1) - x;
213
+		//return x;
214
+	}
215
+
216
+	static inline ssamp crossfade (ssamp lhs, ssamp rhs,  int cur, int start, int end)
217
+	{
218
+		if(cur <= start)
219
+			return lhs;
220
+		if(cur >= end)
221
+			return rhs;
222
+
223
+		// in case we want sine wave interpolation instead of linear here
224
+		//float ang = 3.14159f * (float)(cur - start) / (float)(end - start);
225
+		//cur = start + (int)((1-cosf(ang))*0.5f * (end - start));
226
+
227
+		int inNum = cur - start;
228
+		int outNum = end - cur;
229
+		int denom = end - start;
230
+
231
+		int lrv = ((int)lhs.l * outNum + (int)rhs.l * inNum) / denom;
232
+		int rrv = ((int)lhs.r * outNum + (int)rhs.r * inNum) / denom;
233
+
234
+		return ssamp(lrv,rrv);
235
+	}
236
+
237
+	static inline void emit_sample(int16_t*& outbuf, ssamp sample)
238
+	{
239
+		*outbuf++ = sample.l;
240
+		*outbuf++ = sample.r;
241
+	}
242
+
243
+	static inline void emit_samples(int16_t*& outbuf, const ssamp* samplebuf, int samples)
244
+	{
245
+		for(int i=0;i<samples;i++)
246
+			emit_sample(outbuf,samplebuf[i]);
247
+	}
248
+
249
+public:
250
+	NitsujaSynchronizer()
251
+	{}
252
+
253
+	virtual void enqueue_samples(int16_t* buf, int samples_provided)
254
+	{
255
+		for(int i=0;i<samples_provided;i++)
256
+		{
257
+			sampleQueue.push_back(ssamp(buf[0],buf[1]));
258
+			buf += 2;
259
+		}
260
+	}
261
+
262
+	virtual int output_samples(int16_t* buf, int samples_requested)
263
+	{
264
+		int audiosize = samples_requested;
265
+		int queued = sampleQueue.size();
266
+
267
+		// I am too lazy to deal with odd numbers
268
+		audiosize &= ~1;
269
+		queued &= ~1;
270
+
271
+		if(queued > 0x200 && audiosize > 0) // is there any work to do?
272
+		{
273
+			// are we going at normal speed?
274
+			// or more precisely, are the input and output queues/buffers of similar size?
275
+			if(queued > 900 || audiosize > queued * 2)
276
+			{
277
+				// not normal speed. we have to resample it somehow in this case.
278
+				if(audiosize <= queued)
279
+				{
280
+					// fast forward speed
281
+					// this is the easy case, just crossfade it and it sounds ok
282
+					for(int i = 0; i < audiosize; i++)
283
+					{
284
+						int j = i + queued - audiosize;
285
+						ssamp outsamp = crossfade(sampleQueue[i],sampleQueue[j], i,0,audiosize);
286
+						emit_sample(buf,outsamp);
287
+					}
288
+				}
289
+				else
290
+				{
291
+					// slow motion speed
292
+					// here we take a very different approach,
293
+					// instead of crossfading it, we select a single sample from the queue
294
+					// and make sure that the index we use to select a sample is constantly moving
295
+					// and that it starts at the first sample in the queue and ends on the last one.
296
+					//
297
+					// hopefully the index doesn't move discontinuously or we'll get slight crackling
298
+					// (there might still be a minor bug here that causes this occasionally)
299
+					//
300
+					// here's a diagram of how the index we sample from moves:
301
+					//
302
+					// queued (this axis represents the index we sample from. the top means the end of the queue)
303
+					// ^
304
+					// |   --> audiosize (this axis represents the output index we write to, right meaning forward in output time/position)
305
+					// |   A           C       C  end
306
+					//    A A     B   C C     C
307
+					//   A   A   A B C   C   C
308
+					//  A     A A   B     C C
309
+					// A       A           C
310
+					// start
311
+					//
312
+					// yes, this means we are spending some stretches of time playing the sound backwards,
313
+					// but the stretches are short enough that this doesn't sound weird.
314
+					// this lets us avoid most crackling problems due to the endpoints matching up.
315
+
316
+					// first calculate a shorter-than-full window
317
+					// that has minimal slope at the endpoints
318
+					// (to further reduce crackling, especially in sine waves)
319
+					int beststart = 0, extraAtEnd = 0;
320
+					{
321
+						int bestend = queued;
322
+						static const int worstdiff = 99999999;
323
+						int beststartdiff = worstdiff;
324
+						int bestenddiff = worstdiff;
325
+						for(int i = 0; i < 128; i+=2)
326
+						{
327
+							int diff = abs(sampleQueue[i].l - sampleQueue[i+1].l) + abs(sampleQueue[i].r - sampleQueue[i+1].r);
328
+							if(diff < beststartdiff)
329
+							{
330
+								beststartdiff = diff;
331
+								beststart = i;
332
+							}
333
+						}
334
+						for(int i = queued-3; i > queued-3-128; i-=2)
335
+						{
336
+							int diff = abs(sampleQueue[i].l - sampleQueue[i+1].l) + abs(sampleQueue[i].r - sampleQueue[i+1].r);
337
+							if(diff < bestenddiff)
338
+							{
339
+								bestenddiff = diff;
340
+								bestend = i+1;
341
+							}
342
+						}
343
+
344
+						extraAtEnd = queued - bestend;
345
+						queued = bestend - beststart;
346
+
347
+						int oksize = queued;
348
+						while(oksize + queued*2 + beststart + extraAtEnd <= samples_requested)
349
+							oksize += queued*2;
350
+						audiosize = oksize;
351
+
352
+						for(int x = 0; x < beststart; x++)
353
+						{
354
+							emit_sample(buf,sampleQueue[x]);
355
+						}
356
+						sampleQueue.erase(sampleQueue.begin(), sampleQueue.begin() + beststart);
357
+					}
358
+
359
+
360
+					int midpointX = audiosize >> 1;
361
+					int midpointY = queued >> 1;
362
+
363
+					// all we need to do here is calculate the X position of the leftmost "B" in the above diagram.
364
+					// TODO: we should calculate it with a simple equation like
365
+					//   midpointXOffset = min(something,somethingElse);
366
+					// but it's a little difficult to work it out exactly
367
+					// so here's a stupid search for the value for now:
368
+
369
+					int prevA = 999999;
370
+					int midpointXOffset = queued/2;
371
+					while(true)
372
+					{
373
+						int a = abs(pingpong(midpointX - midpointXOffset, queued) - midpointY) - midpointXOffset;
374
+						if(((a > 0) != (prevA > 0) || (a < 0) != (prevA < 0)) && prevA != 999999)
375
+						{
376
+							if((a + prevA)&1) // there's some sort of off-by-one problem with this search since we're moving diagonally...
377
+								midpointXOffset++; // but this fixes it most of the time...
378
+							break; // found it
379
+						}
380
+						prevA = a;
381
+						midpointXOffset--;
382
+						if(midpointXOffset < 0)
383
+						{
384
+							midpointXOffset = 0;
385
+							break; // failed to find it. the two sides probably meet exactly in the center.
386
+						}
387
+					}
388
+
389
+					int leftMidpointX = midpointX - midpointXOffset;
390
+					int rightMidpointX = midpointX + midpointXOffset;
391
+					int leftMidpointY = pingpong(leftMidpointX, queued);
392
+					int rightMidpointY = (queued-1) - pingpong((int)audiosize-1 - rightMidpointX + queued*2, queued);
393
+
394
+					// output the left almost-half of the sound (section "A")
395
+					for(int x = 0; x < leftMidpointX; x++)
396
+					{
397
+						int i = pingpong(x, queued);
398
+						emit_sample(buf,sampleQueue[i]);
399
+					}
400
+
401
+					// output the middle stretch (section "B")
402
+					int y = leftMidpointY;
403
+					int dyMidLeft  = (leftMidpointY  < midpointY) ? 1 : -1;
404
+					int dyMidRight = (rightMidpointY > midpointY) ? 1 : -1;
405
+					for(int x = leftMidpointX; x < midpointX; x++, y+=dyMidLeft)
406
+						emit_sample(buf,sampleQueue[y]);
407
+					for(int x = midpointX; x < rightMidpointX; x++, y+=dyMidRight)
408
+						emit_sample(buf,sampleQueue[y]);
409
+
410
+					// output the end of the queued sound (section "C")
411
+					for(int x = rightMidpointX; x < audiosize; x++)
412
+					{
413
+						int i = (queued-1) - pingpong((int)audiosize-1 - x + queued*2, queued);
414
+						emit_sample(buf,sampleQueue[i]);
415
+					}
416
+
417
+					for(int x = 0; x < extraAtEnd; x++)
418
+					{
419
+						int i = queued + x;
420
+						emit_sample(buf,sampleQueue[i]);
421
+					}
422
+					queued += extraAtEnd;
423
+					audiosize += beststart + extraAtEnd;
424
+				} //end else
425
+
426
+				sampleQueue.erase(sampleQueue.begin(), sampleQueue.begin() + queued);
427
+				return audiosize;
428
+			}
429
+			else
430
+			{
431
+				// normal speed
432
+				// just output the samples straightforwardly.
433
+				//
434
+				// at almost-full speeds (like 50/60 FPS)
435
+				// what will happen is that we rapidly fluctuate between entering this branch
436
+				// and entering the "slow motion speed" branch above.
437
+				// but that's ok! because all of these branches sound similar enough that we can get away with it.
438
+				// so the two cases actually complement each other.
439
+
440
+				if(audiosize >= queued)
441
+				{
442
+					emit_samples(buf,&sampleQueue[0],queued);
443
+					sampleQueue.erase(sampleQueue.begin(), sampleQueue.begin() + queued);
444
+					return queued;
445
+				}
446
+				else
447
+				{
448
+					emit_samples(buf,&sampleQueue[0],audiosize);
449
+					sampleQueue.erase(sampleQueue.begin(), sampleQueue.begin()+audiosize);
450
+					return audiosize;
451
+				}
452
+
453
+			} //end normal speed
454
+
455
+		} //end if there is any work to do
456
+		else
457
+		{
458
+			return 0;
459
+		}
460
+
461
+	} //output_samples
462
+
463
+private:
464
+
465
+}; //NitsujaSynchronizer
466
+
467
+#ifdef _MSC_VER
468
+class PCSX2Synchronizer : public ISynchronizingAudioBuffer
469
+{
470
+public:
471
+	std::queue<int16_t> readySamples;
472
+	PCSX2Synchronizer()
473
+	{
474
+		SndBuffer::Init();
475
+	}
476
+	virtual void enqueue_samples(int16_t* buf, int samples_provided)
477
+	{
478
+		for(int i=0;i<samples_provided;i++)
479
+		{
480
+			StereoOut32 so32(buf[0],buf[1]);
481
+			SndBuffer::Write(so32);
482
+			buf++;
483
+			buf++;
484
+		}
485
+	}
486
+
487
+	virtual int output_samples(int16_t* buf, int samples_requested)
488
+	{
489
+		for(int i=0;i<samples_requested;i++) {
490
+			if(readySamples.size()==0) {
491
+				//SndOutPacketSize
492
+				StereoOut16 temp[SndOutPacketSize*2];
493
+				SndBuffer::ReadSamples( temp );
494
+				for(int i=0;i<SndOutPacketSize;i++) {
495
+					readySamples.push(temp[i].Left);
496
+					readySamples.push(temp[i].Right);
497
+				}
498
+			}
499
+			*buf++ = readySamples.front(); readySamples.pop();
500
+			*buf++ = readySamples.front(); readySamples.pop();
501
+		}
502
+		return samples_requested;
503
+	}
504
+};
505
+#endif
506
+
507
+ISynchronizingAudioBuffer* metaspu_construct(ESynchMethod method)
508
+{
509
+	switch(method)
510
+	{
511
+	case ESynchMethod_N: return new NitsujaSynchronizer();
512
+	case ESynchMethod_Z: return new ZeromusSynchronizer();
513
+	#ifdef _MSC_VER
514
+	case ESynchMethod_P: return new PCSX2Synchronizer();
515
+	#endif
516
+	default: return NULL;
517
+	}
518
+}