comparison render_sdl.c @ 1931:374a5ae694e8 mame_interp

Merge from default
author Michael Pavone <pavone@retrodev.com>
date Sat, 18 Apr 2020 11:42:53 -0700
parents 33c0c4579c1f
children b387f1c5a1d0
comparison
equal deleted inserted replaced
1843:13abdc98379e 1931:374a5ae694e8
44 static uint8_t render_gl = 1; 44 static uint8_t render_gl = 1;
45 static uint8_t scanlines = 0; 45 static uint8_t scanlines = 0;
46 46
47 static uint32_t last_frame = 0; 47 static uint32_t last_frame = 0;
48 48
49 static uint8_t output_channels;
50 static uint32_t buffer_samples, sample_rate;
51 static uint32_t missing_count;
52
53 static SDL_mutex * audio_mutex; 49 static SDL_mutex * audio_mutex;
54 static SDL_cond * audio_ready; 50 static SDL_cond * audio_ready;
55 static uint8_t quitting = 0; 51 static uint8_t quitting = 0;
56 52
57 struct audio_source {
58 SDL_cond *cond;
59 int16_t *front;
60 int16_t *back;
61 double dt;
62 uint64_t buffer_fraction;
63 uint64_t buffer_inc;
64 float gain_mult;
65 uint32_t buffer_pos;
66 uint32_t read_start;
67 uint32_t read_end;
68 uint32_t lowpass_alpha;
69 uint32_t mask;
70 int16_t last_left;
71 int16_t last_right;
72 uint8_t num_channels;
73 uint8_t front_populated;
74 };
75
76 static audio_source *audio_sources[8];
77 static audio_source *inactive_audio_sources[8];
78 static uint8_t num_audio_sources;
79 static uint8_t num_inactive_audio_sources;
80 static uint8_t sync_to_audio; 53 static uint8_t sync_to_audio;
81 static uint32_t min_buffered; 54 static uint32_t min_buffered;
82 static float overall_gain_mult, *mix_buf; 55
83 static int sample_size; 56 uint32_t render_min_buffered(void)
84 57 {
85 typedef void (*conv_func)(float *samples, void *vstream, int sample_count); 58 return min_buffered;
86 59 }
87 static void convert_null(float *samples, void *vstream, int sample_count) 60
88 { 61 uint8_t render_is_audio_sync(void)
89 memset(vstream, 0, sample_count * sample_size); 62 {
90 } 63 return sync_to_audio;
91 64 }
92 static void convert_s16(float *samples, void *vstream, int sample_count) 65
93 { 66 void render_buffer_consumed(audio_source *src)
94 int16_t *stream = vstream; 67 {
95 for (int16_t *end = stream + sample_count; stream < end; stream++, samples++) 68 SDL_CondSignal(src->opaque);
96 { 69 }
97 float sample = *samples;
98 int16_t out_sample;
99 if (sample >= 1.0f) {
100 out_sample = 0x7FFF;
101 } else if (sample <= -1.0f) {
102 out_sample = -0x8000;
103 } else {
104 out_sample = sample * 0x7FFF;
105 }
106 *stream = out_sample;
107 }
108 }
109
110 static void clamp_f32(float *samples, void *vstream, int sample_count)
111 {
112 for (; sample_count > 0; sample_count--, samples++)
113 {
114 float sample = *samples;
115 if (sample > 1.0f) {
116 sample = 1.0f;
117 } else if (sample < -1.0f) {
118 sample = -1.0f;
119 }
120 *samples = sample;
121 }
122 }
123
124 static int32_t mix_f32(audio_source *audio, float *stream, int samples)
125 {
126 float *end = stream + samples;
127 int16_t *src = audio->front;
128 uint32_t i = audio->read_start;
129 uint32_t i_end = audio->read_end;
130 float *cur = stream;
131 float gain_mult = audio->gain_mult * overall_gain_mult;
132 size_t first_add = output_channels > 1 ? 1 : 0, second_add = output_channels > 1 ? output_channels - 1 : 1;
133 if (audio->num_channels == 1) {
134 while (cur < end && i != i_end)
135 {
136 *cur += gain_mult * ((float)src[i]) / 0x7FFF;
137 cur += first_add;
138 *cur += gain_mult * ((float)src[i++]) / 0x7FFF;
139 cur += second_add;
140 i &= audio->mask;
141 }
142 } else {
143 while(cur < end && i != i_end)
144 {
145 *cur += gain_mult * ((float)src[i++]) / 0x7FFF;
146 cur += first_add;
147 *cur += gain_mult * ((float)src[i++]) / 0x7FFF;
148 cur += second_add;
149 i &= audio->mask;
150 }
151 }
152 if (!sync_to_audio) {
153 audio->read_start = i;
154 }
155 if (cur != end) {
156 debug_message("Underflow of %d samples, read_start: %d, read_end: %d, mask: %X\n", (int)(end-cur)/2, audio->read_start, audio->read_end, audio->mask);
157 return (cur-end)/2;
158 } else {
159 return ((i_end - i) & audio->mask) / audio->num_channels;
160 }
161 }
162
163 static conv_func convert;
164 70
165 static void audio_callback(void * userdata, uint8_t *byte_stream, int len) 71 static void audio_callback(void * userdata, uint8_t *byte_stream, int len)
166 { 72 {
167 uint8_t num_populated;
168 SDL_LockMutex(audio_mutex); 73 SDL_LockMutex(audio_mutex);
74 uint8_t all_ready;
169 do { 75 do {
170 num_populated = 0; 76 all_ready = all_sources_ready();
171 for (uint8_t i = 0; i < num_audio_sources; i++) 77 if (!quitting && !all_ready) {
172 {
173 if (audio_sources[i]->front_populated) {
174 num_populated++;
175 }
176 }
177 if (!quitting && num_populated < num_audio_sources) {
178 fflush(stdout);
179 SDL_CondWait(audio_ready, audio_mutex); 78 SDL_CondWait(audio_ready, audio_mutex);
180 } 79 }
181 } while(!quitting && num_populated < num_audio_sources); 80 } while(!quitting && !all_ready);
182 int samples = len / sample_size;
183 float *mix_dest = mix_buf ? mix_buf : (float *)byte_stream;
184 memset(mix_dest, 0, samples * sizeof(float));
185 if (!quitting) { 81 if (!quitting) {
186 for (uint8_t i = 0; i < num_audio_sources; i++) 82 mix_and_convert(byte_stream, len, NULL);
187 { 83 }
188 mix_f32(audio_sources[i], mix_dest, samples);
189 audio_sources[i]->front_populated = 0;
190 SDL_CondSignal(audio_sources[i]->cond);
191 }
192 }
193 convert(mix_dest, byte_stream, samples);
194 SDL_UnlockMutex(audio_mutex); 84 SDL_UnlockMutex(audio_mutex);
195 } 85 }
196 86
197 #define NO_LAST_BUFFERED -2000000000 87 #define NO_LAST_BUFFERED -2000000000
198 static int32_t last_buffered = NO_LAST_BUFFERED; 88 static int32_t last_buffered = NO_LAST_BUFFERED;
206 { 96 {
207 if (cur_min_buffered < 0) { 97 if (cur_min_buffered < 0) {
208 //underflow last frame, but main thread hasn't gotten a chance to call SDL_PauseAudio yet 98 //underflow last frame, but main thread hasn't gotten a chance to call SDL_PauseAudio yet
209 return; 99 return;
210 } 100 }
211 cur_min_buffered = 0x7FFFFFFF; 101 cur_min_buffered = mix_and_convert(byte_stream, len, &min_remaining_buffer);
212 min_remaining_buffer = 0xFFFFFFFF; 102 }
213 float *mix_dest = mix_buf ? mix_buf : (float *)byte_stream; 103
214 int samples = len / sample_size; 104 void render_lock_audio()
215 memset(mix_dest, 0, samples * sizeof(float));
216 for (uint8_t i = 0; i < num_audio_sources; i++)
217 {
218
219 int32_t buffered = mix_f32(audio_sources[i], mix_dest, samples);
220 cur_min_buffered = buffered < cur_min_buffered ? buffered : cur_min_buffered;
221 uint32_t remaining = (audio_sources[i]->mask + 1)/audio_sources[i]->num_channels - buffered;
222 min_remaining_buffer = remaining < min_remaining_buffer ? remaining : min_remaining_buffer;
223 }
224 convert(mix_dest, byte_stream, samples);
225 }
226
227 static void lock_audio()
228 { 105 {
229 if (sync_to_audio) { 106 if (sync_to_audio) {
230 SDL_LockMutex(audio_mutex); 107 SDL_LockMutex(audio_mutex);
231 } else { 108 } else {
232 SDL_LockAudio(); 109 SDL_LockAudio();
233 } 110 }
234 } 111 }
235 112
236 static void unlock_audio() 113 void render_unlock_audio()
237 { 114 {
238 if (sync_to_audio) { 115 if (sync_to_audio) {
239 SDL_UnlockMutex(audio_mutex); 116 SDL_UnlockMutex(audio_mutex);
240 } else { 117 } else {
241 SDL_UnlockAudio(); 118 SDL_UnlockAudio();
247 SDL_LockMutex(audio_mutex); 124 SDL_LockMutex(audio_mutex);
248 quitting = 1; 125 quitting = 1;
249 SDL_CondSignal(audio_ready); 126 SDL_CondSignal(audio_ready);
250 SDL_UnlockMutex(audio_mutex); 127 SDL_UnlockMutex(audio_mutex);
251 SDL_CloseAudio(); 128 SDL_CloseAudio();
129 /*
130 FIXME: move this to render_audio.c
252 if (mix_buf) { 131 if (mix_buf) {
253 free(mix_buf); 132 free(mix_buf);
254 mix_buf = NULL; 133 mix_buf = NULL;
255 } 134 }
256 } 135 */
257 136 }
258 #define BUFFER_INC_RES 0x40000000UL 137
259 138 void *render_new_audio_opaque(void)
260 void render_audio_adjust_clock(audio_source *src, uint64_t master_clock, uint64_t sample_divider) 139 {
261 { 140 return SDL_CreateCond();
262 src->buffer_inc = ((BUFFER_INC_RES * (uint64_t)sample_rate) / master_clock) * sample_divider; 141 }
263 } 142
264 143 void render_free_audio_opaque(void *opaque)
265 audio_source *render_audio_source(uint64_t master_clock, uint64_t sample_divider, uint8_t channels) 144 {
266 { 145 SDL_DestroyCond(opaque);
267 audio_source *ret = NULL; 146 }
268 uint32_t alloc_size = sync_to_audio ? channels * buffer_samples : nearest_pow2(min_buffered * 4 * channels); 147
269 lock_audio(); 148 void render_audio_created(audio_source *source)
270 if (num_audio_sources < 8) { 149 {
271 ret = malloc(sizeof(audio_source));
272 ret->back = malloc(alloc_size * sizeof(int16_t));
273 ret->front = sync_to_audio ? malloc(alloc_size * sizeof(int16_t)) : ret->back;
274 ret->front_populated = 0;
275 ret->cond = SDL_CreateCond();
276 ret->num_channels = channels;
277 audio_sources[num_audio_sources++] = ret;
278 }
279 unlock_audio();
280 if (!ret) {
281 fatal_error("Too many audio sources!");
282 } else {
283 render_audio_adjust_clock(ret, master_clock, sample_divider);
284 double lowpass_cutoff = get_lowpass_cutoff(config);
285 double rc = (1.0 / lowpass_cutoff) / (2.0 * M_PI);
286 ret->dt = 1.0 / ((double)master_clock / (double)(sample_divider));
287 double alpha = ret->dt / (ret->dt + rc);
288 ret->lowpass_alpha = (int32_t)(((double)0x10000) * alpha);
289 ret->buffer_pos = 0;
290 ret->buffer_fraction = 0;
291 ret->last_left = ret->last_right = 0;
292 ret->read_start = 0;
293 ret->read_end = sync_to_audio ? buffer_samples * channels : 0;
294 ret->mask = sync_to_audio ? 0xFFFFFFFF : alloc_size-1;
295 ret->gain_mult = 1.0f;
296 }
297 if (sync_to_audio && SDL_GetAudioStatus() == SDL_AUDIO_PAUSED) { 150 if (sync_to_audio && SDL_GetAudioStatus() == SDL_AUDIO_PAUSED) {
298 SDL_PauseAudio(0); 151 SDL_PauseAudio(0);
299 } 152 }
300 return ret; 153 }
301 } 154
302 155 void render_source_paused(audio_source *src, uint8_t remaining_sources)
303 static float db_to_mult(float gain) 156 {
304 { 157 if (sync_to_audio) {
305 return powf(10.0f, gain/20.0f); 158 SDL_CondSignal(audio_ready);
306 } 159 }
307 160 if (!remaining_sources) {
308 void render_audio_source_gaindb(audio_source *src, float gain) 161 SDL_PauseAudio(0);
309 { 162 }
310 src->gain_mult = db_to_mult(gain); 163 }
311 } 164
312 165 void render_source_resumed(audio_source *src)
313 void render_pause_source(audio_source *src) 166 {
314 {
315 uint8_t need_pause = 0;
316 lock_audio();
317 for (uint8_t i = 0; i < num_audio_sources; i++)
318 {
319 if (audio_sources[i] == src) {
320 audio_sources[i] = audio_sources[--num_audio_sources];
321 if (sync_to_audio) {
322 SDL_CondSignal(audio_ready);
323 }
324 break;
325 }
326 }
327 if (!num_audio_sources) {
328 need_pause = 1;
329 }
330 unlock_audio();
331 if (need_pause) {
332 SDL_PauseAudio(1);
333 }
334 inactive_audio_sources[num_inactive_audio_sources++] = src;
335 }
336
337 void render_resume_source(audio_source *src)
338 {
339 lock_audio();
340 if (num_audio_sources < 8) {
341 audio_sources[num_audio_sources++] = src;
342 }
343 unlock_audio();
344 for (uint8_t i = 0; i < num_inactive_audio_sources; i++)
345 {
346 if (inactive_audio_sources[i] == src) {
347 inactive_audio_sources[i] = inactive_audio_sources[--num_inactive_audio_sources];
348 }
349 }
350 if (sync_to_audio) { 167 if (sync_to_audio) {
351 SDL_PauseAudio(0); 168 SDL_PauseAudio(0);
352 } 169 }
353 } 170 }
354 171
355 void render_free_source(audio_source *src) 172 void render_do_audio_ready(audio_source *src)
356 {
357 render_pause_source(src);
358
359 free(src->front);
360 if (sync_to_audio) {
361 free(src->back);
362 SDL_DestroyCond(src->cond);
363 }
364 free(src);
365 }
366 static uint32_t sync_samples;
367 static void do_audio_ready(audio_source *src)
368 { 173 {
369 if (sync_to_audio) { 174 if (sync_to_audio) {
370 SDL_LockMutex(audio_mutex); 175 SDL_LockMutex(audio_mutex);
371 while (src->front_populated) { 176 while (src->front_populated) {
372 SDL_CondWait(src->cond, audio_mutex); 177 SDL_CondWait(src->opaque, audio_mutex);
373 } 178 }
374 int16_t *tmp = src->front; 179 int16_t *tmp = src->front;
375 src->front = src->back; 180 src->front = src->back;
376 src->back = tmp; 181 src->back = tmp;
377 src->front_populated = 1; 182 src->front_populated = 1;
388 SDL_PauseAudio(0); 193 SDL_PauseAudio(0);
389 } 194 }
390 } 195 }
391 } 196 }
392 197
393 static int16_t lowpass_sample(audio_source *src, int16_t last, int16_t current)
394 {
395 int32_t tmp = current * src->lowpass_alpha + last * (0x10000 - src->lowpass_alpha);
396 current = tmp >> 16;
397 return current;
398 }
399
400 static void interp_sample(audio_source *src, int16_t last, int16_t current)
401 {
402 int64_t tmp = last * ((src->buffer_fraction << 16) / src->buffer_inc);
403 tmp += current * (0x10000 - ((src->buffer_fraction << 16) / src->buffer_inc));
404 src->back[src->buffer_pos++] = tmp >> 16;
405 }
406
407 void render_put_mono_sample(audio_source *src, int16_t value)
408 {
409 value = lowpass_sample(src, src->last_left, value);
410 src->buffer_fraction += src->buffer_inc;
411 uint32_t base = sync_to_audio ? 0 : src->read_end;
412 while (src->buffer_fraction > BUFFER_INC_RES)
413 {
414 src->buffer_fraction -= BUFFER_INC_RES;
415 interp_sample(src, src->last_left, value);
416
417 if (((src->buffer_pos - base) & src->mask) >= sync_samples) {
418 do_audio_ready(src);
419 }
420 src->buffer_pos &= src->mask;
421 }
422 src->last_left = value;
423 }
424
425 void render_put_stereo_sample(audio_source *src, int16_t left, int16_t right)
426 {
427 left = lowpass_sample(src, src->last_left, left);
428 right = lowpass_sample(src, src->last_right, right);
429 src->buffer_fraction += src->buffer_inc;
430 uint32_t base = sync_to_audio ? 0 : src->read_end;
431 while (src->buffer_fraction > BUFFER_INC_RES)
432 {
433 src->buffer_fraction -= BUFFER_INC_RES;
434
435 interp_sample(src, src->last_left, left);
436 interp_sample(src, src->last_right, right);
437
438 if (((src->buffer_pos - base) & src->mask)/2 >= sync_samples) {
439 do_audio_ready(src);
440 }
441 src->buffer_pos &= src->mask;
442 }
443 src->last_left = left;
444 src->last_right = right;
445 }
446
447 static SDL_Joystick * joysticks[MAX_JOYSTICKS]; 198 static SDL_Joystick * joysticks[MAX_JOYSTICKS];
448 static int joystick_sdl_index[MAX_JOYSTICKS]; 199 static int joystick_sdl_index[MAX_JOYSTICKS];
200 static uint8_t joystick_index_locked[MAX_JOYSTICKS];
449 201
450 int render_width() 202 int render_width()
451 { 203 {
452 return main_width; 204 return main_width;
453 } 205 }
633 static void render_alloc_surfaces() 385 static void render_alloc_surfaces()
634 { 386 {
635 if (texture_init) { 387 if (texture_init) {
636 return; 388 return;
637 } 389 }
638 sdl_textures= malloc(sizeof(SDL_Texture *) * 2); 390 sdl_textures= calloc(sizeof(SDL_Texture *), 3);
639 num_textures = 2; 391 num_textures = 3;
640 texture_init = 1; 392 texture_init = 1;
641 #ifndef DISABLE_OPENGL 393 #ifndef DISABLE_OPENGL
642 if (render_gl) { 394 if (render_gl) {
643 sdl_textures[0] = sdl_textures[1] = NULL;
644 gl_setup(); 395 gl_setup();
645 } else { 396 } else {
646 #endif 397 #endif
647 tern_val def = {.ptrval = "linear"}; 398 tern_val def = {.ptrval = "linear"};
648 char *scaling = tern_find_path_default(config, "video\0scaling\0", def, TVAL_PTR).ptrval; 399 char *scaling = tern_find_path_default(config, "video\0scaling\0", def, TVAL_PTR).ptrval;
887 } 638 }
888 } 639 }
889 return -1; 640 return -1;
890 } 641 }
891 642
643 static int lowest_unlocked_joystick_index(void)
644 {
645 for (int i = 0; i < MAX_JOYSTICKS; i++) {
646 if (!joystick_index_locked[i]) {
647 return i;
648 }
649 }
650 return -1;
651 }
652
892 SDL_Joystick *render_get_joystick(int index) 653 SDL_Joystick *render_get_joystick(int index)
893 { 654 {
894 if (index >= MAX_JOYSTICKS) { 655 if (index >= MAX_JOYSTICKS) {
895 return NULL; 656 return NULL;
896 } 657 }
908 return guid_string; 669 return guid_string;
909 } 670 }
910 671
911 SDL_GameController *render_get_controller(int index) 672 SDL_GameController *render_get_controller(int index)
912 { 673 {
913 if (index >= MAX_JOYSTICKS) { 674 if (index >= MAX_JOYSTICKS || !joysticks[index]) {
914 return NULL; 675 return NULL;
915 } 676 }
916 return SDL_GameControllerOpen(joystick_sdl_index[index]); 677 return SDL_GameControllerOpen(joystick_sdl_index[index]);
678 }
679
680 static uint8_t gc_events_enabled;
681 static SDL_GameController *controllers[MAX_JOYSTICKS];
682 void render_enable_gamepad_events(uint8_t enabled)
683 {
684 if (enabled != gc_events_enabled) {
685 gc_events_enabled = enabled;
686 for (int i = 0; i < MAX_JOYSTICKS; i++) {
687 if (enabled) {
688 controllers[i] = render_get_controller(i);
689 } else if (controllers[i]) {
690 SDL_GameControllerClose(controllers[i]);
691 controllers[i] = NULL;
692 }
693 }
694 }
917 } 695 }
918 696
919 static uint32_t overscan_top[NUM_VID_STD] = {2, 21}; 697 static uint32_t overscan_top[NUM_VID_STD] = {2, 21};
920 static uint32_t overscan_bot[NUM_VID_STD] = {1, 17}; 698 static uint32_t overscan_bot[NUM_VID_STD] = {1, 17};
921 static uint32_t overscan_left[NUM_VID_STD] = {13, 13}; 699 static uint32_t overscan_left[NUM_VID_STD] = {13, 13};
922 static uint32_t overscan_right[NUM_VID_STD] = {14, 14}; 700 static uint32_t overscan_right[NUM_VID_STD] = {14, 14};
923 static vid_std video_standard = VID_NTSC; 701 static vid_std video_standard = VID_NTSC;
924 static uint8_t need_ui_fb_resize; 702 static uint8_t need_ui_fb_resize;
703
704 int lock_joystick_index(int joystick, int desired_index)
705 {
706 if (desired_index < 0) {
707 desired_index = lowest_unlocked_joystick_index();
708 if (desired_index < 0 || desired_index >= joystick) {
709 return joystick;
710 }
711 }
712 SDL_Joystick *tmp_joy = joysticks[joystick];
713 int tmp_index = joystick_sdl_index[joystick];
714 joysticks[joystick] = joysticks[desired_index];
715 joystick_sdl_index[joystick] = joystick_sdl_index[desired_index];
716 joystick_index_locked[joystick] = joystick_sdl_index[desired_index];
717 joysticks[desired_index] = tmp_joy;
718 joystick_sdl_index[desired_index] = tmp_index;
719 joystick_index_locked[desired_index] = 1;
720 //update bindings as the controllers being swapped may have different mappings
721 handle_joy_added(desired_index);
722 if (joysticks[joystick]) {
723 handle_joy_added(joystick);
724 }
725 return desired_index;
726 }
925 727
926 static int32_t handle_event(SDL_Event *event) 728 static int32_t handle_event(SDL_Event *event)
927 { 729 {
928 if (custom_event_handler) { 730 if (custom_event_handler) {
929 custom_event_handler(event); 731 custom_event_handler(event);
937 break; 739 break;
938 case SDL_JOYBUTTONDOWN: 740 case SDL_JOYBUTTONDOWN:
939 handle_joydown(find_joystick_index(event->jbutton.which), event->jbutton.button); 741 handle_joydown(find_joystick_index(event->jbutton.which), event->jbutton.button);
940 break; 742 break;
941 case SDL_JOYBUTTONUP: 743 case SDL_JOYBUTTONUP:
942 handle_joyup(find_joystick_index(event->jbutton.which), event->jbutton.button); 744 handle_joyup(lock_joystick_index(find_joystick_index(event->jbutton.which), -1), event->jbutton.button);
943 break; 745 break;
944 case SDL_JOYHATMOTION: 746 case SDL_JOYHATMOTION:
945 handle_joy_dpad(find_joystick_index(event->jhat.which), event->jhat.hat, event->jhat.value); 747 handle_joy_dpad(lock_joystick_index(find_joystick_index(event->jhat.which), -1), event->jhat.hat, event->jhat.value);
946 break; 748 break;
947 case SDL_JOYAXISMOTION: 749 case SDL_JOYAXISMOTION:
948 handle_joy_axis(find_joystick_index(event->jaxis.which), event->jaxis.axis, event->jaxis.value); 750 handle_joy_axis(lock_joystick_index(find_joystick_index(event->jaxis.which), -1), event->jaxis.axis, event->jaxis.value);
949 break; 751 break;
950 case SDL_JOYDEVICEADDED: 752 case SDL_JOYDEVICEADDED:
951 if (event->jdevice.which < MAX_JOYSTICKS) { 753 if (event->jdevice.which < MAX_JOYSTICKS) {
952 int index = lowest_unused_joystick_index(); 754 int index = lowest_unused_joystick_index();
953 if (index >= 0) { 755 if (index >= 0) {
954 SDL_Joystick * joy = joysticks[index] = SDL_JoystickOpen(event->jdevice.which); 756 SDL_Joystick * joy = joysticks[index] = SDL_JoystickOpen(event->jdevice.which);
955 joystick_sdl_index[index] = event->jdevice.which; 757 joystick_sdl_index[index] = event->jdevice.which;
758 joystick_index_locked[index] = 0;
759 if (gc_events_enabled) {
760 controllers[index] = SDL_GameControllerOpen(event->jdevice.which);
761 }
956 if (joy) { 762 if (joy) {
957 debug_message("Joystick %d added: %s\n", index, SDL_JoystickName(joy)); 763 debug_message("Joystick %d added: %s\n", index, SDL_JoystickName(joy));
958 debug_message("\tNum Axes: %d\n\tNum Buttons: %d\n\tNum Hats: %d\n", SDL_JoystickNumAxes(joy), SDL_JoystickNumButtons(joy), SDL_JoystickNumHats(joy)); 764 debug_message("\tNum Axes: %d\n\tNum Buttons: %d\n\tNum Hats: %d\n", SDL_JoystickNumAxes(joy), SDL_JoystickNumButtons(joy), SDL_JoystickNumHats(joy));
959 handle_joy_added(index); 765 handle_joy_added(index);
960 } 766 }
964 case SDL_JOYDEVICEREMOVED: { 770 case SDL_JOYDEVICEREMOVED: {
965 int index = find_joystick_index(event->jdevice.which); 771 int index = find_joystick_index(event->jdevice.which);
966 if (index >= 0) { 772 if (index >= 0) {
967 SDL_JoystickClose(joysticks[index]); 773 SDL_JoystickClose(joysticks[index]);
968 joysticks[index] = NULL; 774 joysticks[index] = NULL;
775 if (controllers[index]) {
776 SDL_GameControllerClose(controllers[index]);
777 controllers[index] = NULL;
778 }
969 debug_message("Joystick %d removed\n", index); 779 debug_message("Joystick %d removed\n", index);
970 } else { 780 } else {
971 debug_message("Failed to find removed joystick with instance ID: %d\n", index); 781 debug_message("Failed to find removed joystick with instance ID: %d\n", index);
972 } 782 }
973 break; 783 break;
1051 static int source_hz; 861 static int source_hz;
1052 static int source_frame; 862 static int source_frame;
1053 static int source_frame_count; 863 static int source_frame_count;
1054 static int frame_repeat[60]; 864 static int frame_repeat[60];
1055 865
866 static uint32_t sample_rate;
1056 static void init_audio() 867 static void init_audio()
1057 { 868 {
1058 SDL_AudioSpec desired, actual; 869 SDL_AudioSpec desired, actual;
1059 char * rate_str = tern_find_path(config, "audio\0rate\0", TVAL_PTR).ptrval; 870 char * rate_str = tern_find_path(config, "audio\0rate\0", TVAL_PTR).ptrval;
1060 int rate = rate_str ? atoi(rate_str) : 0; 871 int rate = rate_str ? atoi(rate_str) : 0;
1075 desired.userdata = NULL; 886 desired.userdata = NULL;
1076 887
1077 if (SDL_OpenAudio(&desired, &actual) < 0) { 888 if (SDL_OpenAudio(&desired, &actual) < 0) {
1078 fatal_error("Unable to open SDL audio: %s\n", SDL_GetError()); 889 fatal_error("Unable to open SDL audio: %s\n", SDL_GetError());
1079 } 890 }
1080 buffer_samples = actual.samples;
1081 sample_rate = actual.freq; 891 sample_rate = actual.freq;
1082 output_channels = actual.channels;
1083 debug_message("Initialized audio at frequency %d with a %d sample buffer, ", actual.freq, actual.samples); 892 debug_message("Initialized audio at frequency %d with a %d sample buffer, ", actual.freq, actual.samples);
1084 sample_size = SDL_AUDIO_BITSIZE(actual.format) / 8; 893 render_audio_format format = RENDER_AUDIO_UNKNOWN;
1085 if (actual.format == AUDIO_S16SYS) { 894 if (actual.format == AUDIO_S16SYS) {
1086 debug_message("signed 16-bit int format\n"); 895 debug_message("signed 16-bit int format\n");
1087 convert = convert_s16; 896 format = RENDER_AUDIO_S16;
1088 mix_buf = calloc(output_channels * buffer_samples, sizeof(float));
1089 } else if (actual.format == AUDIO_F32SYS) { 897 } else if (actual.format == AUDIO_F32SYS) {
1090 debug_message("32-bit float format\n"); 898 debug_message("32-bit float format\n");
1091 convert = clamp_f32; 899 format = RENDER_AUDIO_FLOAT;
1092 mix_buf = NULL;
1093 } else { 900 } else {
1094 debug_message("unsupported format %X\n", actual.format); 901 debug_message("unsupported format %X\n", actual.format);
1095 warning("Unsupported audio sample format: %X\n", actual.format); 902 warning("Unsupported audio sample format: %X\n", actual.format);
1096 convert = convert_null; 903 }
1097 mix_buf = calloc(output_channels * buffer_samples, sizeof(float)); 904 render_audio_initialized(format, actual.freq, actual.channels, actual.samples, SDL_AUDIO_BITSIZE(actual.format) / 8);
1098 }
1099 char * gain_str = tern_find_path(config, "audio\0gain\0", TVAL_PTR).ptrval;
1100 overall_gain_mult = db_to_mult(gain_str ? atof(gain_str) : 0.0f);
1101 } 905 }
1102 906
1103 void window_setup(void) 907 void window_setup(void)
1104 { 908 {
1105 uint32_t flags = SDL_WINDOW_RESIZABLE; 909 uint32_t flags = SDL_WINDOW_RESIZABLE;
1290 1094
1291 atexit(render_quit); 1095 atexit(render_quit);
1292 } 1096 }
1293 #include<unistd.h> 1097 #include<unistd.h>
1294 static int in_toggle; 1098 static int in_toggle;
1295 static void update_source(audio_source *src, double rc, uint8_t sync_changed)
1296 {
1297 double alpha = src->dt / (src->dt + rc);
1298 int32_t lowpass_alpha = (int32_t)(((double)0x10000) * alpha);
1299 src->lowpass_alpha = lowpass_alpha;
1300 if (sync_changed) {
1301 uint32_t alloc_size = sync_to_audio ? src->num_channels * buffer_samples : nearest_pow2(min_buffered * 4 * src->num_channels);
1302 src->back = realloc(src->back, alloc_size * sizeof(int16_t));
1303 if (sync_to_audio) {
1304 src->front = malloc(alloc_size * sizeof(int16_t));
1305 } else {
1306 free(src->front);
1307 src->front = src->back;
1308 }
1309 src->mask = sync_to_audio ? 0xFFFFFFFF : alloc_size-1;
1310 src->read_start = 0;
1311 src->read_end = sync_to_audio ? buffer_samples * src->num_channels : 0;
1312 src->buffer_pos = 0;
1313 }
1314 }
1315 1099
1316 void render_config_updated(void) 1100 void render_config_updated(void)
1317 { 1101 {
1318 uint8_t old_sync_to_audio = sync_to_audio; 1102 uint8_t old_sync_to_audio = sync_to_audio;
1319 1103
1376 render_close_audio(); 1160 render_close_audio();
1377 quitting = 0; 1161 quitting = 0;
1378 init_audio(); 1162 init_audio();
1379 render_set_video_standard(video_standard); 1163 render_set_video_standard(video_standard);
1380 1164
1381 double lowpass_cutoff = get_lowpass_cutoff(config);
1382 double rc = (1.0 / lowpass_cutoff) / (2.0 * M_PI);
1383 lock_audio();
1384 for (uint8_t i = 0; i < num_audio_sources; i++)
1385 {
1386 update_source(audio_sources[i], rc, old_sync_to_audio != sync_to_audio);
1387 }
1388 unlock_audio();
1389 for (uint8_t i = 0; i < num_inactive_audio_sources; i++)
1390 {
1391 update_source(inactive_audio_sources[i], rc, old_sync_to_audio != sync_to_audio);
1392 }
1393 drain_events(); 1165 drain_events();
1394 in_toggle = 0; 1166 in_toggle = 0;
1395 if (!was_paused) { 1167 if (!was_paused) {
1396 SDL_PauseAudio(0); 1168 SDL_PauseAudio(0);
1397 } 1169 }
1398 } 1170 }
1399 1171
1400 SDL_Window *render_get_window(void) 1172 SDL_Window *render_get_window(void)
1401 { 1173 {
1402 return main_window; 1174 return main_window;
1175 }
1176
1177 uint32_t render_audio_syncs_per_sec(void)
1178 {
1179 //sync samples with audio thread approximately every 8 lines when doing sync to video
1180 return sync_to_audio ? 0 : source_hz * (video_standard == VID_PAL ? 313 : 262) / 8;
1403 } 1181 }
1404 1182
1405 void render_set_video_standard(vid_std std) 1183 void render_set_video_standard(vid_std std)
1406 { 1184 {
1407 video_standard = std; 1185 video_standard = std;
1429 frame_repeat[source_hz-1] += display_hz - dst_frames; 1207 frame_repeat[source_hz-1] += display_hz - dst_frames;
1430 } 1208 }
1431 } 1209 }
1432 source_frame = 0; 1210 source_frame = 0;
1433 source_frame_count = frame_repeat[0]; 1211 source_frame_count = frame_repeat[0];
1434 //sync samples with audio thread approximately every 8 lines
1435 sync_samples = sync_to_audio ? buffer_samples : 8 * sample_rate / (source_hz * (std == VID_PAL ? 313 : 262));
1436 max_repeat++; 1212 max_repeat++;
1437 min_buffered = (((float)max_repeat * (float)sample_rate/(float)source_hz)/* / (float)buffer_samples*/);// + 0.9999; 1213 min_buffered = (((float)max_repeat * (float)sample_rate/(float)source_hz)/* / (float)buffer_samples*/);// + 0.9999;
1438 //min_buffered *= buffer_samples; 1214 //min_buffered *= buffer_samples;
1439 debug_message("Min samples buffered before audio start: %d\n", min_buffered); 1215 debug_message("Min samples buffered before audio start: %d\n", min_buffered);
1440 max_adjust = BASE_MAX_ADJUST / source_hz; 1216 max_adjust = BASE_MAX_ADJUST / source_hz;
1519 if (render_gl && which <= FRAMEBUFFER_EVEN) { 1295 if (render_gl && which <= FRAMEBUFFER_EVEN) {
1520 *pitch = LINEBUF_SIZE * sizeof(uint32_t); 1296 *pitch = LINEBUF_SIZE * sizeof(uint32_t);
1521 return texture_buf; 1297 return texture_buf;
1522 } else { 1298 } else {
1523 #endif 1299 #endif
1524 if (which == FRAMEBUFFER_UI && which >= num_textures) {
1525 sdl_textures = realloc(sdl_textures, sizeof(*sdl_textures) * (FRAMEBUFFER_UI + 1));
1526 for (; num_textures <= FRAMEBUFFER_UI; num_textures++)
1527 {
1528 sdl_textures[num_textures] = NULL;
1529 }
1530 }
1531 if (which == FRAMEBUFFER_UI && !sdl_textures[which]) { 1300 if (which == FRAMEBUFFER_UI && !sdl_textures[which]) {
1532 sdl_textures[which] = SDL_CreateTexture(main_renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, main_width, main_height); 1301 sdl_textures[which] = SDL_CreateTexture(main_renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, main_width, main_height);
1533 } 1302 }
1534 if (which >= num_textures) { 1303 if (which >= num_textures) {
1535 warning("Request for invalid framebuffer number %d\n", which); 1304 warning("Request for invalid framebuffer number %d\n", which);
1591 screenshot_file = fopen(screenshot_path, "wb"); 1360 screenshot_file = fopen(screenshot_path, "wb");
1592 if (screenshot_file) { 1361 if (screenshot_file) {
1593 #ifndef DISABLE_ZLIB 1362 #ifndef DISABLE_ZLIB
1594 ext = path_extension(screenshot_path); 1363 ext = path_extension(screenshot_path);
1595 #endif 1364 #endif
1596 info_message("Saving screenshot to %s\n", screenshot_path); 1365 debug_message("Saving screenshot to %s\n", screenshot_path);
1597 } else { 1366 } else {
1598 warning("Failed to open screenshot file %s for writing\n", screenshot_path); 1367 warning("Failed to open screenshot file %s for writing\n", screenshot_path);
1599 } 1368 }
1600 free(screenshot_path); 1369 free(screenshot_path);
1601 screenshot_path = NULL; 1370 screenshot_path = NULL;
1746 } else if (local_cur_min < min_buffered / 2) { 1515 } else if (local_cur_min < min_buffered / 2) {
1747 adjust_ratio = max_adjust; 1516 adjust_ratio = max_adjust;
1748 } 1517 }
1749 if (adjust_ratio != 0.0f) { 1518 if (adjust_ratio != 0.0f) {
1750 average_change = 0; 1519 average_change = 0;
1751 for (uint8_t i = 0; i < num_audio_sources; i++) 1520 render_audio_adjust_speed(adjust_ratio);
1752 { 1521
1753 audio_sources[i]->buffer_inc = ((double)audio_sources[i]->buffer_inc) + ((double)audio_sources[i]->buffer_inc) * adjust_ratio + 0.5;
1754 }
1755 } 1522 }
1756 while (source_frame_count > 0) 1523 while (source_frame_count > 0)
1757 { 1524 {
1758 render_update_display(); 1525 render_update_display();
1759 source_frame_count--; 1526 source_frame_count--;
1847 uint32_t render_overscan_top() 1614 uint32_t render_overscan_top()
1848 { 1615 {
1849 return overscan_top[video_standard]; 1616 return overscan_top[video_standard];
1850 } 1617 }
1851 1618
1852 void render_wait_quit(vdp_context * context) 1619 uint32_t render_overscan_bot()
1620 {
1621 return overscan_bot[video_standard];
1622 }
1623
1624 void render_wait_quit(void)
1853 { 1625 {
1854 SDL_Event event; 1626 SDL_Event event;
1855 while(SDL_WaitEvent(&event)) { 1627 while(SDL_WaitEvent(&event)) {
1856 switch (event.type) { 1628 switch (event.type) {
1857 case SDL_QUIT: 1629 case SDL_QUIT:
2015 drain_events(); 1787 drain_events();
2016 in_toggle = 0; 1788 in_toggle = 0;
2017 need_ui_fb_resize = 1; 1789 need_ui_fb_resize = 1;
2018 } 1790 }
2019 1791
2020 uint32_t render_audio_buffer()
2021 {
2022 return buffer_samples;
2023 }
2024
2025 uint32_t render_sample_rate()
2026 {
2027 return sample_rate;
2028 }
2029
2030 void render_errorbox(char *title, char *message) 1792 void render_errorbox(char *title, char *message)
2031 { 1793 {
2032 SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, title, message, NULL); 1794 SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, title, message, NULL);
2033 } 1795 }
2034 1796