Mercurial > repos > blastem
comparison render_sdl.c @ 1565:61fafcbc2c38
Audio DRC now sounds good in both NTSC and PAL, just need to adjust constants to minimize latency without leading to dropouts
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Sat, 14 Apr 2018 23:08:08 -0700 |
parents | 48b08986bf8f |
children | cbb40af77a94 |
comparison
equal
deleted
inserted
replaced
1564:48b08986bf8f | 1565:61fafcbc2c38 |
---|---|
180 #define NO_LAST_BUFFERED -2000000000 | 180 #define NO_LAST_BUFFERED -2000000000 |
181 static int32_t last_buffered = NO_LAST_BUFFERED; | 181 static int32_t last_buffered = NO_LAST_BUFFERED; |
182 static uint8_t need_adjust, need_pause; | 182 static uint8_t need_adjust, need_pause; |
183 static float adjust_ratio, average_change; | 183 static float adjust_ratio, average_change; |
184 #define BUFFER_FRAMES_THRESHOLD 6 | 184 #define BUFFER_FRAMES_THRESHOLD 6 |
185 #define MAX_ADJUST 0.000625 | 185 #define BASE_MAX_ADJUST 0.05 |
186 static float max_adjust; | |
186 static void audio_callback_drc(void *userData, uint8_t *byte_stream, int len) | 187 static void audio_callback_drc(void *userData, uint8_t *byte_stream, int len) |
187 { | 188 { |
188 //TODO: update progress tracking so we can adjust resample rate | 189 //TODO: update progress tracking so we can adjust resample rate |
189 memset(byte_stream, 0, len); | 190 memset(byte_stream, 0, len); |
190 int32_t min_buffered = 0x7FFFFFFF; | 191 int32_t cur_min_buffered = 0x7FFFFFFF; |
191 uint32_t min_remaining_buffer = 0xFFFFFFFF; | 192 uint32_t min_remaining_buffer = 0xFFFFFFFF; |
192 for (uint8_t i = 0; i < num_audio_sources; i++) | 193 for (uint8_t i = 0; i < num_audio_sources; i++) |
193 { | 194 { |
194 | 195 |
196 printf("buffered at start: %d, ", ((audio_sources[i]->read_end - audio_sources[i]->read_start) & audio_sources[i]->mask) / audio_sources[i]->num_channels); | |
195 int32_t buffered = mix(audio_sources[i], byte_stream, len); | 197 int32_t buffered = mix(audio_sources[i], byte_stream, len); |
196 min_buffered = buffered < min_buffered ? buffered : min_buffered; | 198 printf("buffered after mix: %d\n", buffered); |
199 cur_min_buffered = buffered < cur_min_buffered ? buffered : cur_min_buffered; | |
197 uint32_t remaining = (audio_sources[i]->mask + 1)/audio_sources[i]->num_channels - buffered; | 200 uint32_t remaining = (audio_sources[i]->mask + 1)/audio_sources[i]->num_channels - buffered; |
198 min_remaining_buffer = remaining < min_remaining_buffer ? remaining : min_remaining_buffer; | 201 min_remaining_buffer = remaining < min_remaining_buffer ? remaining : min_remaining_buffer; |
199 } | 202 } |
200 if (last_buffered > NO_LAST_BUFFERED) { | 203 if (last_buffered > NO_LAST_BUFFERED) { |
201 average_change *= 0.8f; | 204 average_change *= 0.8f; |
202 average_change += ((int32_t)min_buffered - last_buffered) * 0.2f; | 205 average_change += ((int32_t)cur_min_buffered - last_buffered) * 0.2f; |
203 } | 206 } |
204 last_buffered = min_buffered; | 207 last_buffered = cur_min_buffered; |
205 float frames_to_problem; | 208 float frames_to_problem; |
206 if (average_change < 0) { | 209 if (average_change < 0) { |
207 frames_to_problem = (float)min_buffered / -average_change; | 210 frames_to_problem = (float)cur_min_buffered / -average_change; |
208 } else { | 211 } else { |
209 frames_to_problem = (float)min_remaining_buffer / average_change; | 212 frames_to_problem = (float)min_remaining_buffer / average_change; |
210 } | 213 } |
211 if (frames_to_problem < BUFFER_FRAMES_THRESHOLD || min_buffered < 0) { | 214 if ( |
215 frames_to_problem < BUFFER_FRAMES_THRESHOLD || cur_min_buffered < 0 | |
216 || (cur_min_buffered < min_buffered/2 && average_change < 0) | |
217 || (cur_min_buffered > (2*min_buffered) && average_change > 0) | |
218 ) { | |
212 need_adjust = num_audio_sources; | 219 need_adjust = num_audio_sources; |
213 if (min_buffered < 0) { | 220 if (cur_min_buffered < 0) { |
214 adjust_ratio = MAX_ADJUST; | 221 adjust_ratio = max_adjust; |
215 need_pause = 1; | 222 need_pause = 1; |
216 } else { | 223 } else { |
217 adjust_ratio = -1.5 * average_change / buffer_samples; | 224 adjust_ratio = -1.5 * average_change / buffer_samples; |
218 if (fabsf(adjust_ratio) > MAX_ADJUST) { | 225 if (fabsf(adjust_ratio) > max_adjust) { |
219 adjust_ratio = adjust_ratio > 0 ? MAX_ADJUST : -MAX_ADJUST; | 226 adjust_ratio = adjust_ratio > 0 ? max_adjust : -max_adjust; |
220 } | 227 } |
221 } | 228 } |
222 printf("frames_to_problem: %f, avg_change: %f, adjust_ratio: %f\n", frames_to_problem, average_change, adjust_ratio); | 229 printf("frames_to_problem: %f, avg_change: %f, adjust_ratio: %f\n", frames_to_problem, average_change, adjust_ratio); |
223 average_change = 0; | 230 average_change = 0; |
224 last_buffered = NO_LAST_BUFFERED; | 231 last_buffered = NO_LAST_BUFFERED; |
225 for (uint8_t i = 0; i < num_audio_sources; i++) | 232 for (uint8_t i = 0; i < num_audio_sources; i++) |
226 { | 233 { |
227 audio_sources[i]->adjusted = 0; | 234 audio_sources[i]->adjusted = 0; |
228 } | 235 } |
229 } else { | 236 } else { |
230 printf("no adjust - frames_to_problem: %f, avg_change: %f, min_buffered: %d, min_remaining_buffer: %d\n", frames_to_problem, average_change, min_buffered, min_remaining_buffer); | 237 printf("no adjust - frames_to_problem: %f, avg_change: %f, cur_min_buffered: %d, min_remaining_buffer: %d\n", frames_to_problem, average_change, cur_min_buffered, min_remaining_buffer); |
231 } | 238 } |
232 } | 239 } |
233 | 240 |
234 static void lock_audio() | 241 static void lock_audio() |
235 { | 242 { |
363 } else { | 370 } else { |
364 uint32_t num_buffered; | 371 uint32_t num_buffered; |
365 uint8_t local_need_pause; | 372 uint8_t local_need_pause; |
366 SDL_LockAudio(); | 373 SDL_LockAudio(); |
367 src->read_end = src->buffer_pos; | 374 src->read_end = src->buffer_pos; |
368 num_buffered = (src->read_end - src->read_start) & src->mask; | 375 num_buffered = ((src->read_end - src->read_start) & src->mask) / src->num_channels; |
369 if (need_adjust && !src->adjusted) { | 376 if (need_adjust && !src->adjusted) { |
370 src->adjusted = 1; | 377 src->adjusted = 1; |
371 need_adjust--; | 378 need_adjust--; |
372 src->buffer_inc = ((double)src->buffer_inc) + ((double)src->buffer_inc) * adjust_ratio + 0.5; | 379 src->buffer_inc = ((double)src->buffer_inc) + ((double)src->buffer_inc) * adjust_ratio + 0.5; |
373 } | 380 } |
841 if (SDL_OpenAudio(&desired, &actual) < 0) { | 848 if (SDL_OpenAudio(&desired, &actual) < 0) { |
842 fatal_error("Unable to open SDL audio: %s\n", SDL_GetError()); | 849 fatal_error("Unable to open SDL audio: %s\n", SDL_GetError()); |
843 } | 850 } |
844 buffer_samples = actual.samples; | 851 buffer_samples = actual.samples; |
845 sample_rate = actual.freq; | 852 sample_rate = actual.freq; |
853 max_adjust = BASE_MAX_ADJUST * (float)buffer_samples / (float)sample_rate; | |
846 printf("Initialized audio at frequency %d with a %d sample buffer, ", actual.freq, actual.samples); | 854 printf("Initialized audio at frequency %d with a %d sample buffer, ", actual.freq, actual.samples); |
847 if (actual.format == AUDIO_S16SYS) { | 855 if (actual.format == AUDIO_S16SYS) { |
848 puts("signed 16-bit int format"); | 856 puts("signed 16-bit int format"); |
849 mix = mix_s16; | 857 mix = mix_s16; |
850 } else if (actual.format == AUDIO_F32SYS) { | 858 } else if (actual.format == AUDIO_F32SYS) { |
909 sync_samples = 8 * sample_rate / (source_hz * (VID_PAL ? 313 : 262)); | 917 sync_samples = 8 * sample_rate / (source_hz * (VID_PAL ? 313 : 262)); |
910 max_repeat++; | 918 max_repeat++; |
911 float mult = max_repeat > 1 ? 2.5 : 1.5; | 919 float mult = max_repeat > 1 ? 2.5 : 1.5; |
912 min_buffered = (((float)max_repeat * mult * (float)sample_rate/(float)source_hz) / (float)buffer_samples) + 0.9999; | 920 min_buffered = (((float)max_repeat * mult * (float)sample_rate/(float)source_hz) / (float)buffer_samples) + 0.9999; |
913 min_buffered *= buffer_samples; | 921 min_buffered *= buffer_samples; |
922 printf("Min samples buffered before audio start: %d\n", min_buffered); | |
914 } | 923 } |
915 | 924 |
916 void render_update_caption(char *title) | 925 void render_update_caption(char *title) |
917 { | 926 { |
918 caption = title; | 927 caption = title; |