Mercurial > repos > blastem
comparison render_sdl.c @ 1551:ce1f93be0104
Small cleanup to audio interface between emulation code and renderer backend
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Wed, 28 Mar 2018 23:36:08 -0700 |
parents | c59adc305e46 |
children | 13a82adb185b |
comparison
equal
deleted
inserted
replaced
1550:b525491b4e5b | 1551:ce1f93be0104 |
---|---|
42 static uint32_t buffer_samples, sample_rate; | 42 static uint32_t buffer_samples, sample_rate; |
43 static uint32_t missing_count; | 43 static uint32_t missing_count; |
44 | 44 |
45 static SDL_mutex * audio_mutex; | 45 static SDL_mutex * audio_mutex; |
46 static SDL_cond * audio_ready; | 46 static SDL_cond * audio_ready; |
47 static SDL_cond * psg_cond; | |
48 static SDL_cond * ym_cond; | |
49 static uint8_t quitting = 0; | 47 static uint8_t quitting = 0; |
50 static uint8_t ym_enabled = 1; | 48 |
49 struct audio_source { | |
50 SDL_cond *cond; | |
51 int16_t *front; | |
52 int16_t *back; | |
53 uint8_t num_channels; | |
54 uint8_t front_populated; | |
55 }; | |
56 | |
57 static audio_source *audio_sources[8]; | |
58 static uint8_t num_audio_sources; | |
51 | 59 |
52 static void audio_callback(void * userdata, uint8_t *byte_stream, int len) | 60 static void audio_callback(void * userdata, uint8_t *byte_stream, int len) |
53 { | 61 { |
54 //puts("audio_callback"); | |
55 int16_t * stream = (int16_t *)byte_stream; | 62 int16_t * stream = (int16_t *)byte_stream; |
56 int samples = len/(sizeof(int16_t)*2); | 63 int samples = len/(sizeof(int16_t)*2); |
57 int16_t * psg_buf, * ym_buf; | 64 uint8_t num_populated; |
58 uint8_t local_quit; | 65 memset(stream, 0, len); |
59 SDL_LockMutex(audio_mutex); | 66 SDL_LockMutex(audio_mutex); |
60 psg_buf = NULL; | |
61 ym_buf = NULL; | |
62 do { | 67 do { |
63 if (!psg_buf) { | 68 num_populated = 0; |
64 psg_buf = current_psg; | 69 for (uint8_t i = 0; i < num_audio_sources; i++) |
65 current_psg = NULL; | 70 { |
66 SDL_CondSignal(psg_cond); | 71 if (audio_sources[i]->front_populated) { |
67 } | 72 num_populated++; |
68 if (ym_enabled && !ym_buf) { | 73 } |
69 ym_buf = current_ym; | 74 } |
70 current_ym = NULL; | 75 if (!quitting && num_populated < num_audio_sources) { |
71 SDL_CondSignal(ym_cond); | |
72 } | |
73 if (!quitting && (!psg_buf || (ym_enabled && !ym_buf))) { | |
74 SDL_CondWait(audio_ready, audio_mutex); | 76 SDL_CondWait(audio_ready, audio_mutex); |
75 } | 77 } |
76 } while(!quitting && (!psg_buf || (ym_enabled && !ym_buf))); | 78 } while(!quitting && num_populated < num_audio_sources); |
77 | 79 if (!quitting) { |
78 local_quit = quitting; | 80 int16_t *end = stream + 2*samples; |
81 for (uint8_t i = 0; i < num_audio_sources; i++) | |
82 { | |
83 int16_t *src = audio_sources[i]->front; | |
84 if (audio_sources[i]->num_channels == 1) { | |
85 for (int16_t *cur = stream; cur < end;) | |
86 { | |
87 *(cur++) += *src; | |
88 *(cur++) += *(src++); | |
89 } | |
90 } else { | |
91 for (int16_t *cur = stream; cur < end;) | |
92 { | |
93 *(cur++) += *(src++); | |
94 *(cur++) += *(src++); | |
95 } | |
96 } | |
97 audio_sources[i]->front_populated = 0; | |
98 SDL_CondSignal(audio_sources[i]->cond); | |
99 } | |
100 } | |
79 SDL_UnlockMutex(audio_mutex); | 101 SDL_UnlockMutex(audio_mutex); |
80 if (!local_quit) { | |
81 if (ym_enabled) { | |
82 for (int i = 0; i < samples; i++) | |
83 { | |
84 *(stream++) = psg_buf[i] + *(ym_buf++); | |
85 *(stream++) = psg_buf[i] + *(ym_buf++); | |
86 } | |
87 } else { | |
88 for (int i = 0; i < samples; i++) | |
89 { | |
90 *(stream++) = psg_buf[i]; | |
91 *(stream++) = psg_buf[i]; | |
92 } | |
93 } | |
94 } | |
95 } | |
96 | |
97 void render_disable_ym() | |
98 { | |
99 ym_enabled = 0; | |
100 } | |
101 | |
102 void render_enable_ym() | |
103 { | |
104 ym_enabled = 1; | |
105 } | 102 } |
106 | 103 |
107 static void render_close_audio() | 104 static void render_close_audio() |
108 { | 105 { |
109 SDL_LockMutex(audio_mutex); | 106 SDL_LockMutex(audio_mutex); |
110 quitting = 1; | 107 quitting = 1; |
111 SDL_CondSignal(audio_ready); | 108 SDL_CondSignal(audio_ready); |
112 SDL_UnlockMutex(audio_mutex); | 109 SDL_UnlockMutex(audio_mutex); |
113 SDL_CloseAudio(); | 110 SDL_CloseAudio(); |
111 } | |
112 | |
113 audio_source *render_audio_source(uint8_t channels) | |
114 { | |
115 audio_source *ret = NULL; | |
116 SDL_LockMutex(audio_mutex); | |
117 if (num_audio_sources < 8) { | |
118 ret = malloc(sizeof(audio_source)); | |
119 ret->front = malloc(channels * buffer_samples * sizeof(int16_t)); | |
120 ret->back = malloc(channels * buffer_samples * sizeof(int16_t)); | |
121 ret->front_populated = 0; | |
122 ret->cond = SDL_CreateCond(); | |
123 ret->num_channels = channels; | |
124 audio_sources[num_audio_sources++] = ret; | |
125 } | |
126 SDL_UnlockMutex(audio_mutex); | |
127 if (!ret) { | |
128 fatal_error("Too many audio sources!"); | |
129 } | |
130 return ret; | |
131 } | |
132 | |
133 void render_pause_source(audio_source *src) | |
134 { | |
135 SDL_LockMutex(audio_mutex); | |
136 for (uint8_t i = 0; i < num_audio_sources; i++) | |
137 { | |
138 if (audio_sources[i] == src) { | |
139 audio_sources[i] = audio_sources[--num_audio_sources]; | |
140 SDL_CondSignal(audio_ready); | |
141 break; | |
142 } | |
143 } | |
144 SDL_UnlockMutex(audio_mutex); | |
145 } | |
146 | |
147 void render_resume_source(audio_source *src) | |
148 { | |
149 SDL_LockMutex(audio_mutex); | |
150 if (num_audio_sources < 8) { | |
151 audio_sources[num_audio_sources++] = src; | |
152 } | |
153 SDL_UnlockMutex(audio_mutex); | |
154 } | |
155 | |
156 void render_free_source(audio_source *src) | |
157 { | |
158 render_pause_source(src); | |
159 | |
160 free(src->front); | |
161 free(src->back); | |
162 SDL_DestroyCond(src->cond); | |
163 free(src); | |
114 } | 164 } |
115 | 165 |
116 static SDL_Joystick * joysticks[MAX_JOYSTICKS]; | 166 static SDL_Joystick * joysticks[MAX_JOYSTICKS]; |
117 static int joystick_sdl_index[MAX_JOYSTICKS]; | 167 static int joystick_sdl_index[MAX_JOYSTICKS]; |
118 | 168 |
478 scanlines = !strcmp(tern_find_path_default(config, "video\0scanlines\0", def, TVAL_PTR).ptrval, "on"); | 528 scanlines = !strcmp(tern_find_path_default(config, "video\0scanlines\0", def, TVAL_PTR).ptrval, "on"); |
479 | 529 |
480 caption = title; | 530 caption = title; |
481 | 531 |
482 audio_mutex = SDL_CreateMutex(); | 532 audio_mutex = SDL_CreateMutex(); |
483 psg_cond = SDL_CreateCond(); | |
484 ym_cond = SDL_CreateCond(); | |
485 audio_ready = SDL_CreateCond(); | 533 audio_ready = SDL_CreateCond(); |
486 | 534 |
487 SDL_AudioSpec desired, actual; | 535 SDL_AudioSpec desired, actual; |
488 char * rate_str = tern_find_path(config, "audio\0rate\0", TVAL_PTR).ptrval; | 536 char * rate_str = tern_find_path(config, "audio\0rate\0", TVAL_PTR).ptrval; |
489 int rate = rate_str ? atoi(rate_str) : 0; | 537 int rate = rate_str ? atoi(rate_str) : 0; |
1188 SDL_SetWindowSize(main_window, windowed_width, windowed_height); | 1236 SDL_SetWindowSize(main_window, windowed_width, windowed_height); |
1189 drain_events(); | 1237 drain_events(); |
1190 in_toggle = 0; | 1238 in_toggle = 0; |
1191 } | 1239 } |
1192 | 1240 |
1193 void render_wait_psg(psg_context * context) | 1241 int16_t *render_audio_source_buffer(audio_source *src) |
1242 { | |
1243 return src->back; | |
1244 } | |
1245 | |
1246 int16_t *render_audio_ready(audio_source *src) | |
1194 { | 1247 { |
1195 SDL_LockMutex(audio_mutex); | 1248 SDL_LockMutex(audio_mutex); |
1196 while (current_psg != NULL) { | 1249 while (src->front_populated) { |
1197 SDL_CondWait(psg_cond, audio_mutex); | 1250 SDL_CondWait(src->cond, audio_mutex); |
1198 } | 1251 } |
1199 current_psg = context->audio_buffer; | 1252 int16_t *tmp = src->front; |
1253 src->front = src->back; | |
1254 src->back = tmp; | |
1255 src->front_populated = 1; | |
1200 SDL_CondSignal(audio_ready); | 1256 SDL_CondSignal(audio_ready); |
1201 | |
1202 context->audio_buffer = context->back_buffer; | |
1203 context->back_buffer = current_psg; | |
1204 SDL_UnlockMutex(audio_mutex); | 1257 SDL_UnlockMutex(audio_mutex); |
1205 context->buffer_pos = 0; | 1258 return src->back; |
1206 } | |
1207 | |
1208 void render_wait_ym(ym2612_context * context) | |
1209 { | |
1210 SDL_LockMutex(audio_mutex); | |
1211 while (current_ym != NULL) { | |
1212 SDL_CondWait(ym_cond, audio_mutex); | |
1213 } | |
1214 current_ym = context->audio_buffer; | |
1215 SDL_CondSignal(audio_ready); | |
1216 | |
1217 context->audio_buffer = context->back_buffer; | |
1218 context->back_buffer = current_ym; | |
1219 SDL_UnlockMutex(audio_mutex); | |
1220 context->buffer_pos = 0; | |
1221 } | 1259 } |
1222 | 1260 |
1223 uint32_t render_audio_buffer() | 1261 uint32_t render_audio_buffer() |
1224 { | 1262 { |
1225 return buffer_samples; | 1263 return buffer_samples; |