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;