diff --git a/android/app/src/main/res/values/strings.xml b/android/app/src/main/res/values/strings.xml
index ad898765b..d432de9c3 100644
--- a/android/app/src/main/res/values/strings.xml
+++ b/android/app/src/main/res/values/strings.xml
@@ -47,6 +47,8 @@
Writes log messages to the Android message logger. Only useful when attached to a computer with adb.
Volume
Controls the volume of the emulator\'s sound output.
+ Volume
+ Controls the volume of the emulator\'s sound output when fast forwarding.
Mute All Sound
Prevents the emulator from emitting any sound.
Mute CD Audio
diff --git a/android/app/src/main/res/xml/audio_preferences.xml b/android/app/src/main/res/xml/audio_preferences.xml
index b8fbede83..8c3871db6 100644
--- a/android/app/src/main/res/xml/audio_preferences.xml
+++ b/android/app/src/main/res/xml/audio_preferences.xml
@@ -26,6 +26,15 @@
app:min="0"
app:iconSpaceReserved="false"
app:showSeekBarValue="true" />
+
Reconfigure(AUDIO_SAMPLE_RATE, AUDIO_CHANNELS, g_settings.audio_buffer_size);
}
- m_audio_stream->SetOutputVolume(g_settings.audio_output_muted ? 0 : g_settings.audio_output_volume);
+ m_audio_stream->SetOutputVolume(GetAudioOutputVolume());
+}
+
+s32 HostInterface::GetAudioOutputVolume() const
+{
+ return g_settings.audio_output_muted ? 0 : g_settings.audio_output_volume;
}
bool HostInterface::BootSystem(const SystemBootParameters& parameters)
@@ -479,6 +484,7 @@ void HostInterface::SetDefaultSettings(SettingsInterface& si)
si.SetStringValue("Audio", "Backend", Settings::GetAudioBackendName(Settings::DEFAULT_AUDIO_BACKEND));
si.SetIntValue("Audio", "OutputVolume", 100);
+ si.SetIntValue("Audio", "FastForwardVolume", 100);
si.SetIntValue("Audio", "BufferSize", DEFAULT_AUDIO_BUFFER_SIZE);
si.SetIntValue("Audio", "OutputMuted", false);
si.SetBoolValue("Audio", "Sync", true);
@@ -638,7 +644,7 @@ void HostInterface::CheckForSettingsChanges(const Settings& old_settings)
CPU::ClearICache();
}
- m_audio_stream->SetOutputVolume(g_settings.audio_output_muted ? 0 : g_settings.audio_output_volume);
+ m_audio_stream->SetOutputVolume(GetAudioOutputVolume());
if (g_settings.gpu_resolution_scale != old_settings.gpu_resolution_scale ||
g_settings.gpu_multisamples != old_settings.gpu_multisamples ||
diff --git a/src/core/host_interface.h b/src/core/host_interface.h
index 4a6b7f193..3233041ea 100644
--- a/src/core/host_interface.h
+++ b/src/core/host_interface.h
@@ -144,6 +144,7 @@ protected:
virtual bool AcquireHostDisplay() = 0;
virtual void ReleaseHostDisplay() = 0;
virtual std::unique_ptr CreateAudioStream(AudioBackend backend) = 0;
+ virtual s32 GetAudioOutputVolume() const;
virtual void OnSystemCreated();
virtual void OnSystemDestroyed();
diff --git a/src/core/settings.cpp b/src/core/settings.cpp
index 611c45adc..22cb672b9 100644
--- a/src/core/settings.cpp
+++ b/src/core/settings.cpp
@@ -196,6 +196,7 @@ void Settings::Load(SettingsInterface& si)
ParseAudioBackend(si.GetStringValue("Audio", "Backend", GetAudioBackendName(DEFAULT_AUDIO_BACKEND)).c_str())
.value_or(DEFAULT_AUDIO_BACKEND);
audio_output_volume = si.GetIntValue("Audio", "OutputVolume", 100);
+ audio_fast_forward_volume = si.GetIntValue("Audio", "FastForwardVolume", 100);
audio_buffer_size = si.GetIntValue("Audio", "BufferSize", HostInterface::DEFAULT_AUDIO_BUFFER_SIZE);
audio_output_muted = si.GetBoolValue("Audio", "OutputMuted", false);
audio_sync_enabled = si.GetBoolValue("Audio", "Sync", true);
@@ -327,6 +328,7 @@ void Settings::Save(SettingsInterface& si) const
si.SetStringValue("Audio", "Backend", GetAudioBackendName(audio_backend));
si.SetIntValue("Audio", "OutputVolume", audio_output_volume);
+ si.SetIntValue("Audio", "FastForwardVolume", audio_fast_forward_volume);
si.SetIntValue("Audio", "BufferSize", audio_buffer_size);
si.SetBoolValue("Audio", "OutputMuted", audio_output_muted);
si.SetBoolValue("Audio", "Sync", audio_sync_enabled);
diff --git a/src/core/settings.h b/src/core/settings.h
index 27b9a49be..5f9432e27 100644
--- a/src/core/settings.h
+++ b/src/core/settings.h
@@ -142,6 +142,7 @@ struct Settings
AudioBackend audio_backend = AudioBackend::Cubeb;
s32 audio_output_volume = 100;
+ s32 audio_fast_forward_volume = 100;
u32 audio_buffer_size = 2048;
bool audio_output_muted = false;
bool audio_sync_enabled = true;
@@ -200,6 +201,11 @@ struct Settings
!cpu_recompiler_memory_exceptions);
}
+ ALWAYS_INLINE s32 GetAudioOutputVolume(bool fast_forwarding) const
+ {
+ return audio_output_muted ? 0 : (fast_forwarding ? audio_fast_forward_volume : audio_output_volume);
+ }
+
bool HasAnyPerGameMemoryCards() const;
static void CPUOverclockPercentToFraction(u32 percent, u32* numerator, u32* denominator);
diff --git a/src/duckstation-qt/audiosettingswidget.cpp b/src/duckstation-qt/audiosettingswidget.cpp
index 97ee9c62b..c958dda92 100644
--- a/src/duckstation-qt/audiosettingswidget.cpp
+++ b/src/duckstation-qt/audiosettingswidget.cpp
@@ -25,11 +25,13 @@ AudioSettingsWidget::AudioSettingsWidget(QtHostInterface* host_interface, QWidge
SettingWidgetBinder::BindWidgetToBoolSetting(m_host_interface, m_ui.startDumpingOnBoot, "Audio", "DumpOnBoot");
SettingWidgetBinder::BindWidgetToBoolSetting(m_host_interface, m_ui.muteCDAudio, "CDROM", "MuteCDAudio");
- m_ui.volume->setValue(m_host_interface->GetIntSettingValue("Audio", "OutputVolume"));
- m_ui.muted->setChecked(m_host_interface->GetBoolSettingValue("Audio", "OutputMuted"));
+ m_ui.volume->setValue(m_host_interface->GetIntSettingValue("Audio", "OutputVolume", 100));
+ m_ui.fastForwardVolume->setValue(m_host_interface->GetIntSettingValue("Audio", "FastForwardVolume", 100));
+ m_ui.muted->setChecked(m_host_interface->GetBoolSettingValue("Audio", "OutputMuted", false));
connect(m_ui.bufferSize, &QSlider::valueChanged, this, &AudioSettingsWidget::updateBufferingLabel);
connect(m_ui.volume, &QSlider::valueChanged, this, &AudioSettingsWidget::onOutputVolumeChanged);
+ connect(m_ui.fastForwardVolume, &QSlider::valueChanged, this, &AudioSettingsWidget::onFastForwardVolumeChanged);
connect(m_ui.muted, &QCheckBox::stateChanged, this, &AudioSettingsWidget::onOutputMutedChanged);
updateBufferingLabel();
@@ -53,8 +55,11 @@ AudioSettingsWidget::AudioSettingsWidget(QtHostInterface* host_interface, QWidge
dialog->registerWidgetHelp(
m_ui.startDumpingOnBoot, tr("Start Dumping On Boot"), tr("Unchecked"),
tr("Start dumping audio to file as soon as the emulator is started. Mainly useful as a debug option."));
- dialog->registerWidgetHelp(m_ui.volume, tr("Volume"), "100",
+ dialog->registerWidgetHelp(m_ui.volume, tr("Output Volume"), "100",
tr("Controls the volume of the audio played on the host. Values are in percentage."));
+ dialog->registerWidgetHelp(
+ m_ui.fastForwardVolume, tr("Fast Forward Volume"), "100",
+ tr("Controls the volume of the audio played on the host when fast forwarding. Values are in percentage."));
dialog->registerWidgetHelp(m_ui.muted, tr("Mute All Sound"), tr("Unchecked"),
tr("Prevents the emulator from producing any audible sound."));
dialog->registerWidgetHelp(m_ui.muteCDAudio, tr("Mute CD Audio"), tr("Unchecked"),
@@ -83,13 +88,23 @@ void AudioSettingsWidget::updateBufferingLabel()
void AudioSettingsWidget::updateVolumeLabel()
{
m_ui.volumeLabel->setText(tr("%1%").arg(m_ui.volume->value()));
+ m_ui.fastForwardVolumeLabel->setText(tr("%1%").arg(m_ui.fastForwardVolume->value()));
}
void AudioSettingsWidget::onOutputVolumeChanged(int new_value)
{
m_host_interface->SetIntSettingValue("Audio", "OutputVolume", new_value);
if (!m_ui.muted->isChecked())
- m_host_interface->setAudioOutputVolume(new_value);
+ m_host_interface->setAudioOutputVolume(new_value, m_ui.fastForwardVolume->value());
+
+ updateVolumeLabel();
+}
+
+void AudioSettingsWidget::onFastForwardVolumeChanged(int new_value)
+{
+ m_host_interface->SetIntSettingValue("Audio", "FastForwardVolume", new_value);
+ if (!m_ui.muted->isChecked())
+ m_host_interface->setAudioOutputVolume(m_ui.volume->value(), new_value);
updateVolumeLabel();
}
diff --git a/src/duckstation-qt/audiosettingswidget.h b/src/duckstation-qt/audiosettingswidget.h
index e285f85bc..5ee5df002 100644
--- a/src/duckstation-qt/audiosettingswidget.h
+++ b/src/duckstation-qt/audiosettingswidget.h
@@ -19,6 +19,7 @@ private Q_SLOTS:
void updateBufferingLabel();
void updateVolumeLabel();
void onOutputVolumeChanged(int new_value);
+ void onFastForwardVolumeChanged(int new_value);
void onOutputMutedChanged(int new_state);
private:
diff --git a/src/duckstation-qt/audiosettingswidget.ui b/src/duckstation-qt/audiosettingswidget.ui
index 8ecc39ec7..e83d034e7 100644
--- a/src/duckstation-qt/audiosettingswidget.ui
+++ b/src/duckstation-qt/audiosettingswidget.ui
@@ -7,7 +7,7 @@
0
0
502
- 308
+ 312
@@ -123,66 +123,109 @@
-
- Volume:
+ Output Volume:
-
-
-
- 100
-
-
- 100
-
-
- Qt::Horizontal
-
-
- QSlider::TicksBothSides
-
-
- 10
+
+
-
+
+
+ 100
+
+
+ 100
+
+
+ Qt::Horizontal
+
+
+ QSlider::TicksBothSides
+
+
+ 10
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ 100%
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ -
+
+
-
+
+
+ 100
+
+
+ 100
+
+
+ Qt::Horizontal
+
+
+ QSlider::TicksBothSides
+
+
+ 10
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ 100%
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ -
+
+
+ Fast Forward Volume:
- -
+
-
Mute All Sound
- -
+
-
Mute CD Audio
- -
-
-
- 100%
-
-
- Qt::AlignCenter
-
-
-
- -
-
-
- Qt::Horizontal
-
-
-
- 40
- 20
-
-
-
-
@@ -202,7 +245,7 @@
-
+
diff --git a/src/duckstation-qt/qthostinterface.cpp b/src/duckstation-qt/qthostinterface.cpp
index 58015c4aa..76ad26e96 100644
--- a/src/duckstation-qt/qthostinterface.cpp
+++ b/src/duckstation-qt/qthostinterface.cpp
@@ -1162,18 +1162,19 @@ void QtHostInterface::saveState(bool global, qint32 slot, bool block_until_done
SaveState(global, slot);
}
-void QtHostInterface::setAudioOutputVolume(int value)
+void QtHostInterface::setAudioOutputVolume(int volume, int fast_forward_volume)
{
if (!isOnWorkerThread())
{
- QMetaObject::invokeMethod(this, "setAudioOutputVolume", Q_ARG(int, value));
+ QMetaObject::invokeMethod(this, "setAudioOutputVolume", Q_ARG(int, volume), Q_ARG(int, fast_forward_volume));
return;
}
if (m_audio_stream)
- m_audio_stream->SetOutputVolume(value);
+ m_audio_stream->SetOutputVolume(m_speed_limiter_enabled ? volume : fast_forward_volume);
- g_settings.audio_output_volume = value;
+ g_settings.audio_output_volume = volume;
+ g_settings.audio_fast_forward_volume = fast_forward_volume;
}
void QtHostInterface::setAudioOutputMuted(bool muted)
@@ -1185,7 +1186,7 @@ void QtHostInterface::setAudioOutputMuted(bool muted)
}
if (m_audio_stream)
- m_audio_stream->SetOutputVolume(muted ? 0 : g_settings.audio_output_volume);
+ m_audio_stream->SetOutputVolume(GetAudioOutputVolume());
g_settings.audio_output_muted = muted;
}
diff --git a/src/duckstation-qt/qthostinterface.h b/src/duckstation-qt/qthostinterface.h
index aaa5125ad..7dc9660c9 100644
--- a/src/duckstation-qt/qthostinterface.h
+++ b/src/duckstation-qt/qthostinterface.h
@@ -159,7 +159,7 @@ public Q_SLOTS:
void loadState(const QString& filename);
void loadState(bool global, qint32 slot);
void saveState(bool global, qint32 slot, bool block_until_done = false);
- void setAudioOutputVolume(int value);
+ void setAudioOutputVolume(int volume, int fast_forward_volume);
void setAudioOutputMuted(bool muted);
void startDumpingAudio();
void stopDumpingAudio();
diff --git a/src/frontend-common/common_host_interface.cpp b/src/frontend-common/common_host_interface.cpp
index 5859dd2be..e77edc5ae 100644
--- a/src/frontend-common/common_host_interface.cpp
+++ b/src/frontend-common/common_host_interface.cpp
@@ -474,6 +474,11 @@ std::unique_ptr CommonHostInterface::CreateAudioStream(AudioBackend
}
}
+s32 CommonHostInterface::GetAudioOutputVolume() const
+{
+ return g_settings.GetAudioOutputVolume(!m_speed_limiter_enabled);
+}
+
void CommonHostInterface::UpdateControllerInterface()
{
const std::string backend_str = GetStringSettingValue(
@@ -615,6 +620,7 @@ void CommonHostInterface::UpdateSpeedLimiterState()
if (m_audio_stream)
{
+ m_audio_stream->SetOutputVolume(GetAudioOutputVolume());
m_audio_stream->SetSync(audio_sync_enabled);
if (audio_sync_enabled)
m_audio_stream->EmptyBuffers();
@@ -1670,19 +1676,19 @@ void CommonHostInterface::RegisterSaveStateHotkeys()
void CommonHostInterface::RegisterAudioHotkeys()
{
- RegisterHotkey(
- StaticString(TRANSLATABLE("Hotkeys", "Audio")), StaticString("AudioMute"),
- StaticString(TRANSLATABLE("Hotkeys", "Toggle Mute")), [this](bool pressed) {
- if (pressed && System::IsValid())
- {
- g_settings.audio_output_muted = !g_settings.audio_output_muted;
- m_audio_stream->SetOutputVolume(g_settings.audio_output_muted ? 0 : g_settings.audio_output_volume);
- if (g_settings.audio_output_muted)
- AddOSDMessage(TranslateStdString("OSDMessage", "Volume: Muted"), 2.0f);
- else
- AddFormattedOSDMessage(2.0f, TranslateString("OSDMessage", "Volume: %d%%"), g_settings.audio_output_volume);
- }
- });
+ RegisterHotkey(StaticString(TRANSLATABLE("Hotkeys", "Audio")), StaticString("AudioMute"),
+ StaticString(TRANSLATABLE("Hotkeys", "Toggle Mute")), [this](bool pressed) {
+ if (pressed && System::IsValid())
+ {
+ g_settings.audio_output_muted = !g_settings.audio_output_muted;
+ const s32 volume = GetAudioOutputVolume();
+ m_audio_stream->SetOutputVolume(volume);
+ if (g_settings.audio_output_muted)
+ AddOSDMessage(TranslateStdString("OSDMessage", "Volume: Muted"), 2.0f);
+ else
+ AddFormattedOSDMessage(2.0f, TranslateString("OSDMessage", "Volume: %d%%"), volume);
+ }
+ });
RegisterHotkey(StaticString(TRANSLATABLE("Hotkeys", "Audio")), StaticString("AudioCDAudioMute"),
StaticString(TRANSLATABLE("Hotkeys", "Toggle CD Audio Mute")), [this](bool pressed) {
if (pressed && System::IsValid())
@@ -1698,22 +1704,24 @@ void CommonHostInterface::RegisterAudioHotkeys()
StaticString(TRANSLATABLE("Hotkeys", "Volume Up")), [this](bool pressed) {
if (pressed && System::IsValid())
{
- g_settings.audio_output_volume = std::min(g_settings.audio_output_volume + 10, 100);
+ const s32 volume = std::min(GetAudioOutputVolume() + 10, 100);
+ g_settings.audio_output_volume = volume;
+ g_settings.audio_fast_forward_volume = volume;
g_settings.audio_output_muted = false;
- m_audio_stream->SetOutputVolume(g_settings.audio_output_volume);
- AddFormattedOSDMessage(2.0f, TranslateString("OSDMessage", "Volume: %d%%"),
- g_settings.audio_output_volume);
+ m_audio_stream->SetOutputVolume(volume);
+ AddFormattedOSDMessage(2.0f, TranslateString("OSDMessage", "Volume: %d%%"), volume);
}
});
RegisterHotkey(StaticString(TRANSLATABLE("Hotkeys", "Audio")), StaticString("AudioVolumeDown"),
StaticString(TRANSLATABLE("Hotkeys", "Volume Down")), [this](bool pressed) {
if (pressed && System::IsValid())
{
- g_settings.audio_output_volume = std::max(g_settings.audio_output_volume - 10, 0);
+ const s32 volume = std::max(GetAudioOutputVolume() - 10, 0);
+ g_settings.audio_output_volume = volume;
+ g_settings.audio_fast_forward_volume = volume;
g_settings.audio_output_muted = false;
- m_audio_stream->SetOutputVolume(g_settings.audio_output_volume);
- AddFormattedOSDMessage(2.0f, TranslateString("OSDMessage", "Volume: %d%%"),
- g_settings.audio_output_volume);
+ m_audio_stream->SetOutputVolume(volume);
+ AddFormattedOSDMessage(2.0f, TranslateString("OSDMessage", "Volume: %d%%"), volume);
}
});
}
diff --git a/src/frontend-common/common_host_interface.h b/src/frontend-common/common_host_interface.h
index 48ea81e5e..f95461da5 100644
--- a/src/frontend-common/common_host_interface.h
+++ b/src/frontend-common/common_host_interface.h
@@ -230,6 +230,7 @@ protected:
virtual bool SetFullscreen(bool enabled);
virtual std::unique_ptr CreateAudioStream(AudioBackend backend) override;
+ virtual s32 GetAudioOutputVolume() const override;
virtual void UpdateControllerInterface();
virtual void OnSystemCreated() override;