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
+
+
+
-