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