diff --git a/Source/Core/AudioCommon/AudioCommon.cpp b/Source/Core/AudioCommon/AudioCommon.cpp index a8f09c2688..467406dd9c 100644 --- a/Source/Core/AudioCommon/AudioCommon.cpp +++ b/Source/Core/AudioCommon/AudioCommon.cpp @@ -101,6 +101,11 @@ std::string GetDefaultSoundBackend() return backend; } +DPL2Quality GetDefaultDPL2Quality() +{ + return DPL2Quality::High; +} + std::vector GetSoundBackends() { std::vector backends; diff --git a/Source/Core/AudioCommon/AudioCommon.h b/Source/Core/AudioCommon/AudioCommon.h index d4dbd84a48..a294057590 100644 --- a/Source/Core/AudioCommon/AudioCommon.h +++ b/Source/Core/AudioCommon/AudioCommon.h @@ -9,6 +9,7 @@ #include #include +#include "AudioCommon/Enums.h" #include "AudioCommon/SoundStream.h" class Mixer; @@ -21,6 +22,7 @@ void InitSoundStream(); void ShutdownSoundStream(); std::string GetDefaultSoundBackend(); std::vector GetSoundBackends(); +DPL2Quality GetDefaultDPL2Quality(); bool SupportsDPL2Decoder(std::string_view backend); bool SupportsLatencyControl(std::string_view backend); bool SupportsVolumeChanges(std::string_view backend); diff --git a/Source/Core/AudioCommon/AudioCommon.vcxproj b/Source/Core/AudioCommon/AudioCommon.vcxproj index 419cfa4ea6..09c8734b7d 100644 --- a/Source/Core/AudioCommon/AudioCommon.vcxproj +++ b/Source/Core/AudioCommon/AudioCommon.vcxproj @@ -53,6 +53,7 @@ + diff --git a/Source/Core/AudioCommon/AudioCommon.vcxproj.filters b/Source/Core/AudioCommon/AudioCommon.vcxproj.filters index 7f4c74fed6..0d9a4818ad 100644 --- a/Source/Core/AudioCommon/AudioCommon.vcxproj.filters +++ b/Source/Core/AudioCommon/AudioCommon.vcxproj.filters @@ -56,6 +56,7 @@ SoundStreams + diff --git a/Source/Core/AudioCommon/CMakeLists.txt b/Source/Core/AudioCommon/CMakeLists.txt index cac46b6b33..908c60ed5e 100644 --- a/Source/Core/AudioCommon/CMakeLists.txt +++ b/Source/Core/AudioCommon/CMakeLists.txt @@ -7,6 +7,7 @@ add_library(audiocommon CubebStream.h CubebUtils.cpp CubebUtils.h + Enums.h Mixer.cpp Mixer.h SurroundDecoder.cpp diff --git a/Source/Core/AudioCommon/Enums.h b/Source/Core/AudioCommon/Enums.h new file mode 100644 index 0000000000..20c34779a5 --- /dev/null +++ b/Source/Core/AudioCommon/Enums.h @@ -0,0 +1,16 @@ +// Copyright 2019 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#pragma once + +namespace AudioCommon +{ +enum class DPL2Quality +{ + Low = 0, + Medium = 1, + High = 2, + Highest = 3 +}; +} // namespace AudioCommon diff --git a/Source/Core/AudioCommon/Mixer.cpp b/Source/Core/AudioCommon/Mixer.cpp index 5c1cb3a33f..1636c29018 100644 --- a/Source/Core/AudioCommon/Mixer.cpp +++ b/Source/Core/AudioCommon/Mixer.cpp @@ -3,6 +3,7 @@ // Refer to the license.txt file included. #include "AudioCommon/Mixer.h" +#include "AudioCommon/Enums.h" #include #include @@ -12,11 +13,28 @@ #include "Common/CommonTypes.h" #include "Common/Logging/Log.h" #include "Common/Swap.h" +#include "Core/Config/MainSettings.h" #include "Core/ConfigManager.h" +static u32 DPL2QualityToFrameBlockSize(AudioCommon::DPL2Quality quality) +{ + switch (quality) + { + case AudioCommon::DPL2Quality::Low: + return 512; + case AudioCommon::DPL2Quality::Medium: + return 1024; + case AudioCommon::DPL2Quality::Highest: + return 4096; + default: + return 2048; + } +} + Mixer::Mixer(unsigned int BackendSampleRate) : m_sampleRate(BackendSampleRate), m_stretcher(BackendSampleRate), - m_surround_decoder(BackendSampleRate, SURROUND_BLOCK_SIZE) + m_surround_decoder(BackendSampleRate, + DPL2QualityToFrameBlockSize(Config::Get(Config::MAIN_DPL2_QUALITY))) { INFO_LOG(AUDIO_INTERFACE, "Mixer is initialized"); } diff --git a/Source/Core/AudioCommon/Mixer.h b/Source/Core/AudioCommon/Mixer.h index 83a13cf5d6..b38ab7f47a 100644 --- a/Source/Core/AudioCommon/Mixer.h +++ b/Source/Core/AudioCommon/Mixer.h @@ -54,7 +54,6 @@ private: static constexpr u32 CONTROL_AVG = 32; // In freq_shift per FIFO size offset const unsigned int SURROUND_CHANNELS = 6; - const unsigned int SURROUND_BLOCK_SIZE = 512; class MixerFifo final { diff --git a/Source/Core/Core/Config/MainSettings.cpp b/Source/Core/Core/Config/MainSettings.cpp index 9497bba6d2..20162c2111 100644 --- a/Source/Core/Core/Config/MainSettings.cpp +++ b/Source/Core/Core/Config/MainSettings.cpp @@ -31,6 +31,8 @@ const ConfigInfo MAIN_GC_LANGUAGE{{System::Main, "Core", "SelectedLanguage" const ConfigInfo MAIN_OVERRIDE_REGION_SETTINGS{ {System::Main, "Core", "OverrideRegionSettings"}, false}; const ConfigInfo MAIN_DPL2_DECODER{{System::Main, "Core", "DPL2Decoder"}, false}; +const ConfigInfo MAIN_DPL2_QUALITY{{System::Main, "Core", "DPL2Quality"}, + AudioCommon::GetDefaultDPL2Quality()}; const ConfigInfo MAIN_AUDIO_LATENCY{{System::Main, "Core", "AudioLatency"}, 20}; const ConfigInfo MAIN_AUDIO_STRETCH{{System::Main, "Core", "AudioStretch"}, false}; const ConfigInfo MAIN_AUDIO_STRETCH_LATENCY{{System::Main, "Core", "AudioStretchMaxLatency"}, @@ -137,5 +139,4 @@ const ConfigInfo MAIN_AUDIO_VOLUME{{System::Main, "DSP", "Volume"}, 100}; const ConfigInfo MAIN_DUMP_PATH{{System::Main, "General", "DumpPath"}, ""}; const ConfigInfo MAIN_FS_PATH{{System::Main, "General", "NANDRootPath"}, ""}; const ConfigInfo MAIN_SD_PATH{{System::Main, "General", "WiiSDCardPath"}, ""}; - } // namespace Config diff --git a/Source/Core/Core/Config/MainSettings.h b/Source/Core/Core/Config/MainSettings.h index 0f14728bba..e522576760 100644 --- a/Source/Core/Core/Config/MainSettings.h +++ b/Source/Core/Core/Config/MainSettings.h @@ -13,6 +13,11 @@ namespace PowerPC enum class CPUCore; } +namespace AudioCommon +{ +enum class DPL2Quality; +} + namespace Config { // Main.Core @@ -32,6 +37,7 @@ extern const ConfigInfo MAIN_ENABLE_CHEATS; extern const ConfigInfo MAIN_GC_LANGUAGE; extern const ConfigInfo MAIN_OVERRIDE_REGION_SETTINGS; extern const ConfigInfo MAIN_DPL2_DECODER; +extern const ConfigInfo MAIN_DPL2_QUALITY; extern const ConfigInfo MAIN_AUDIO_LATENCY; extern const ConfigInfo MAIN_AUDIO_STRETCH; extern const ConfigInfo MAIN_AUDIO_STRETCH_LATENCY; @@ -106,5 +112,4 @@ extern const ConfigInfo MAIN_DISABLE_SCREENSAVER; extern const ConfigInfo MAIN_DUMP_PATH; extern const ConfigInfo MAIN_FS_PATH; extern const ConfigInfo MAIN_SD_PATH; - } // namespace Config diff --git a/Source/Core/Core/ConfigLoaders/IsSettingSaveable.cpp b/Source/Core/Core/ConfigLoaders/IsSettingSaveable.cpp index 15711a65b8..a621a78a2e 100644 --- a/Source/Core/Core/ConfigLoaders/IsSettingSaveable.cpp +++ b/Source/Core/Core/ConfigLoaders/IsSettingSaveable.cpp @@ -32,6 +32,8 @@ bool IsSettingSaveable(const Config::ConfigLocation& config_location) Config::MAIN_MEMCARD_A_PATH.location, Config::MAIN_MEMCARD_B_PATH.location, Config::MAIN_AUTO_DISC_CHANGE.location, + Config::MAIN_DPL2_DECODER.location, + Config::MAIN_DPL2_QUALITY.location, // Main.Display Config::MAIN_FULLSCREEN_DISPLAY_RES.location, @@ -142,7 +144,6 @@ bool IsSettingSaveable(const Config::ConfigLocation& config_location) // UI.General Config::MAIN_USE_DISCORD_PRESENCE.location, - }; return std::find(s_setting_saveable.begin(), s_setting_saveable.end(), config_location) != diff --git a/Source/Core/DolphinQt/Settings/AudioPane.cpp b/Source/Core/DolphinQt/Settings/AudioPane.cpp index 4d780a3e1b..8d55b22f63 100644 --- a/Source/Core/DolphinQt/Settings/AudioPane.cpp +++ b/Source/Core/DolphinQt/Settings/AudioPane.cpp @@ -18,6 +18,7 @@ #include #include "AudioCommon/AudioCommon.h" +#include "AudioCommon/Enums.h" #include "AudioCommon/WASAPIStream.h" #include "Core/Config/MainSettings.h" @@ -91,6 +92,29 @@ void AudioPane::CreateWidgets() m_dolby_pro_logic->setToolTip( tr("Enables Dolby Pro Logic II emulation using 5.1 surround. Certain backends only.")); + auto* dolby_quality_layout = new QHBoxLayout; + + m_dolby_quality_label = new QLabel(tr("Decoding Quality:")); + + m_dolby_quality_slider = new QSlider(Qt::Horizontal); + m_dolby_quality_slider->setMinimum(0); + m_dolby_quality_slider->setMaximum(3); + m_dolby_quality_slider->setPageStep(1); + m_dolby_quality_slider->setTickPosition(QSlider::TicksBelow); + m_dolby_quality_slider->setToolTip( + tr("Quality of the DPLII decoder. Audio latency increases with quality.")); + m_dolby_quality_slider->setTracking(true); + + m_dolby_quality_low_label = new QLabel(GetDPL2QualityLabel(AudioCommon::DPL2Quality::Low)); + m_dolby_quality_highest_label = + new QLabel(GetDPL2QualityLabel(AudioCommon::DPL2Quality::Highest)); + m_dolby_quality_latency_label = + new QLabel(GetDPL2ApproximateLatencyLabel(AudioCommon::DPL2Quality::Highest)); + + dolby_quality_layout->addWidget(m_dolby_quality_low_label); + dolby_quality_layout->addWidget(m_dolby_quality_slider); + dolby_quality_layout->addWidget(m_dolby_quality_highest_label); + backend_layout->setFormAlignment(Qt::AlignLeft | Qt::AlignTop); backend_layout->setFieldGrowthPolicy(QFormLayout::AllNonFixedFieldsGrow); backend_layout->addRow(m_backend_label, m_backend_combo); @@ -105,6 +129,9 @@ void AudioPane::CreateWidgets() #endif backend_layout->addRow(m_dolby_pro_logic); + backend_layout->addRow(m_dolby_quality_label); + backend_layout->addRow(dolby_quality_layout); + backend_layout->addRow(m_dolby_quality_latency_label); auto* stretching_box = new QGroupBox(tr("Audio Stretching Settings")); auto* stretching_layout = new QGridLayout; @@ -152,6 +179,7 @@ void AudioPane::ConnectWidgets() } connect(m_stretching_buffer_slider, &QSlider::valueChanged, this, &AudioPane::SaveSettings); connect(m_dolby_pro_logic, &QCheckBox::toggled, this, &AudioPane::SaveSettings); + connect(m_dolby_quality_slider, &QSlider::valueChanged, this, &AudioPane::SaveSettings); connect(m_stretching_enable, &QCheckBox::toggled, this, &AudioPane::SaveSettings); connect(m_dsp_hle, &QRadioButton::toggled, this, &AudioPane::SaveSettings); connect(m_dsp_lle, &QRadioButton::toggled, this, &AudioPane::SaveSettings); @@ -201,6 +229,13 @@ void AudioPane::LoadSettings() // DPL2 m_dolby_pro_logic->setChecked(SConfig::GetInstance().bDPL2Decoder); + m_dolby_quality_slider->setValue(int(Config::Get(Config::MAIN_DPL2_QUALITY))); + m_dolby_quality_latency_label->setText( + GetDPL2ApproximateLatencyLabel(Config::Get(Config::MAIN_DPL2_QUALITY))); + if (AudioCommon::SupportsDPL2Decoder(current)) + { + EnableDolbyQualityWidgets(m_dolby_pro_logic->isChecked()); + } // Latency if (m_latency_control_supported) @@ -255,6 +290,14 @@ void AudioPane::SaveSettings() // DPL2 SConfig::GetInstance().bDPL2Decoder = m_dolby_pro_logic->isChecked(); + Config::SetBase(Config::MAIN_DPL2_QUALITY, + static_cast(m_dolby_quality_slider->value())); + m_dolby_quality_latency_label->setText( + GetDPL2ApproximateLatencyLabel(Config::Get(Config::MAIN_DPL2_QUALITY))); + if (AudioCommon::SupportsDPL2Decoder(backend)) + { + EnableDolbyQualityWidgets(m_dolby_pro_logic->isChecked()); + } // Latency if (m_latency_control_supported) @@ -286,6 +329,7 @@ void AudioPane::OnBackendChanged() const auto backend = SConfig::GetInstance().sBackend; m_dolby_pro_logic->setEnabled(AudioCommon::SupportsDPL2Decoder(backend)); + EnableDolbyQualityWidgets(AudioCommon::SupportsDPL2Decoder(backend)); if (m_latency_control_supported) { m_latency_label->setEnabled(AudioCommon::SupportsLatencyControl(backend)); @@ -316,9 +360,13 @@ void AudioPane::OnEmulationStateChanged(bool running) m_dsp_hle->setEnabled(!running); m_dsp_lle->setEnabled(!running); m_dsp_interpreter->setEnabled(!running); - m_dolby_pro_logic->setEnabled(!running); m_backend_label->setEnabled(!running); m_backend_combo->setEnabled(!running); + if (AudioCommon::SupportsDPL2Decoder(SConfig::GetInstance().sBackend)) + { + m_dolby_pro_logic->setEnabled(!running); + EnableDolbyQualityWidgets(!running); + } if (m_latency_control_supported) { m_latency_label->setEnabled(!running); @@ -342,3 +390,42 @@ void AudioPane::CheckNeedForLatencyControl() m_latency_control_supported = std::any_of(backends.cbegin(), backends.cend(), AudioCommon::SupportsLatencyControl); } + +QString AudioPane::GetDPL2QualityLabel(AudioCommon::DPL2Quality value) const +{ + switch (value) + { + case AudioCommon::DPL2Quality::Low: + return tr("Low"); + case AudioCommon::DPL2Quality::Medium: + return tr("Medium"); + case AudioCommon::DPL2Quality::Highest: + return tr("Highest"); + default: + return tr("High"); + } +} + +QString AudioPane::GetDPL2ApproximateLatencyLabel(AudioCommon::DPL2Quality value) const +{ + switch (value) + { + case AudioCommon::DPL2Quality::Low: + return tr("Latency: ~10ms"); + case AudioCommon::DPL2Quality::Medium: + return tr("Latency: ~20ms"); + case AudioCommon::DPL2Quality::Highest: + return tr("Latency: ~80ms"); + default: + return tr("Latency: ~40ms"); + } +} + +void AudioPane::EnableDolbyQualityWidgets(bool enabled) const +{ + m_dolby_quality_label->setEnabled(enabled); + m_dolby_quality_slider->setEnabled(enabled); + m_dolby_quality_low_label->setEnabled(enabled); + m_dolby_quality_highest_label->setEnabled(enabled); + m_dolby_quality_latency_label->setEnabled(enabled); +} diff --git a/Source/Core/DolphinQt/Settings/AudioPane.h b/Source/Core/DolphinQt/Settings/AudioPane.h index 45bd6d6c60..398f994481 100644 --- a/Source/Core/DolphinQt/Settings/AudioPane.h +++ b/Source/Core/DolphinQt/Settings/AudioPane.h @@ -6,6 +6,11 @@ #include +namespace AudioCommon +{ +enum class DPL2Quality; +} + class QCheckBox; class QComboBox; class QLabel; @@ -35,6 +40,10 @@ private: void CheckNeedForLatencyControl(); bool m_latency_control_supported; + QString GetDPL2QualityLabel(AudioCommon::DPL2Quality value) const; + QString GetDPL2ApproximateLatencyLabel(AudioCommon::DPL2Quality value) const; + void EnableDolbyQualityWidgets(bool enabled) const; + QGridLayout* m_main_layout; // DSP Engine @@ -50,6 +59,11 @@ private: QLabel* m_backend_label; QComboBox* m_backend_combo; QCheckBox* m_dolby_pro_logic; + QLabel* m_dolby_quality_label; + QSlider* m_dolby_quality_slider; + QLabel* m_dolby_quality_low_label; + QLabel* m_dolby_quality_highest_label; + QLabel* m_dolby_quality_latency_label; QLabel* m_latency_label; QSpinBox* m_latency_spin; #ifdef _WIN32