OXYGENHUB
◆ main x16-emulator / src / audio.c
17.9 KiB · C · last changed main: while the CPU waits in WAI, step the machine to its next event at once 14 days ago source blame history raw
1
// Commander X16 Emulator
2
// Copyright (c) 2020 Frank van den Hoef
3
// All rights reserved. License: 2-clause BSD
4
5
#include "audio.h"
6
#include "glue.h"
7
#include "vera_psg.h"
8
#include "vera_pcm.h"
9
#include "wav_recorder.h"
10
#include "ymglue.h"
11
#include "midi.h"
12
#include <stdint.h>
13
#include <stdio.h>
14
#include <string.h>
15
#include <stdlib.h>
16
17
/* RRDC (control_backend.c): tee each mixed stereo pair into the /audio ring. */
18
void x16_control_push_audio(int16_t l, int16_t r);
19
20
#ifdef __EMSCRIPTEN__
21
	#define SAMPLES_PER_BUFFER (1024)
22
	#define SAMP_POS_FRAC_BITS (22)
23
#else
24
	#define SAMPLES_PER_BUFFER (256)
25
	#define SAMP_POS_FRAC_BITS (24)
26
#endif
27
28
#define VERA_SAMP_CLKS_PER_CPU_CLK ((25000000ULL << SAMP_POS_FRAC_BITS) / 512 / MHZ / 1000000)
29
#define YM_SAMP_CLKS_PER_CPU_CLK ((3579545ULL << SAMP_POS_FRAC_BITS) / 64 / MHZ / 1000000)
30
#define FS_SAMP_CLKS_PER_CPU_CLK VERA_SAMP_CLKS_PER_CPU_CLK
31
#define SAMPLE_BYTES (2 * sizeof(int16_t))
32
#define SAMP_POS_MASK (SAMPLES_PER_BUFFER - 1)
33
#define SAMP_POS_MASK_FRAC (((uint32_t)SAMPLES_PER_BUFFER << SAMP_POS_FRAC_BITS) - 1)
34
35
// windowed sinc
36
static const int16_t filter[512] = {
37
	32767,32765,32761,32755,32746,32736,32723,32707,32690,32670,32649,32625,32598,32570,32539,32507,
38
	32472,32435,32395,32354,32310,32265,32217,32167,32115,32061,32004,31946,31885,31823,31758,31691,
39
	31623,31552,31479,31404,31327,31248,31168,31085,31000,30913,30825,30734,30642,30547,30451,30353,
40
	30253,30151,30048,29943,29835,29726,29616,29503,29389,29273,29156,29037,28916,28793,28669,28544,
41
	28416,28288,28157,28025,27892,27757,27621,27483,27344,27204,27062,26918,26774,26628,26481,26332,
42
	26182,26031,25879,25726,25571,25416,25259,25101,24942,24782,24621,24459,24296,24132,23967,23801,
43
	23634,23466,23298,23129,22959,22788,22616,22444,22271,22097,21923,21748,21572,21396,21219,21042,
44
	20864,20686,20507,20328,20148,19968,19788,19607,19426,19245,19063,18881,18699,18517,18334,18152,
45
	17969,17786,17603,17420,17237,17054,16871,16688,16505,16322,16139,15957,15774,15592,15409,15227,
46
	15046,14864,14683,14502,14321,14141,13961,13781,13602,13423,13245,13067,12890,12713,12536,12360,
47
	12185,12010,11836,11663,11490,11317,11146,10975,10804,10635,10466,10298,10131, 9964, 9799, 9634,
48
	 9470, 9306, 9144, 8983, 8822, 8662, 8504, 8346, 8189, 8033, 7878, 7724, 7571, 7419, 7268, 7118,
49
	 6969, 6822, 6675, 6529, 6385, 6241, 6099, 5958, 5818, 5679, 5541, 5405, 5269, 5135, 5002, 4870,
50
	 4739, 4610, 4482, 4355, 4229, 4104, 3981, 3859, 3738, 3619, 3500, 3383, 3268, 3153, 3040, 2928,
51
	 2817, 2708, 2600, 2493, 2388, 2284, 2181, 2079, 1979, 1880, 1783, 1686, 1591, 1498, 1405, 1314,
52
	 1225, 1136, 1049,  963,  879,  795,  714,  633,  554,  476,  399,  323,  249,  176,  105,   34,
53
	  -34, -102, -168, -234, -298, -361, -422, -482, -542, -599, -656, -712, -766, -819, -871, -922,
54
	 -971,-1020,-1067,-1113,-1158,-1202,-1244,-1286,-1326,-1366,-1404,-1441,-1477,-1512,-1546,-1579,
55
	-1611,-1642,-1671,-1700,-1728,-1755,-1781,-1806,-1830,-1852,-1874,-1896,-1916,-1935,-1953,-1971,
56
	-1987,-2003,-2018,-2032,-2045,-2058,-2069,-2080,-2090,-2099,-2108,-2116,-2123,-2129,-2134,-2139,
57
	-2143,-2147,-2150,-2152,-2153,-2154,-2154,-2154,-2153,-2151,-2149,-2146,-2143,-2139,-2135,-2130,
58
	-2124,-2118,-2112,-2105,-2098,-2090,-2082,-2073,-2064,-2054,-2045,-2034,-2024,-2012,-2001,-1989,
59
	-1977,-1965,-1952,-1939,-1926,-1912,-1898,-1884,-1870,-1855,-1840,-1825,-1810,-1794,-1778,-1762,
60
	-1746,-1730,-1714,-1697,-1680,-1663,-1646,-1629,-1612,-1595,-1577,-1560,-1542,-1525,-1507,-1489, 
61
	-1471,-1453,-1435,-1418,-1400,-1382,-1364,-1346,-1328,-1310,-1292,-1274,-1256,-1238,-1220,-1203,
62
	-1185,-1167,-1150,-1132,-1115,-1097,-1080,-1063,-1046,-1029,-1012, -995, -978, -962, -945, -929,
63
     -912, -896, -880, -864, -849, -833, -817, -802, -787, -772, -757, -742, -727, -713, -699, -684,
64
	 -670, -656, -643, -629, -616, -603, -589, -577, -564, -551, -539, -526, -514, -502, -491, -479,
65
	 -468, -456, -445, -434, -423, -413, -402, -392, -381, -371, -361, -352, -342, -333, -323, -314,
66
	 -305, -296, -288, -279, -270, -262, -254, -246, -238, -230, -222, -215, -207, -200, -193, -186,
67
	 -179, -172, -165, -158, -152, -145, -139, -133, -127, -120, -114, -108, -103,  -97,  -91,  -85,
68
	  -80,  -74,  -69,  -63,  -58,  -53,  -47,  -42,  -37,  -32,  -27,  -22,  -17,  -12,   -7,   -2
69
};
70
71
static SDL_AudioDeviceID audio_dev;
72
static int16_t * buffer;
73
static uint32_t buffer_size = 0;
74
static uint32_t rdidx = 0;
75
static uint32_t wridx = 0;
76
static uint32_t buffer_written = 0;
77
static uint32_t vera_samp_pos_rd = 0;
78
static uint32_t vera_samp_pos_wr = 0;
79
static uint32_t vera_samp_pos_hd = 0;
80
static uint32_t ym_samp_pos_rd = 0;
81
static uint32_t ym_samp_pos_wr = 0;
82
static uint32_t ym_samp_pos_hd = 0;
83
static uint32_t fs_samp_pos_rd = 0;
84
static uint32_t fs_samp_pos_wr = 0;
85
static uint32_t fs_samp_pos_hd = 0;
86
static uint32_t vera_samps_per_host_samps = 0;
87
static uint32_t ym_samps_per_host_samps = 0;
88
static uint32_t fs_samps_per_host_samps = 0;
89
// The *_SAMP_CLKS_PER_CPU_CLK ratios, worked out once in audio_init():
90
// MHZ is a variable, so the macros divide at run time, and audio_step()
91
// runs after every instruction.
92
static uint64_t vera_samp_clks_per_cpu_clk = 0;
93
static uint64_t ym_samp_clks_per_cpu_clk = 0;
94
static uint64_t fs_samp_clks_per_cpu_clk = 0;
95
static uint32_t limiter_amp = 0;
96
97
static int16_t psg_buf[2 * SAMPLES_PER_BUFFER];
98
static int16_t pcm_buf[2 * SAMPLES_PER_BUFFER];
99
static int16_t ym_buf[2 * SAMPLES_PER_BUFFER];
100
static int16_t fs_buf[2 * SAMPLES_PER_BUFFER];
101
102
uint32_t host_sample_rate = 0;
103
104
static void
105
audio_callback(void *userdata, Uint8 *stream, int len)
106
{
107
	if (audio_dev == 0) {
108
		return;
109
	}
110
111
	int expected = SAMPLES_PER_BUFFER * SAMPLE_BYTES;
112
	if (len != expected) {
113
		printf("Audio buffer size mismatch! (expected: %d, got: %d)\n", expected, len);
114
		return;
115
	}
116
117
	uint32_t spos = 0;
118
	if (rdidx > wridx) {
119
		uint32_t actual_len = SDL_min(len / SAMPLE_BYTES, (buffer_size - rdidx) / 2);
120
		if (actual_len > 0) {
121
			memcpy(&stream[spos], &buffer[rdidx], actual_len * SAMPLE_BYTES);
122
			spos += actual_len * SAMPLE_BYTES;
123
			len -= actual_len * SAMPLE_BYTES;
124
			rdidx = (rdidx + actual_len * 2) % buffer_size;
125
			buffer_written -= actual_len * 2;
126
		}
127
	}
128
	uint32_t actual_len = SDL_min(len / SAMPLE_BYTES, (wridx - rdidx) / 2);
129
	if (actual_len > 0) {
130
		memcpy(&stream[spos], &buffer[rdidx], actual_len * SAMPLE_BYTES);
131
		spos += actual_len * SAMPLE_BYTES;
132
		len -= actual_len * SAMPLE_BYTES;
133
		rdidx = (rdidx + actual_len * 2) % buffer_size;
134
		buffer_written -= actual_len * 2;
135
	}
136
	if (len > 0) memset(&stream[spos], 0, len);
137
}
138
139
void
140
audio_init(const char *dev_name, int num_audio_buffers)
141
{
142
	if (audio_dev > 0) {
143
		audio_close();
144
	}
145
146
	if (dev_name) {
147
		if (!strcmp("none", dev_name)) {
148
			return;
149
		}
150
	}
151
152
	// Set number of buffers
153
	int num_bufs = num_audio_buffers;
154
	if (num_bufs < 3) {
155
		num_bufs = 3;
156
	}
157
	if (num_bufs > 1024) {
158
		num_bufs = 1024;
159
	}
160
	buffer_size = SAMPLES_PER_BUFFER * num_bufs * 2;
161
162
	// Allocate audio buffer
163
	buffer = malloc(buffer_size * sizeof(int16_t));
164
	rdidx = 0;
165
	wridx = 0;
166
	buffer_written = 0;
167
168
	SDL_AudioSpec desired;
169
	SDL_AudioSpec obtained;
170
171
	// Setup SDL audio
172
	memset(&desired, 0, sizeof(desired));
173
	desired.freq     = AUDIO_SAMPLERATE;
174
	desired.format   = AUDIO_S16SYS;
175
	desired.samples  = SAMPLES_PER_BUFFER;
176
	desired.channels = 2;
177
	desired.callback = audio_callback;
178
179
	audio_dev = SDL_OpenAudioDevice(dev_name, 0, &desired, &obtained, SDL_AUDIO_ALLOW_FREQUENCY_CHANGE);
180
	if (audio_dev <= 0) {
181
		fprintf(stderr, "SDL_OpenAudioDevice failed: %s\n", SDL_GetError());
182
		if (dev_name != NULL) {
183
			audio_usage();
184
		}
185
		exit(-1);
186
	}
187
	if (obtained.freq <= 0 || (AUDIO_SAMPLERATE / obtained.freq) > SAMPLES_PER_BUFFER) {
188
		fprintf(stderr, "Obtained sample rate is too low");
189
		audio_close();
190
		return;
191
	}
192
193
	// Init YM2151 emulation. 3.579545 MHz clock
194
	YM_Create(3579545);
195
	YM_init(3579545/64, 60);
196
197
	host_sample_rate = obtained.freq;
198
	vera_samps_per_host_samps = ((25000000ULL << SAMP_POS_FRAC_BITS) / 512 / host_sample_rate);
199
	ym_samps_per_host_samps = ((3579545ULL << SAMP_POS_FRAC_BITS) / 64 / host_sample_rate);
200
	fs_samps_per_host_samps = vera_samps_per_host_samps;
201
	vera_samp_clks_per_cpu_clk = VERA_SAMP_CLKS_PER_CPU_CLK;
202
	ym_samp_clks_per_cpu_clk = YM_SAMP_CLKS_PER_CPU_CLK;
203
	fs_samp_clks_per_cpu_clk = FS_SAMP_CLKS_PER_CPU_CLK;
204
	vera_samp_pos_rd = 0;
205
	vera_samp_pos_wr = 0;
206
	vera_samp_pos_hd = 0;
207
	ym_samp_pos_rd = 0;
208
	ym_samp_pos_wr = 0;
209
	ym_samp_pos_hd = 0;
210
	fs_samp_pos_rd = 0;
211
	fs_samp_pos_wr = 0;
212
	fs_samp_pos_hd = 0;
213
	limiter_amp = (1 << 16);
214
215
	psg_buf[0] = psg_buf[1] = 0;
216
	pcm_buf[0] = pcm_buf[1] = 0;
217
	ym_buf[0] = ym_buf[1] = 0;
218
	fs_buf[0] = fs_buf[1] = 0;
219
220
	// Start playback
221
	SDL_PauseAudioDevice(audio_dev, 0);
222
}
223
224
void
225
audio_close(void)
226
{
227
	if (audio_dev == 0) {
228
		return;
229
	}
230
231
	SDL_CloseAudioDevice(audio_dev);
232
	audio_dev = 0;
233
234
	// Free audio buffers
235
	if (buffer != NULL) {
236
		free(buffer);
237
		buffer = NULL;
238
	}
239
}
240
241
void
242
audio_step(int cpu_clocks)
243
{
244
	// Accumulate how many samples each source have to render
245
	if (audio_dev == 0) {
246
		return;
247
	}
248
249
	while (cpu_clocks > 0) {
250
		// Only the source with the higest sample rate (YM2151) is needed for calculation
251
		uint32_t ym_room = (ym_samp_pos_rd - ym_samp_pos_hd - (1 << SAMP_POS_FRAC_BITS)) & SAMP_POS_MASK_FRAC;
252
		// min(cpu_clocks, ym_room / ratio), dividing only when the buffer
253
		// is nearly full rather than after every instruction
254
		uint32_t max_cpu_clks = (uint64_t)cpu_clocks * ym_samp_clks_per_cpu_clk <= ym_room ? (uint32_t)cpu_clocks : (uint32_t)(ym_room / ym_samp_clks_per_cpu_clk);
255
		vera_samp_pos_hd = (vera_samp_pos_hd + max_cpu_clks * vera_samp_clks_per_cpu_clk) & SAMP_POS_MASK_FRAC;
256
		ym_samp_pos_hd = (ym_samp_pos_hd + max_cpu_clks * ym_samp_clks_per_cpu_clk) & SAMP_POS_MASK_FRAC;
257
		fs_samp_pos_hd = (fs_samp_pos_hd + max_cpu_clks * fs_samp_clks_per_cpu_clk) & SAMP_POS_MASK_FRAC;
258
		cpu_clocks -= max_cpu_clks;
259
		if (cpu_clocks > 0) audio_render();
260
	}
261
}
262
263
// How many CPU clocks audio_step() can take in one call and still do
264
// exactly what that many one-clock calls would: up to and including the
265
// clock on which it next has to render, which is when the CPU can see a
266
// change (the PCM FIFO, VERA's AFLOW interrupt, the YM2151's state).
267
uint32_t
268
audio_clocks_to_render(void)
269
{
270
	if (audio_dev == 0) {
271
		return UINT32_MAX;
272
	}
273
	uint32_t ym_room = (ym_samp_pos_rd - ym_samp_pos_hd - (1 << SAMP_POS_FRAC_BITS)) & SAMP_POS_MASK_FRAC;
274
	return (uint32_t)(ym_room / ym_samp_clks_per_cpu_clk) + 1;
275
}
276
277
void
278
audio_render()
279
{
280
	// Render all audio sources until read and write positions catch up
281
	// This happens when there's a change to sound registers or one of the
282
	// sources' sample buffer head position is too far
283
	if (audio_dev == 0) {
284
		return;
285
	}
286
287
	uint32_t pos, len;
288
289
	pos = (vera_samp_pos_wr + 1) & SAMP_POS_MASK;
290
	len = ((vera_samp_pos_hd >> SAMP_POS_FRAC_BITS) - vera_samp_pos_wr) & SAMP_POS_MASK;
291
	vera_samp_pos_wr = vera_samp_pos_hd >> SAMP_POS_FRAC_BITS;
292
	if (pos + len > SAMPLES_PER_BUFFER) {
293
		psg_render(&psg_buf[pos * 2], SAMPLES_PER_BUFFER - pos);
294
		pcm_render(&pcm_buf[pos * 2], SAMPLES_PER_BUFFER - pos);
295
		len -= SAMPLES_PER_BUFFER - pos;
296
		pos = 0;
297
	}
298
	if (len > 0) {
299
		psg_render(&psg_buf[pos * 2], len);
300
		pcm_render(&pcm_buf[pos * 2], len);
301
	}
302
303
	pos = (ym_samp_pos_wr + 1) & SAMP_POS_MASK;
304
	len = ((ym_samp_pos_hd >> SAMP_POS_FRAC_BITS) - ym_samp_pos_wr) & SAMP_POS_MASK;
305
	ym_samp_pos_wr = ym_samp_pos_hd >> SAMP_POS_FRAC_BITS;
306
	if ((pos + len) > SAMPLES_PER_BUFFER) {
307
		YM_stream_update((uint16_t *)&ym_buf[pos * 2], SAMPLES_PER_BUFFER - pos);
308
		len -= SAMPLES_PER_BUFFER - pos;
309
		pos = 0;
310
	}
311
	if (len > 0) {
312
		YM_stream_update((uint16_t *)&ym_buf[pos * 2], len);
313
	}
314
315
	pos = (fs_samp_pos_wr + 1) & SAMP_POS_MASK;
316
	len = ((fs_samp_pos_hd >> SAMP_POS_FRAC_BITS) - fs_samp_pos_wr) & SAMP_POS_MASK;
317
	fs_samp_pos_wr = fs_samp_pos_hd >> SAMP_POS_FRAC_BITS;
318
	if ((pos + len) > SAMPLES_PER_BUFFER) {
319
		midi_synth_render(&fs_buf[pos * 2], SAMPLES_PER_BUFFER - pos);
320
		len -= SAMPLES_PER_BUFFER - pos;
321
		pos = 0;
322
	}
323
	if (len > 0) {
324
		midi_synth_render(&fs_buf[pos * 2], len);
325
	}
326
327
	uint32_t wridx_old = wridx;
328
	uint32_t len_vera = (vera_samp_pos_hd - vera_samp_pos_rd) & SAMP_POS_MASK_FRAC;
329
	uint32_t len_ym = (ym_samp_pos_hd - ym_samp_pos_rd) & SAMP_POS_MASK_FRAC;
330
	uint32_t len_fs = (fs_samp_pos_hd - fs_samp_pos_rd) & SAMP_POS_MASK_FRAC;
331
	if (len_vera < (4 << SAMP_POS_FRAC_BITS) || len_ym < (4 << SAMP_POS_FRAC_BITS) || len_fs < (4 << SAMP_POS_FRAC_BITS)) {
332
		// not enough samples yet, at least 4 are needed for the filter
333
		return;
334
	}
335
	len_vera = (len_vera - (4 << SAMP_POS_FRAC_BITS)) / vera_samps_per_host_samps;
336
	len_ym = (len_ym - (4 << SAMP_POS_FRAC_BITS)) / ym_samps_per_host_samps;
337
	len_fs = (len_fs - (4 << SAMP_POS_FRAC_BITS)) / fs_samps_per_host_samps;
338
	len = SDL_min(len_vera, len_ym);
339
	len = SDL_min(len, len_fs);
340
	SDL_LockAudioDevice(audio_dev);
341
	for (int i = 0; i < len; i++) {
342
		int32_t samp[8];
343
		int32_t filter_idx = 0;
344
		int32_t vera_out_l = 0;
345
		int32_t vera_out_r = 0;
346
		int32_t ym_out_l = 0;
347
		int32_t ym_out_r = 0;
348
		int32_t fs_out_l = 0;
349
		int32_t fs_out_r = 0;
350
		// Don't resample VERA outputs if the host sample rate is as desired
351
		if (host_sample_rate == AUDIO_SAMPLERATE) {
352
			pos = (vera_samp_pos_rd >> SAMP_POS_FRAC_BITS) * 2;
353
			vera_out_l = ((uint32_t)psg_buf[pos] + pcm_buf[pos]) << 14;
354
			vera_out_r = ((uint32_t)psg_buf[pos + 1] + pcm_buf[pos + 1]) << 14;
355
		} else {
356
			filter_idx = (vera_samp_pos_rd >> (SAMP_POS_FRAC_BITS - 8)) & 0xff;
357
			pos = (vera_samp_pos_rd >> SAMP_POS_FRAC_BITS) * 2;
358
			for (int j = 0; j < 8; j += 2) {
359
				samp[j] = (int32_t)psg_buf[pos] + pcm_buf[pos];
360
				samp[j + 1] = (int32_t)psg_buf[pos + 1] + pcm_buf[pos + 1];
361
				pos = (pos + 2) & (SAMP_POS_MASK * 2);
362
			}
363
			vera_out_l += samp[0] * filter[256 + filter_idx];
364
			vera_out_r += samp[1] * filter[256 + filter_idx];
365
			vera_out_l += samp[2] * filter[  0 + filter_idx];
366
			vera_out_r += samp[3] * filter[  0 + filter_idx];
367
			vera_out_l += samp[4] * filter[255 - filter_idx];
368
			vera_out_r += samp[5] * filter[255 - filter_idx];
369
			vera_out_l += samp[6] * filter[511 - filter_idx];
370
			vera_out_r += samp[7] * filter[511 - filter_idx];
371
		}
372
		filter_idx = (ym_samp_pos_rd >> (SAMP_POS_FRAC_BITS - 8)) & 0xff;
373
		pos = (ym_samp_pos_rd >> SAMP_POS_FRAC_BITS) * 2;
374
		for (int j = 0; j < 8; j += 2) {
375
			samp[j] = ym_buf[pos];
376
			samp[j + 1] = ym_buf[pos + 1];
377
			pos = (pos + 2) & (SAMP_POS_MASK * 2);
378
		}
379
		ym_out_l += samp[0] * filter[256 + filter_idx];
380
		ym_out_r += samp[1] * filter[256 + filter_idx];
381
		ym_out_l += samp[2] * filter[  0 + filter_idx];
382
		ym_out_r += samp[3] * filter[  0 + filter_idx];
383
		ym_out_l += samp[4] * filter[255 - filter_idx];
384
		ym_out_r += samp[5] * filter[255 - filter_idx];
385
		ym_out_l += samp[6] * filter[511 - filter_idx];
386
		ym_out_r += samp[7] * filter[511 - filter_idx];
387
		// Don't resample MIDI synth outputs if the host sample rate matches it
388
		if (host_sample_rate == AUDIO_SAMPLERATE) {
389
			pos = (fs_samp_pos_rd >> SAMP_POS_FRAC_BITS) * 2;
390
			fs_out_l = (uint32_t)fs_buf[pos] << 14;
391
			fs_out_r = (uint32_t)fs_buf[pos + 1] << 14;
392
		} else {
393
			filter_idx = (fs_samp_pos_rd >> (SAMP_POS_FRAC_BITS - 8)) & 0xff;
394
			pos = (fs_samp_pos_rd >> SAMP_POS_FRAC_BITS) * 2;
395
			for (int j = 0; j < 8; j += 2) {
396
				samp[j] = fs_buf[pos];
397
				samp[j + 1] = fs_buf[pos + 1];
398
				pos = (pos + 2) & (SAMP_POS_MASK * 2);
399
			}
400
			fs_out_l += samp[0] * filter[256 + filter_idx];
401
			fs_out_r += samp[1] * filter[256 + filter_idx];
402
			fs_out_l += samp[2] * filter[  0 + filter_idx];
403
			fs_out_r += samp[3] * filter[  0 + filter_idx];
404
			fs_out_l += samp[4] * filter[255 - filter_idx];
405
			fs_out_r += samp[5] * filter[255 - filter_idx];
406
			fs_out_l += samp[6] * filter[511 - filter_idx];
407
			fs_out_r += samp[7] * filter[511 - filter_idx];
408
		}
409
		// VERA+YM mixing is according to the Developer Board
410
		// Loudest single PSG channel is 1/8 times the max output
411
		// mix = (psg + pcm) * 2 + ym + fs * 4
412
		int32_t mix_l = (vera_out_l >> 13) + (ym_out_l >> 15) + (fs_out_l >> 12);
413
		int32_t mix_r = (vera_out_r >> 13) + (ym_out_r >> 15) + (fs_out_r >> 12);
414
		uint32_t amp = SDL_max(SDL_abs(mix_l), SDL_abs(mix_r));
415
		if (amp > 32767) {
416
			uint32_t limiter_amp_new = (32767 << 16) / amp;
417
			limiter_amp = SDL_min(limiter_amp_new, limiter_amp);
418
		}
419
		buffer[wridx++] = (int16_t)((mix_l * limiter_amp) >> 16);
420
		buffer[wridx++] = (int16_t)((mix_r * limiter_amp) >> 16);
421
		x16_control_push_audio(buffer[wridx - 2], buffer[wridx - 1]);  /* RRDC /audio tee */
422
		if (limiter_amp < (1 << 16)) limiter_amp++;
423
		vera_samp_pos_rd = (vera_samp_pos_rd + vera_samps_per_host_samps) & SAMP_POS_MASK_FRAC;
424
		ym_samp_pos_rd = (ym_samp_pos_rd + ym_samps_per_host_samps) & SAMP_POS_MASK_FRAC;
425
		fs_samp_pos_rd = (fs_samp_pos_rd + fs_samps_per_host_samps) & SAMP_POS_MASK_FRAC;
426
		if (wridx == buffer_size) {
427
			wav_recorder_process(&buffer[wridx_old], (buffer_size - wridx_old) / 2);
428
			wridx = 0;
429
			wridx_old = 0;
430
		}
431
	}
432
	if ((wridx - wridx_old) > 0) {
433
		wav_recorder_process(&buffer[wridx_old], (wridx - wridx_old) / 2);
434
	}
435
	buffer_written += len * 2;
436
	if (buffer_written > buffer_size) {
437
		// Prevent the buffer from overflowing by skipping the read pointer ahead.
438
		uint32_t buffer_skip_amount = (buffer_written / buffer_size) * SAMPLES_PER_BUFFER * 2;
439
		rdidx = (rdidx + buffer_skip_amount) % buffer_size;
440
		buffer_written -= buffer_skip_amount;
441
	}
442
	SDL_UnlockAudioDevice(audio_dev);
443
444
	// catch up all buffers if they are too far behind
445
	uint32_t skip = len_vera - len;
446
	if (skip > 1) {
447
		vera_samp_pos_rd = (vera_samp_pos_rd + vera_samps_per_host_samps) & SAMP_POS_MASK_FRAC;
448
	}
449
	skip = len_ym - len;
450
	if (skip > 1) {
451
		ym_samp_pos_rd = (ym_samp_pos_rd + ym_samps_per_host_samps) & SAMP_POS_MASK_FRAC;
452
	}
453
	skip = len_fs - len;
454
	if (skip > 1) {
455
		fs_samp_pos_rd = (fs_samp_pos_rd + fs_samps_per_host_samps) & SAMP_POS_MASK_FRAC;
456
	}
457
}
458
459
void
460
audio_usage(void)
461
{
462
	// SDL_GetAudioDeviceName doesn't work if audio isn't initialized.
463
	// Since argument parsing happens before initializing SDL, ensure the
464
	// audio subsystem is initialized before printing audio device names.
465
	SDL_InitSubSystem(SDL_INIT_AUDIO);
466
467
	// List all available sound devices
468
	printf("The following sound output devices are available:\n");
469
	const int sounds = SDL_GetNumAudioDevices(0);
470
	for (int i = 0; i < sounds; ++i) {
471
		printf("\t%s\n", SDL_GetAudioDeviceName(i, 0));
472
	}
473
474
	SDL_Quit();
475
	exit(1);
476
}