diff --git a/pcsx2-qt/QtHost.cpp b/pcsx2-qt/QtHost.cpp index 07e53c27908af..ca012221b9186 100644 --- a/pcsx2-qt/QtHost.cpp +++ b/pcsx2-qt/QtHost.cpp @@ -879,38 +879,6 @@ void EmuThread::endCapture() MTGS::RunOnGSThread(&GSEndCapture); } -void EmuThread::setAudioOutputVolume(int volume, int fast_forward_volume) -{ - if (!isOnEmuThread()) - { - QMetaObject::invokeMethod(this, "setAudioOutputVolume", Qt::QueuedConnection, Q_ARG(int, volume), - Q_ARG(int, fast_forward_volume)); - return; - } - - if (!VMManager::HasValidVM()) - return; - - EmuConfig.SPU2.OutputVolume = static_cast(volume); - EmuConfig.SPU2.FastForwardVolume = static_cast(fast_forward_volume); - SPU2::SetOutputVolume(SPU2::GetResetVolume()); -} - -void EmuThread::setAudioOutputMuted(bool muted) -{ - if (!isOnEmuThread()) - { - QMetaObject::invokeMethod(this, "setAudioOutputMuted", Qt::QueuedConnection, Q_ARG(bool, muted)); - return; - } - - if (!VMManager::HasValidVM()) - return; - - EmuConfig.SPU2.OutputMuted = muted; - SPU2::SetOutputVolume(SPU2::GetResetVolume()); -} - std::optional EmuThread::acquireRenderWindow(bool recreate_window) { // Check if we're wanting to get exclusive fullscreen. This should be safe to read, since we're going to be calling from the GS thread. diff --git a/pcsx2-qt/QtHost.h b/pcsx2-qt/QtHost.h index 0d6bac097bb4c..46a7ba290e200 100644 --- a/pcsx2-qt/QtHost.h +++ b/pcsx2-qt/QtHost.h @@ -112,8 +112,6 @@ public Q_SLOTS: void queueSnapshot(quint32 gsdump_frames); void beginCapture(const QString& path); void endCapture(); - void setAudioOutputVolume(int volume, int fast_forward_volume); - void setAudioOutputMuted(bool muted); Q_SIGNALS: bool messageConfirmed(const QString& title, const QString& message); diff --git a/pcsx2-qt/Settings/AudioSettingsWidget.cpp b/pcsx2-qt/Settings/AudioSettingsWidget.cpp index c6f00c74557d9..d28cd02b7bebf 100644 --- a/pcsx2-qt/Settings/AudioSettingsWidget.cpp +++ b/pcsx2-qt/Settings/AudioSettingsWidget.cpp @@ -73,21 +73,21 @@ AudioSettingsWidget::AudioSettingsWidget(SettingsWindow* settings_dialog, QWidge // for per-game, just use the normal path, since it needs to re-read/apply if (!dialog()->isPerGameSettings()) { - m_ui.volume->setValue(dialog()->getEffectiveIntValue("SPU2/Output", "OutputVolume", 100)); + m_ui.standardVolume->setValue(dialog()->getEffectiveIntValue("SPU2/Output", "StandardVolume", 100)); m_ui.fastForwardVolume->setValue(dialog()->getEffectiveIntValue("SPU2/Output", "FastForwardVolume", 100)); m_ui.muted->setChecked(dialog()->getEffectiveBoolValue("SPU2/Output", "OutputMuted", false)); - connect(m_ui.volume, &QSlider::valueChanged, this, &AudioSettingsWidget::onOutputVolumeChanged); + connect(m_ui.standardVolume, &QSlider::valueChanged, this, &AudioSettingsWidget::onStandardVolumeChanged); connect(m_ui.fastForwardVolume, &QSlider::valueChanged, this, &AudioSettingsWidget::onFastForwardVolumeChanged); connect(m_ui.muted, &QCheckBox::checkStateChanged, this, &AudioSettingsWidget::onOutputMutedChanged); updateVolumeLabel(); } else { - SettingWidgetBinder::BindWidgetAndLabelToIntSetting(sif, m_ui.volume, m_ui.volumeLabel, tr("%"), "SPU2/Output", "OutputVolume", 100); + SettingWidgetBinder::BindWidgetAndLabelToIntSetting(sif, m_ui.standardVolume, m_ui.standardVolumeLabel, tr("%"), "SPU2/Output", "StandardVolume", 100); SettingWidgetBinder::BindWidgetAndLabelToIntSetting(sif, m_ui.fastForwardVolume, m_ui.fastForwardVolumeLabel, tr("%"), "SPU2/Output", "FastForwardVolume", 100); SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.muted, "SPU2/Output", "OutputMuted", false); } - connect(m_ui.resetVolume, &QToolButton::clicked, this, [this]() { resetVolume(false); }); + connect(m_ui.resetStandardVolume, &QToolButton::clicked, this, [this]() { resetVolume(false); }); connect(m_ui.resetFastForwardVolume, &QToolButton::clicked, this, [this]() { resetVolume(true); }); dialog()->registerWidgetHelp( @@ -103,8 +103,8 @@ AudioSettingsWidget::AudioSettingsWidget(SettingsWindow* settings_dialog, QWidge m_ui.outputLatencyMS, tr("Output Latency"), tr("%1 ms").arg(AudioStreamParameters::DEFAULT_OUTPUT_LATENCY_MS), tr("Determines the latency from the buffer to the host audio output. This can be set lower than the target latency " "to reduce audio delay.")); - dialog()->registerWidgetHelp(m_ui.volume, tr("Output Volume"), "100%", - tr("Controls the volume of the audio played on the host.")); + dialog()->registerWidgetHelp(m_ui.standardVolume, tr("Standard Volume"), "100%", + tr("Controls the volume of the audio played on the host at normal speed.")); dialog()->registerWidgetHelp(m_ui.fastForwardVolume, tr("Fast Forward Volume"), "100%", tr("Controls the volume of the audio played on the host when fast forwarding.")); dialog()->registerWidgetHelp(m_ui.muted, tr("Mute All Sound"), tr("Unchecked"), @@ -118,9 +118,9 @@ AudioSettingsWidget::AudioSettingsWidget(SettingsWindow* settings_dialog, QWidge tr("When running outside of 100% speed, adjusts the tempo on audio instead of dropping frames. Produces much nicer fast-forward/slowdown audio.")); dialog()->registerWidgetHelp(m_ui.stretchSettings, tr("Stretch Settings"), tr("N/A"), tr("These settings fine-tune the behavior of the SoundTouch audio time stretcher when running outside of 100% speed.")); - dialog()->registerWidgetHelp(m_ui.resetVolume, tr("Reset Volume"), tr("N/A"), - dialog()->isPerGameSettings() ? tr("Resets output volume back to the global/inherited setting.") : - tr("Resets output volume back to the default.")); + dialog()->registerWidgetHelp(m_ui.resetStandardVolume, tr("Reset Standard Volume"), tr("N/A"), + dialog()->isPerGameSettings() ? tr("Resets standard volume back to the global/inherited setting.") : + tr("Resets standard volume back to the default.")); dialog()->registerWidgetHelp(m_ui.resetFastForwardVolume, tr("Reset Fast Forward Volume"), tr("N/A"), dialog()->isPerGameSettings() ? tr("Resets fast forward volume back to the global/inherited setting.") : tr("Resets fast forward volume back to the default.")); @@ -292,7 +292,7 @@ void AudioSettingsWidget::updateLatencyLabel() void AudioSettingsWidget::updateVolumeLabel() { - m_ui.volumeLabel->setText(tr("%1%").arg(m_ui.volume->value())); + m_ui.standardVolumeLabel->setText(tr("%1%").arg(m_ui.standardVolume->value())); m_ui.fastForwardVolumeLabel->setText(tr("%1%").arg(m_ui.fastForwardVolume->value())); } @@ -303,18 +303,18 @@ void AudioSettingsWidget::onMinimalOutputLatencyChanged() updateLatencyLabel(); } -void AudioSettingsWidget::onOutputVolumeChanged(int new_value) +void AudioSettingsWidget::onStandardVolumeChanged(const int new_value) { // only called for base settings pxAssert(!dialog()->isPerGameSettings()); - Host::SetBaseIntSettingValue("SPU2/Output", "OutputVolume", new_value); + Host::SetBaseIntSettingValue("SPU2/Output", "StandardVolume", new_value); Host::CommitBaseSettingChanges(); g_emu_thread->applySettings(); updateVolumeLabel(); } -void AudioSettingsWidget::onFastForwardVolumeChanged(int new_value) +void AudioSettingsWidget::onFastForwardVolumeChanged(const int new_value) { // only called for base settings pxAssert(!dialog()->isPerGameSettings()); @@ -325,7 +325,7 @@ void AudioSettingsWidget::onFastForwardVolumeChanged(int new_value) updateVolumeLabel(); } -void AudioSettingsWidget::onOutputMutedChanged(int new_state) +void AudioSettingsWidget::onOutputMutedChanged(const int new_state) { // only called for base settings pxAssert(!dialog()->isPerGameSettings()); @@ -478,11 +478,11 @@ void AudioSettingsWidget::onStretchSettingsClicked() dlg.exec(); } -void AudioSettingsWidget::resetVolume(bool fast_forward) +void AudioSettingsWidget::resetVolume(const bool fast_forward) { - const char* key = fast_forward ? "FastForwardVolume" : "OutputVolume"; - QSlider* const slider = fast_forward ? m_ui.fastForwardVolume : m_ui.volume; - QLabel* const label = fast_forward ? m_ui.fastForwardVolumeLabel : m_ui.volumeLabel; + const char* key = fast_forward ? "FastForwardVolume" : "StandardVolume"; + QSlider* const slider = fast_forward ? m_ui.fastForwardVolume : m_ui.standardVolume; + QLabel* const label = fast_forward ? m_ui.fastForwardVolumeLabel : m_ui.standardVolumeLabel; if (dialog()->isPerGameSettings()) { diff --git a/pcsx2-qt/Settings/AudioSettingsWidget.h b/pcsx2-qt/Settings/AudioSettingsWidget.h index cbf4ab156c0e8..30ae3e6444c42 100644 --- a/pcsx2-qt/Settings/AudioSettingsWidget.h +++ b/pcsx2-qt/Settings/AudioSettingsWidget.h @@ -27,9 +27,9 @@ private Q_SLOTS: void updateLatencyLabel(); void updateVolumeLabel(); void onMinimalOutputLatencyChanged(); - void onOutputVolumeChanged(int new_value); - void onFastForwardVolumeChanged(int new_value); - void onOutputMutedChanged(int new_state); + void onStandardVolumeChanged(const int new_value); + void onFastForwardVolumeChanged(const int new_value); + void onOutputMutedChanged(const int new_state); void onExpansionSettingsClicked(); void onStretchSettingsClicked(); @@ -38,7 +38,7 @@ private Q_SLOTS: AudioBackend getEffectiveBackend() const; AudioExpansionMode getEffectiveExpansionMode() const; u32 getEffectiveExpansionBlockSize() const; - void resetVolume(bool fast_forward); + void resetVolume(const bool fast_forward); Ui::AudioSettingsWidget m_ui; u32 m_output_device_latency = 0; diff --git a/pcsx2-qt/Settings/AudioSettingsWidget.ui b/pcsx2-qt/Settings/AudioSettingsWidget.ui index f1625e29a65d4..00069bb016724 100644 --- a/pcsx2-qt/Settings/AudioSettingsWidget.ui +++ b/pcsx2-qt/Settings/AudioSettingsWidget.ui @@ -219,14 +219,14 @@ - Output Volume: + Standard Volume: - + 200 @@ -245,7 +245,7 @@ - + 0 @@ -261,9 +261,9 @@ - + - Reset Volume + Reset Standard Volume diff --git a/pcsx2/Config.h b/pcsx2/Config.h index 98b532c4a138d..9ad5fc1031b8e 100644 --- a/pcsx2/Config.h +++ b/pcsx2/Config.h @@ -942,7 +942,7 @@ struct Pcsx2Config VisualDebugEnabled : 1; BITFIELD_END - u32 OutputVolume = 100; + u32 StandardVolume = 100; u32 FastForwardVolume = 100; bool OutputMuted = false; diff --git a/pcsx2/Hotkeys.cpp b/pcsx2/Hotkeys.cpp index cfad631873e29..daa3eef413f4c 100644 --- a/pcsx2/Hotkeys.cpp +++ b/pcsx2/Hotkeys.cpp @@ -40,26 +40,56 @@ static void HotkeyAdjustTargetSpeed(double delta) Host::OSD_QUICK_DURATION); } -static void HotkeyAdjustVolume(s32 fixed, s32 delta) +static void HotkeyAdjustVolume(const s32 delta) { if (!VMManager::HasValidVM()) return; - const s32 current_vol = static_cast(SPU2::GetOutputVolume()); - const s32 new_volume = - std::clamp((fixed >= 0) ? fixed : (current_vol + delta), 0, static_cast(Pcsx2Config::SPU2Options::MAX_VOLUME)); - if (current_vol != new_volume) + // Volume-adjusting hotkeys override mute toggle hotkey. EmuConfig.SPU2.OutputMuted overrides hotkeys. + if (!SPU2::SetOutputMuted(false)) + { + Host::AddIconOSDMessage("VolumeChanged", ICON_FA_VOLUME_XMARK, TRANSLATE_STR("Hotkeys", "Volume: Muted in Settings")); + return; + } + + const s32 current_volume = static_cast(SPU2::GetOutputVolume()); + const s32 maximum_volume = static_cast(Pcsx2Config::SPU2Options::MAX_VOLUME); + const s32 new_volume = std::clamp(current_volume + delta, 0, maximum_volume); + + if (current_volume != new_volume) SPU2::SetOutputVolume(static_cast(new_volume)); - if (new_volume == 0) + if (new_volume > 0 && new_volume < maximum_volume) { - Host::AddIconOSDMessage("VolumeChanged", ICON_FA_VOLUME_XMARK, TRANSLATE_STR("Hotkeys", "Volume: Muted")); + Host::AddIconOSDMessage("VolumeChanged", new_volume < 100 ? ICON_FA_VOLUME_LOW : ICON_FA_VOLUME_HIGH, + fmt::format(TRANSLATE_FS("Hotkeys", "Volume: {} to {}%"), delta < 0 ? TRANSLATE_STR("Hotkeys", "Decreased") : TRANSLATE_STR("Hotkeys", "Increased"), new_volume)); } else { - Host::AddIconOSDMessage("VolumeChanged", (current_vol < new_volume) ? ICON_FA_VOLUME_HIGH : ICON_FA_VOLUME_LOW, - fmt::format(TRANSLATE_FS("Hotkeys", "Volume: {}%"), new_volume)); + Host::AddIconOSDMessage("VolumeChanged", delta < 0 ? ICON_FA_VOLUME_OFF : ICON_FA_VOLUME_HIGH, + fmt::format(TRANSLATE_FS("Hotkeys", "Volume: {} {}% Reached"), delta < 0 ? TRANSLATE_STR("Hotkeys", "Minimum") : TRANSLATE_STR("Hotkeys", "Maximum"), new_volume)); + } +} + +static void HotkeyToggleMute() +{ + if (!VMManager::HasValidVM()) + return; + + // Attempt to toggle output muting. EmuConfig.SPU2.OutputMuted overrides hotkeys. + if (SPU2::SetOutputMuted(!SPU2::IsOutputMuted())) + { + if (SPU2::IsOutputMuted()) + Host::AddIconOSDMessage("VolumeChanged", ICON_FA_VOLUME_XMARK, TRANSLATE_STR("Hotkeys", "Volume: Muted")); + else + { + const u32 current_volume = SPU2::GetOutputVolume(); + Host::AddIconOSDMessage("VolumeChanged", current_volume < 100 ? (current_volume == 0 ? ICON_FA_VOLUME_OFF : ICON_FA_VOLUME_LOW) : ICON_FA_VOLUME_HIGH, + fmt::format(TRANSLATE_FS("Hotkeys", "Volume: Unmuted to {}%"), current_volume)); + } } + else + Host::AddIconOSDMessage("VolumeChanged", ICON_FA_VOLUME_XMARK, TRANSLATE_STR("Hotkeys", "Volume: Muted in Settings")); } static void HotkeyLoadStateSlot(s32 slot) @@ -293,16 +323,16 @@ DEFINE_HOTKEY_LOADSTATE_X(10, TRANSLATE_NOOP("Hotkeys", "Load State From Slot 10 #undef DEFINE_HOTKEY_LOADSTATE_X DEFINE_HOTKEY("Mute", TRANSLATE_NOOP("Hotkeys", "Audio"), TRANSLATE_NOOP("Hotkeys", "Toggle Mute"), [](s32 pressed) { if (!pressed && VMManager::HasValidVM()) - HotkeyAdjustVolume((SPU2::GetOutputVolume() == 0) ? SPU2::GetResetVolume() : 0, 0); + HotkeyToggleMute(); }) DEFINE_HOTKEY("IncreaseVolume", TRANSLATE_NOOP("Hotkeys", "Audio"), TRANSLATE_NOOP("Hotkeys", "Increase Volume"), [](s32 pressed) { if (!pressed && VMManager::HasValidVM()) - HotkeyAdjustVolume(-1, 5); + HotkeyAdjustVolume(5); }) DEFINE_HOTKEY("DecreaseVolume", TRANSLATE_NOOP("Hotkeys", "Audio"), TRANSLATE_NOOP("Hotkeys", "Decrease Volume"), [](s32 pressed) { if (!pressed && VMManager::HasValidVM()) - HotkeyAdjustVolume(-1, -5); + HotkeyAdjustVolume(-5); }) END_HOTKEY_LIST() diff --git a/pcsx2/ImGui/FullscreenUI.cpp b/pcsx2/ImGui/FullscreenUI.cpp index 8e32e78950c11..0bef4bd120bc0 100644 --- a/pcsx2/ImGui/FullscreenUI.cpp +++ b/pcsx2/ImGui/FullscreenUI.cpp @@ -4511,8 +4511,8 @@ void FullscreenUI::DrawAudioSettingsPage() MenuHeading(FSUI_CSTR("Audio Control")); - DrawIntRangeSetting(bsi, FSUI_ICONSTR(ICON_FA_VOLUME_HIGH, "Output Volume"), - FSUI_CSTR("Controls the volume of the audio played on the host."), "SPU2/Output", "OutputVolume", 100, + DrawIntRangeSetting(bsi, FSUI_ICONSTR(ICON_FA_VOLUME_HIGH, "Standard Volume"), + FSUI_CSTR("Controls the volume of the audio played on the host at normal speed."), "SPU2/Output", "StandardVolume", 100, 0, 100, "%d%%"); DrawIntRangeSetting(bsi, FSUI_ICONSTR(ICON_FA_FORWARD_FAST, "Fast Forward Volume"), FSUI_CSTR("Controls the volume of the audio played on the host when fast forwarding."), "SPU2/Output", @@ -8288,7 +8288,7 @@ TRANSLATE_NOOP("FullscreenUI", "Determines what frame rate NTSC games run at."); TRANSLATE_NOOP("FullscreenUI", "PAL Frame Rate"); TRANSLATE_NOOP("FullscreenUI", "Determines what frame rate PAL games run at."); TRANSLATE_NOOP("FullscreenUI", "Audio Control"); -TRANSLATE_NOOP("FullscreenUI", "Controls the volume of the audio played on the host."); +TRANSLATE_NOOP("FullscreenUI", "Controls the volume of the audio played on the host at normal speed."); TRANSLATE_NOOP("FullscreenUI", "Controls the volume of the audio played on the host when fast forwarding."); TRANSLATE_NOOP("FullscreenUI", "Prevents the emulator from producing any audible sound."); TRANSLATE_NOOP("FullscreenUI", "Backend Settings"); @@ -8839,7 +8839,7 @@ TRANSLATE_NOOP("FullscreenUI", "Shade Boost Brightness"); TRANSLATE_NOOP("FullscreenUI", "Shade Boost Contrast"); TRANSLATE_NOOP("FullscreenUI", "Shade Boost Saturation"); TRANSLATE_NOOP("FullscreenUI", "TV Shaders"); -TRANSLATE_NOOP("FullscreenUI", "Output Volume"); +TRANSLATE_NOOP("FullscreenUI", "Standard Volume"); TRANSLATE_NOOP("FullscreenUI", "Fast Forward Volume"); TRANSLATE_NOOP("FullscreenUI", "Mute All Sound"); TRANSLATE_NOOP("FullscreenUI", "Audio Backend"); diff --git a/pcsx2/Pcsx2Config.cpp b/pcsx2/Pcsx2Config.cpp index c435923f87bc4..3d48bf39785be 100644 --- a/pcsx2/Pcsx2Config.cpp +++ b/pcsx2/Pcsx2Config.cpp @@ -1228,7 +1228,7 @@ void Pcsx2Config::SPU2Options::LoadSave(SettingsWrapper& wrap) { SettingsWrapSection("SPU2/Output"); - SettingsWrapEntry(OutputVolume); + SettingsWrapEntry(StandardVolume); SettingsWrapEntry(FastForwardVolume); SettingsWrapEntry(OutputMuted); SettingsWrapParsedEnum(Backend, "Backend", &AudioStream::ParseBackendName, &AudioStream::GetBackendName); @@ -1247,7 +1247,7 @@ bool Pcsx2Config::SPU2Options::operator!=(const SPU2Options& right) const bool Pcsx2Config::SPU2Options::operator==(const SPU2Options& right) const { return OpEqu(bitset) && - OpEqu(OutputVolume) && + OpEqu(StandardVolume) && OpEqu(FastForwardVolume) && OpEqu(OutputMuted) && OpEqu(Backend) && diff --git a/pcsx2/SPU2/spu2.cpp b/pcsx2/SPU2/spu2.cpp index 4da7e1c253edd..d1e49befd3f99 100644 --- a/pcsx2/SPU2/spu2.cpp +++ b/pcsx2/SPU2/spu2.cpp @@ -28,10 +28,13 @@ u32 lClocks = 0; static bool s_audio_capture_active = false; static bool s_psxmode = false; +static bool s_output_muted = false; static std::unique_ptr s_output_stream; static std::array s_current_chunk; static u32 s_current_chunk_pos; +static u32 s_standard_volume = 0; +static u32 s_fast_forward_volume = 0; u32 SPU2::GetConsoleSampleRate() { @@ -97,8 +100,17 @@ void SPU2writeDMA7Mem(u16* pMem, u32 size) void SPU2::CreateOutputStream() { - // Persist volume through stream recreates. - const u32 volume = s_output_stream ? s_output_stream->GetOutputVolume() : GetResetVolume(); + // Initialize volume and mute settings on new session. + if (!s_output_stream) + { + s_standard_volume = EmuConfig.SPU2.StandardVolume; + s_fast_forward_volume = EmuConfig.SPU2.FastForwardVolume; + s_output_muted = EmuConfig.SPU2.OutputMuted; + } + // Else persist volume through stream recreates. + else if (!s_output_muted) + SPU2::SaveOutputVolume(); + const u32 sample_rate = GetConsoleSampleRate(); s_output_stream.reset(); @@ -114,7 +126,7 @@ void SPU2::CreateOutputStream() s_output_stream = AudioStream::CreateNullStream(sample_rate, EmuConfig.SPU2.StreamParameters.buffer_ms); } - s_output_stream->SetOutputVolume(volume); + SPU2::UpdateOutputVolume(); s_output_stream->SetNominalRate(GetNominalRate()); s_output_stream->SetPaused(VMManager::GetState() == VMState::Paused); } @@ -144,20 +156,52 @@ void SPU2::SetOutputVolume(u32 volume) s_output_stream->SetOutputVolume(volume); } -u32 SPU2::GetResetVolume() -{ - return EmuConfig.SPU2.OutputMuted ? 0 : - ((VMManager::GetTargetSpeed() != 1.0f) ? - EmuConfig.SPU2.FastForwardVolume : - EmuConfig.SPU2.OutputVolume); -} - float SPU2::GetNominalRate() { // Adjust nominal rate when syncing to host. return VMManager::IsTargetSpeedAdjustedToHost() ? VMManager::GetTargetSpeed() : 1.0f; } +bool SPU2::SetOutputMuted(const bool muted) +{ + // User setting takes precedence. Unmute not guaranteed by design. + if (!s_output_stream || (!muted && EmuConfig.SPU2.OutputMuted)) + return false; + + if (muted == s_output_muted) + return true; + + if (muted) + SPU2::SaveOutputVolume(); + + s_output_muted = muted; + SPU2::UpdateOutputVolume(); + return true; +} + +bool SPU2::IsOutputMuted() +{ + return s_output_muted; +} + +void SPU2::UpdateOutputVolume() +{ + s_output_stream->SetOutputVolume(s_output_muted ? + 0 : (VMManager::GetTargetSpeed() == 1.0f ? + s_standard_volume : s_fast_forward_volume)); +} + +void SPU2::SaveOutputVolume() +{ + if (!s_output_muted) + { + if (VMManager::GetTargetSpeed() == 1.0f) + s_standard_volume = s_output_stream->GetOutputVolume(); + else + s_fast_forward_volume = s_output_stream->GetOutputVolume(); + } +} + void SPU2::SetOutputPaused(bool paused) { s_output_stream->SetPaused(paused); @@ -210,8 +254,20 @@ void SPU2::OnTargetSpeedChanged() s_output_stream->SetNominalRate(GetNominalRate()); - if (EmuConfig.SPU2.OutputVolume != EmuConfig.SPU2.FastForwardVolume && !EmuConfig.SPU2.OutputMuted) - s_output_stream->SetOutputVolume(GetResetVolume()); + // Flipped save as speed has already changed. + if (!s_output_muted) + { + if (VMManager::GetTargetSpeed() == 1.0f) + { + s_fast_forward_volume = s_output_stream->GetOutputVolume(); + s_output_stream->SetOutputVolume(s_standard_volume); + } + else + { + s_standard_volume = s_output_stream->GetOutputVolume(); + s_output_stream->SetOutputVolume(s_fast_forward_volume); + } + } } bool SPU2::Open() @@ -262,32 +318,44 @@ bool SPU2::IsRunningPSXMode() void SPU2::CheckForConfigChanges(const Pcsx2Config& old_config) { const Pcsx2Config::SPU2Options& opts = EmuConfig.SPU2; - const Pcsx2Config::SPU2Options& oldopts = old_config.SPU2; + const Pcsx2Config::SPU2Options& old_opts = old_config.SPU2; // No need to reinit for volume change. - if ((opts.OutputVolume != oldopts.OutputVolume && VMManager::GetTargetSpeed() == 1.0f) || - (opts.FastForwardVolume != oldopts.FastForwardVolume && VMManager::GetTargetSpeed() != 1.0f) || - opts.OutputMuted != oldopts.OutputMuted) + if (opts.OutputMuted != old_opts.OutputMuted) + SPU2::SetOutputMuted(opts.OutputMuted); + + bool volume_settings_changed = false; + if (opts.StandardVolume != old_opts.StandardVolume) { - SetOutputVolume(GetResetVolume()); + s_standard_volume = opts.StandardVolume; + volume_settings_changed = true; } + if (opts.FastForwardVolume != old_opts.FastForwardVolume) + { + s_fast_forward_volume = opts.FastForwardVolume; + volume_settings_changed = true; + } + + if (volume_settings_changed) + SPU2::UpdateOutputVolume(); + // Things which require re-initialzing the output. - if (opts.Backend != oldopts.Backend || - opts.StreamParameters != oldopts.StreamParameters || - opts.DriverName != oldopts.DriverName || - opts.DeviceName != oldopts.DeviceName) + if (opts.Backend != old_opts.Backend || + opts.StreamParameters != old_opts.StreamParameters || + opts.DriverName != old_opts.DriverName || + opts.DeviceName != old_opts.DeviceName) { CreateOutputStream(); } - else if (opts.IsTimeStretchEnabled() != oldopts.IsTimeStretchEnabled()) + else if (opts.IsTimeStretchEnabled() != old_opts.IsTimeStretchEnabled()) { s_output_stream->SetStretchEnabled(opts.IsTimeStretchEnabled()); } #ifdef PCSX2_DEVBUILD // AccessLog controls file output. - if (opts.AccessLog != oldopts.AccessLog) + if (opts.AccessLog != old_opts.AccessLog) { if (AccessLog()) OpenFileLog(); diff --git a/pcsx2/SPU2/spu2.h b/pcsx2/SPU2/spu2.h index 3865b6ed3dbb5..ca944569ca4f4 100644 --- a/pcsx2/SPU2/spu2.h +++ b/pcsx2/SPU2/spu2.h @@ -36,8 +36,17 @@ u32 GetOutputVolume(); /// Directly updates the output volume without going through the configuration. void SetOutputVolume(u32 volume); -/// Returns the volume that we would reset the output to on startup. -u32 GetResetVolume(); +/// Sets up muting and unmuting and reports success or failure. +bool SetOutputMuted(const bool muted); + +/// Returns true if the output is muted (distinct from 0%). +bool IsOutputMuted(); + +/// Updates the current volume based on running state. +void UpdateOutputVolume(); + +/// Saves the current volume based on running state. +void SaveOutputVolume(); /// Pauses/resumes the output stream. void SetOutputPaused(bool paused); @@ -74,4 +83,3 @@ extern u32 lClocks; extern void TimeUpdate(u32 cClocks); extern void SPU2_FastWrite(u32 rmem, u16 value); -//#define PCM24_S1_INTERLEAVE