aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--config.c1
-rw-r--r--main.c8
-rw-r--r--menu.c6
-rw-r--r--options.c1
-rw-r--r--options.h1
-rw-r--r--plat_sdl.c71
6 files changed, 77 insertions, 11 deletions
diff --git a/config.c b/config.c
index 6f3670a..91835f8 100644
--- a/config.c
+++ b/config.c
@@ -25,6 +25,7 @@ static const struct {
CE_NUM(show_fps),
CE_NUM(show_cpu),
CE_NUM(limit_frames),
+ CE_NUM(enable_drc),
CE_NUM(audio_buffer_size),
CE_NUM(scale_size),
CE_NUM(scale_filter),
diff --git a/main.c b/main.c
index af55f0f..e91b832 100644
--- a/main.c
+++ b/main.c
@@ -31,6 +31,8 @@ static int last_screenshot = 0;
static uint32_t vsyncs;
static uint32_t renders;
+#define UNDERRUN_THRESHOLD 0.5
+
static void toggle_fast_forward(int force_off)
{
static int frameskip_style_was;
@@ -198,6 +200,7 @@ void set_defaults(void)
show_hud = 1;
limit_frames = 1;
enable_audio = 1;
+ enable_drc = 1;
audio_buffer_size = 5;
scale_size = SCALE_SIZE_NONE;
scale_filter = SCALE_FILTER_NEAREST;
@@ -496,7 +499,10 @@ static void adjust_audio(void) {
if (current_core.retro_audio_buffer_status) {
float occupancy = 1.0 - plat_sound_capacity();
- current_core.retro_audio_buffer_status(true, (int)(occupancy * 100), occupancy < 0.50);
+ if (enable_drc)
+ occupancy = MIN(1.0, occupancy * 2.0);
+
+ current_core.retro_audio_buffer_status(true, (int)(occupancy * 100), occupancy < UNDERRUN_THRESHOLD);
}
}
diff --git a/menu.c b/menu.c
index 52a05fe..2926a86 100644
--- a/menu.c
+++ b/menu.c
@@ -484,6 +484,7 @@ static const char h_restore_def[] = "Switches back to default settings";
static const char h_show_fps[] = "Shows frames and vsyncs per second";
static const char h_show_cpu[] = "Shows CPU usage";
+static const char h_enable_drc[] = "Dynamically adjusts audio rate for smoother video";
static const char h_audio_buffer_size[] =
"The size of the audio buffer, in frames. Higher\n"
@@ -511,6 +512,7 @@ static menu_entry e_menu_video_options[] =
mee_enum_h ("Screen size", 0, scale_size, men_scale_size, h_scale_size),
mee_enum_h ("Filter", 0, scale_filter, men_scale_filter, h_scale_filter),
mee_range_h ("Audio buffer", 0, audio_buffer_size, 1, 15, h_audio_buffer_size),
+ mee_onoff_h ("Audio adjustment", 0, enable_drc, 1, h_enable_drc),
mee_end,
};
@@ -519,7 +521,7 @@ static int menu_loop_video_options(int id, int keys)
static int sel = 0;
me_loop(e_menu_video_options, &sel);
- scale_update_scaler();
+ plat_reinit();
return 0;
}
@@ -676,7 +678,7 @@ void menu_loop(void)
me_enable(e_menu_main, MA_MAIN_SAVE_STATE, state_allowed());
me_enable(e_menu_main, MA_MAIN_LOAD_STATE, state_allowed());
me_enable(e_menu_main, MA_MAIN_CHEATS, cheats != NULL);
-
+
me_enable(e_menu_main, MA_MAIN_DISC_CTRL, needs_disc_ctrl);
if (override)
diff --git a/options.c b/options.c
index 95b4c71..6cf27cd 100644
--- a/options.c
+++ b/options.c
@@ -11,6 +11,7 @@ int show_cpu;
int show_hud;
int limit_frames;
int enable_audio;
+int enable_drc;
unsigned audio_buffer_size;
enum scale_size scale_size;
enum scale_filter scale_filter;
diff --git a/options.h b/options.h
index 268a619..c76e251 100644
--- a/options.h
+++ b/options.h
@@ -8,6 +8,7 @@ extern int show_cpu;
extern int show_hud;
extern int limit_frames;
extern int enable_audio;
+extern int enable_drc;
extern unsigned audio_buffer_size;
extern enum scale_size scale_size;
extern enum scale_filter scale_filter;
diff --git a/plat_sdl.c b/plat_sdl.c
index 0beb924..817a47e 100644
--- a/plat_sdl.c
+++ b/plat_sdl.c
@@ -18,6 +18,8 @@ struct audio_state {
struct audio_frame *buf;
int in_sample_rate;
int out_sample_rate;
+ int sample_rate_adj;
+ int adj_out_sample_rate;
};
struct audio_state audio;
@@ -25,11 +27,16 @@ struct audio_state audio;
static void plat_sound_select_resampler(void);
void (*plat_sound_write)(const struct audio_frame *data, int frames);
+#define DRC_MAX_ADJUSTMENT 0.003
+#define DRC_ADJ_BELOW 0.4
+#define DRC_ADJ_ABOVE 0.6
+
static char msg[HUD_LEN];
static unsigned msg_priority = 0;
static unsigned msg_expire = 0;
static bool frame_dirty = false;
+static int frame_time = 1000000 / 60;
static void video_expire_msg(void)
{
@@ -65,16 +72,16 @@ static int audio_resample_nearest(struct audio_frame data) {
static int diff = 0;
int consumed = 0;
- if (diff < audio.out_sample_rate) {
+ if (diff < audio.adj_out_sample_rate) {
audio.buf[audio.buf_w++] = data;
if (audio.buf_w >= audio.buf_len) audio.buf_w = 0;
diff += audio.in_sample_rate;
}
- if (diff >= audio.out_sample_rate) {
+ if (diff >= audio.adj_out_sample_rate) {
consumed++;
- diff -= audio.out_sample_rate;
+ diff -= audio.adj_out_sample_rate;
}
return consumed;
@@ -233,9 +240,25 @@ void plat_video_process(const void *data, unsigned width, unsigned height, size_
void plat_video_flip(void)
{
- if (frame_dirty)
+ static unsigned int next_frame_time_us = 0;
+
+ if (frame_dirty) {
+ unsigned int time = plat_get_ticks_us();
+
+ if (limit_frames && enable_drc && time < next_frame_time_us) {
+ usleep(next_frame_time_us - time);
+ }
+
+ if (!next_frame_time_us)
+ next_frame_time_us = time;
+
fb_flip();
+ do {
+ next_frame_time_us += frame_time;
+ } while (next_frame_time_us < time);
+ }
+
frame_dirty = false;
}
@@ -324,6 +347,9 @@ static int plat_sound_init(void)
audio.in_sample_rate = sample_rate;
audio.out_sample_rate = received.freq;
+ audio.sample_rate_adj = audio.out_sample_rate * DRC_MAX_ADJUSTMENT;
+ audio.adj_out_sample_rate = audio.out_sample_rate;
+
plat_sound_select_resampler();
plat_sound_resize_buffer();
@@ -347,12 +373,22 @@ float plat_sound_capacity(void)
}
#define BATCH_SIZE 100
-void plat_sound_write_resample(const struct audio_frame *data, int frames, int (*resample)(struct audio_frame data))
+void plat_sound_write_resample(const struct audio_frame *data, int frames, int (*resample)(struct audio_frame data), bool drc)
{
int consumed = 0;
if (audio.buf_len == 0)
return;
+ if (drc) {
+ if (plat_sound_capacity() < DRC_ADJ_BELOW) {
+ audio.adj_out_sample_rate = audio.out_sample_rate - audio.sample_rate_adj;
+ } else if (plat_sound_capacity() > DRC_ADJ_ABOVE) {
+ audio.adj_out_sample_rate = audio.out_sample_rate + audio.sample_rate_adj;
+ } else {
+ audio.adj_out_sample_rate = audio.out_sample_rate;
+ }
+ }
+
SDL_LockAudio();
while (frames > 0) {
@@ -382,12 +418,17 @@ void plat_sound_write_resample(const struct audio_frame *data, int frames, int (
void plat_sound_write_passthrough(const struct audio_frame *data, int frames)
{
- plat_sound_write_resample(data, frames, audio_resample_passthrough);
+ plat_sound_write_resample(data, frames, audio_resample_passthrough, false);
}
void plat_sound_write_nearest(const struct audio_frame *data, int frames)
{
- plat_sound_write_resample(data, frames, audio_resample_nearest);
+ plat_sound_write_resample(data, frames, audio_resample_nearest, false);
+}
+
+void plat_sound_write_drc(const struct audio_frame *data, int frames)
+{
+ plat_sound_write_resample(data, frames, audio_resample_nearest, true);
}
void plat_sound_resize_buffer(void) {
@@ -398,6 +439,10 @@ void plat_sound_resize_buffer(void) {
? current_audio_buffer_size * audio.in_sample_rate / frame_rate
: 0;
+ /* Dynamic adjustment keeps buffer 50% full, need double size */
+ if (enable_drc)
+ audio.buf_len *= 2;
+
if (audio.buf_len == 0) {
SDL_UnlockAudio();
return;
@@ -422,7 +467,10 @@ void plat_sound_resize_buffer(void) {
static void plat_sound_select_resampler(void)
{
- if (audio.in_sample_rate == audio.out_sample_rate) {
+ if (enable_drc) {
+ PA_INFO("Using audio adjustment (in: %d, out: %d-%d)\n", audio.in_sample_rate, audio.out_sample_rate - audio.sample_rate_adj, audio.out_sample_rate + audio.sample_rate_adj);
+ plat_sound_write = plat_sound_write_drc;
+ } else if (audio.in_sample_rate == audio.out_sample_rate) {
PA_INFO("Using passthrough resampler (in: %d, out: %d)\n", audio.in_sample_rate, audio.out_sample_rate);
plat_sound_write = plat_sound_write_passthrough;
} else {
@@ -479,7 +527,14 @@ int plat_reinit(void)
PA_ERROR("SDL sound failed to init: %s\n", SDL_GetError());
return -1;
}
+ } else {
+ plat_sound_resize_buffer();
+ plat_sound_select_resampler();
}
+
+ if (frame_rate != 0)
+ frame_time = 1000000 / frame_rate;
+
scale_update_scaler();
return 0;
}