changeset 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
files genesis.c render_sdl.c
diffstat 2 files changed, 24 insertions(+), 14 deletions(-) [+]
line wrap: on
line diff
--- a/genesis.c	Sat Apr 14 00:07:20 2018 -0700
+++ b/genesis.c	Sat Apr 14 23:08:08 2018 -0700
@@ -1072,7 +1072,6 @@
 {
 	genesis_context *gen = (genesis_context *)system;
 	set_keybindings(&gen->io);
-	render_set_video_standard((gen->version_reg & HZ50) ? VID_PAL : VID_NTSC);
 	if (statefile) {
 		//first try loading as a native format savestate
 		deserialize_buffer state;
@@ -1237,6 +1236,8 @@
 	gen->int_latency_prev1 = MCLKS_PER_68K * 32;
 	gen->int_latency_prev2 = MCLKS_PER_68K * 16;
 	
+	render_set_video_standard((gen->version_reg & HZ50) ? VID_PAL : VID_NTSC);
+	
 	gen->ym = malloc(sizeof(ym2612_context));
 	ym_init(gen->ym, gen->master_clock, MCLKS_PER_YM, system_opts);
 
--- a/render_sdl.c	Sat Apr 14 00:07:20 2018 -0700
+++ b/render_sdl.c	Sat Apr 14 23:08:08 2018 -0700
@@ -182,41 +182,48 @@
 static uint8_t need_adjust, need_pause;
 static float adjust_ratio, average_change;
 #define BUFFER_FRAMES_THRESHOLD 6
-#define MAX_ADJUST 0.000625
+#define BASE_MAX_ADJUST 0.05
+static float max_adjust;
 static void audio_callback_drc(void *userData, uint8_t *byte_stream, int len)
 {
 	//TODO: update progress tracking so we can adjust resample rate
 	memset(byte_stream, 0, len);
-	int32_t min_buffered = 0x7FFFFFFF;
+	int32_t cur_min_buffered = 0x7FFFFFFF;
 	uint32_t min_remaining_buffer = 0xFFFFFFFF;
 	for (uint8_t i = 0; i < num_audio_sources; i++)
 	{
 		
+		printf("buffered at start: %d, ", ((audio_sources[i]->read_end - audio_sources[i]->read_start) & audio_sources[i]->mask) / audio_sources[i]->num_channels);
 		int32_t buffered = mix(audio_sources[i], byte_stream, len);
-		min_buffered = buffered < min_buffered ? buffered : min_buffered;
+		printf("buffered after mix: %d\n", buffered);
+		cur_min_buffered = buffered < cur_min_buffered ? buffered : cur_min_buffered;
 		uint32_t remaining = (audio_sources[i]->mask + 1)/audio_sources[i]->num_channels - buffered;
 		min_remaining_buffer = remaining < min_remaining_buffer ? remaining : min_remaining_buffer;
 	}
 	if (last_buffered > NO_LAST_BUFFERED) {
 		average_change *= 0.8f;
-		average_change += ((int32_t)min_buffered - last_buffered) * 0.2f;
+		average_change += ((int32_t)cur_min_buffered - last_buffered) * 0.2f;
 	}
-	last_buffered = min_buffered;
+	last_buffered = cur_min_buffered;
 	float frames_to_problem;
 	if (average_change < 0) {
-		frames_to_problem = (float)min_buffered / -average_change;
+		frames_to_problem = (float)cur_min_buffered / -average_change;
 	} else {
 		frames_to_problem = (float)min_remaining_buffer / average_change;
 	}
-	if (frames_to_problem < BUFFER_FRAMES_THRESHOLD || min_buffered < 0) {
+	if (
+		frames_to_problem < BUFFER_FRAMES_THRESHOLD || cur_min_buffered < 0 
+		|| (cur_min_buffered < min_buffered/2 && average_change < 0)
+		|| (cur_min_buffered > (2*min_buffered) && average_change > 0)
+	) {
 		need_adjust = num_audio_sources;
-		if (min_buffered < 0) {
-			adjust_ratio = MAX_ADJUST;
+		if (cur_min_buffered < 0) {
+			adjust_ratio = max_adjust;
 			need_pause = 1;
 		} else {
 			adjust_ratio = -1.5 * average_change / buffer_samples;
-			if (fabsf(adjust_ratio) > MAX_ADJUST) {
-				adjust_ratio = adjust_ratio > 0 ? MAX_ADJUST : -MAX_ADJUST;
+			if (fabsf(adjust_ratio) > max_adjust) {
+				adjust_ratio = adjust_ratio > 0 ? max_adjust : -max_adjust;
 			}
 		}
 		printf("frames_to_problem: %f, avg_change: %f, adjust_ratio: %f\n", frames_to_problem, average_change, adjust_ratio);
@@ -227,7 +234,7 @@
 			audio_sources[i]->adjusted = 0;
 		}
 	} else {
-		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);
+		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);
 	}
 }
 
@@ -365,7 +372,7 @@
 		uint8_t local_need_pause;
 		SDL_LockAudio();
 			src->read_end = src->buffer_pos;
-			num_buffered = (src->read_end - src->read_start) & src->mask;
+			num_buffered = ((src->read_end - src->read_start) & src->mask) / src->num_channels;
 			if (need_adjust && !src->adjusted) {
 				src->adjusted = 1;
 				need_adjust--;
@@ -843,6 +850,7 @@
 	}
 	buffer_samples = actual.samples;
 	sample_rate = actual.freq;
+	max_adjust = BASE_MAX_ADJUST * (float)buffer_samples / (float)sample_rate;
 	printf("Initialized audio at frequency %d with a %d sample buffer, ", actual.freq, actual.samples);
 	if (actual.format == AUDIO_S16SYS) {
 		puts("signed 16-bit int format");
@@ -911,6 +919,7 @@
 	float mult = max_repeat > 1 ? 2.5 : 1.5;
 	min_buffered = (((float)max_repeat * mult * (float)sample_rate/(float)source_hz) / (float)buffer_samples) + 0.9999;
 	min_buffered *= buffer_samples;
+	printf("Min samples buffered before audio start: %d\n", min_buffered);
 }
 
 void render_update_caption(char *title)