Allow user to change DPLII decoding quality

This commit is contained in:
LAGonauta 2019-03-18 08:22:27 -03:00
parent 5f8e189207
commit 3c9eb37381
13 changed files with 157 additions and 6 deletions

View File

@ -101,6 +101,11 @@ std::string GetDefaultSoundBackend()
return backend; return backend;
} }
DPL2Quality GetDefaultDPL2Quality()
{
return DPL2Quality::High;
}
std::vector<std::string> GetSoundBackends() std::vector<std::string> GetSoundBackends()
{ {
std::vector<std::string> backends; std::vector<std::string> backends;

View File

@ -9,6 +9,7 @@
#include <string_view> #include <string_view>
#include <vector> #include <vector>
#include "AudioCommon/Enums.h"
#include "AudioCommon/SoundStream.h" #include "AudioCommon/SoundStream.h"
class Mixer; class Mixer;
@ -21,6 +22,7 @@ void InitSoundStream();
void ShutdownSoundStream(); void ShutdownSoundStream();
std::string GetDefaultSoundBackend(); std::string GetDefaultSoundBackend();
std::vector<std::string> GetSoundBackends(); std::vector<std::string> GetSoundBackends();
DPL2Quality GetDefaultDPL2Quality();
bool SupportsDPL2Decoder(std::string_view backend); bool SupportsDPL2Decoder(std::string_view backend);
bool SupportsLatencyControl(std::string_view backend); bool SupportsLatencyControl(std::string_view backend);
bool SupportsVolumeChanges(std::string_view backend); bool SupportsVolumeChanges(std::string_view backend);

View File

@ -53,6 +53,7 @@
<ClInclude Include="AudioStretcher.h" /> <ClInclude Include="AudioStretcher.h" />
<ClInclude Include="CubebStream.h" /> <ClInclude Include="CubebStream.h" />
<ClInclude Include="CubebUtils.h" /> <ClInclude Include="CubebUtils.h" />
<ClInclude Include="Enums.h" />
<ClInclude Include="Mixer.h" /> <ClInclude Include="Mixer.h" />
<ClInclude Include="NullSoundStream.h" /> <ClInclude Include="NullSoundStream.h" />
<ClInclude Include="OpenALStream.h" /> <ClInclude Include="OpenALStream.h" />

View File

@ -56,6 +56,7 @@
<Filter>SoundStreams</Filter> <Filter>SoundStreams</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="SurroundDecoder.h" /> <ClInclude Include="SurroundDecoder.h" />
<ClInclude Include="Enums.h" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Text Include="CMakeLists.txt" /> <Text Include="CMakeLists.txt" />

View File

@ -7,6 +7,7 @@ add_library(audiocommon
CubebStream.h CubebStream.h
CubebUtils.cpp CubebUtils.cpp
CubebUtils.h CubebUtils.h
Enums.h
Mixer.cpp Mixer.cpp
Mixer.h Mixer.h
SurroundDecoder.cpp SurroundDecoder.cpp

View File

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

View File

@ -3,6 +3,7 @@
// Refer to the license.txt file included. // Refer to the license.txt file included.
#include "AudioCommon/Mixer.h" #include "AudioCommon/Mixer.h"
#include "AudioCommon/Enums.h"
#include <algorithm> #include <algorithm>
#include <cmath> #include <cmath>
@ -12,11 +13,28 @@
#include "Common/CommonTypes.h" #include "Common/CommonTypes.h"
#include "Common/Logging/Log.h" #include "Common/Logging/Log.h"
#include "Common/Swap.h" #include "Common/Swap.h"
#include "Core/Config/MainSettings.h"
#include "Core/ConfigManager.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) Mixer::Mixer(unsigned int BackendSampleRate)
: m_sampleRate(BackendSampleRate), m_stretcher(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"); INFO_LOG(AUDIO_INTERFACE, "Mixer is initialized");
} }

View File

@ -54,7 +54,6 @@ private:
static constexpr u32 CONTROL_AVG = 32; // In freq_shift per FIFO size offset static constexpr u32 CONTROL_AVG = 32; // In freq_shift per FIFO size offset
const unsigned int SURROUND_CHANNELS = 6; const unsigned int SURROUND_CHANNELS = 6;
const unsigned int SURROUND_BLOCK_SIZE = 512;
class MixerFifo final class MixerFifo final
{ {

View File

@ -31,6 +31,8 @@ const ConfigInfo<int> MAIN_GC_LANGUAGE{{System::Main, "Core", "SelectedLanguage"
const ConfigInfo<bool> MAIN_OVERRIDE_REGION_SETTINGS{ const ConfigInfo<bool> MAIN_OVERRIDE_REGION_SETTINGS{
{System::Main, "Core", "OverrideRegionSettings"}, false}; {System::Main, "Core", "OverrideRegionSettings"}, false};
const ConfigInfo<bool> MAIN_DPL2_DECODER{{System::Main, "Core", "DPL2Decoder"}, false}; const ConfigInfo<bool> MAIN_DPL2_DECODER{{System::Main, "Core", "DPL2Decoder"}, false};
const ConfigInfo<AudioCommon::DPL2Quality> MAIN_DPL2_QUALITY{{System::Main, "Core", "DPL2Quality"},
AudioCommon::GetDefaultDPL2Quality()};
const ConfigInfo<int> MAIN_AUDIO_LATENCY{{System::Main, "Core", "AudioLatency"}, 20}; const ConfigInfo<int> MAIN_AUDIO_LATENCY{{System::Main, "Core", "AudioLatency"}, 20};
const ConfigInfo<bool> MAIN_AUDIO_STRETCH{{System::Main, "Core", "AudioStretch"}, false}; const ConfigInfo<bool> MAIN_AUDIO_STRETCH{{System::Main, "Core", "AudioStretch"}, false};
const ConfigInfo<int> MAIN_AUDIO_STRETCH_LATENCY{{System::Main, "Core", "AudioStretchMaxLatency"}, const ConfigInfo<int> MAIN_AUDIO_STRETCH_LATENCY{{System::Main, "Core", "AudioStretchMaxLatency"},
@ -137,5 +139,4 @@ const ConfigInfo<int> MAIN_AUDIO_VOLUME{{System::Main, "DSP", "Volume"}, 100};
const ConfigInfo<std::string> MAIN_DUMP_PATH{{System::Main, "General", "DumpPath"}, ""}; const ConfigInfo<std::string> MAIN_DUMP_PATH{{System::Main, "General", "DumpPath"}, ""};
const ConfigInfo<std::string> MAIN_FS_PATH{{System::Main, "General", "NANDRootPath"}, ""}; const ConfigInfo<std::string> MAIN_FS_PATH{{System::Main, "General", "NANDRootPath"}, ""};
const ConfigInfo<std::string> MAIN_SD_PATH{{System::Main, "General", "WiiSDCardPath"}, ""}; const ConfigInfo<std::string> MAIN_SD_PATH{{System::Main, "General", "WiiSDCardPath"}, ""};
} // namespace Config } // namespace Config

View File

@ -13,6 +13,11 @@ namespace PowerPC
enum class CPUCore; enum class CPUCore;
} }
namespace AudioCommon
{
enum class DPL2Quality;
}
namespace Config namespace Config
{ {
// Main.Core // Main.Core
@ -32,6 +37,7 @@ extern const ConfigInfo<bool> MAIN_ENABLE_CHEATS;
extern const ConfigInfo<int> MAIN_GC_LANGUAGE; extern const ConfigInfo<int> MAIN_GC_LANGUAGE;
extern const ConfigInfo<bool> MAIN_OVERRIDE_REGION_SETTINGS; extern const ConfigInfo<bool> MAIN_OVERRIDE_REGION_SETTINGS;
extern const ConfigInfo<bool> MAIN_DPL2_DECODER; extern const ConfigInfo<bool> MAIN_DPL2_DECODER;
extern const ConfigInfo<AudioCommon::DPL2Quality> MAIN_DPL2_QUALITY;
extern const ConfigInfo<int> MAIN_AUDIO_LATENCY; extern const ConfigInfo<int> MAIN_AUDIO_LATENCY;
extern const ConfigInfo<bool> MAIN_AUDIO_STRETCH; extern const ConfigInfo<bool> MAIN_AUDIO_STRETCH;
extern const ConfigInfo<int> MAIN_AUDIO_STRETCH_LATENCY; extern const ConfigInfo<int> MAIN_AUDIO_STRETCH_LATENCY;
@ -106,5 +112,4 @@ extern const ConfigInfo<bool> MAIN_DISABLE_SCREENSAVER;
extern const ConfigInfo<std::string> MAIN_DUMP_PATH; extern const ConfigInfo<std::string> MAIN_DUMP_PATH;
extern const ConfigInfo<std::string> MAIN_FS_PATH; extern const ConfigInfo<std::string> MAIN_FS_PATH;
extern const ConfigInfo<std::string> MAIN_SD_PATH; extern const ConfigInfo<std::string> MAIN_SD_PATH;
} // namespace Config } // namespace Config

View File

@ -32,6 +32,8 @@ bool IsSettingSaveable(const Config::ConfigLocation& config_location)
Config::MAIN_MEMCARD_A_PATH.location, Config::MAIN_MEMCARD_A_PATH.location,
Config::MAIN_MEMCARD_B_PATH.location, Config::MAIN_MEMCARD_B_PATH.location,
Config::MAIN_AUTO_DISC_CHANGE.location, Config::MAIN_AUTO_DISC_CHANGE.location,
Config::MAIN_DPL2_DECODER.location,
Config::MAIN_DPL2_QUALITY.location,
// Main.Display // Main.Display
Config::MAIN_FULLSCREEN_DISPLAY_RES.location, Config::MAIN_FULLSCREEN_DISPLAY_RES.location,
@ -142,7 +144,6 @@ bool IsSettingSaveable(const Config::ConfigLocation& config_location)
// UI.General // UI.General
Config::MAIN_USE_DISCORD_PRESENCE.location, Config::MAIN_USE_DISCORD_PRESENCE.location,
}; };
return std::find(s_setting_saveable.begin(), s_setting_saveable.end(), config_location) != return std::find(s_setting_saveable.begin(), s_setting_saveable.end(), config_location) !=

View File

@ -18,6 +18,7 @@
#include <QVBoxLayout> #include <QVBoxLayout>
#include "AudioCommon/AudioCommon.h" #include "AudioCommon/AudioCommon.h"
#include "AudioCommon/Enums.h"
#include "AudioCommon/WASAPIStream.h" #include "AudioCommon/WASAPIStream.h"
#include "Core/Config/MainSettings.h" #include "Core/Config/MainSettings.h"
@ -91,6 +92,29 @@ void AudioPane::CreateWidgets()
m_dolby_pro_logic->setToolTip( m_dolby_pro_logic->setToolTip(
tr("Enables Dolby Pro Logic II emulation using 5.1 surround. Certain backends only.")); 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->setFormAlignment(Qt::AlignLeft | Qt::AlignTop);
backend_layout->setFieldGrowthPolicy(QFormLayout::AllNonFixedFieldsGrow); backend_layout->setFieldGrowthPolicy(QFormLayout::AllNonFixedFieldsGrow);
backend_layout->addRow(m_backend_label, m_backend_combo); backend_layout->addRow(m_backend_label, m_backend_combo);
@ -105,6 +129,9 @@ void AudioPane::CreateWidgets()
#endif #endif
backend_layout->addRow(m_dolby_pro_logic); 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_box = new QGroupBox(tr("Audio Stretching Settings"));
auto* stretching_layout = new QGridLayout; auto* stretching_layout = new QGridLayout;
@ -152,6 +179,7 @@ void AudioPane::ConnectWidgets()
} }
connect(m_stretching_buffer_slider, &QSlider::valueChanged, this, &AudioPane::SaveSettings); connect(m_stretching_buffer_slider, &QSlider::valueChanged, this, &AudioPane::SaveSettings);
connect(m_dolby_pro_logic, &QCheckBox::toggled, 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_stretching_enable, &QCheckBox::toggled, this, &AudioPane::SaveSettings);
connect(m_dsp_hle, &QRadioButton::toggled, this, &AudioPane::SaveSettings); connect(m_dsp_hle, &QRadioButton::toggled, this, &AudioPane::SaveSettings);
connect(m_dsp_lle, &QRadioButton::toggled, this, &AudioPane::SaveSettings); connect(m_dsp_lle, &QRadioButton::toggled, this, &AudioPane::SaveSettings);
@ -201,6 +229,13 @@ void AudioPane::LoadSettings()
// DPL2 // DPL2
m_dolby_pro_logic->setChecked(SConfig::GetInstance().bDPL2Decoder); 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 // Latency
if (m_latency_control_supported) if (m_latency_control_supported)
@ -255,6 +290,14 @@ void AudioPane::SaveSettings()
// DPL2 // DPL2
SConfig::GetInstance().bDPL2Decoder = m_dolby_pro_logic->isChecked(); SConfig::GetInstance().bDPL2Decoder = m_dolby_pro_logic->isChecked();
Config::SetBase(Config::MAIN_DPL2_QUALITY,
static_cast<AudioCommon::DPL2Quality>(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 // Latency
if (m_latency_control_supported) if (m_latency_control_supported)
@ -286,6 +329,7 @@ void AudioPane::OnBackendChanged()
const auto backend = SConfig::GetInstance().sBackend; const auto backend = SConfig::GetInstance().sBackend;
m_dolby_pro_logic->setEnabled(AudioCommon::SupportsDPL2Decoder(backend)); m_dolby_pro_logic->setEnabled(AudioCommon::SupportsDPL2Decoder(backend));
EnableDolbyQualityWidgets(AudioCommon::SupportsDPL2Decoder(backend));
if (m_latency_control_supported) if (m_latency_control_supported)
{ {
m_latency_label->setEnabled(AudioCommon::SupportsLatencyControl(backend)); m_latency_label->setEnabled(AudioCommon::SupportsLatencyControl(backend));
@ -316,9 +360,13 @@ void AudioPane::OnEmulationStateChanged(bool running)
m_dsp_hle->setEnabled(!running); m_dsp_hle->setEnabled(!running);
m_dsp_lle->setEnabled(!running); m_dsp_lle->setEnabled(!running);
m_dsp_interpreter->setEnabled(!running); m_dsp_interpreter->setEnabled(!running);
m_dolby_pro_logic->setEnabled(!running);
m_backend_label->setEnabled(!running); m_backend_label->setEnabled(!running);
m_backend_combo->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) if (m_latency_control_supported)
{ {
m_latency_label->setEnabled(!running); m_latency_label->setEnabled(!running);
@ -342,3 +390,42 @@ void AudioPane::CheckNeedForLatencyControl()
m_latency_control_supported = m_latency_control_supported =
std::any_of(backends.cbegin(), backends.cend(), AudioCommon::SupportsLatencyControl); 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);
}

View File

@ -6,6 +6,11 @@
#include <QWidget> #include <QWidget>
namespace AudioCommon
{
enum class DPL2Quality;
}
class QCheckBox; class QCheckBox;
class QComboBox; class QComboBox;
class QLabel; class QLabel;
@ -35,6 +40,10 @@ private:
void CheckNeedForLatencyControl(); void CheckNeedForLatencyControl();
bool m_latency_control_supported; 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; QGridLayout* m_main_layout;
// DSP Engine // DSP Engine
@ -50,6 +59,11 @@ private:
QLabel* m_backend_label; QLabel* m_backend_label;
QComboBox* m_backend_combo; QComboBox* m_backend_combo;
QCheckBox* m_dolby_pro_logic; 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; QLabel* m_latency_label;
QSpinBox* m_latency_spin; QSpinBox* m_latency_spin;
#ifdef _WIN32 #ifdef _WIN32