From 07b3f8334318656fc7113af6adf1bd8deb562ad0 Mon Sep 17 00:00:00 2001 From: Flyinghead Date: Mon, 20 May 2019 19:12:28 +0200 Subject: [PATCH 1/2] audio: new option for automatic limitFPS LimitFPS now can be enabled, disabled or automatic. The latter option doesn't wait for audio if the emulator is running slow (over the last 2 secs) Renamed `Audio Backend` to `Audio Driver` in the UI. --- core/nullDC.cpp | 6 ++--- core/oslib/audiostream.cpp | 3 ++- core/rend/gui.cpp | 47 ++++++++++++++++++++++++-------------- core/types.h | 7 +++++- 4 files changed, 41 insertions(+), 22 deletions(-) diff --git a/core/nullDC.cpp b/core/nullDC.cpp index 1deeebad7..1937b8018 100755 --- a/core/nullDC.cpp +++ b/core/nullDC.cpp @@ -499,7 +499,7 @@ void InitSettings() settings.dreamcast.language = 6; // default settings.dreamcast.FullMMU = false; settings.dynarec.SmcCheckLevel = FullCheck; - settings.aica.LimitFPS = true; + settings.aica.LimitFPS = LimitFPSEnabled; settings.aica.NoBatch = false; // This also controls the DSP. Disabled by default settings.aica.NoSound = false; settings.audio.backend = "auto"; @@ -580,7 +580,7 @@ void LoadSettings(bool game_specific) settings.dreamcast.broadcast = cfgLoadInt(config_section, "Dreamcast.Broadcast", settings.dreamcast.broadcast); settings.dreamcast.language = cfgLoadInt(config_section, "Dreamcast.Language", settings.dreamcast.language); settings.dreamcast.FullMMU = cfgLoadBool(config_section, "Dreamcast.FullMMU", settings.dreamcast.FullMMU); - settings.aica.LimitFPS = cfgLoadBool(config_section, "aica.LimitFPS", settings.aica.LimitFPS); + settings.aica.LimitFPS = (LimitFPSEnum)cfgLoadInt(config_section, "aica.LimitFPS", (int)settings.aica.LimitFPS); settings.aica.NoBatch = cfgLoadBool(config_section, "aica.NoBatch", settings.aica.NoBatch); settings.aica.NoSound = cfgLoadBool(config_section, "aica.NoSound", settings.aica.NoSound); settings.audio.backend = cfgLoadStr(audio_section, "backend", settings.audio.backend.c_str()); @@ -717,7 +717,7 @@ void SaveSettings() cfgSaveInt("config", "Dynarec.SmcCheckLevel", (int)settings.dynarec.SmcCheckLevel); cfgSaveInt("config", "Dreamcast.Language", settings.dreamcast.language); - cfgSaveBool("config", "aica.LimitFPS", settings.aica.LimitFPS); + cfgSaveInt("config", "aica.LimitFPS", (int)settings.aica.LimitFPS); cfgSaveBool("config", "aica.NoBatch", settings.aica.NoBatch); cfgSaveBool("config", "aica.NoSound", settings.aica.NoSound); cfgSaveStr("audio", "backend", settings.audio.backend.c_str()); diff --git a/core/oslib/audiostream.cpp b/core/oslib/audiostream.cpp index 1d6f4f079..d0f1ebeb4 100644 --- a/core/oslib/audiostream.cpp +++ b/core/oslib/audiostream.cpp @@ -150,7 +150,8 @@ void WriteSample(s16 r, s16 l) if (WritePtr==(SAMPLE_COUNT-1)) { - bool do_wait = settings.aica.LimitFPS && (mspdf <= 11); + bool do_wait = settings.aica.LimitFPS == LimitFPSEnabled + || (settings.aica.LimitFPS == LimitFPSAuto && mspdf <= 11); PushAudio(RingBuffer,SAMPLE_COUNT, do_wait); } diff --git a/core/rend/gui.cpp b/core/rend/gui.cpp index 4feec179b..58872b54b 100644 --- a/core/rend/gui.cpp +++ b/core/rend/gui.cpp @@ -1029,9 +1029,28 @@ static void gui_display_settings() ImGui::Checkbox("Enable DSP", &settings.aica.NoBatch); ImGui::SameLine(); ShowHelpMarker("Enable the Dreamcast Digital Sound Processor. Only recommended on fast and arm64 platforms"); - ImGui::Checkbox("Limit FPS", &settings.aica.LimitFPS); - ImGui::SameLine(); - ShowHelpMarker("Use the sound output to limit the speed of the emulator. Recommended in most cases"); + const char *preview = settings.aica.LimitFPS == LimitFPSDisabled ? "Disabled" : settings.aica.LimitFPS == LimitFPSAuto ? "Automatic" : "Enabled"; + if (ImGui::BeginCombo("Limit Emulator Speed", preview, ImGuiComboFlags_None)) + { + bool is_selected = settings.aica.LimitFPS == LimitFPSDisabled; + if (ImGui::Selectable("Disabled", &is_selected)) + settings.aica.LimitFPS = LimitFPSDisabled; + if (is_selected) + ImGui::SetItemDefaultFocus(); + is_selected = settings.aica.LimitFPS == LimitFPSAuto; + if (ImGui::Selectable("Automatic", &is_selected)) + settings.aica.LimitFPS = LimitFPSAuto; + if (is_selected) + ImGui::SetItemDefaultFocus(); + is_selected = settings.aica.LimitFPS == LimitFPSEnabled; + if (ImGui::Selectable("Enabled", &is_selected)) + settings.aica.LimitFPS = LimitFPSEnabled; + if (is_selected) + ImGui::SetItemDefaultFocus(); + ImGui::EndCombo(); + } + ImGui::SameLine(); + ShowHelpMarker("Whether to limit the emulator speed using the audio output. Enabled recommended"); audiobackend_t* backend = NULL;; std::string backend_name = settings.audio.backend; @@ -1045,19 +1064,15 @@ static void gui_display_settings() SortAudioBackends(); audiobackend_t* current_backend = backend; - if (ImGui::BeginCombo("Audio Backend", backend_name.c_str(), ImGuiComboFlags_None)) + if (ImGui::BeginCombo("Audio Driver", backend_name.c_str(), ImGuiComboFlags_None)) { bool is_selected = (settings.audio.backend == "auto"); - if (ImGui::Selectable("auto", &is_selected)) + if (ImGui::Selectable("auto - Automatic driver selection", &is_selected)) settings.audio.backend = "auto"; - ImGui::SameLine(); ImGui::Text("-"); - ImGui::SameLine(); ImGui::Text("Autoselect audio backend"); is_selected = (settings.audio.backend == "none"); - if (ImGui::Selectable("none", &is_selected)) + if (ImGui::Selectable("none - No audio driver", &is_selected)) settings.audio.backend = "none"; - ImGui::SameLine(); ImGui::Text("-"); - ImGui::SameLine(); ImGui::Text("No audio backend"); for (int i = 0; i < GetAudioBackendCount(); i++) { @@ -1067,17 +1082,15 @@ static void gui_display_settings() if (is_selected) current_backend = backend; - if (ImGui::Selectable(backend->slug.c_str(), &is_selected)) + if (ImGui::Selectable((backend->slug + " - " + backend->name).c_str(), &is_selected)) settings.audio.backend = backend->slug; - ImGui::SameLine(); ImGui::Text("-"); - ImGui::SameLine(); ImGui::Text(backend->name.c_str()); - if (is_selected) - ImGui::SetItemDefaultFocus(); + if (is_selected) + ImGui::SetItemDefaultFocus(); } ImGui::EndCombo(); } - ImGui::SameLine(); - ShowHelpMarker("The audio backend to use"); + ImGui::SameLine(); + ShowHelpMarker("The audio driver to use"); if (current_backend != NULL && current_backend->get_options != NULL) { diff --git a/core/types.h b/core/types.h index 8b1a039a8..b8f2e67bf 100644 --- a/core/types.h +++ b/core/types.h @@ -607,6 +607,11 @@ enum SmcCheckEnum { FastCheck = 1, NoCheck = 2 }; +enum LimitFPSEnum { + LimitFPSDisabled = 0, + LimitFPSAuto = 1, + LimitFPSEnabled = 2 +}; struct settings_t { @@ -669,7 +674,7 @@ struct settings_t { u32 HW_mixing; //(0) -> SW , 1 -> HW , 2 -> Auto u32 BufferSize; //In samples ,*4 for bytes (1024) - bool LimitFPS; // defaults to true + LimitFPSEnum LimitFPS; u32 GlobalFocus; //0 -> only hwnd , (1) -> Global u32 BufferCount; //BufferCount+2 buffers used , max 60 , default 0 u32 CDDAMute; From 4cfcf2ea835b37f3268ecdb58fba6b483178ed08 Mon Sep 17 00:00:00 2001 From: Flyinghead Date: Mon, 20 May 2019 19:13:08 +0200 Subject: [PATCH 2/2] alsa: don't spam console if underrun --- core/oslib/audiobackend_alsa.cpp | 21 ++------------------- 1 file changed, 2 insertions(+), 19 deletions(-) diff --git a/core/oslib/audiobackend_alsa.cpp b/core/oslib/audiobackend_alsa.cpp index 47c4f348c..2ac08fe46 100644 --- a/core/oslib/audiobackend_alsa.cpp +++ b/core/oslib/audiobackend_alsa.cpp @@ -159,30 +159,13 @@ static u32 alsa_push(void* frame, u32 samples, bool wait) if (rc == -EPIPE) { /* EPIPE means underrun */ - fprintf(stderr, "ALSA: underrun occurred\n"); snd_pcm_prepare(handle); // Write some silence then our samples const size_t silence_size = period_size * 4; void *silence = alloca(silence_size * 4); memset(silence, 0, silence_size * 4); - rc = snd_pcm_writei(handle, silence, silence_size); - if (rc < 0) - fprintf(stderr, "ALSA: error from writei(silence): %s\n", snd_strerror(rc)); - else if (rc < silence_size) - fprintf(stderr, "ALSA: short write from writei(silence): %d/%ld frames\n", rc, silence_size); - rc = snd_pcm_writei(handle, frame, samples); - if (rc < 0) - fprintf(stderr, "ALSA: error from writei(again): %s\n", snd_strerror(rc)); - else if (rc < samples) - fprintf(stderr, "ALSA: short write from writei(again): %d/%d frames\n", rc, samples); - } - else if (rc < 0) - { - fprintf(stderr, "ALSA: error from writei: %s\n", snd_strerror(rc)); - } - else if (rc != samples) - { - fprintf(stderr, "ALSA: short write, wrote %d frames of %d\n", rc, samples); + snd_pcm_writei(handle, silence, silence_size); + snd_pcm_writei(handle, frame, samples); } return 1; }