From 94aef197dd8e614dc44c7c9cf5df75032893ba89 Mon Sep 17 00:00:00 2001 From: Megamouse Date: Wed, 1 Jun 2022 21:42:30 +0200 Subject: [PATCH] cellAudioOut: switch to manual multi-selection of format as seen on PS3 --- rpcs3/Emu/Cell/Modules/cellAudio.h | 2 +- rpcs3/Emu/Cell/Modules/cellAudioOut.cpp | 38 ++++----- rpcs3/Emu/system_config.h | 3 +- rpcs3/Emu/system_config_types.cpp | 6 +- rpcs3/Emu/system_config_types.h | 15 ++-- rpcs3/rpcs3qt/emu_settings.cpp | 16 ++-- rpcs3/rpcs3qt/emu_settings_type.h | 2 + rpcs3/rpcs3qt/settings_dialog.cpp | 107 +++++++++++++----------- rpcs3/rpcs3qt/settings_dialog.ui | 43 ++++++---- rpcs3/rpcs3qt/tooltips.h | 2 +- 10 files changed, 126 insertions(+), 108 deletions(-) diff --git a/rpcs3/Emu/Cell/Modules/cellAudio.h b/rpcs3/Emu/Cell/Modules/cellAudio.h index 8dad8d9371..ad99d3236c 100644 --- a/rpcs3/Emu/Cell/Modules/cellAudio.h +++ b/rpcs3/Emu/Cell/Modules/cellAudio.h @@ -201,7 +201,7 @@ struct cell_audio_config s64 time_stretching_threshold = 0; bool convert_to_s16 = false; bool dump_to_file = false; - audio_format format = audio_format::lpcm_2_48khz; + audio_format format = audio_format::manual; audio_renderer renderer = audio_renderer::null; audio_provider provider = audio_provider::none; }; diff --git a/rpcs3/Emu/Cell/Modules/cellAudioOut.cpp b/rpcs3/Emu/Cell/Modules/cellAudioOut.cpp index 126ff3b24c..8ca6f8042f 100644 --- a/rpcs3/Emu/Cell/Modules/cellAudioOut.cpp +++ b/rpcs3/Emu/Cell/Modules/cellAudioOut.cpp @@ -108,31 +108,21 @@ audio_out_configuration::audio_out_configuration() break; } - case audio_format::lpcm_2_48khz: // Linear PCM 2 Ch. 48 kHz + case audio_format::manual: // Manual based on selected formats { - // Already added by default - break; - } - case audio_format::lpcm_5_1_48khz: // Linear PCM 5.1 Ch. 48 kHz - { - add_sound_mode_to_both_outputs(CELL_AUDIO_OUT_CODING_TYPE_LPCM, CELL_AUDIO_OUT_CHNUM_6, CELL_AUDIO_OUT_FS_48KHZ, CELL_AUDIO_OUT_SPEAKER_LAYOUT_6CH_LREClr); - break; - } - case audio_format::lpcm_7_1_48khz: // Linear PCM 7.1 Ch. 48 kHz - { - // Also add 5.1 in case 7.1 is not supported - add_sound_mode_to_both_outputs(CELL_AUDIO_OUT_CODING_TYPE_LPCM, CELL_AUDIO_OUT_CHNUM_6, CELL_AUDIO_OUT_FS_48KHZ, CELL_AUDIO_OUT_SPEAKER_LAYOUT_6CH_LREClr); - add_sound_mode_to_both_outputs(CELL_AUDIO_OUT_CODING_TYPE_LPCM, CELL_AUDIO_OUT_CHNUM_8, CELL_AUDIO_OUT_FS_48KHZ, CELL_AUDIO_OUT_SPEAKER_LAYOUT_8CH_LREClrxy); - break; - } - case audio_format::ac3: // Dolby Digital 5.1 Ch. - { - add_sound_mode_to_both_outputs(CELL_AUDIO_OUT_CODING_TYPE_AC3, CELL_AUDIO_OUT_CHNUM_6, CELL_AUDIO_OUT_FS_48KHZ, CELL_AUDIO_OUT_SPEAKER_LAYOUT_6CH_LREClr); - break; - } - case audio_format::dts: // DTS 5.1 Ch. - { - add_sound_mode_to_both_outputs(CELL_AUDIO_OUT_CODING_TYPE_DTS, CELL_AUDIO_OUT_CHNUM_6, CELL_AUDIO_OUT_FS_48KHZ, CELL_AUDIO_OUT_SPEAKER_LAYOUT_6CH_LREClr); + const u32 selected_formats = g_cfg.audio.formats; + + if (selected_formats & static_cast(audio_format_flag::lpcm_5_1_48khz)) // Linear PCM 5.1 Ch. 48 kHz + add_sound_mode_to_both_outputs(CELL_AUDIO_OUT_CODING_TYPE_LPCM, CELL_AUDIO_OUT_CHNUM_6, CELL_AUDIO_OUT_FS_48KHZ, CELL_AUDIO_OUT_SPEAKER_LAYOUT_6CH_LREClr); + + if (selected_formats & static_cast(audio_format_flag::lpcm_7_1_48khz)) // Linear PCM 7.1 Ch. 48 kHz + add_sound_mode_to_both_outputs(CELL_AUDIO_OUT_CODING_TYPE_LPCM, CELL_AUDIO_OUT_CHNUM_8, CELL_AUDIO_OUT_FS_48KHZ, CELL_AUDIO_OUT_SPEAKER_LAYOUT_8CH_LREClrxy); + + if (selected_formats & static_cast(audio_format_flag::ac3)) // Dolby Digital 5.1 Ch. + add_sound_mode_to_both_outputs(CELL_AUDIO_OUT_CODING_TYPE_AC3, CELL_AUDIO_OUT_CHNUM_6, CELL_AUDIO_OUT_FS_48KHZ, CELL_AUDIO_OUT_SPEAKER_LAYOUT_6CH_LREClr); + + if (selected_formats & static_cast(audio_format_flag::dts)) // DTS 5.1 Ch. + add_sound_mode_to_both_outputs(CELL_AUDIO_OUT_CODING_TYPE_DTS, CELL_AUDIO_OUT_CHNUM_6, CELL_AUDIO_OUT_FS_48KHZ, CELL_AUDIO_OUT_SPEAKER_LAYOUT_6CH_LREClr); break; } } diff --git a/rpcs3/Emu/system_config.h b/rpcs3/Emu/system_config.h index d1981071f8..c7e4465ad2 100644 --- a/rpcs3/Emu/system_config.h +++ b/rpcs3/Emu/system_config.h @@ -235,7 +235,8 @@ struct cfg_root : cfg::node cfg::_enum rsxaudio_port{ this, "RSXAudio Avport", audio_avport::hdmi_0, true }; cfg::_bool dump_to_file{ this, "Dump to file", false, true }; cfg::_bool convert_to_s16{ this, "Convert to 16 bit", false, true }; - cfg::_enum format{ this, "Audio Format", audio_format::lpcm_2_48khz, false }; + cfg::_enum format{ this, "Audio Format", audio_format::manual, false }; + cfg::uint<0, umax> formats{ this, "Audio Formats", static_cast(audio_format_flag::lpcm_2_48khz), false }; cfg::_int<0, 200> volume{ this, "Master Volume", 100, true }; cfg::_bool enable_buffering{ this, "Enable Buffering", true, true }; cfg::_int <4, 250> desired_buffer_duration{ this, "Desired Audio Buffer Duration", 100, true }; diff --git a/rpcs3/Emu/system_config_types.cpp b/rpcs3/Emu/system_config_types.cpp index 14efc82c5b..1148a3dcc1 100644 --- a/rpcs3/Emu/system_config_types.cpp +++ b/rpcs3/Emu/system_config_types.cpp @@ -538,12 +538,8 @@ void fmt_class_string::format(std::string& out, u64 arg) { switch (value) { + case audio_format::manual: return "Manual"; case audio_format::automatic: return "Automatic"; - case audio_format::lpcm_2_48khz: return "Linear PCM 2 Ch. 48 kHz"; - case audio_format::lpcm_5_1_48khz: return "Linear PCM 5.1 Ch. 48 kHz"; - case audio_format::lpcm_7_1_48khz: return "Linear PCM 7.1 Ch. 48 kHz"; - case audio_format::ac3: return "Dolby Digital 5.1 Ch."; - case audio_format::dts: return "DTS 5.1 Ch."; } return unknown; diff --git a/rpcs3/Emu/system_config_types.h b/rpcs3/Emu/system_config_types.h index 6a4eff238d..d86d9b7748 100644 --- a/rpcs3/Emu/system_config_types.h +++ b/rpcs3/Emu/system_config_types.h @@ -78,14 +78,19 @@ enum class audio_avport enum class audio_format { - lpcm_2_48khz, - lpcm_5_1_48khz, - lpcm_7_1_48khz, - ac3, - dts, + manual, automatic, }; +enum class audio_format_flag : unsigned +{ + lpcm_2_48khz = 0x00000000, // Linear PCM 2 Ch. 48 kHz (always available) + lpcm_5_1_48khz = 0x00000001, // Linear PCM 5.1 Ch. 48 kHz + lpcm_7_1_48khz = 0x00000002, // Linear PCM 7.1 Ch. 48 kHz + ac3 = 0x00000004, // Dolby Digital 5.1 Ch. + dts = 0x00000008, // DTS 5.1 Ch. +}; + enum class music_handler { null, diff --git a/rpcs3/rpcs3qt/emu_settings.cpp b/rpcs3/rpcs3qt/emu_settings.cpp index 2520eb1b44..f76f3333e1 100644 --- a/rpcs3/rpcs3qt/emu_settings.cpp +++ b/rpcs3/rpcs3qt/emu_settings.cpp @@ -1143,12 +1143,18 @@ QString emu_settings::GetLocalizedSetting(const QString& original, emu_settings_ case emu_settings_type::AudioFormat: switch (static_cast(index)) { + case audio_format::manual: return tr("Manual", "Audio format"); case audio_format::automatic: return tr("Automatic", "Audio format"); - case audio_format::lpcm_2_48khz: return tr("Linear PCM 2 Ch. 48 kHz", "Audio format"); - case audio_format::lpcm_5_1_48khz: return tr("Linear PCM 5.1 Ch. 48 kHz", "Audio format"); - case audio_format::lpcm_7_1_48khz: return tr("Linear PCM 7.1 Ch. 48 kHz", "Audio format"); - case audio_format::ac3: return tr("Dolby Digital 5.1 Ch.", "Audio format"); - case audio_format::dts: return tr("DTS 5.1 Ch.", "Audio format"); + } + break; + case emu_settings_type::AudioFormats: + switch (static_cast(index)) + { + case audio_format_flag::lpcm_2_48khz: return tr("Linear PCM 2 Ch. 48 kHz", "Audio format flag"); + case audio_format_flag::lpcm_5_1_48khz: return tr("Linear PCM 5.1 Ch. 48 kHz", "Audio format flag"); + case audio_format_flag::lpcm_7_1_48khz: return tr("Linear PCM 7.1 Ch. 48 kHz", "Audio format flag"); + case audio_format_flag::ac3: return tr("Dolby Digital 5.1 Ch.", "Audio format flag"); + case audio_format_flag::dts: return tr("DTS 5.1 Ch.", "Audio format flag"); } break; case emu_settings_type::LicenseArea: diff --git a/rpcs3/rpcs3qt/emu_settings_type.h b/rpcs3/rpcs3qt/emu_settings_type.h index 2e545c3e7c..959af3bbf2 100644 --- a/rpcs3/rpcs3qt/emu_settings_type.h +++ b/rpcs3/rpcs3qt/emu_settings_type.h @@ -122,6 +122,7 @@ enum class emu_settings_type DumpToFile, ConvertTo16Bit, AudioFormat, + AudioFormats, AudioProvider, AudioAvport, MasterVolume, @@ -292,6 +293,7 @@ inline static const QMap settings_location = { emu_settings_type::DumpToFile, { "Audio", "Dump to file"}}, { emu_settings_type::ConvertTo16Bit, { "Audio", "Convert to 16 bit"}}, { emu_settings_type::AudioFormat, { "Audio", "Audio Format"}}, + { emu_settings_type::AudioFormats, { "Audio", "Audio Formats"}}, { emu_settings_type::AudioProvider, { "Audio", "Audio Provider"}}, { emu_settings_type::AudioAvport, { "Audio", "RSXAudio Avport"}}, { emu_settings_type::MasterVolume, { "Audio", "Master Volume"}}, diff --git a/rpcs3/rpcs3qt/settings_dialog.cpp b/rpcs3/rpcs3qt/settings_dialog.cpp index d54cb67630..1c8848d527 100644 --- a/rpcs3/rpcs3qt/settings_dialog.cpp +++ b/rpcs3/rpcs3qt/settings_dialog.cpp @@ -111,6 +111,17 @@ settings_dialog::settings_dialog(std::shared_ptr gui_settings, std const auto apply_configs = [this, use_discord_old = m_use_discord, discord_state_old = m_discord_state, game](bool do_exit) { + u32 selected_audio_formats = 0; + for (int i = 0; i < ui->list_audio_formats->count(); ++i) + { + const auto& item = ui->list_audio_formats->item(i); + if (item->checkState() != Qt::CheckState::Unchecked) + { + selected_audio_formats |= item->data(Qt::UserRole).toUInt(); + } + } + m_emu_settings->SetSetting(emu_settings_type::AudioFormats, std::to_string(selected_audio_formats)); + std::set selected; for (int i = 0; i < ui->lleList->count(); ++i) { @@ -956,65 +967,65 @@ settings_dialog::settings_dialog(std::shared_ptr gui_settings, std #else SubscribeTooltip(ui->gb_audio_out, tooltips.settings.audio_out_linux); #endif - connect(ui->audioOutBox, QOverload::of(&QComboBox::currentIndexChanged), enable_buffering); + connect(ui->audioOutBox, QOverload::of(&QComboBox::currentIndexChanged), this, enable_buffering); + connect(ui->combo_audio_format, QOverload::of(&QComboBox::currentIndexChanged), this, [this](int index) + { + const QVariantList var_list = ui->combo_audio_format->itemData(index).toList(); + ensure(var_list.size() == 2 && var_list[1].canConvert()); + ui->list_audio_formats->setEnabled(static_cast(var_list[1].toInt()) == audio_format::manual); + }); m_emu_settings->EnhanceComboBox(ui->combo_audio_format, emu_settings_type::AudioFormat); SubscribeTooltip(ui->gb_audio_format, tooltips.settings.audio_format); - bool saved_audio_format_index_removed = false; - if (game && game->sound_format > 0) + + // Manual audio format selection + const std::string audio_formats_str = m_emu_settings->GetSetting(emu_settings_type::AudioFormats); + u64 selected_audio_formats = 0; + if (!try_to_uint64(&selected_audio_formats, audio_formats_str, 0, 0xFFFFFFFF)) { - const std::map> formats + cfg_log.error("Can not interpret AudioFormats value '%s' as number", audio_formats_str); + } + const std::array audio_formats = { + audio_format_flag::lpcm_2_48khz, + audio_format_flag::lpcm_5_1_48khz, + audio_format_flag::lpcm_7_1_48khz, + audio_format_flag::ac3, + audio_format_flag::dts, + }; + for (const audio_format_flag& audio_fmt : audio_formats) + { + const QString audio_format_name = m_emu_settings->GetLocalizedSetting("", emu_settings_type::AudioFormats, static_cast(audio_fmt)); + QListWidgetItem* item = new QListWidgetItem(audio_format_name, ui->list_audio_formats); + item->setData(Qt::UserRole, static_cast(audio_fmt)); + if (audio_fmt == audio_format_flag::lpcm_2_48khz) { - { psf::sound_format_flag::lpcm_2, { audio_format::lpcm_2_48khz } }, - { psf::sound_format_flag::lpcm_5_1, { audio_format::lpcm_5_1_48khz } }, - { psf::sound_format_flag::lpcm_7_1, { audio_format::lpcm_7_1_48khz } }, - { psf::sound_format_flag::ac3, { audio_format::ac3 } }, - { psf::sound_format_flag::dts, { audio_format::dts } }, - }; - - const int saved_index = ui->combo_audio_format->currentIndex(); - - for (int i = ui->combo_audio_format->count() - 1; i >= 0; i--) + item->setFlags(item->flags() & ~Qt::ItemIsEnabled); + item->setCheckState(Qt::Checked); + } + else { - const QVariantList var_list = ui->combo_audio_format->itemData(i).toList(); - ensure(var_list.size() == 2 && var_list[1].canConvert()); - - const audio_format format = static_cast(var_list[1].toInt()); - - bool has_format = false; - for (const auto& entry : formats) + item->setFlags(item->flags() | Qt::ItemIsUserCheckable); + item->setCheckState(!!(selected_audio_formats & static_cast(audio_fmt)) ? Qt::Checked : Qt::Unchecked); + } + ui->list_audio_formats->addItem(item); + } + connect(this, &settings_dialog::signal_restore_dependant_defaults, this, [this]() + { + const u32 default_audio_formats = std::stoi(m_emu_settings->GetSettingDefault(emu_settings_type::AudioFormats)); + for (int i = 0; i < ui->list_audio_formats->count(); ++i) + { + const auto& item = ui->list_audio_formats->item(i); + const u32 audio_fmt = item->data(Qt::UserRole).toUInt(); + if (audio_fmt == static_cast(audio_format_flag::lpcm_2_48khz)) { - if ((game->sound_format & entry.first) && std::find(entry.second.cbegin(), entry.second.cend(), format) != entry.second.cend()) - { - has_format = true; - break; - } + item->setCheckState(Qt::Checked); } - if (!has_format) + else { - ui->combo_audio_format->removeItem(i); - if (i == saved_index) - { - saved_audio_format_index_removed = true; - } + item->setCheckState(!!(default_audio_formats & audio_fmt) ? Qt::Checked : Qt::Unchecked); } } - } - // Set the current selection to the default if the original setting wasn't valid - if (saved_audio_format_index_removed) - { - for (int i = 0; i < ui->combo_audio_format->count(); i++) - { - const QVariantList var_list = ui->combo_audio_format->itemData(i).toList(); - ensure(var_list.size() == 2 && var_list[1].canConvert()); - - if (var_list[1].toInt() == static_cast(g_cfg.audio.format.def)) - { - ui->combo_audio_format->setCurrentIndex(i); - break; - } - } - } + }); m_emu_settings->EnhanceComboBox(ui->audioProviderBox, emu_settings_type::AudioProvider); SubscribeTooltip(ui->gb_audio_provider, tooltips.settings.audio_provider); diff --git a/rpcs3/rpcs3qt/settings_dialog.ui b/rpcs3/rpcs3qt/settings_dialog.ui index 423a6494f1..1c9b0b1c6a 100644 --- a/rpcs3/rpcs3qt/settings_dialog.ui +++ b/rpcs3/rpcs3qt/settings_dialog.ui @@ -1039,6 +1039,19 @@ + + + + + 0 + 0 + + + + QAbstractItemView::ExtendedSelection + + + @@ -1081,18 +1094,6 @@ - - - - Music Handler - - - - - - - - @@ -1137,6 +1138,18 @@ + + + + Music Handler + + + + + + + + @@ -2308,9 +2321,6 @@ QAbstractItemView::ExtendedSelection - - QListView::ListMode - @@ -2324,9 +2334,6 @@ QAbstractItemView::ExtendedSelection - - QListView::ListMode - diff --git a/rpcs3/rpcs3qt/tooltips.h b/rpcs3/rpcs3qt/tooltips.h index 3dc25a4e20..12bf0b23a8 100644 --- a/rpcs3/rpcs3qt/tooltips.h +++ b/rpcs3/rpcs3qt/tooltips.h @@ -51,7 +51,7 @@ public: const QString audio_avport = tr("Controls which avport is used to sample audio data from."); const QString audio_dump = tr("Saves all audio as a raw wave file. If unsure, leave this unchecked."); const QString convert = tr("Uses 16-bit audio samples instead of default 32-bit floating point.\nUse with buggy audio drivers if you have no sound or completely broken sound."); - const QString audio_format = tr("Determines the sound format.\nConfigure this setting if you want to switch between stereo and surround sound.\nChanging this value requires a restart of the game.\nThe automatic setting will let the game choose from all available formats."); + const QString audio_format = tr("Determines the sound format.\nConfigure this setting if you want to switch between stereo and surround sound.\nChanging these values requires a restart of the game.\nThe manual setting will use your selected formats while the automatic setting will let the game choose from all available formats."); const QString master_volume = tr("Controls the overall volume of the emulation.\nValues above 100% might reduce the audio quality."); const QString enable_buffering = tr("Enables audio buffering, which reduces crackle/stutter but increases audio latency."); const QString audio_buffer_duration = tr("Target buffer duration in milliseconds.\nHigher values make the buffering algorithm's job easier, but may introduce noticeable audio latency.");