comparison render_sdl.c @ 2640:c30e5548154f

Get sync to audio working in emscripten
author Michael Pavone <pavone@retrodev.com>
date Wed, 26 Feb 2025 22:55:42 -0800
parents f5603b4ee14d
children c5c9498ff279
comparison
equal deleted inserted replaced
2639:0046305e3fa8 2640:c30e5548154f
24 #include <SDL_opengles2.h> 24 #include <SDL_opengles2.h>
25 #else 25 #else
26 #include <GL/glew.h> 26 #include <GL/glew.h>
27 #endif 27 #endif
28 #endif 28 #endif
29 #ifdef __EMSCRIPTEN__
30 #include <emscripten.h>
31 #endif
29 32
30 #define MAX_EVENT_POLL_PER_FRAME 2 33 #define MAX_EVENT_POLL_PER_FRAME 2
31 34
32 35
33 typedef struct { 36 typedef struct {
121 124
122 static void audio_callback(void * userdata, uint8_t *byte_stream, int len) 125 static void audio_callback(void * userdata, uint8_t *byte_stream, int len)
123 { 126 {
124 SDL_LockMutex(audio_mutex); 127 SDL_LockMutex(audio_mutex);
125 uint8_t all_ready; 128 uint8_t all_ready;
129 #ifdef __EMSCRIPTEN__
130 if (!all_sources_ready()) {
131 memset(byte_stream, 0, len);
132 SDL_UnlockMutex(audio_mutex);
133 return;
134 }
135 #else
126 do { 136 do {
127 all_ready = all_sources_ready(); 137 all_ready = all_sources_ready();
128 if (!quitting && !all_ready) { 138 if (!quitting && !all_ready) {
129 SDL_CondWait(audio_ready, audio_mutex); 139 SDL_CondWait(audio_ready, audio_mutex);
130 } 140 }
131 } while(!quitting && !all_ready); 141 } while(!quitting && !all_ready);
142 #endif
132 if (!quitting) { 143 if (!quitting) {
133 mix_and_convert(byte_stream, len, NULL); 144 mix_and_convert(byte_stream, len, NULL);
134 } 145 }
135 SDL_UnlockMutex(audio_mutex); 146 SDL_UnlockMutex(audio_mutex);
136 } 147 }
253 } 264 }
254 } 265 }
255 266
256 uint8_t audio_deadlock_hack(void); 267 uint8_t audio_deadlock_hack(void);
257 268
269 static ui_render_fun audio_full_cb;
270 void render_set_audio_full_fun(ui_render_fun cb)
271 {
272 audio_full_cb = cb;
273 }
274
258 void render_do_audio_ready(audio_source *src) 275 void render_do_audio_ready(audio_source *src)
259 { 276 {
260 if (sync_src == SYNC_AUDIO_THREAD) { 277 if (sync_src == SYNC_AUDIO_THREAD) {
261 int16_t *tmp = src->front; 278 int16_t *tmp = src->front;
262 src->front = src->back; 279 src->front = src->back;
266 if (all_sources_ready()) { 283 if (all_sources_ready()) {
267 //we've emulated far enough to fill the current buffer 284 //we've emulated far enough to fill the current buffer
268 system_request_exit(current_system, 0); 285 system_request_exit(current_system, 0);
269 } 286 }
270 } else if (sync_src == SYNC_AUDIO) { 287 } else if (sync_src == SYNC_AUDIO) {
288 uint8_t all_ready = 0;
271 SDL_LockMutex(audio_mutex); 289 SDL_LockMutex(audio_mutex);
290 #ifndef __EMSCRIPTEN__
272 if (src->front_populated) { 291 if (src->front_populated) {
273 if (audio_deadlock_hack()) { 292 if (audio_deadlock_hack()) {
274 SDL_CondSignal(audio_ready); 293 SDL_CondSignal(audio_ready);
275 } 294 }
276 } 295 }
277 while (src->front_populated) { 296 while (src->front_populated) {
278 SDL_CondWait(src->opaque, audio_mutex); 297 SDL_CondWait(src->opaque, audio_mutex);
279 } 298 }
299 #endif
280 int16_t *tmp = src->front; 300 int16_t *tmp = src->front;
281 src->front = src->back; 301 src->front = src->back;
282 src->back = tmp; 302 src->back = tmp;
283 src->front_populated = 1; 303 src->front_populated = 1;
284 src->buffer_pos = 0; 304 src->buffer_pos = 0;
305 all_ready = all_sources_ready();
285 SDL_CondSignal(audio_ready); 306 SDL_CondSignal(audio_ready);
286 SDL_UnlockMutex(audio_mutex); 307 SDL_UnlockMutex(audio_mutex);
308 if (all_ready && audio_full_cb) {
309 audio_full_cb();
310 }
287 } else { 311 } else {
288 uint32_t num_buffered; 312 uint32_t num_buffered;
289 SDL_LockAudio(); 313 SDL_LockAudio();
290 src->read_end = src->buffer_pos; 314 src->read_end = src->buffer_pos;
291 num_buffered = ((src->read_end - src->read_start) & src->mask) / src->num_channels; 315 num_buffered = ((src->read_end - src->read_start) & src->mask) / src->num_channels;
1068 format = RENDER_AUDIO_FLOAT; 1092 format = RENDER_AUDIO_FLOAT;
1069 } else { 1093 } else {
1070 debug_message("unsupported format %X\n", actual.format); 1094 debug_message("unsupported format %X\n", actual.format);
1071 warning("Unsupported audio sample format: %X\n", actual.format); 1095 warning("Unsupported audio sample format: %X\n", actual.format);
1072 } 1096 }
1097 #ifdef __EMSCRIPTEN__
1098 if (sync_src == SYNC_AUDIO) {
1099 printf("emscripten_set_main_loop_timing %d\n", actual.samples * 500 / actual.freq);
1100 emscripten_set_main_loop_timing(EM_TIMING_SETTIMEOUT, actual.samples * 500 / actual.freq);
1101 }
1102 #endif
1073 render_audio_initialized(format, actual.freq, actual.channels, actual.samples, SDL_AUDIO_BITSIZE(actual.format) / 8); 1103 render_audio_initialized(format, actual.freq, actual.channels, actual.samples, SDL_AUDIO_BITSIZE(actual.format) / 8);
1074 } 1104 }
1075 1105
1076 static void update_cursor(void) 1106 static void update_cursor(void)
1077 { 1107 {