Browse code

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

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

Naram Qashat authored on 2014/09/17 19:51:45
Showing 1 changed files
... ...
@@ -6,6 +6,7 @@
6 6
 #include "../apu/Gb_Apu.h"
7 7
 #include "../apu/Multi_Buffer.h"
8 8
 #include "../common/SoundDriver.h"
9
+#include "XSFCommon.h"
9 10
 
10 11
 extern SoundDriver *systemSoundInit();
11 12
 
... ...
@@ -117,7 +118,7 @@ void Gba_Pcm::apply_control(int idx)
117 118
 				// base filtering on how long since last sample was output
118 119
 				int32_t period = time - this->last_time;
119 120
 
120
-				int idx = period / 512;
121
+				idx = period / 512;
121 122
 				if (idx >= 3)
122 123
 					idx = 3;
123 124
 
... ...
@@ -189,11 +190,11 @@ void Gba_Pcm_Fifo::timer_overflowed(int which_timer)
189 190
 			if (!this->count)
190 191
 			{
191 192
 				// Not filled by DMA, so fill with 16 bytes of silence
192
-				int reg = this->which ? FIFOB_L : FIFOA_L;
193
+				int regi = this->which ? FIFOB_L : FIFOA_L;
193 194
 				for (int n = 8; n--; )
194 195
 				{
195
-					soundEvent(reg, static_cast<uint16_t>(0));
196
-					soundEvent(reg + 2, static_cast<uint16_t>(0));
196
+					soundEvent(regi, static_cast<uint16_t>(0));
197
+					soundEvent(regi + 2, static_cast<uint16_t>(0));
197 198
 				}
198 199
 			}
199 200
 		}
... ...
@@ -393,10 +394,10 @@ void psoundTickfn()
393 394
 
394 395
 		flush_samples(stereo_buffer.get());
395 396
 
396
-		if (soundFiltering_ != soundFiltering)
397
+		if (!fEqual(soundFiltering_, soundFiltering))
397 398
 			apply_filtering();
398 399
 
399
-		if (soundVolume_ != soundVolume)
400
+		if (!fEqual(soundVolume_, soundVolume))
400 401
 			apply_volume();
401 402
 	}
402 403
 }
... ...
@@ -412,10 +413,12 @@ static void apply_muting()
412 413
 	if (gb_apu)
413 414
 		// APU
414 415
 		for (int i = 0; i < 4; ++i)
416
+		{
415 417
 			if (soundEnableFlag >> i & 1)
416 418
 				gb_apu->set_output(stereo_buffer->center(), stereo_buffer->left(), stereo_buffer->right(), i);
417 419
 			else
418 420
 				gb_apu->set_output(nullptr, nullptr, nullptr, i);
421
+		}
419 422
 }
420 423
 
421 424
 static void reset_apu()
Browse code

[GSF] Copied a few things from kode54's viogsf.

Naram Qashat authored on 2014/09/15 14:27:18
Showing 1 changed files
... ...
@@ -115,7 +115,7 @@ void Gba_Pcm::apply_control(int idx)
115 115
 			if (soundInterpolation)
116 116
 			{
117 117
 				// base filtering on how long since last sample was output
118
-				int period = time - this->last_time;
118
+				int32_t period = time - this->last_time;
119 119
 
120 120
 				int idx = period / 512;
121 121
 				if (idx >= 3)
... ...
@@ -158,7 +158,7 @@ void Gba_Pcm::update(int dac)
158 158
 			if (soundInterpolation)
159 159
 			{
160 160
 				// base filtering on how long since last sample was output
161
-				int period = time - this->last_time;
161
+				int32_t period = time - this->last_time;
162 162
 
163 163
 				int idx = period / 512;
164 164
 				if (idx >= 3)
... ...
@@ -350,22 +350,21 @@ void flush_samples(Multi_Buffer *buffer)
350 350
 	// that don't use the length parameter of the write method.
351 351
 	// TODO: Update the Win32 audio drivers (DS, OAL, XA2), and flush all the
352 352
 	// samples at once to help reducing the audio delay on all platforms.
353
-	int soundBufferLen = (soundSampleRate / 60) * 4;
353
+	int32_t soundBufferLen = (soundSampleRate / 60) * 4;
354 354
 
355 355
 	// soundBufferLen should have a whole number of sample pairs
356 356
 	assert(!(soundBufferLen % (2 * sizeof(*soundFinalWave))));
357 357
 
358 358
 	// number of samples in output buffer
359
-	int out_buf_size = soundBufferLen / sizeof(*soundFinalWave);
359
+	int32_t out_buf_size = soundBufferLen / sizeof(*soundFinalWave);
360 360
 
361
-	// Keep filling and writing soundFinalWave until it can't be fully filled
362
-	while (buffer->samples_avail() >= out_buf_size)
361
+	while (buffer->samples_avail())
363 362
 	{
364
-		buffer->read_samples(reinterpret_cast<blip_sample_t *>(soundFinalWave), out_buf_size);
363
+		long samples_read = buffer->read_samples(reinterpret_cast<blip_sample_t *>(soundFinalWave), out_buf_size);
365 364
 		if (soundPaused)
366 365
 			soundResume();
367 366
 
368
-		soundDriver->write(soundFinalWave, soundBufferLen);
367
+		soundDriver->write(soundFinalWave, samples_read * sizeof(*soundFinalWave));
369 368
 	}
370 369
 }
371 370
 
... ...
@@ -374,11 +373,11 @@ static void apply_filtering()
374 373
 	soundFiltering_ = soundFiltering;
375 374
 
376 375
 	int base_freq = static_cast<int>(32768 - soundFiltering_ * 16384);
377
-	int nyquist = stereo_buffer->sample_rate() / 2;
376
+	int32_t nyquist = stereo_buffer->sample_rate() / 2;
378 377
 
379 378
 	for (int i = 0; i < 3; ++i)
380 379
 	{
381
-		int cutoff = base_freq >> i;
380
+		int32_t cutoff = base_freq >> i;
382 381
 		if (cutoff > nyquist)
383 382
 			cutoff = nyquist;
384 383
 		pcm_synth[i].treble_eq(blip_eq_t(0, 0, stereo_buffer->sample_rate(), cutoff));
... ...
@@ -400,8 +399,6 @@ void psoundTickfn()
400 399
 		if (soundVolume_ != soundVolume)
401 400
 			apply_volume();
402 401
 	}
403
-
404
-	ioMem[NR52] = (ioMem[NR52] & 0x80) | (gb_apu->read_status() & 0x7f);
405 402
 }
406 403
 
407 404
 static void apply_muting()
... ...
@@ -423,8 +420,11 @@ static void apply_muting()
423 420
 
424 421
 static void reset_apu()
425 422
 {
426
-	gb_apu->reduce_clicks(true);
427
-	gb_apu->reset(gb_apu->mode_agb, true);
423
+	if (gb_apu)
424
+	{
425
+		gb_apu->reduce_clicks(true);
426
+		gb_apu->reset(Gb_Apu::mode_agb, true);
427
+	}
428 428
 
429 429
 	if (stereo_buffer)
430 430
 		stereo_buffer->clear();
... ...
@@ -438,23 +438,24 @@ static void remake_stereo_buffer()
438 438
 	pcm[0].pcm.init();
439 439
 	pcm[1].pcm.init();
440 440
 
441
-	// APU
442
-	if (!gb_apu)
443
-	{
444
-		gb_apu.reset(new Gb_Apu); // TODO: handle out of memory
445
-		reset_apu();
446
-	}
447
-
448 441
 	// Stereo_Buffer
449 442
 	stereo_buffer.reset(new Stereo_Buffer); // TODO: handle out of memory
450 443
 	stereo_buffer->set_sample_rate(soundSampleRate); // TODO: handle out of memory
451
-	stereo_buffer->clock_rate(gb_apu->clock_rate);
452 444
 
453 445
 	// PCM
454 446
 	pcm[0].which = 0;
455 447
 	pcm[1].which = 1;
456 448
 	apply_filtering();
457 449
 
450
+	// APU
451
+	if (!gb_apu)
452
+	{
453
+		gb_apu.reset(new Gb_Apu); // TODO: handle out of memory
454
+		reset_apu();
455
+		gb_apu->treble_eq(blip_eq_t(0, 0, soundSampleRate, soundSampleRate / 2));
456
+	}
457
+	stereo_buffer->clock_rate(gb_apu->clock_rate);
458
+
458 459
 	// Volume Level
459 460
 	apply_muting();
460 461
 	apply_volume();
Browse code

Updating the VBA-M code to revision 1231.

Naram Qashat authored on 2014/09/08 12:20:28
Showing 1 changed files
... ...
@@ -8,7 +8,6 @@
8 8
 #include "../common/SoundDriver.h"
9 9
 
10 10
 extern SoundDriver *systemSoundInit();
11
-bool soundDeclicking = true;
12 11
 
13 12
 static const uint32_t NR52 = 0x84;
14 13
 
... ...
@@ -20,12 +19,12 @@ static uint16_t soundFinalWave[6400];
20 19
 static long soundSampleRate = 44100;
21 20
 bool soundInterpolation = true;
22 21
 static bool soundPaused = true;
23
-static float soundFiltering = 0.5f; // 0.0 = none, 1.0 = max
22
+static float soundFiltering = 1.0f;
24 23
 int SOUND_CLOCK_TICKS = SOUND_CLOCK_TICKS_;
25 24
 int soundTicks = SOUND_CLOCK_TICKS_;
26 25
 
27 26
 static float soundVolume = 1.0f;
28
-static int soundEnableFlag = 0x30f; // emulator channels enabled
27
+static int soundEnableFlag = 0x3ff; // emulator channels enabled
29 28
 static float soundFiltering_ = -1;
30 29
 static float soundVolume_ = -1;
31 30
 
... ...
@@ -85,11 +84,11 @@ inline void Gba_Pcm::init()
85 84
 
86 85
 void Gba_Pcm::apply_control(int idx)
87 86
 {
88
-	this->shift = (~ioMem[SGCNT0_H] >> (2 + idx)) & 1;
87
+	this->shift = ~ioMem[SGCNT0_H] >> (2 + idx) & 1;
89 88
 
90 89
 	int ch = 0;
91
-	if (((soundEnableFlag >> idx) & 0x100) && (ioMem[NR52] & 0x80))
92
-		ch = (ioMem[SGCNT0_H + 1] >> (idx * 4)) & 3;
90
+	if ((soundEnableFlag >> idx & 0x100) && (ioMem[NR52] & 0x80))
91
+		ch = ioMem[SGCNT0_H + 1] >> (idx * 4) & 3;
93 92
 
94 93
 	Blip_Buffer *out = nullptr;
95 94
 	switch (ch)
... ...
@@ -108,7 +107,7 @@ void Gba_Pcm::apply_control(int idx)
108 107
 	{
109 108
 		if (this->output)
110 109
 		{
111
-			blip_time_t time = blip_time();
110
+			auto time = blip_time();
112 111
 
113 112
 			this->output->set_modified();
114 113
 
... ...
@@ -147,7 +146,7 @@ void Gba_Pcm::update(int dac)
147 146
 {
148 147
 	if (this->output)
149 148
 	{
150
-		blip_time_t time = blip_time();
149
+		auto time = blip_time();
151 150
 
152 151
 		dac = static_cast<int8_t>(dac) >> this->shift;
153 152
 		int delta = dac - this->last_amp;
... ...
@@ -179,15 +178,19 @@ void Gba_Pcm_Fifo::timer_overflowed(int which_timer)
179 178
 {
180 179
 	if (which_timer == this->timer && this->enabled)
181 180
 	{
182
-		if (this->count <= 16)
181
+		/* Mother 3 fix, refined to not break Metroid Fusion */
182
+		if (this->count == 16 || !this->count)
183 183
 		{
184 184
 			// Need to fill FIFO
185
+			int saved_count = this->count;
185 186
 			CPUCheckDMA(3, this->which ? 4 : 2);
186
-			if (this->count <= 16)
187
+			if (!saved_count && this->count == 16)
188
+				CPUCheckDMA(3, this->which ? 4 : 2);
189
+			if (!this->count)
187 190
 			{
188 191
 				// Not filled by DMA, so fill with 16 bytes of silence
189 192
 				int reg = this->which ? FIFOB_L : FIFOA_L;
190
-				for (int n = 4; n--; )
193
+				for (int n = 8; n--; )
191 194
 				{
192 195
 					soundEvent(reg, static_cast<uint16_t>(0));
193 196
 					soundEvent(reg + 2, static_cast<uint16_t>(0));
... ...
@@ -412,7 +415,7 @@ static void apply_muting()
412 415
 	if (gb_apu)
413 416
 		// APU
414 417
 		for (int i = 0; i < 4; ++i)
415
-			if ((soundEnableFlag >> i) & 1)
418
+			if (soundEnableFlag >> i & 1)
416 419
 				gb_apu->set_output(stereo_buffer->center(), stereo_buffer->left(), stereo_buffer->right(), i);
417 420
 			else
418 421
 				gb_apu->set_output(nullptr, nullptr, nullptr, i);
... ...
@@ -420,7 +423,7 @@ static void apply_muting()
420 423
 
421 424
 static void reset_apu()
422 425
 {
423
-	gb_apu->reduce_clicks(soundDeclicking);
426
+	gb_apu->reduce_clicks(true);
424 427
 	gb_apu->reset(gb_apu->mode_agb, true);
425 428
 
426 429
 	if (stereo_buffer)
Browse code

[GSF] Some more code cleanup, also removed a few files that were unneeded.

Naram Qashat authored on 2013/05/16 01:25:34
Showing 1 changed files
... ...
@@ -68,7 +68,7 @@ static Gba_Pcm_Fifo pcm[2];
68 68
 static std::unique_ptr<Gb_Apu> gb_apu;
69 69
 static std::unique_ptr<Stereo_Buffer> stereo_buffer;
70 70
 
71
-static Blip_Synth<blip_best_quality, 1> pcm_synth[3]; // 32 kHz, 16 kHz, 8 kHz
71
+static Blip_Synth<blip_high_quality, 1> pcm_synth[3]; // 32 kHz, 16 kHz, 8 kHz
72 72
 
73 73
 static inline blip_time_t blip_time()
74 74
 {
Browse code

[GSF] Massive code cleanup.

(As an aside, blargg's code style makes me go blarg myself.)

Naram Qashat authored on 2013/05/14 01:07:18
Showing 1 changed files
... ...
@@ -1,275 +1,268 @@
1
-#include <string.h>
2
-
1
+#include <memory>
3 2
 #include "Sound.h"
4
-
5 3
 #include "GBA.h"
6 4
 #include "Globals.h"
7
-//#include "../Util.h"
8 5
 #include "../common/Port.h"
9
-
10 6
 #include "../apu/Gb_Apu.h"
11 7
 #include "../apu/Multi_Buffer.h"
12
-
13 8
 #include "../common/SoundDriver.h"
14 9
 
15 10
 extern SoundDriver *systemSoundInit();
16 11
 bool soundDeclicking = true;
17 12
 
18
-#define NR10 0x60
19
-#define NR11 0x62
20
-#define NR12 0x63
21
-#define NR13 0x64
22
-#define NR14 0x65
23
-#define NR21 0x68
24
-#define NR22 0x69
25
-#define NR23 0x6c
26
-#define NR24 0x6d
27
-#define NR30 0x70
28
-#define NR31 0x72
29
-#define NR32 0x73
30
-#define NR33 0x74
31
-#define NR34 0x75
32
-#define NR41 0x78
33
-#define NR42 0x79
34
-#define NR43 0x7c
35
-#define NR44 0x7d
36
-#define NR50 0x80
37
-#define NR51 0x81
38
-#define NR52 0x84
39
-
40
-SoundDriver * soundDriver = 0;
41
-
42
-extern bool stopState;      // TODO: silence sound when true
43
-
44
-int const SOUND_CLOCK_TICKS_ = 167772; // 1/100 second
45
-
46
-static uint16_t   soundFinalWave [6400];
47
-long  soundSampleRate    = 44100;
48
-bool  soundInterpolation = true;
49
-bool  soundPaused        = true;
50
-float soundFiltering     = 0.5f;
51
-int   SOUND_CLOCK_TICKS  = SOUND_CLOCK_TICKS_;
52
-int   soundTicks         = SOUND_CLOCK_TICKS_;
53
-
54
-static float soundVolume     = 1.0f;
55
-static int soundEnableFlag   = 0x3ff; // emulator channels enabled
56
-static float soundFiltering_ = -1;
57
-static float soundVolume_    = -1;
13
+static const uint32_t NR52 = 0x84;
14
+
15
+static std::unique_ptr<SoundDriver> soundDriver;
58 16
 
59
-void interp_rate() { /* empty for now */ }
17
+static const int SOUND_CLOCK_TICKS_ = 167772; // 1/100 second
60 18
 
61
-class Gba_Pcm {
19
+static uint16_t soundFinalWave[6400];
20
+static long soundSampleRate = 44100;
21
+bool soundInterpolation = true;
22
+static bool soundPaused = true;
23
+static float soundFiltering = 0.5f; // 0.0 = none, 1.0 = max
24
+int SOUND_CLOCK_TICKS = SOUND_CLOCK_TICKS_;
25
+int soundTicks = SOUND_CLOCK_TICKS_;
26
+
27
+static float soundVolume = 1.0f;
28
+static int soundEnableFlag = 0x30f; // emulator channels enabled
29
+static float soundFiltering_ = -1;
30
+static float soundVolume_ = -1;
31
+
32
+class Gba_Pcm
33
+{
62 34
 public:
63 35
 	void init();
64
-	void apply_control( int idx );
65
-	void update( int dac );
66
-	void end_frame( blip_time_t );
36
+	void apply_control(int idx);
37
+	void update(int dac);
38
+	void end_frame(blip_time_t);
67 39
 
68 40
 private:
69
-	Blip_Buffer* output;
41
+	Blip_Buffer *output;
70 42
 	blip_time_t last_time;
71 43
 	int last_amp;
72 44
 	int shift;
73 45
 };
74 46
 
75
-class Gba_Pcm_Fifo {
47
+class Gba_Pcm_Fifo
48
+{
76 49
 public:
77
-	int     which;
50
+	int which;
78 51
 	Gba_Pcm pcm;
79 52
 
80
-	void write_control( int data );
81
-	void write_fifo( int data );
82
-	void timer_overflowed( int which_timer );
53
+	void write_control(int data);
54
+	void write_fifo(int data);
55
+	void timer_overflowed(int which_timer);
83 56
 
84
-	// public only so save state routines can access it
85
-	int  readIndex;
86
-	int  count;
87
-	int  writeIndex;
88
-	uint8_t   fifo [32];
89
-	int  dac;
90 57
 private:
91
-
92
-	int  timer;
58
+	int readIndex;
59
+	int count;
60
+	int writeIndex;
61
+	uint8_t fifo[32];
62
+	int dac;
63
+	int timer;
93 64
 	bool enabled;
94 65
 };
95 66
 
96
-static Gba_Pcm_Fifo     pcm [2];
97
-static Gb_Apu*          gb_apu;
98
-static Stereo_Buffer*   stereo_buffer;
67
+static Gba_Pcm_Fifo pcm[2];
68
+static std::unique_ptr<Gb_Apu> gb_apu;
69
+static std::unique_ptr<Stereo_Buffer> stereo_buffer;
99 70
 
100
-static Blip_Synth<blip_best_quality,1> pcm_synth [3]; // 32 kHz, 16 kHz, 8 kHz
71
+static Blip_Synth<blip_best_quality, 1> pcm_synth[3]; // 32 kHz, 16 kHz, 8 kHz
101 72
 
102 73
 static inline blip_time_t blip_time()
103 74
 {
104 75
 	return SOUND_CLOCK_TICKS - soundTicks;
105 76
 }
106 77
 
107
-void Gba_Pcm::init()
78
+inline void Gba_Pcm::init()
108 79
 {
109
-	output    = 0;
110
-	last_time = 0;
111
-	last_amp  = 0;
112
-	shift     = 0;
80
+	this->output = nullptr;
81
+	this->last_time = 0;
82
+	this->last_amp = 0;
83
+	this->shift = 0;
113 84
 }
114 85
 
115
-void Gba_Pcm::apply_control( int idx )
86
+void Gba_Pcm::apply_control(int idx)
116 87
 {
117
-	shift = ~ioMem [SGCNT0_H] >> (2 + idx) & 1;
88
+	this->shift = (~ioMem[SGCNT0_H] >> (2 + idx)) & 1;
118 89
 
119 90
 	int ch = 0;
120
-	if ( (soundEnableFlag >> idx & 0x100) && (ioMem [NR52] & 0x80) )
121
-		ch = ioMem [SGCNT0_H+1] >> (idx * 4) & 3;
91
+	if (((soundEnableFlag >> idx) & 0x100) && (ioMem[NR52] & 0x80))
92
+		ch = (ioMem[SGCNT0_H + 1] >> (idx * 4)) & 3;
122 93
 
123
-	Blip_Buffer* out = 0;
124
-	switch ( ch )
94
+	Blip_Buffer *out = nullptr;
95
+	switch (ch)
125 96
 	{
126
-	case 1: out = stereo_buffer->right();  break;
127
-	case 2: out = stereo_buffer->left();   break;
128
-	case 3: out = stereo_buffer->center(); break;
97
+		case 1:
98
+			out = stereo_buffer->right();
99
+			break;
100
+		case 2:
101
+			out = stereo_buffer->left();
102
+			break;
103
+		case 3:
104
+			out = stereo_buffer->center();
129 105
 	}
130 106
 
131
-	if ( output != out )
107
+	if (this->output != out)
132 108
 	{
133
-		if ( output )
109
+		if (this->output)
134 110
 		{
135
-			output->set_modified();
136
-			pcm_synth [0].offset( blip_time(), -last_amp, output );
111
+			blip_time_t time = blip_time();
112
+
113
+			this->output->set_modified();
114
+
115
+			int filter = 0;
116
+			if (soundInterpolation)
117
+			{
118
+				// base filtering on how long since last sample was output
119
+				int period = time - this->last_time;
120
+
121
+				int idx = period / 512;
122
+				if (idx >= 3)
123
+					idx = 3;
124
+
125
+				static const int filters[] = { 0, 0, 1, 2 };
126
+				filter = filters[idx];
127
+			}
128
+
129
+			pcm_synth[filter].offset(time, -this->last_amp, this->output);
137 130
 		}
138
-		last_amp = 0;
139
-		output = out;
131
+		this->last_amp = 0;
132
+		this->output = out;
140 133
 	}
141 134
 }
142 135
 
143
-void Gba_Pcm::end_frame( blip_time_t time )
136
+inline void Gba_Pcm::end_frame(blip_time_t time)
144 137
 {
145
-	last_time -= time;
146
-	if ( last_time < -2048 )
147
-		last_time = -2048;
138
+	this->last_time -= time;
139
+	if (this->last_time < -2048)
140
+		this->last_time = -2048;
148 141
 
149
-	if ( output )
150
-		output->set_modified();
142
+	if (this->output)
143
+		this->output->set_modified();
151 144
 }
152 145
 
153
-void Gba_Pcm::update( int dac )
146
+void Gba_Pcm::update(int dac)
154 147
 {
155
-	if ( output )
148
+	if (this->output)
156 149
 	{
157 150
 		blip_time_t time = blip_time();
158 151
 
159
-		dac = (int8_t) dac >> shift;
160
-		int delta = dac - last_amp;
161
-		if ( delta )
152
+		dac = static_cast<int8_t>(dac) >> this->shift;
153
+		int delta = dac - this->last_amp;
154
+		if (delta)
162 155
 		{
163
-			last_amp = dac;
156
+			this->last_amp = dac;
164 157
 
165 158
 			int filter = 0;
166
-			if ( soundInterpolation )
159
+			if (soundInterpolation)
167 160
 			{
168 161
 				// base filtering on how long since last sample was output
169
-				int period = time - last_time;
162
+				int period = time - this->last_time;
170 163
 
171
-				int idx = (unsigned) period / 512;
172
-				if ( idx >= 3 )
164
+				int idx = period / 512;
165
+				if (idx >= 3)
173 166
 					idx = 3;
174 167
 
175
-				static int const filters [4] = { 0, 0, 1, 2 };
176
-				filter = filters [idx];
168
+				static const int filters[] = { 0, 0, 1, 2 };
169
+				filter = filters[idx];
177 170
 			}
178 171
 
179
-			pcm_synth [filter].offset( time, delta, output );
172
+			pcm_synth[filter].offset(time, delta, this->output);
180 173
 		}
181
-		last_time = time;
174
+		this->last_time = time;
182 175
 	}
183 176
 }
184 177
 
185
-void Gba_Pcm_Fifo::timer_overflowed( int which_timer )
178
+void Gba_Pcm_Fifo::timer_overflowed(int which_timer)
186 179
 {
187
-	if ( which_timer == timer && enabled )
180
+	if (which_timer == this->timer && this->enabled)
188 181
 	{
189
-		if ( count <= 16 )
182
+		if (this->count <= 16)
190 183
 		{
191 184
 			// Need to fill FIFO
192
-			CPUCheckDMA( 3, which ? 4 : 2 );
193
-			if ( count <= 16 )
185
+			CPUCheckDMA(3, this->which ? 4 : 2);
186
+			if (this->count <= 16)
194 187
 			{
195 188
 				// Not filled by DMA, so fill with 16 bytes of silence
196
-				int reg = which ? FIFOB_L : FIFOA_L;
197
-				for ( int n = 4; n--; )
189
+				int reg = this->which ? FIFOB_L : FIFOA_L;
190
+				for (int n = 4; n--; )
198 191
 				{
199
-					soundEvent(reg  , (uint16_t)0);
200
-					soundEvent(reg+2, (uint16_t)0);
192
+					soundEvent(reg, static_cast<uint16_t>(0));
193
+					soundEvent(reg + 2, static_cast<uint16_t>(0));
201 194
 				}
202 195
 			}
203 196
 		}
204 197
 
205 198
 		// Read next sample from FIFO
206
-		count--;
207
-		dac = fifo [readIndex];
208
-		readIndex = (readIndex + 1) & 31;
209
-		pcm.update( dac );
199
+		--this->count;
200
+		this->dac = this->fifo[this->readIndex];
201
+		this->readIndex = (this->readIndex + 1) & 31;
202
+		this->pcm.update(this->dac);
210 203
 	}
211 204
 }
212 205
 
213
-void Gba_Pcm_Fifo::write_control( int data )
206
+void Gba_Pcm_Fifo::write_control(int data)
214 207
 {
215
-	enabled = (data & 0x0300) ? true : false;
216
-	timer   = (data & 0x0400) ? 1 : 0;
208
+	this->enabled = !!(data & 0x0300);
209
+	this->timer = !!(data & 0x0400);
217 210
 
218
-	if ( data & 0x0800 )
211
+	if (data & 0x0800)
219 212
 	{
220 213
 		// Reset
221
-		writeIndex = 0;
222
-		readIndex  = 0;
223
-		count      = 0;
224
-		dac        = 0;
225
-		memset( fifo, 0, sizeof fifo );
214
+		this->writeIndex = 0;
215
+		this->readIndex = 0;
216
+		this->count = 0;
217
+		this->dac = 0;
218
+		memset(this->fifo, 0, sizeof(this->fifo));
226 219
 	}
227 220
 
228
-	pcm.apply_control( which );
229
-	pcm.update( dac );
221
+	this->pcm.apply_control(this->which);
222
+	this->pcm.update(this->dac);
230 223
 }
231 224
 
232
-void Gba_Pcm_Fifo::write_fifo( int data )
225
+inline void Gba_Pcm_Fifo::write_fifo(int data)
233 226
 {
234
-	fifo [writeIndex  ] = data & 0xFF;
235
-	fifo [writeIndex+1] = data >> 8;
236
-	count += 2;
237
-	writeIndex = (writeIndex + 2) & 31;
227
+	this->fifo[this->writeIndex] = data & 0xFF;
228
+	this->fifo[this->writeIndex + 1] = data >> 8;
229
+	this->count += 2;
230
+	this->writeIndex = (this->writeIndex + 2) & 31;
238 231
 }
239 232
 
240 233
 static void apply_control()
241 234
 {
242
-	pcm [0].pcm.apply_control( 0 );
243
-	pcm [1].pcm.apply_control( 1 );
235
+	pcm[0].pcm.apply_control(0);
236
+	pcm[1].pcm.apply_control(1);
244 237
 }
245 238
 
246
-static int gba_to_gb_sound( int addr )
239
+static int gba_to_gb_sound(int addr)
247 240
 {
248
-	static const int table [0x40] =
241
+	static const int table[] =
249 242
 	{
250
-		0xFF10,     0,0xFF11,0xFF12,0xFF13,0xFF14,     0,     0,
251
-		0xFF16,0xFF17,     0,     0,0xFF18,0xFF19,     0,     0,
252
-		0xFF1A,     0,0xFF1B,0xFF1C,0xFF1D,0xFF1E,     0,     0,
253
-		0xFF20,0xFF21,     0,     0,0xFF22,0xFF23,     0,     0,
254
-		0xFF24,0xFF25,     0,     0,0xFF26,     0,     0,     0,
255
-		     0,     0,     0,     0,     0,     0,     0,     0,
256
-		0xFF30,0xFF31,0xFF32,0xFF33,0xFF34,0xFF35,0xFF36,0xFF37,
257
-		0xFF38,0xFF39,0xFF3A,0xFF3B,0xFF3C,0xFF3D,0xFF3E,0xFF3F,
243
+		0xFF10, 0, 0xFF11, 0xFF12, 0xFF13, 0xFF14, 0, 0,
244
+		0xFF16, 0xFF17, 0, 0, 0xFF18, 0xFF19, 0, 0,
245
+		0xFF1A, 0, 0xFF1B, 0xFF1C, 0xFF1D, 0xFF1E, 0, 0,
246
+		0xFF20, 0xFF21, 0, 0, 0xFF22, 0xFF23, 0, 0,
247
+		0xFF24, 0xFF25, 0, 0, 0xFF26, 0, 0, 0,
248
+		0, 0, 0, 0, 0, 0, 0, 0,
249
+		0xFF30, 0xFF31, 0xFF32, 0xFF33, 0xFF34, 0xFF35, 0xFF36, 0xFF37,
250
+		0xFF38, 0xFF39, 0xFF3A, 0xFF3B, 0xFF3C, 0xFF3D, 0xFF3E, 0xFF3F,
258 251
 	};
259
-	if ( addr >= 0x60 && addr < 0xA0 )
260
-		return table [addr - 0x60];
252
+	if (addr >= 0x60 && addr < 0xA0)
253
+		return table[addr - 0x60];
261 254
 	return 0;
262 255
 }
263 256
 
264 257
 void soundEvent(uint32_t address, uint8_t data)
265 258
 {
266
-	int gb_addr = gba_to_gb_sound( address );
267
-	if ( gb_addr )
259
+	int gb_addr = gba_to_gb_sound(address);
260
+	if (gb_addr)
268 261
 	{
269 262
 		ioMem[address] = data;
270
-		gb_apu->write_register( blip_time(), gb_addr, data );
263
+		gb_apu->write_register(blip_time(), gb_addr, data);
271 264
 
272
-		if ( address == NR52 )
265
+		if (address == NR52)
273 266
 			apply_control();
274 267
 	}
275 268
 
... ...
@@ -278,102 +271,98 @@ void soundEvent(uint32_t address, uint8_t data)
278 271
 	// TODO: what about byte writes to SGCNT0_H etc.?
279 272
 }
280 273
 
281
-static void apply_volume( bool apu_only = false )
274
+static void apply_volume(bool apu_only = false)
282 275
 {
283
-	if ( !apu_only )
276
+	if (!apu_only)
284 277
 		soundVolume_ = soundVolume;
285 278
 
286
-	if ( gb_apu )
279
+	if (gb_apu)
287 280
 	{
288
-		static float const apu_vols [4] = { 0.25, 0.5, 1, 0.25 };
289
-		gb_apu->volume( soundVolume_ * apu_vols [ioMem [SGCNT0_H] & 3] );
281
+		static const float apu_vols[] = { 0.25, 0.5, 1, 0.25 };
282
+		gb_apu->volume(soundVolume_ * apu_vols[ioMem[SGCNT0_H] & 3]);
290 283
 	}
291 284
 
292
-	if ( !apu_only )
293
-	{
294
-		for ( int i = 0; i < 3; i++ )
295
-			pcm_synth [i].volume( 0.66 / 256 * soundVolume_ );
296
-	}
285
+	if (!apu_only)
286
+		for (int i = 0; i < 3; ++i)
287
+			pcm_synth[i].volume(0.66 / 256 * soundVolume_);
297 288
 }
298 289
 
299
-static void write_SGCNT0_H( int data )
290
+static void write_SGCNT0_H(int data)
300 291
 {
301
-	WRITE16LE( &ioMem [SGCNT0_H], data & 0x770F );
302
-	pcm [0].write_control( data      );
303
-	pcm [1].write_control( data >> 4 );
304
-	apply_volume( true );
292
+	WRITE16LE(&ioMem[SGCNT0_H], data & 0x770F);
293
+	pcm[0].write_control(data);
294
+	pcm[1].write_control(data >> 4);
295
+	apply_volume(true);
305 296
 }
306 297
 
307 298
 void soundEvent(uint32_t address, uint16_t data)
308 299
 {
309
-	switch ( address )
300
+	switch (address)
310 301
 	{
311
-	case SGCNT0_H:
312
-		write_SGCNT0_H( data );
313
-		break;
314
-
315
-	case FIFOA_L:
316
-	case FIFOA_H:
317
-		pcm [0].write_fifo( data );
318
-		WRITE16LE( &ioMem[address], data );
319
-		break;
320
-
321
-	case FIFOB_L:
322
-	case FIFOB_H:
323
-		pcm [1].write_fifo( data );
324
-		WRITE16LE( &ioMem[address], data );
325
-		break;
326
-
327
-	case 0x88:
328
-		data &= 0xC3FF;
329
-		WRITE16LE( &ioMem[address], data );
330
-		break;
331
-
332
-	default:
333
-		soundEvent( address & ~1, (uint8_t) (data     ) ); // even
334
-		soundEvent( address |  1, (uint8_t) (data >> 8) ); // odd
335
-		break;
302
+		case SGCNT0_H:
303
+			write_SGCNT0_H(data);
304
+			break;
305
+
306
+		case FIFOA_L:
307
+		case FIFOA_H:
308
+			pcm[0].write_fifo(data);
309
+			WRITE16LE(&ioMem[address], data);
310
+			break;
311
+
312
+		case FIFOB_L:
313
+		case FIFOB_H:
314
+			pcm[1].write_fifo(data);
315
+			WRITE16LE(&ioMem[address], data);
316
+			break;
317
+
318
+		case 0x88:
319
+			data &= 0xC3FF;
320
+			WRITE16LE(&ioMem[address], data);
321
+			break;
322
+
323
+		default:
324
+			soundEvent(address & ~1, static_cast<uint8_t>(data)); // even
325
+			soundEvent(address | 1, static_cast<uint8_t>(data >> 8)); // odd
336 326
 	}
337 327
 }
338 328
 
339 329
 void soundTimerOverflow(int timer)
340 330
 {
341
-	pcm [0].timer_overflowed( timer );
342
-	pcm [1].timer_overflowed( timer );
331
+	pcm[0].timer_overflowed(timer);
332
+	pcm[1].timer_overflowed(timer);
343 333
 }
344 334
 
345
-static void end_frame( blip_time_t time )
335
+static void end_frame(blip_time_t time)
346 336
 {
347
-	pcm [0].pcm.end_frame( time );
348
-	pcm [1].pcm.end_frame( time );
337
+	pcm[0].pcm.end_frame(time);
338
+	pcm[1].pcm.end_frame(time);
349 339
 
350
-	gb_apu       ->end_frame( time );
351
-	stereo_buffer->end_frame( time );
340
+	gb_apu->end_frame(time);
341
+	stereo_buffer->end_frame(time);
352 342
 }
353 343
 
354
-void flush_samples(Multi_Buffer * buffer)
344
+void flush_samples(Multi_Buffer *buffer)
355 345
 {
356 346
 	// We want to write the data frame by frame to support legacy audio drivers
357 347
 	// that don't use the length parameter of the write method.
358 348
 	// TODO: Update the Win32 audio drivers (DS, OAL, XA2), and flush all the
359 349
 	// samples at once to help reducing the audio delay on all platforms.
360
-	int soundBufferLen = ( soundSampleRate / 60 ) * 4;
350
+	int soundBufferLen = (soundSampleRate / 60) * 4;
361 351
 
362 352
 	// soundBufferLen should have a whole number of sample pairs
363
-	assert( soundBufferLen % (2 * sizeof *soundFinalWave) == 0 );
353
+	assert(!(soundBufferLen % (2 * sizeof(*soundFinalWave))));
364 354
 
365 355
 	// number of samples in output buffer
366
-	int const out_buf_size = soundBufferLen / sizeof *soundFinalWave;
356
+	int out_buf_size = soundBufferLen / sizeof(*soundFinalWave);
367 357
 
368 358
 	// Keep filling and writing soundFinalWave until it can't be fully filled
369
-	while ( buffer->samples_avail() >= out_buf_size )
359
+	while (buffer->samples_avail() >= out_buf_size)
370 360
 	{
371
-		buffer->read_samples( (blip_sample_t*) soundFinalWave, out_buf_size );
372
-		if(soundPaused)
361
+		buffer->read_samples(reinterpret_cast<blip_sample_t *>(soundFinalWave), out_buf_size);
362
+		if (soundPaused)
373 363
 			soundResume();
374 364
 
375 365
 		soundDriver->write(soundFinalWave, soundBufferLen);
376
-		//systemOnWriteDataToSoundBuffer(soundFinalWave, soundBufferLen);
377 366
 	}
378 367
 }
379 368
 
... ...
@@ -381,31 +370,31 @@ static void apply_filtering()
381 370
 {
382 371
 	soundFiltering_ = soundFiltering;
383 372
 
384
-	int const base_freq = (int) (32768 - soundFiltering_ * 16384);
385
-	int const nyquist = stereo_buffer->sample_rate() / 2;
373
+	int base_freq = static_cast<int>(32768 - soundFiltering_ * 16384);
374
+	int nyquist = stereo_buffer->sample_rate() / 2;
386 375
 
387
-	for ( int i = 0; i < 3; i++ )
376
+	for (int i = 0; i < 3; ++i)
388 377
 	{
389 378
 		int cutoff = base_freq >> i;
390
-		if ( cutoff > nyquist )
379
+		if (cutoff > nyquist)
391 380
 			cutoff = nyquist;
392
-		pcm_synth [i].treble_eq( blip_eq_t( 0, 0, stereo_buffer->sample_rate(), cutoff ) );
381
+		pcm_synth[i].treble_eq(blip_eq_t(0, 0, stereo_buffer->sample_rate(), cutoff));
393 382
 	}
394 383
 }
395 384
 
396 385
 void psoundTickfn()
397 386
 {
398
- 	if ( gb_apu && stereo_buffer )
387
+ 	if (gb_apu && stereo_buffer)
399 388
 	{
400 389
 		// Run sound hardware to present
401
-		end_frame( SOUND_CLOCK_TICKS );
390
+		end_frame(SOUND_CLOCK_TICKS);
402 391
 
403
-		flush_samples(stereo_buffer);
392
+		flush_samples(stereo_buffer.get());
404 393
 
405
-		if ( soundFiltering_ != soundFiltering )
394
+		if (soundFiltering_ != soundFiltering)
406 395
 			apply_filtering();
407 396
 
408
-		if ( soundVolume_ != soundVolume )
397
+		if (soundVolume_ != soundVolume)
409 398
 			apply_volume();
410 399
 	}
411 400
 
... ...
@@ -414,32 +403,27 @@ void psoundTickfn()
414 403
 
415 404
 static void apply_muting()
416 405
 {
417
-	if ( !stereo_buffer || !ioMem )
406
+	if (!stereo_buffer)
418 407
 		return;
419 408
 
420 409
 	// PCM
421 410
 	apply_control();
422 411
 
423
-	if ( gb_apu )
424
-	{
412
+	if (gb_apu)
425 413
 		// APU
426
-		for ( int i = 0; i < 4; i++ )
427
-		{
428
-			if ( soundEnableFlag >> i & 1 )
429
-				gb_apu->set_output( stereo_buffer->center(),
430
-						stereo_buffer->left(), stereo_buffer->right(), i );
414
+		for (int i = 0; i < 4; ++i)
415
+			if ((soundEnableFlag >> i) & 1)
416
+				gb_apu->set_output(stereo_buffer->center(), stereo_buffer->left(), stereo_buffer->right(), i);
431 417
 			else
432
-				gb_apu->set_output( 0, 0, 0, i );
433
-		}
434
-	}
418
+				gb_apu->set_output(nullptr, nullptr, nullptr, i);
435 419
 }
436 420
 
437 421
 static void reset_apu()
438 422
 {
439 423
 	gb_apu->reduce_clicks(soundDeclicking);
440
-	gb_apu->reset( gb_apu->mode_agb, true );
424
+	gb_apu->reset(gb_apu->mode_agb, true);
441 425
 
442
-	if ( stereo_buffer )
426
+	if (stereo_buffer)
443 427
 		stereo_buffer->clear();
444 428
 
445 429
 	soundTicks = SOUND_CLOCK_TICKS;
... ...
@@ -447,31 +431,25 @@ static void reset_apu()
447 431
 
448 432
 static void remake_stereo_buffer()
449 433
 {
450
-	if ( !ioMem )
451
-		return;
452
-
453 434
 	// Clears pointers kept to old stereo_buffer
454
-	pcm [0].pcm.init();
455
-	pcm [1].pcm.init();
435
+	pcm[0].pcm.init();
436
+	pcm[1].pcm.init();
456 437
 
457 438
 	// APU
458
-	if ( !gb_apu )
439
+	if (!gb_apu)
459 440
 	{
460
-		gb_apu = new Gb_Apu; // TODO: handle out of memory
441
+		gb_apu.reset(new Gb_Apu); // TODO: handle out of memory
461 442
 		reset_apu();
462 443
 	}
463 444
 
464 445
 	// Stereo_Buffer
465
-	delete stereo_buffer;
466
-	stereo_buffer = 0;
467
-
468
-	stereo_buffer = new Stereo_Buffer; // TODO: handle out of memory
469
-	stereo_buffer->set_sample_rate( soundSampleRate ); // TODO: handle out of memory
470
-	stereo_buffer->clock_rate( gb_apu->clock_rate );
446
+	stereo_buffer.reset(new Stereo_Buffer); // TODO: handle out of memory
447
+	stereo_buffer->set_sample_rate(soundSampleRate); // TODO: handle out of memory
448
+	stereo_buffer->clock_rate(gb_apu->clock_rate);
471 449
 
472 450
 	// PCM
473
-	pcm [0].which = 0;
474
-	pcm [1].which = 1;
451
+	pcm[0].which = 0;
452
+	pcm[1].which = 1;
475 453
 	apply_filtering();
476 454
 
477 455
 	// Volume Level
... ...
@@ -481,27 +459,13 @@ static void remake_stereo_buffer()
481 459
 
482 460
 void soundShutdown()
483 461
 {
484
-	if (soundDriver)
485
-	{
486
-		delete soundDriver;
487
-		soundDriver = 0;
488
-	}
462
+	soundDriver.reset();
489 463
 
490 464
 	// APU
491
-	if ( gb_apu )
492
-	{
493
-		delete gb_apu;
494
-		gb_apu = 0;
495
-	}
465
+	gb_apu.reset();
496 466
 
497 467
 	// Stereo_Buffer
498
-	if (stereo_buffer)
499
-	{
500
-		delete stereo_buffer;
501
-		stereo_buffer = 0;
502
-	}
503
-
504
-	//systemOnSoundShutdown();
468
+	stereo_buffer.reset();
505 469
 }
506 470
 
507 471
 void soundPause()
... ...
@@ -518,27 +482,12 @@ void soundResume()
518 482
 		soundDriver->resume();
519 483
 }
520 484
 
521
-void soundSetVolume( float volume )
522
-{
523
-	soundVolume = volume;
524
-}
525
-
526
-float soundGetVolume()
527
-{
528
-	return soundVolume;
529
-}
530
-
531 485
 void soundSetEnable(int channels)
532 486
 {
533 487
 	soundEnableFlag = channels;
534 488
 	apply_muting();
535 489
 }
536 490
 
537
-int soundGetEnable()
538
-{
539
-	return (soundEnableFlag & 0x30f);
540
-}
541
-
542 491
 void soundReset()
543 492
 {
544 493
 	soundDriver->reset();
... ...
@@ -547,16 +496,15 @@ void soundReset()
547 496
 	reset_apu();
548 497
 
549 498
 	soundPaused = true;
550
-	SOUND_CLOCK_TICKS = SOUND_CLOCK_TICKS_;
551
-	soundTicks        = SOUND_CLOCK_TICKS_;
499
+	SOUND_CLOCK_TICKS = soundTicks = SOUND_CLOCK_TICKS_;
552 500
 
553
-	soundEvent( NR52, (uint8_t) 0x80 );
501
+	soundEvent(NR52, static_cast<uint8_t>(0x80));
554 502
 }
555 503
 
556 504
 bool soundInit()
557 505
 {
558
-	soundDriver = systemSoundInit();
559
-	if ( !soundDriver )
506
+	soundDriver.reset(systemSoundInit());
507
+	if (!soundDriver)
560 508
 		return false;
561 509
 
562 510
 	if (!soundDriver->init(soundSampleRate))
... ...
@@ -566,266 +514,12 @@ bool soundInit()
566 514
 	return true;
567 515
 }
568 516
 
569
-void soundSetThrottle(unsigned short throttle)
570
-{
571
-	if(!soundDriver)
572
-		return;
573
-	soundDriver->setThrottle(throttle);
574
-}
575
-
576
-long soundGetSampleRate()
577
-{
578
-	return soundSampleRate;
579
-}
580
-
581 517
 void soundSetSampleRate(long sampleRate)
582 518
 {
583
-	if ( soundSampleRate != sampleRate )
519
+	if (soundSampleRate != sampleRate)
584 520
 	{
585
-		/*if ( systemCanChangeSoundQuality() )
586
-		{
587
-			soundShutdown();
588
-			soundSampleRate      = sampleRate;
589
-			soundInit();
590
-		}
591
-		else*/
592
-		{
593
-			soundSampleRate      = sampleRate;
594
-		}
521
+		soundSampleRate = sampleRate;
595 522
 
596 523
 		remake_stereo_buffer();
597 524
 	}
598 525
 }
599
-
600
-/*static int dummy_state [16];
601
-
602
-#define SKIP( type, name ) { dummy_state, sizeof (type) }
603
-
604
-#define LOAD( type, name ) { &name, sizeof (type) }
605
-
606
-static struct {
607
-	gb_apu_state_t apu;
608
-
609
-	// old state
610
-	u8 soundDSAValue;
611
-	int soundDSBValue;
612
-} state;
613
-
614
-// Old GBA sound state format
615
-static variable_desc old_gba_state [] =
616
-{
617
-	SKIP( int, soundPaused ),
618
-	SKIP( int, soundPlay ),
619
-	SKIP( int, soundTicks ),
620
-	SKIP( int, SOUND_CLOCK_TICKS ),
621
-	SKIP( int, soundLevel1 ),
622
-	SKIP( int, soundLevel2 ),
623
-	SKIP( int, soundBalance ),
624
-	SKIP( int, soundMasterOn ),
625
-	SKIP( int, soundIndex ),
626
-	SKIP( int, sound1On ),
627
-	SKIP( int, sound1ATL ),
628
-	SKIP( int, sound1Skip ),
629
-	SKIP( int, sound1Index ),
630
-	SKIP( int, sound1Continue ),
631
-	SKIP( int, sound1EnvelopeVolume ),
632
-	SKIP( int, sound1EnvelopeATL ),
633
-	SKIP( int, sound1EnvelopeATLReload ),
634
-	SKIP( int, sound1EnvelopeUpDown ),
635
-	SKIP( int, sound1SweepATL ),
636
-	SKIP( int, sound1SweepATLReload ),
637
-	SKIP( int, sound1SweepSteps ),
638
-	SKIP( int, sound1SweepUpDown ),
639
-	SKIP( int, sound1SweepStep ),
640
-	SKIP( int, sound2On ),
641
-	SKIP( int, sound2ATL ),
642
-	SKIP( int, sound2Skip ),
643
-	SKIP( int, sound2Index ),
644
-	SKIP( int, sound2Continue ),
645
-	SKIP( int, sound2EnvelopeVolume ),
646
-	SKIP( int, sound2EnvelopeATL ),
647
-	SKIP( int, sound2EnvelopeATLReload ),
648
-	SKIP( int, sound2EnvelopeUpDown ),
649
-	SKIP( int, sound3On ),
650
-	SKIP( int, sound3ATL ),
651
-	SKIP( int, sound3Skip ),
652
-	SKIP( int, sound3Index ),
653
-	SKIP( int, sound3Continue ),
654
-	SKIP( int, sound3OutputLevel ),
655
-	SKIP( int, sound4On ),
656
-	SKIP( int, sound4ATL ),
657
-	SKIP( int, sound4Skip ),
658
-	SKIP( int, sound4Index ),
659
-	SKIP( int, sound4Clock ),
660
-	SKIP( int, sound4ShiftRight ),
661
-	SKIP( int, sound4ShiftSkip ),
662
-	SKIP( int, sound4ShiftIndex ),
663
-	SKIP( int, sound4NSteps ),
664
-	SKIP( int, sound4CountDown ),
665
-	SKIP( int, sound4Continue ),
666
-	SKIP( int, sound4EnvelopeVolume ),
667
-	SKIP( int, sound4EnvelopeATL ),
668
-	SKIP( int, sound4EnvelopeATLReload ),
669
-	SKIP( int, sound4EnvelopeUpDown ),
670
-	LOAD( int, soundEnableFlag ),
671
-	SKIP( int, soundControl ),
672
-	LOAD( int, pcm [0].readIndex ),
673
-	LOAD( int, pcm [0].count ),
674
-	LOAD( int, pcm [0].writeIndex ),
675
-	SKIP( u8,  soundDSAEnabled ), // was bool, which was one byte on MS compiler
676
-	SKIP( int, soundDSATimer ),
677
-	LOAD( u8 [32], pcm [0].fifo ),
678
-	LOAD( u8,  state.soundDSAValue ),
679
-	LOAD( int, pcm [1].readIndex ),
680
-	LOAD( int, pcm [1].count ),
681
-	LOAD( int, pcm [1].writeIndex ),
682
-	SKIP( int, soundDSBEnabled ),
683
-	SKIP( int, soundDSBTimer ),
684
-	LOAD( u8 [32], pcm [1].fifo ),
685
-	LOAD( int, state.soundDSBValue ),
686
-
687
-	// skipped manually
688
-	//LOAD( int, soundBuffer[0][0], 6*735 },
689
-	//LOAD( int, soundFinalWave[0], 2*735 },
690
-	{ NULL, 0 }
691
-};
692
-
693
-variable_desc old_gba_state2 [] =
694
-{
695
-	LOAD( u8 [0x20], state.apu.regs [0x20] ),
696
-	SKIP( int, sound3Bank ),
697
-	SKIP( int, sound3DataSize ),
698
-	SKIP( int, sound3ForcedOutput ),
699
-	{ NULL, 0 }
700
-};
701
-
702
-// New state format
703
-static variable_desc gba_state [] =
704
-{
705
-	// PCM
706
-	LOAD( int, pcm [0].readIndex ),
707
-	LOAD( int, pcm [0].count ),
708
-	LOAD( int, pcm [0].writeIndex ),
709
-	LOAD(u8[32],pcm[0].fifo ),
710
-	LOAD( int, pcm [0].dac ),
711
-
712
-	SKIP( int [4], room_for_expansion ),
713
-
714
-	LOAD( int, pcm [1].readIndex ),
715
-	LOAD( int, pcm [1].count ),
716
-	LOAD( int, pcm [1].writeIndex ),
717
-	LOAD(u8[32],pcm[1].fifo ),
718
-	LOAD( int, pcm [1].dac ),
719
-
720
-	SKIP( int [4], room_for_expansion ),
721
-
722
-	// APU
723
-	LOAD( u8 [0x40], state.apu.regs ),      // last values written to registers and wave RAM (both banks)
724
-	LOAD( int, state.apu.frame_time ),      // clocks until next frame sequencer action
725
-	LOAD( int, state.apu.frame_phase ),     // next step frame sequencer will run
726
-
727
-	LOAD( int, state.apu.sweep_freq ),      // sweep's internal frequency register
728
-	LOAD( int, state.apu.sweep_delay ),     // clocks until next sweep action
729
-	LOAD( int, state.apu.sweep_enabled ),
730
-	LOAD( int, state.apu.sweep_neg ),       // obscure internal flag
731
-	LOAD( int, state.apu.noise_divider ),
732
-	LOAD( int, state.apu.wave_buf ),        // last read byte of wave RAM
733
-
734
-	LOAD( int [4], state.apu.delay ),       // clocks until next channel action
735
-	LOAD( int [4], state.apu.length_ctr ),
736
-	LOAD( int [4], state.apu.phase ),       // square/wave phase, noise LFSR
737
-	LOAD( int [4], state.apu.enabled ),     // internal enabled flag
738
-
739
-	LOAD( int [3], state.apu.env_delay ),   // clocks until next envelope action
740
-	LOAD( int [3], state.apu.env_volume ),
741
-	LOAD( int [3], state.apu.env_enabled ),
742
-
743
-	SKIP( int [13], room_for_expansion ),
744
-
745
-	// Emulator
746
-	LOAD( int, soundEnableFlag ),
747
-
748
-	SKIP( int [15], room_for_expansion ),
749
-
750
-	{ NULL, 0 }
751
-};
752
-
753
-// Reads and discards count bytes from in
754
-static void skip_read( gzFile in, int count )
755
-{
756
-	char buf [512];
757
-
758
-	while ( count )
759
-	{
760
-		int n = sizeof buf;
761
-		if ( n > count )
762
-			n = count;
763
-
764
-		count -= n;
765
-		utilGzRead( in, buf, n );
766
-	}
767
-}
768
-
769
-void soundSaveGame( gzFile out )
770
-{
771
-	gb_apu->save_state( &state.apu );
772
-
773
-	// Be sure areas for expansion get written as zero
774
-	memset( dummy_state, 0, sizeof dummy_state );
775
-
776
-	utilWriteData( out, gba_state );
777
-}
778
-
779
-static void soundReadGameOld( gzFile in, int version )
780
-{
781
-	// Read main data
782
-	utilReadData( in, old_gba_state );
783
-	skip_read( in, 6*735 + 2*735 );
784
-
785
-	// Copy APU regs
786
-	static int const regs_to_copy [] = {
787
-		NR10, NR11, NR12, NR13, NR14,
788
-		      NR21, NR22, NR23, NR24,
789
-		NR30, NR31, NR32, NR33, NR34,
790
-		      NR41, NR42, NR43, NR44,
791
-		NR50, NR51, NR52, -1
792
-	};
793
-
794
-	ioMem [NR52] |= 0x80; // old sound played even when this wasn't set (power on)
795
-
796
-	for ( int i = 0; regs_to_copy [i] >= 0; i++ )
797
-		state.apu.regs [gba_to_gb_sound( regs_to_copy [i] ) - 0xFF10] = ioMem [regs_to_copy [i]];
798
-
799
-	// Copy wave RAM to both banks
800
-	memcpy( &state.apu.regs [0x20], &ioMem [0x90], 0x10 );
801
-	memcpy( &state.apu.regs [0x30], &ioMem [0x90], 0x10 );
802
-
803
-	// Read both banks of wave RAM if available
804
-	if ( version >= SAVE_GAME_VERSION_3 )
805
-		utilReadData( in, old_gba_state2 );
806
-
807
-	// Restore PCM
808
-	pcm [0].dac = state.soundDSAValue;
809
-	pcm [1].dac = state.soundDSBValue;
810
-
811
-	(void) utilReadInt( in ); // ignore quality
812
-}
813
-
814
-#include <stdio.h>
815
-
816
-void soundReadGame( gzFile in, int version )
817
-{
818
-	// Prepare APU and default state
819
-	reset_apu();
820
-	gb_apu->save_state( &state.apu );
821
-
822
-	if ( version > SAVE_GAME_VERSION_9 )
823
-		utilReadData( in, gba_state );
824
-	else
825
-		soundReadGameOld( in, version );
826
-
827
-	gb_apu->load_state( state.apu );
828
-	write_SGCNT0_H( READ16LE( &ioMem [SGCNT0_H] ) & 0x770F );
829
-
830
-	apply_muting();
831
-}*/
Browse code

[GSF] Cleanup, a tiny bit of making sure it was like viogsf, also used the standard integer types and not VBA-M's typedefs.

Naram Qashat authored on 2013/05/10 17:45:36
Showing 1 changed files
... ...
@@ -13,6 +13,7 @@
13 13
 #include "../common/SoundDriver.h"
14 14
 
15 15
 extern SoundDriver *systemSoundInit();
16
+bool soundDeclicking = true;
16 17
 
17 18
 #define NR10 0x60
18 19
 #define NR11 0x62
... ...
@@ -42,7 +43,7 @@ extern bool stopState;      // TODO: silence sound when true
42 43
 
43 44
 int const SOUND_CLOCK_TICKS_ = 167772; // 1/100 second
44 45
 
45
-static u16   soundFinalWave [6400];
46
+static uint16_t   soundFinalWave [6400];
46 47
 long  soundSampleRate    = 44100;
47 48
 bool  soundInterpolation = true;
48 49
 bool  soundPaused        = true;
... ...
@@ -84,7 +85,7 @@ public:
84 85
 	int  readIndex;
85 86
 	int  count;
86 87
 	int  writeIndex;
87
-	u8   fifo [32];
88
+	uint8_t   fifo [32];
88 89
 	int  dac;
89 90
 private:
90 91
 
... ...
@@ -155,7 +156,7 @@ void Gba_Pcm::update( int dac )
155 156
 	{
156 157
 		blip_time_t time = blip_time();
157 158
 
158
-		dac = (s8) dac >> shift;
159
+		dac = (int8_t) dac >> shift;
159 160
 		int delta = dac - last_amp;
160 161
 		if ( delta )
161 162
 		{
... ...
@@ -195,8 +196,8 @@ void Gba_Pcm_Fifo::timer_overflowed( int which_timer )
195 196
 				int reg = which ? FIFOB_L : FIFOA_L;
196 197
 				for ( int n = 4; n--; )
197 198
 				{
198
-					soundEvent(reg  , (u16)0);
199
-					soundEvent(reg+2, (u16)0);
199
+					soundEvent(reg  , (uint16_t)0);
200
+					soundEvent(reg+2, (uint16_t)0);
200 201
 				}
201 202
 			}
202 203
 		}
... ...
@@ -260,7 +261,7 @@ static int gba_to_gb_sound( int addr )
260 261
 	return 0;
261 262
 }
262 263
 
263
-void soundEvent(u32 address, u8 data)
264
+void soundEvent(uint32_t address, uint8_t data)
264 265
 {
265 266
 	int gb_addr = gba_to_gb_sound( address );
266 267
 	if ( gb_addr )
... ...
@@ -303,7 +304,7 @@ static void write_SGCNT0_H( int data )
303 304
 	apply_volume( true );
304 305
 }
305 306
 
306
-void soundEvent(u32 address, u16 data)
307
+void soundEvent(uint32_t address, uint16_t data)
307 308
 {
308 309
 	switch ( address )
309 310
 	{
... ...
@@ -329,8 +330,8 @@ void soundEvent(u32 address, u16 data)
329 330
 		break;
330 331
 
331 332
 	default:
332
-		soundEvent( address & ~1, (u8) (data     ) ); // even
333
-		soundEvent( address |  1, (u8) (data >> 8) ); // odd
333
+		soundEvent( address & ~1, (uint8_t) (data     ) ); // even
334
+		soundEvent( address |  1, (uint8_t) (data >> 8) ); // odd
334 335
 		break;
335 336
 	}
336 337
 }
... ...
@@ -435,6 +436,7 @@ static void apply_muting()
435 436
 
436 437
 static void reset_apu()
437 438
 {
439
+	gb_apu->reduce_clicks(soundDeclicking);
438 440
 	gb_apu->reset( gb_apu->mode_agb, true );
439 441
 
440 442
 	if ( stereo_buffer )
... ...
@@ -485,6 +487,20 @@ void soundShutdown()
485 487
 		soundDriver = 0;
486 488
 	}
487 489
 
490
+	// APU
491
+	if ( gb_apu )
492
+	{
493
+		delete gb_apu;
494
+		gb_apu = 0;
495
+	}
496
+
497
+	// Stereo_Buffer
498
+	if (stereo_buffer)
499
+	{
500
+		delete stereo_buffer;
501
+		stereo_buffer = 0;
502
+	}
503
+
488 504
 	//systemOnSoundShutdown();
489 505
 }
490 506
 
... ...
@@ -534,7 +550,7 @@ void soundReset()
534 550
 	SOUND_CLOCK_TICKS = SOUND_CLOCK_TICKS_;
535 551
 	soundTicks        = SOUND_CLOCK_TICKS_;
536 552
 
537
-	soundEvent( NR52, (u8) 0x80 );
553
+	soundEvent( NR52, (uint8_t) 0x80 );
538 554
 }
539 555
 
540 556
 bool soundInit()
Browse code

Removed the save state loading from the 2SF player and updated the VBA-M code to the latest revision.

Naram Qashat authored on 2013/04/12 20:27:27
Showing 1 changed files
... ...
@@ -42,7 +42,7 @@ extern bool stopState;      // TODO: silence sound when true
42 42
 
43 43
 int const SOUND_CLOCK_TICKS_ = 167772; // 1/100 second
44 44
 
45
-static u16   soundFinalWave [1600];
45
+static u16   soundFinalWave [6400];
46 46
 long  soundSampleRate    = 44100;
47 47
 bool  soundInterpolation = true;
48 48
 bool  soundPaused        = true;
... ...
@@ -452,6 +452,13 @@ static void remake_stereo_buffer()
452 452
 	pcm [0].pcm.init();
453 453
 	pcm [1].pcm.init();
454 454
 
455
+	// APU
456
+	if ( !gb_apu )
457
+	{
458
+		gb_apu = new Gb_Apu; // TODO: handle out of memory
459
+		reset_apu();
460
+	}
461
+
455 462
 	// Stereo_Buffer
456 463
 	delete stereo_buffer;
457 464
 	stereo_buffer = 0;
... ...
@@ -465,13 +472,7 @@ static void remake_stereo_buffer()
465 472
 	pcm [1].which = 1;
466 473
 	apply_filtering();
467 474
 
468
-	// APU
469
-	if ( !gb_apu )
470
-	{
471
-		gb_apu = new Gb_Apu; // TODO: handle out of memory
472
-		reset_apu();
473
-	}
474
-
475
+	// Volume Level
475 476
 	apply_muting();
476 477
 	apply_volume();
477 478
 }
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,814 @@
1
+#include <string.h>
2
+
3
+#include "Sound.h"
4
+
5
+#include "GBA.h"
6
+#include "Globals.h"
7
+//#include "../Util.h"
8
+#include "../common/Port.h"
9
+
10
+#include "../apu/Gb_Apu.h"
11
+#include "../apu/Multi_Buffer.h"
12
+
13
+#include "../common/SoundDriver.h"
14
+
15
+extern SoundDriver *systemSoundInit();
16
+
17
+#define NR10 0x60
18
+#define NR11 0x62
19
+#define NR12 0x63
20
+#define NR13 0x64
21
+#define NR14 0x65
22
+#define NR21 0x68
23
+#define NR22 0x69
24
+#define NR23 0x6c
25
+#define NR24 0x6d
26
+#define NR30 0x70
27
+#define NR31 0x72
28
+#define NR32 0x73
29
+#define NR33 0x74
30
+#define NR34 0x75
31
+#define NR41 0x78
32
+#define NR42 0x79
33
+#define NR43 0x7c
34
+#define NR44 0x7d
35
+#define NR50 0x80
36
+#define NR51 0x81
37
+#define NR52 0x84
38
+
39
+SoundDriver * soundDriver = 0;
40
+
41
+extern bool stopState;      // TODO: silence sound when true
42
+
43
+int const SOUND_CLOCK_TICKS_ = 167772; // 1/100 second
44
+
45
+static u16   soundFinalWave [1600];
46
+long  soundSampleRate    = 44100;
47
+bool  soundInterpolation = true;
48
+bool  soundPaused        = true;
49
+float soundFiltering     = 0.5f;
50
+int   SOUND_CLOCK_TICKS  = SOUND_CLOCK_TICKS_;
51
+int   soundTicks         = SOUND_CLOCK_TICKS_;
52
+
53
+static float soundVolume     = 1.0f;
54
+static int soundEnableFlag   = 0x3ff; // emulator channels enabled
55
+static float soundFiltering_ = -1;
56
+static float soundVolume_    = -1;
57
+
58
+void interp_rate() { /* empty for now */ }
59
+
60
+class Gba_Pcm {
61
+public:
62
+	void init();
63
+	void apply_control( int idx );
64
+	void update( int dac );
65
+	void end_frame( blip_time_t );
66
+
67
+private:
68
+	Blip_Buffer* output;
69
+	blip_time_t last_time;
70
+	int last_amp;
71
+	int shift;
72
+};
73
+
74
+class Gba_Pcm_Fifo {
75
+public:
76
+	int     which;
77
+	Gba_Pcm pcm;
78
+
79
+	void write_control( int data );
80
+	void write_fifo( int data );
81
+	void timer_overflowed( int which_timer );
82
+
83
+	// public only so save state routines can access it
84
+	int  readIndex;
85
+	int  count;
86
+	int  writeIndex;
87
+	u8   fifo [32];
88
+	int  dac;
89
+private:
90
+
91
+	int  timer;
92
+	bool enabled;
93
+};
94
+
95
+static Gba_Pcm_Fifo     pcm [2];
96
+static Gb_Apu*          gb_apu;
97
+static Stereo_Buffer*   stereo_buffer;
98
+
99
+static Blip_Synth<blip_best_quality,1> pcm_synth [3]; // 32 kHz, 16 kHz, 8 kHz
100
+
101
+static inline blip_time_t blip_time()
102
+{
103
+	return SOUND_CLOCK_TICKS - soundTicks;
104
+}
105
+
106
+void Gba_Pcm::init()
107
+{
108
+	output    = 0;
109
+	last_time = 0;
110
+	last_amp  = 0;
111
+	shift     = 0;
112
+}
113
+
114
+void Gba_Pcm::apply_control( int idx )
115
+{
116
+	shift = ~ioMem [SGCNT0_H] >> (2 + idx) & 1;
117
+
118
+	int ch = 0;
119
+	if ( (soundEnableFlag >> idx & 0x100) && (ioMem [NR52] & 0x80) )
120
+		ch = ioMem [SGCNT0_H+1] >> (idx * 4) & 3;
121
+
122
+	Blip_Buffer* out = 0;
123
+	switch ( ch )
124
+	{
125
+	case 1: out = stereo_buffer->right();  break;
126
+	case 2: out = stereo_buffer->left();   break;
127
+	case 3: out = stereo_buffer->center(); break;
128
+	}
129
+
130
+	if ( output != out )
131
+	{
132
+		if ( output )
133
+		{
134
+			output->set_modified();
135
+			pcm_synth [0].offset( blip_time(), -last_amp, output );
136
+		}
137
+		last_amp = 0;
138
+		output = out;
139
+	}
140
+}
141
+
142
+void Gba_Pcm::end_frame( blip_time_t time )
143
+{
144
+	last_time -= time;
145
+	if ( last_time < -2048 )
146
+		last_time = -2048;
147
+
148
+	if ( output )
149
+		output->set_modified();
150
+}
151
+
152
+void Gba_Pcm::update( int dac )
153
+{
154
+	if ( output )
155
+	{
156
+		blip_time_t time = blip_time();
157
+
158
+		dac = (s8) dac >> shift;
159
+		int delta = dac - last_amp;
160
+		if ( delta )
161
+		{
162
+			last_amp = dac;
163
+
164
+			int filter = 0;
165
+			if ( soundInterpolation )
166
+			{
167
+				// base filtering on how long since last sample was output
168
+				int period = time - last_time;
169
+
170
+				int idx = (unsigned) period / 512;
171
+				if ( idx >= 3 )
172
+					idx = 3;
173
+
174
+				static int const filters [4] = { 0, 0, 1, 2 };
175
+				filter = filters [idx];
176
+			}
177
+
178
+			pcm_synth [filter].offset( time, delta, output );
179
+		}
180
+		last_time = time;
181
+	}
182
+}
183
+
184
+void Gba_Pcm_Fifo::timer_overflowed( int which_timer )
185
+{
186
+	if ( which_timer == timer && enabled )
187
+	{
188
+		if ( count <= 16 )
189
+		{
190
+			// Need to fill FIFO
191
+			CPUCheckDMA( 3, which ? 4 : 2 );
192
+			if ( count <= 16 )
193
+			{
194
+				// Not filled by DMA, so fill with 16 bytes of silence
195
+				int reg = which ? FIFOB_L : FIFOA_L;
196
+				for ( int n = 4; n--; )
197
+				{
198
+					soundEvent(reg  , (u16)0);
199
+					soundEvent(reg+2, (u16)0);
200
+				}
201
+			}
202
+		}
203
+
204
+		// Read next sample from FIFO
205
+		count--;
206
+		dac = fifo [readIndex];
207
+		readIndex = (readIndex + 1) & 31;
208
+		pcm.update( dac );
209
+	}
210
+}
211
+
212
+void Gba_Pcm_Fifo::write_control( int data )
213
+{
214
+	enabled = (data & 0x0300) ? true : false;
215
+	timer   = (data & 0x0400) ? 1 : 0;
216
+
217
+	if ( data & 0x0800 )
218
+	{
219
+		// Reset
220
+		writeIndex = 0;
221
+		readIndex  = 0;
222
+		count      = 0;
223
+		dac        = 0;
224
+		memset( fifo, 0, sizeof fifo );
225
+	}
226
+
227
+	pcm.apply_control( which );
228
+	pcm.update( dac );
229
+}
230
+
231
+void Gba_Pcm_Fifo::write_fifo( int data )
232
+{
233
+	fifo [writeIndex  ] = data & 0xFF;
234
+	fifo [writeIndex+1] = data >> 8;
235
+	count += 2;
236
+	writeIndex = (writeIndex + 2) & 31;
237
+}
238
+
239
+static void apply_control()
240
+{
241
+	pcm [0].pcm.apply_control( 0 );
242
+	pcm [1].pcm.apply_control( 1 );
243
+}
244
+
245
+static int gba_to_gb_sound( int addr )
246
+{
247
+	static const int table [0x40] =
248
+	{
249
+		0xFF10,     0,0xFF11,0xFF12,0xFF13,0xFF14,     0,     0,
250
+		0xFF16,0xFF17,     0,     0,0xFF18,0xFF19,     0,     0,
251
+		0xFF1A,     0,0xFF1B,0xFF1C,0xFF1D,0xFF1E,     0,     0,
252
+		0xFF20,0xFF21,     0,     0,0xFF22,0xFF23,     0,     0,
253
+		0xFF24,0xFF25,     0,     0,0xFF26,     0,     0,     0,
254
+		     0,     0,     0,     0,     0,     0,     0,     0,
255
+		0xFF30,0xFF31,0xFF32,0xFF33,0xFF34,0xFF35,0xFF36,0xFF37,
256
+		0xFF38,0xFF39,0xFF3A,0xFF3B,0xFF3C,0xFF3D,0xFF3E,0xFF3F,
257
+	};
258
+	if ( addr >= 0x60 && addr < 0xA0 )
259
+		return table [addr - 0x60];
260
+	return 0;
261
+}
262
+
263
+void soundEvent(u32 address, u8 data)
264
+{
265
+	int gb_addr = gba_to_gb_sound( address );
266
+	if ( gb_addr )
267
+	{
268
+		ioMem[address] = data;
269
+		gb_apu->write_register( blip_time(), gb_addr, data );
270
+
271
+		if ( address == NR52 )
272
+			apply_control();
273
+	}
274
+
275
+	ioMem[NR52] = (ioMem[NR52] & 0x80) | (gb_apu->read_status() & 0x7f);
276
+
277
+	// TODO: what about byte writes to SGCNT0_H etc.?
278
+}
279
+
280
+static void apply_volume( bool apu_only = false )
281
+{
282
+	if ( !apu_only )
283
+		soundVolume_ = soundVolume;
284
+
285
+	if ( gb_apu )
286
+	{
287
+		static float const apu_vols [4] = { 0.25, 0.5, 1, 0.25 };
288
+		gb_apu->volume( soundVolume_ * apu_vols [ioMem [SGCNT0_H] & 3] );
289
+	}
290
+
291
+	if ( !apu_only )
292
+	{
293
+		for ( int i = 0; i < 3; i++ )
294
+			pcm_synth [i].volume( 0.66 / 256 * soundVolume_ );
295
+	}
296
+}
297
+
298
+static void write_SGCNT0_H( int data )
299
+{
300
+	WRITE16LE( &ioMem [SGCNT0_H], data & 0x770F );
301
+	pcm [0].write_control( data      );
302
+	pcm [1].write_control( data >> 4 );
303
+	apply_volume( true );
304
+}
305
+
306
+void soundEvent(u32 address, u16 data)
307
+{
308
+	switch ( address )
309
+	{
310
+	case SGCNT0_H:
311
+		write_SGCNT0_H( data );
312
+		break;
313
+
314
+	case FIFOA_L:
315
+	case FIFOA_H:
316
+		pcm [0].write_fifo( data );
317
+		WRITE16LE( &ioMem[address], data );
318
+		break;
319
+
320
+	case FIFOB_L:
321
+	case FIFOB_H:
322
+		pcm [1].write_fifo( data );
323
+		WRITE16LE( &ioMem[address], data );
324
+		break;
325
+
326
+	case 0x88:
327
+		data &= 0xC3FF;
328
+		WRITE16LE( &ioMem[address], data );
329
+		break;
330
+
331
+	default:
332
+		soundEvent( address & ~1, (u8) (data     ) ); // even
333
+		soundEvent( address |  1, (u8) (data >> 8) ); // odd
334
+		break;
335
+	}
336
+}
337
+
338
+void soundTimerOverflow(int timer)
339
+{
340
+	pcm [0].timer_overflowed( timer );
341
+	pcm [1].timer_overflowed( timer );
342
+}
343
+
344
+static void end_frame( blip_time_t time )
345
+{
346
+	pcm [0].pcm.end_frame( time );
347
+	pcm [1].pcm.end_frame( time );
348
+
349
+	gb_apu       ->end_frame( time );
350
+	stereo_buffer->end_frame( time );
351
+}
352
+
353
+void flush_samples(Multi_Buffer * buffer)
354
+{
355
+	// We want to write the data frame by frame to support legacy audio drivers
356
+	// that don't use the length parameter of the write method.
357
+	// TODO: Update the Win32 audio drivers (DS, OAL, XA2), and flush all the
358
+	// samples at once to help reducing the audio delay on all platforms.
359
+	int soundBufferLen = ( soundSampleRate / 60 ) * 4;
360
+
361
+	// soundBufferLen should have a whole number of sample pairs
362
+	assert( soundBufferLen % (2 * sizeof *soundFinalWave) == 0 );
363
+
364
+	// number of samples in output buffer
365
+	int const out_buf_size = soundBufferLen / sizeof *soundFinalWave;
366
+
367
+	// Keep filling and writing soundFinalWave until it can't be fully filled
368
+	while ( buffer->samples_avail() >= out_buf_size )
369
+	{
370
+		buffer->read_samples( (blip_sample_t*) soundFinalWave, out_buf_size );
371
+		if(soundPaused)
372
+			soundResume();
373
+
374
+		soundDriver->write(soundFinalWave, soundBufferLen);
375
+		//systemOnWriteDataToSoundBuffer(soundFinalWave, soundBufferLen);
376
+	}
377
+}
378
+
379
+static void apply_filtering()
380
+{
381
+	soundFiltering_ = soundFiltering;
382
+
383
+	int const base_freq = (int) (32768 - soundFiltering_ * 16384);
384
+	int const nyquist = stereo_buffer->sample_rate() / 2;
385
+
386
+	for ( int i = 0; i < 3; i++ )
387
+	{
388
+		int cutoff = base_freq >> i;
389
+		if ( cutoff > nyquist )
390
+			cutoff = nyquist;
391
+		pcm_synth [i].treble_eq( blip_eq_t( 0, 0, stereo_buffer->sample_rate(), cutoff ) );
392
+	}
393
+}
394
+
395
+void psoundTickfn()
396
+{
397
+ 	if ( gb_apu && stereo_buffer )
398
+	{
399
+		// Run sound hardware to present
400
+		end_frame( SOUND_CLOCK_TICKS );
401
+
402
+		flush_samples(stereo_buffer);
403
+
404
+		if ( soundFiltering_ != soundFiltering )
405
+			apply_filtering();
406
+
407
+		if ( soundVolume_ != soundVolume )
408
+			apply_volume();
409
+	}
410
+
411
+	ioMem[NR52] = (ioMem[NR52] & 0x80) | (gb_apu->read_status() & 0x7f);
412
+}
413
+
414
+static void apply_muting()
415
+{
416
+	if ( !stereo_buffer || !ioMem )
417
+		return;
418
+
419
+	// PCM
420
+	apply_control();
421
+
422
+	if ( gb_apu )
423
+	{
424
+		// APU
425
+		for ( int i = 0; i < 4; i++ )
426
+		{
427
+			if ( soundEnableFlag >> i & 1 )
428
+				gb_apu->set_output( stereo_buffer->center(),
429
+						stereo_buffer->left(), stereo_buffer->right(), i );
430
+			else
431
+				gb_apu->set_output( 0, 0, 0, i );
432
+		}
433
+	}
434
+}
435
+
436
+static void reset_apu()
437
+{
438
+	gb_apu->reset( gb_apu->mode_agb, true );
439
+
440
+	if ( stereo_buffer )
441
+		stereo_buffer->clear();
442
+
443
+	soundTicks = SOUND_CLOCK_TICKS;
444
+}
445
+
446
+static void remake_stereo_buffer()
447
+{
448
+	if ( !ioMem )
449
+		return;
450
+
451
+	// Clears pointers kept to old stereo_buffer
452
+	pcm [0].pcm.init();
453
+	pcm [1].pcm.init();
454
+
455
+	// Stereo_Buffer
456
+	delete stereo_buffer;
457
+	stereo_buffer = 0;
458
+
459
+	stereo_buffer = new Stereo_Buffer; // TODO: handle out of memory
460
+	stereo_buffer->set_sample_rate( soundSampleRate ); // TODO: handle out of memory
461
+	stereo_buffer->clock_rate( gb_apu->clock_rate );
462
+
463
+	// PCM
464
+	pcm [0].which = 0;
465
+	pcm [1].which = 1;
466
+	apply_filtering();
467
+
468
+	// APU
469
+	if ( !gb_apu )
470
+	{
471
+		gb_apu = new Gb_Apu; // TODO: handle out of memory
472
+		reset_apu();
473
+	}
474
+
475
+	apply_muting();
476
+	apply_volume();
477
+}
478
+
479
+void soundShutdown()
480
+{
481
+	if (soundDriver)
482
+	{
483
+		delete soundDriver;
484
+		soundDriver = 0;
485
+	}
486
+
487
+	//systemOnSoundShutdown();
488
+}
489
+
490
+void soundPause()
491
+{
492
+	soundPaused = true;
493
+	if (soundDriver)
494
+		soundDriver->pause();
495
+}
496
+
497
+void soundResume()
498
+{
499
+	soundPaused = false;
500
+	if (soundDriver)
501
+		soundDriver->resume();
502
+}
503
+
504
+void soundSetVolume( float volume )
505
+{
506
+	soundVolume = volume;
507
+}
508
+
509
+float soundGetVolume()
510
+{
511
+	return soundVolume;
512
+}
513
+
514
+void soundSetEnable(int channels)
515
+{
516
+	soundEnableFlag = channels;
517
+	apply_muting();
518
+}
519
+
520
+int soundGetEnable()
521
+{
522
+	return (soundEnableFlag & 0x30f);
523
+}
524
+
525
+void soundReset()
526
+{
527
+	soundDriver->reset();
528
+
529
+	remake_stereo_buffer();
530
+	reset_apu();
531
+
532
+	soundPaused = true;
533
+	SOUND_CLOCK_TICKS = SOUND_CLOCK_TICKS_;
534
+	soundTicks        = SOUND_CLOCK_TICKS_;
535
+
536
+	soundEvent( NR52, (u8) 0x80 );
537
+}
538
+
539
+bool soundInit()
540
+{
541
+	soundDriver = systemSoundInit();
542
+	if ( !soundDriver )
543
+		return false;
544
+
545
+	if (!soundDriver->init(soundSampleRate))
546
+		return false;
547
+
548
+	soundPaused = true;
549
+	return true;
550
+}
551
+
552
+void soundSetThrottle(unsigned short throttle)
553
+{
554
+	if(!soundDriver)
555
+		return;
556
+	soundDriver->setThrottle(throttle);
557
+}
558
+
559
+long soundGetSampleRate()
560
+{
561
+	return soundSampleRate;
562
+}
563
+
564
+void soundSetSampleRate(long sampleRate)
565
+{
566
+	if ( soundSampleRate != sampleRate )
567
+	{
568
+		/*if ( systemCanChangeSoundQuality() )
569
+		{
570
+			soundShutdown();
571
+			soundSampleRate      = sampleRate;
572
+			soundInit();
573
+		}
574
+		else*/
575
+		{
576
+			soundSampleRate      = sampleRate;
577
+		}
578
+
579
+		remake_stereo_buffer();
580
+	}
581
+}
582
+
583
+/*static int dummy_state [16];
584
+
585
+#define SKIP( type, name ) { dummy_state, sizeof (type) }
586
+
587
+#define LOAD( type, name ) { &name, sizeof (type) }
588
+
589
+static struct {
590
+	gb_apu_state_t apu;
591
+
592
+	// old state
593
+	u8 soundDSAValue;
594
+	int soundDSBValue;
595
+} state;
596
+
597
+// Old GBA sound state format
598
+static variable_desc old_gba_state [] =
599
+{
600
+	SKIP( int, soundPaused ),
601
+	SKIP( int, soundPlay ),
602
+	SKIP( int, soundTicks ),
603
+	SKIP( int, SOUND_CLOCK_TICKS ),
604
+	SKIP( int, soundLevel1 ),
605
+	SKIP( int, soundLevel2 ),
606
+	SKIP( int, soundBalance ),
607
+	SKIP( int, soundMasterOn ),
608
+	SKIP( int, soundIndex ),
609
+	SKIP( int, sound1On ),
610
+	SKIP( int, sound1ATL ),
611
+	SKIP( int, sound1Skip ),
612
+	SKIP( int, sound1Index ),
613
+	SKIP( int, sound1Continue ),
614
+	SKIP( int, sound1EnvelopeVolume ),
615
+	SKIP( int, sound1EnvelopeATL ),
616
+	SKIP( int, sound1EnvelopeATLReload ),
617
+	SKIP( int, sound1EnvelopeUpDown ),
618
+	SKIP( int, sound1SweepATL ),
619
+	SKIP( int, sound1SweepATLReload ),
620
+	SKIP( int, sound1SweepSteps ),
621
+	SKIP( int, sound1SweepUpDown ),
622
+	SKIP( int, sound1SweepStep ),
623
+	SKIP( int, sound2On ),
624
+	SKIP( int, sound2ATL ),
625
+	SKIP( int, sound2Skip ),
626
+	SKIP( int, sound2Index ),
627
+	SKIP( int, sound2Continue ),
628
+	SKIP( int, sound2EnvelopeVolume ),
629
+	SKIP( int, sound2EnvelopeATL ),
630
+	SKIP( int, sound2EnvelopeATLReload ),
631
+	SKIP( int, sound2EnvelopeUpDown ),
632
+	SKIP( int, sound3On ),
633
+	SKIP( int, sound3ATL ),
634
+	SKIP( int, sound3Skip ),
635
+	SKIP( int, sound3Index ),
636
+	SKIP( int, sound3Continue ),
637
+	SKIP( int, sound3OutputLevel ),
638
+	SKIP( int, sound4On ),
639
+	SKIP( int, sound4ATL ),
640
+	SKIP( int, sound4Skip ),
641
+	SKIP( int, sound4Index ),
642
+	SKIP( int, sound4Clock ),
643
+	SKIP( int, sound4ShiftRight ),
644
+	SKIP( int, sound4ShiftSkip ),
645
+	SKIP( int, sound4ShiftIndex ),
646
+	SKIP( int, sound4NSteps ),
647
+	SKIP( int, sound4CountDown ),
648
+	SKIP( int, sound4Continue ),
649
+	SKIP( int, sound4EnvelopeVolume ),
650
+	SKIP( int, sound4EnvelopeATL ),
651
+	SKIP( int, sound4EnvelopeATLReload ),
652
+	SKIP( int, sound4EnvelopeUpDown ),
653
+	LOAD( int, soundEnableFlag ),
654
+	SKIP( int, soundControl ),
655
+	LOAD( int, pcm [0].readIndex ),
656
+	LOAD( int, pcm [0].count ),
657
+	LOAD( int, pcm [0].writeIndex ),
658
+	SKIP( u8,  soundDSAEnabled ), // was bool, which was one byte on MS compiler
659
+	SKIP( int, soundDSATimer ),
660
+	LOAD( u8 [32], pcm [0].fifo ),
661
+	LOAD( u8,  state.soundDSAValue ),
662
+	LOAD( int, pcm [1].readIndex ),
663
+	LOAD( int, pcm [1].count ),
664
+	LOAD( int, pcm [1].writeIndex ),
665
+	SKIP( int, soundDSBEnabled ),
666
+	SKIP( int, soundDSBTimer ),
667
+	LOAD( u8 [32], pcm [1].fifo ),
668
+	LOAD( int, state.soundDSBValue ),
669
+
670
+	// skipped manually
671
+	//LOAD( int, soundBuffer[0][0], 6*735 },
672
+	//LOAD( int, soundFinalWave[0], 2*735 },
673
+	{ NULL, 0 }
674
+};
675
+
676
+variable_desc old_gba_state2 [] =
677
+{
678
+	LOAD( u8 [0x20], state.apu.regs [0x20] ),
679
+	SKIP( int, sound3Bank ),
680
+	SKIP( int, sound3DataSize ),
681
+	SKIP( int, sound3ForcedOutput ),
682
+	{ NULL, 0 }
683
+};
684
+
685
+// New state format
686
+static variable_desc gba_state [] =
687
+{
688
+	// PCM
689
+	LOAD( int, pcm [0].readIndex ),
690
+	LOAD( int, pcm [0].count ),
691
+	LOAD( int, pcm [0].writeIndex ),
692
+	LOAD(u8[32],pcm[0].fifo ),
693
+	LOAD( int, pcm [0].dac ),
694
+
695
+	SKIP( int [4], room_for_expansion ),
696
+
697
+	LOAD( int, pcm [1].readIndex ),
698
+	LOAD( int, pcm [1].count ),
699
+	LOAD( int, pcm [1].writeIndex ),
700
+	LOAD(u8[32],pcm[1].fifo ),
701
+	LOAD( int, pcm [1].dac ),
702
+
703
+	SKIP( int [4], room_for_expansion ),
704
+
705
+	// APU
706
+	LOAD( u8 [0x40], state.apu.regs ),      // last values written to registers and wave RAM (both banks)
707
+	LOAD( int, state.apu.frame_time ),      // clocks until next frame sequencer action
708
+	LOAD( int, state.apu.frame_phase ),     // next step frame sequencer will run
709
+
710
+	LOAD( int, state.apu.sweep_freq ),      // sweep's internal frequency register
711
+	LOAD( int, state.apu.sweep_delay ),     // clocks until next sweep action
712
+	LOAD( int, state.apu.sweep_enabled ),
713
+	LOAD( int, state.apu.sweep_neg ),       // obscure internal flag
714
+	LOAD( int, state.apu.noise_divider ),
715
+	LOAD( int, state.apu.wave_buf ),        // last read byte of wave RAM
716
+
717
+	LOAD( int [4], state.apu.delay ),       // clocks until next channel action
718
+	LOAD( int [4], state.apu.length_ctr ),
719
+	LOAD( int [4], state.apu.phase ),       // square/wave phase, noise LFSR
720
+	LOAD( int [4], state.apu.enabled ),     // internal enabled flag
721
+
722
+	LOAD( int [3], state.apu.env_delay ),   // clocks until next envelope action
723
+	LOAD( int [3], state.apu.env_volume ),
724
+	LOAD( int [3], state.apu.env_enabled ),
725
+
726
+	SKIP( int [13], room_for_expansion ),
727
+
728
+	// Emulator
729
+	LOAD( int, soundEnableFlag ),
730
+
731
+	SKIP( int [15], room_for_expansion ),
732
+
733
+	{ NULL, 0 }
734
+};
735
+
736
+// Reads and discards count bytes from in
737
+static void skip_read( gzFile in, int count )
738
+{
739
+	char buf [512];
740
+
741
+	while ( count )
742
+	{
743
+		int n = sizeof buf;
744
+		if ( n > count )
745
+			n = count;
746
+
747
+		count -= n;
748
+		utilGzRead( in, buf, n );
749
+	}
750
+}
751
+
752
+void soundSaveGame( gzFile out )
753
+{
754
+	gb_apu->save_state( &state.apu );
755
+
756
+	// Be sure areas for expansion get written as zero
757
+	memset( dummy_state, 0, sizeof dummy_state );
758
+
759
+	utilWriteData( out, gba_state );
760
+}
761
+
762
+static void soundReadGameOld( gzFile in, int version )
763
+{
764
+	// Read main data
765
+	utilReadData( in, old_gba_state );
766
+	skip_read( in, 6*735 + 2*735 );
767
+
768
+	// Copy APU regs
769
+	static int const regs_to_copy [] = {
770
+		NR10, NR11, NR12, NR13, NR14,
771
+		      NR21, NR22, NR23, NR24,
772
+		NR30, NR31, NR32, NR33, NR34,
773
+		      NR41, NR42, NR43, NR44,
774
+		NR50, NR51, NR52, -1
775
+	};
776
+
777
+	ioMem [NR52] |= 0x80; // old sound played even when this wasn't set (power on)
778
+
779
+	for ( int i = 0; regs_to_copy [i] >= 0; i++ )
780
+		state.apu.regs [gba_to_gb_sound( regs_to_copy [i] ) - 0xFF10] = ioMem [regs_to_copy [i]];
781
+
782
+	// Copy wave RAM to both banks
783
+	memcpy( &state.apu.regs [0x20], &ioMem [0x90], 0x10 );
784
+	memcpy( &state.apu.regs [0x30], &ioMem [0x90], 0x10 );
785
+
786
+	// Read both banks of wave RAM if available
787
+	if ( version >= SAVE_GAME_VERSION_3 )
788
+		utilReadData( in, old_gba_state2 );
789
+
790
+	// Restore PCM
791
+	pcm [0].dac = state.soundDSAValue;
792
+	pcm [1].dac = state.soundDSBValue;
793
+
794
+	(void) utilReadInt( in ); // ignore quality
795
+}
796
+
797
+#include <stdio.h>
798
+
799
+void soundReadGame( gzFile in, int version )
800
+{
801
+	// Prepare APU and default state
802
+	reset_apu();
803
+	gb_apu->save_state( &state.apu );
804
+
805
+	if ( version > SAVE_GAME_VERSION_9 )
806
+		utilReadData( in, gba_state );
807
+	else
808
+		soundReadGameOld( in, version );
809
+
810
+	gb_apu->load_state( state.apu );
811
+	write_SGCNT0_H( READ16LE( &ioMem [SGCNT0_H] ) & 0x770F );
812
+
813
+	apply_muting();
814
+}*/