diff --git a/config.def.h b/config.def.h index 5d2378c843..a97d669c4d 100644 --- a/config.def.h +++ b/config.def.h @@ -129,7 +129,10 @@ static const unsigned out_rate = 48000; // Input samplerate from libSNES. // Lower this (slightly) if you are experiencing frequent audio dropouts while vsync is enabled. -static const unsigned in_rate = 31980; +static const float in_rate = 31980.0; + +// When changing input rate on-the-fly +static const float audio_rate_step = 0.25; // Audio device (e.g. hw:0,0 or /dev/audio). If NULL, will use defaults. static const char* audio_device = NULL; @@ -179,6 +182,8 @@ static const struct snes_keybind snes_keybinds_1[] = { { SSNES_QUIT_KEY, SDLK_ESCAPE, NO_BTN, AXIS_NONE }, { SSNES_STATE_SLOT_MINUS, SDLK_F6, NO_BTN, AXIS_NONE }, { SSNES_STATE_SLOT_PLUS, SDLK_F7, NO_BTN, AXIS_NONE }, + { SSNES_AUDIO_INPUT_RATE_PLUS, SDLK_KP_PLUS, NO_BTN, AXIS_NONE }, + { SSNES_AUDIO_INPUT_RATE_MINUS, SDLK_KP_MINUS, NO_BTN, AXIS_NONE }, { -1 } }; diff --git a/driver.h b/driver.h index 0a0458a5d4..0149ffb6ef 100644 --- a/driver.h +++ b/driver.h @@ -34,6 +34,8 @@ enum SSNES_QUIT_KEY, SSNES_STATE_SLOT_PLUS, SSNES_STATE_SLOT_MINUS, + SSNES_AUDIO_INPUT_RATE_PLUS, + SSNES_AUDIO_INPUT_RATE_MINUS, }; struct snes_keybind diff --git a/general.h b/general.h index e2c9424f30..c60f237e9e 100644 --- a/general.h +++ b/general.h @@ -35,7 +35,7 @@ #define MAX_PLAYERS 5 -#define MAX_BINDS 20 // Needs to be increased every time there are new binds added. +#define MAX_BINDS 22 // Needs to be increased every time there are new binds added. #define SSNES_NO_JOYPAD 0xFFFF struct settings { @@ -67,7 +67,8 @@ struct settings char driver[32]; bool enable; unsigned out_rate; - unsigned in_rate; + float in_rate; + float rate_step; char device[256]; unsigned latency; bool sync; diff --git a/settings.c b/settings.c index 8592993a23..e2b7c444a9 100644 --- a/settings.c +++ b/settings.c @@ -117,6 +117,7 @@ static void set_defaults(void) g_settings.audio.enable = audio_enable; g_settings.audio.out_rate = out_rate; g_settings.audio.in_rate = in_rate; + g_settings.audio.rate_step = audio_rate_step; if (audio_device) strncpy(g_settings.audio.device, audio_device, sizeof(g_settings.audio.device)); g_settings.audio.latency = out_latency; @@ -323,8 +324,11 @@ static void parse_config_file(void) if (config_get_int(conf, "audio_out_rate", &tmp_int)) g_settings.audio.out_rate = tmp_int; - if (config_get_int(conf, "audio_in_rate", &tmp_int)) - g_settings.audio.in_rate = tmp_int; + if (config_get_double(conf, "audio_in_rate", &tmp_double)) + g_settings.audio.in_rate = tmp_double; + + if (config_get_double(conf, "audio_rate_step", &tmp_double)) + g_settings.audio.rate_step = tmp_double; if (config_get_string(conf, "audio_device", &tmp_str)) { @@ -405,6 +409,8 @@ static const struct bind_map bind_maps[MAX_PLAYERS][MAX_BINDS - 1] = { DECLARE_BIND(state_slot_decrease, SSNES_STATE_SLOT_MINUS) DECLARE_BIND(exit_emulator, SSNES_QUIT_KEY) DECLARE_BIND(toggle_fullscreen, SSNES_FULLSCREEN_TOGGLE_KEY) + DECLARE_BIND(rate_step_up, SSNES_AUDIO_INPUT_RATE_PLUS) + DECLARE_BIND(rate_step_down, SSNES_AUDIO_INPUT_RATE_MINUS) }, { DECLARE_BIND(player2_a, SNES_DEVICE_ID_JOYPAD_A) @@ -426,6 +432,8 @@ static const struct bind_map bind_maps[MAX_PLAYERS][MAX_BINDS - 1] = { DECLARE_BIND(state_slot_decrease, SSNES_STATE_SLOT_MINUS) DECLARE_BIND(exit_emulator, SSNES_QUIT_KEY) DECLARE_BIND(toggle_fullscreen, SSNES_FULLSCREEN_TOGGLE_KEY) + DECLARE_BIND(rate_step_up, SSNES_AUDIO_INPUT_RATE_PLUS) + DECLARE_BIND(rate_step_down, SSNES_AUDIO_INPUT_RATE_MINUS) }, { DECLARE_BIND(player3_a, SNES_DEVICE_ID_JOYPAD_A) @@ -447,6 +455,8 @@ static const struct bind_map bind_maps[MAX_PLAYERS][MAX_BINDS - 1] = { DECLARE_BIND(state_slot_decrease, SSNES_STATE_SLOT_MINUS) DECLARE_BIND(exit_emulator, SSNES_QUIT_KEY) DECLARE_BIND(toggle_fullscreen, SSNES_FULLSCREEN_TOGGLE_KEY) + DECLARE_BIND(rate_step_up, SSNES_AUDIO_INPUT_RATE_PLUS) + DECLARE_BIND(rate_step_down, SSNES_AUDIO_INPUT_RATE_MINUS) }, { DECLARE_BIND(player4_a, SNES_DEVICE_ID_JOYPAD_A) @@ -468,6 +478,8 @@ static const struct bind_map bind_maps[MAX_PLAYERS][MAX_BINDS - 1] = { DECLARE_BIND(state_slot_decrease, SSNES_STATE_SLOT_MINUS) DECLARE_BIND(exit_emulator, SSNES_QUIT_KEY) DECLARE_BIND(toggle_fullscreen, SSNES_FULLSCREEN_TOGGLE_KEY) + DECLARE_BIND(rate_step_up, SSNES_AUDIO_INPUT_RATE_PLUS) + DECLARE_BIND(rate_step_down, SSNES_AUDIO_INPUT_RATE_MINUS) }, { DECLARE_BIND(player5_a, SNES_DEVICE_ID_JOYPAD_A) @@ -489,6 +501,8 @@ static const struct bind_map bind_maps[MAX_PLAYERS][MAX_BINDS - 1] = { DECLARE_BIND(state_slot_decrease, SSNES_STATE_SLOT_MINUS) DECLARE_BIND(exit_emulator, SSNES_QUIT_KEY) DECLARE_BIND(toggle_fullscreen, SSNES_FULLSCREEN_TOGGLE_KEY) + DECLARE_BIND(rate_step_up, SSNES_AUDIO_INPUT_RATE_PLUS) + DECLARE_BIND(rate_step_down, SSNES_AUDIO_INPUT_RATE_MINUS) }, }; @@ -515,6 +529,8 @@ static const struct key_map sdlk_map[] = { { "alt", SDLK_LALT }, { "space", SDLK_SPACE }, { "escape", SDLK_ESCAPE }, + { "kp_plus", SDLK_KP_PLUS }, + { "kp_minus", SDLK_KP_MINUS }, { "f1", SDLK_F1 }, { "f2", SDLK_F2 }, { "f3", SDLK_F3 }, diff --git a/ssnes.c b/ssnes.c index d5956b3639..90ae5fac3b 100644 --- a/ssnes.c +++ b/ssnes.c @@ -746,6 +746,31 @@ static void check_stateslots(void) old_should_slot_decrease = should_slot_decrease; } +static void check_input_rate(void) +{ + bool display = false; + if (driver.input->key_pressed(driver.input_data, SSNES_AUDIO_INPUT_RATE_PLUS)) + { + g_settings.audio.in_rate += g_settings.audio.rate_step; + display = true; + } + else if (driver.input->key_pressed(driver.input_data, SSNES_AUDIO_INPUT_RATE_MINUS)) + { + g_settings.audio.in_rate -= g_settings.audio.rate_step; + display = true; + } + + if (display) + { + char msg[256]; + snprintf(msg, sizeof(msg), "Audio input rate: %.2f Hz", g_settings.audio.in_rate); + + msg_queue_clear(g_extern.msg_queue); + msg_queue_push(g_extern.msg_queue, msg, 0, 180); + SSNES_LOG("%s\n", msg); + } +} + static void do_state_checks(void) { set_fast_forward_button(driver.input->key_pressed(driver.input_data, SSNES_FAST_FORWARD_KEY)); @@ -753,6 +778,7 @@ static void do_state_checks(void) check_stateslots(); check_savestates(); check_fullscreen(); + check_input_rate(); } diff --git a/ssnes.cfg b/ssnes.cfg index 9a497a8f7f..1155336b69 100644 --- a/ssnes.cfg +++ b/ssnes.cfg @@ -62,6 +62,9 @@ # but lots of dropped frames. Reasonable values for this is 32000 +/- 100 Hz. # audio_in_rate = 31980 +# When altering audio_in_rate on-the-fly, define by how much each time. +# audio_rate_step = 0.25 + # Audio driver backend. Depending on configuration possible candidates are: alsa, pulse, oss, jack, rsound, roar, openal, sdl and xaudio # audio_driver = @@ -183,3 +186,7 @@ # Key to exit emulator cleanly. # Killing it in any hard way (SIGTERM, SIGKILL, etc, will terminate emulator without saving RAM, etc.) # input_exit_emulator = escape + +# Decrease/increase input sample rate on the fly. Amount to decrease/increase is defined by audio_rate_step. +# input_rate_step_up = kp_plus +# input_rate_step_down = kp_minus