diff --git a/src/android/app/src/main/java/io/github/lime3ds/android/features/settings/model/IntSetting.kt b/src/android/app/src/main/java/io/github/lime3ds/android/features/settings/model/IntSetting.kt index 289d2f8c5..c4637d4b7 100644 --- a/src/android/app/src/main/java/io/github/lime3ds/android/features/settings/model/IntSetting.kt +++ b/src/android/app/src/main/java/io/github/lime3ds/android/features/settings/model/IntSetting.kt @@ -35,6 +35,7 @@ enum class IntSetting( ASYNC_CUSTOM_LOADING("async_custom_loading", Settings.SECTION_UTILITY, 1), PRELOAD_TEXTURES("preload_textures", Settings.SECTION_UTILITY, 0), ENABLE_AUDIO_STRETCHING("enable_audio_stretching", Settings.SECTION_AUDIO, 1), + ENABLE_REALTIME_AUDIO("enable_realtime_audio", Settings.SECTION_AUDIO, 0), CPU_JIT("use_cpu_jit", Settings.SECTION_CORE, 1), HW_SHADER("use_hw_shader", Settings.SECTION_RENDERER, 1), VSYNC("use_vsync_new", Settings.SECTION_RENDERER, 1), diff --git a/src/android/app/src/main/java/io/github/lime3ds/android/features/settings/ui/SettingsFragmentPresenter.kt b/src/android/app/src/main/java/io/github/lime3ds/android/features/settings/ui/SettingsFragmentPresenter.kt index 6cba97e00..f85881ee1 100644 --- a/src/android/app/src/main/java/io/github/lime3ds/android/features/settings/ui/SettingsFragmentPresenter.kt +++ b/src/android/app/src/main/java/io/github/lime3ds/android/features/settings/ui/SettingsFragmentPresenter.kt @@ -859,6 +859,15 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView) IntSetting.ENABLE_AUDIO_STRETCHING.defaultValue ) ) + add( + SwitchSetting( + IntSetting.ENABLE_REALTIME_AUDIO, + R.string.realtime_audio, + R.string.realtime_audio_description, + IntSetting.ENABLE_REALTIME_AUDIO.key, + IntSetting.ENABLE_REALTIME_AUDIO.defaultValue + ) + ) add( SingleChoiceSetting( IntSetting.AUDIO_INPUT_TYPE, diff --git a/src/android/app/src/main/jni/config.cpp b/src/android/app/src/main/jni/config.cpp index fce2a244c..941db7610 100644 --- a/src/android/app/src/main/jni/config.cpp +++ b/src/android/app/src/main/jni/config.cpp @@ -195,6 +195,7 @@ void Config::ReadValues() { // Audio ReadSetting("Audio", Settings::values.audio_emulation); ReadSetting("Audio", Settings::values.enable_audio_stretching); + ReadSetting("Audio", Settings::values.enable_realtime_audio); ReadSetting("Audio", Settings::values.volume); ReadSetting("Audio", Settings::values.output_type); ReadSetting("Audio", Settings::values.output_device); diff --git a/src/android/app/src/main/jni/default_ini.h b/src/android/app/src/main/jni/default_ini.h index c46395fea..11a24bf7b 100644 --- a/src/android/app/src/main/jni/default_ini.h +++ b/src/android/app/src/main/jni/default_ini.h @@ -240,6 +240,10 @@ enable_dsp_lle_thread = # 0: No, 1 (default): Yes enable_audio_stretching = +# Simulates the Nintendo 3DS audio for HLE +# 0 (default): No, 1: Yes +enable_realtime_audio = + # Output volume. # 1.0 (default): 100%, 0.0; mute volume = diff --git a/src/android/app/src/main/res/values-es/strings.xml b/src/android/app/src/main/res/values-es/strings.xml index c7f5657a8..06322267d 100644 --- a/src/android/app/src/main/res/values-es/strings.xml +++ b/src/android/app/src/main/res/values-es/strings.xml @@ -246,6 +246,8 @@ Se esperan fallos gráficos temporales cuando ésta esté activado. Volumen Extensión de Audio Extiende el audio para reducir los parones. Cuando se active, la latencia de audio se incrementará y reducirá un poco el rendimiento. + Activar audio en tiempo real + Simula el audio de la Nintendo 3DS para HLE, corrigiendo el retraso del audio cuando la velocidad es inferior al 100%. Podría causar problemas de desincronización del audio Dispositivo de entrada de audio Modo de salida del audio diff --git a/src/android/app/src/main/res/values/strings.xml b/src/android/app/src/main/res/values/strings.xml index 8aa13c2d0..faea46b18 100644 --- a/src/android/app/src/main/res/values/strings.xml +++ b/src/android/app/src/main/res/values/strings.xml @@ -271,6 +271,8 @@ Volume Audio Stretching Stretches audio to reduce stuttering. When enabled, increases audio latency and slightly reduces performance. + Enable real-time audio + Simulates the Nintendo 3DS audio for HLE, fixing audio lag when speed is lower from 100%. Might cause audio desync issues Audio Input Device Sound Output Mode diff --git a/src/audio_core/hle/hle.cpp b/src/audio_core/hle/hle.cpp index f0be7f2c1..a5e2cf63a 100644 --- a/src/audio_core/hle/hle.cpp +++ b/src/audio_core/hle/hle.cpp @@ -2,6 +2,8 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include + #include #include #include @@ -21,6 +23,7 @@ #include "common/common_types.h" #include "common/hash.h" #include "common/logging/log.h" +#include "common/settings.h" #include "core/core.h" #include "core/core_timing.h" @@ -414,7 +417,12 @@ void DspHle::Impl::AudioTickCallback(s64 cycles_late) { } // Reschedule recurrent event - core_timing.ScheduleEvent(audio_frame_ticks - cycles_late, tick_event); + const double time_scale = + Settings::values.enable_realtime_audio + ? std::clamp(Core::System::GetInstance().GetLastFrameTimeScale(), 1.0, 3.0) + : 1.0; + s64 adjusted_ticks = static_cast(audio_frame_ticks / time_scale - cycles_late); + core_timing.ScheduleEvent(adjusted_ticks, tick_event); } DspHle::DspHle(Core::System& system, Memory::MemorySystem& memory, Core::Timing& timing) diff --git a/src/common/settings.cpp b/src/common/settings.cpp index 0c51c40c2..5a533750e 100644 --- a/src/common/settings.cpp +++ b/src/common/settings.cpp @@ -121,6 +121,7 @@ void LogSettings() { log_setting("Audio_InputType", values.input_type.GetValue()); log_setting("Audio_InputDevice", values.input_device.GetValue()); log_setting("Audio_EnableAudioStretching", values.enable_audio_stretching.GetValue()); + log_setting("Audio_EnableRealtime", values.enable_realtime_audio.GetValue()); using namespace Service::CAM; log_setting("Camera_OuterRightName", values.camera_name[OuterRightCamera]); log_setting("Camera_OuterRightConfig", values.camera_config[OuterRightCamera]); @@ -171,6 +172,7 @@ void RestoreGlobalState(bool is_powered_on) { // Audio values.audio_emulation.SetGlobal(true); values.enable_audio_stretching.SetGlobal(true); + values.enable_realtime_audio.SetGlobal(true); values.volume.SetGlobal(true); // Core diff --git a/src/common/settings.h b/src/common/settings.h index 3526d3a35..e7228aef3 100644 --- a/src/common/settings.h +++ b/src/common/settings.h @@ -521,6 +521,7 @@ struct Values { bool audio_muted; SwitchableSetting audio_emulation{AudioEmulation::HLE, "audio_emulation"}; SwitchableSetting enable_audio_stretching{true, "enable_audio_stretching"}; + SwitchableSetting enable_realtime_audio{false, "enable_realtime_audio"}; SwitchableSetting volume{1.f, 0.f, 1.f, "volume"}; Setting output_type{AudioCore::SinkType::Auto, "output_type"}; Setting output_device{"auto", "output_device"}; diff --git a/src/core/core.cpp b/src/core/core.cpp index 9c376c168..3a3f2f551 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -392,6 +392,10 @@ PerfStats::Results System::GetLastPerfStats() { return perf_stats ? perf_stats->GetLastStats() : PerfStats::Results{}; } +double System::GetLastFrameTimeScale() { + return perf_stats->GetLastFrameTimeScale(); +} + void System::Reschedule() { if (!reschedule_pending) { return; diff --git a/src/core/core.h b/src/core/core.h index c703803c0..7b2f00784 100644 --- a/src/core/core.h +++ b/src/core/core.h @@ -193,6 +193,8 @@ public: [[nodiscard]] PerfStats::Results GetLastPerfStats(); + double GetLastFrameTimeScale(); + /** * Gets a reference to the emulated CPU. * @returns A reference to the emulated CPU. diff --git a/src/lime/config.cpp b/src/lime/config.cpp index dec7acbd1..17b452123 100644 --- a/src/lime/config.cpp +++ b/src/lime/config.cpp @@ -184,6 +184,7 @@ void Config::ReadValues() { // Audio ReadSetting("Audio", Settings::values.audio_emulation); ReadSetting("Audio", Settings::values.enable_audio_stretching); + ReadSetting("Audio", Settings::values.enable_realtime_audio); ReadSetting("Audio", Settings::values.volume); ReadSetting("Audio", Settings::values.output_type); ReadSetting("Audio", Settings::values.output_device); diff --git a/src/lime/default_ini.h b/src/lime/default_ini.h index b3cdf9293..ea641efce 100644 --- a/src/lime/default_ini.h +++ b/src/lime/default_ini.h @@ -252,6 +252,10 @@ enable_dsp_lle_thread = # 0: No, 1 (default): Yes enable_audio_stretching = +# Simulates the Nintendo 3DS audio for HLE +# 0 (default): No, 1: Yes +enable_realtime_audio = + # Output volume. # 1.0 (default): 100%, 0.0; mute volume = diff --git a/src/lime_qt/configuration/config.cpp b/src/lime_qt/configuration/config.cpp index a767ce1dc..3eba3f958 100644 --- a/src/lime_qt/configuration/config.cpp +++ b/src/lime_qt/configuration/config.cpp @@ -278,6 +278,7 @@ void Config::ReadAudioValues() { ReadGlobalSetting(Settings::values.audio_emulation); ReadGlobalSetting(Settings::values.enable_audio_stretching); + ReadGlobalSetting(Settings::values.enable_realtime_audio); ReadGlobalSetting(Settings::values.volume); if (global) { @@ -885,6 +886,7 @@ void Config::SaveAudioValues() { WriteGlobalSetting(Settings::values.audio_emulation); WriteGlobalSetting(Settings::values.enable_audio_stretching); + WriteGlobalSetting(Settings::values.enable_realtime_audio); WriteGlobalSetting(Settings::values.volume); if (global) { diff --git a/src/lime_qt/configuration/configure_audio.cpp b/src/lime_qt/configuration/configure_audio.cpp index 64b4bc1e4..fff5fd034 100644 --- a/src/lime_qt/configuration/configure_audio.cpp +++ b/src/lime_qt/configuration/configure_audio.cpp @@ -64,6 +64,7 @@ void ConfigureAudio::SetConfiguration() { SetInputDeviceFromDeviceID(); ui->toggle_audio_stretching->setChecked(Settings::values.enable_audio_stretching.GetValue()); + ui->toggle_realtime_audio->setChecked(Settings::values.enable_realtime_audio.GetValue()); const s32 volume = static_cast(Settings::values.volume.GetValue() * ui->volume_slider->maximum()); @@ -155,6 +156,8 @@ void ConfigureAudio::SetVolumeIndicatorText(int percentage) { void ConfigureAudio::ApplyConfiguration() { ConfigurationShared::ApplyPerGameSetting(&Settings::values.enable_audio_stretching, ui->toggle_audio_stretching, audio_stretching); + ConfigurationShared::ApplyPerGameSetting(&Settings::values.enable_realtime_audio, + ui->toggle_realtime_audio, realtime_audio); ConfigurationShared::ApplyPerGameSetting(&Settings::values.audio_emulation, ui->emulation_combo_box); ConfigurationShared::ApplyPerGameSetting( @@ -235,4 +238,7 @@ void ConfigureAudio::SetupPerGameUI() { ConfigurationShared::SetColoredTristate( ui->toggle_audio_stretching, Settings::values.enable_audio_stretching, audio_stretching); + + ConfigurationShared::SetColoredTristate(ui->toggle_realtime_audio, + Settings::values.enable_realtime_audio, realtime_audio); } diff --git a/src/lime_qt/configuration/configure_audio.h b/src/lime_qt/configuration/configure_audio.h index 001d574ed..b732d79fc 100644 --- a/src/lime_qt/configuration/configure_audio.h +++ b/src/lime_qt/configuration/configure_audio.h @@ -39,5 +39,6 @@ private: void SetupPerGameUI(); ConfigurationShared::CheckState audio_stretching; + ConfigurationShared::CheckState realtime_audio; std::unique_ptr ui; }; diff --git a/src/lime_qt/configuration/configure_audio.ui b/src/lime_qt/configuration/configure_audio.ui index 63df78c5a..60c31a352 100644 --- a/src/lime_qt/configuration/configure_audio.ui +++ b/src/lime_qt/configuration/configure_audio.ui @@ -95,6 +95,16 @@ + + + + Simulates the Nintendo 3DS audio for HLE, fixing audio lag when speed is lower from 100%. Might cause audio desync issues + + + Enable real-time audio + + +