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;