cellAudioOut: switch to manual multi-selection of format as seen on PS3

This commit is contained in:
Megamouse 2022-06-01 21:42:30 +02:00
parent a86e7eeba0
commit 94aef197dd
10 changed files with 126 additions and 108 deletions

View File

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

View File

@ -108,30 +108,20 @@ audio_out_configuration::audio_out_configuration()
break;
}
case audio_format::lpcm_2_48khz: // Linear PCM 2 Ch. 48 kHz
{
// Already added by default
break;
}
case audio_format::lpcm_5_1_48khz: // Linear PCM 5.1 Ch. 48 kHz
case audio_format::manual: // Manual based on selected formats
{
const u32 selected_formats = g_cfg.audio.formats;
if (selected_formats & static_cast<u32>(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);
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);
if (selected_formats & static_cast<u32>(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);
break;
}
case audio_format::ac3: // Dolby Digital 5.1 Ch.
{
if (selected_formats & static_cast<u32>(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);
break;
}
case audio_format::dts: // DTS 5.1 Ch.
{
if (selected_formats & static_cast<u32>(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;
}

View File

@ -235,7 +235,8 @@ struct cfg_root : cfg::node
cfg::_enum<audio_avport> 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<audio_format> format{ this, "Audio Format", audio_format::lpcm_2_48khz, false };
cfg::_enum<audio_format> format{ this, "Audio Format", audio_format::manual, false };
cfg::uint<0, umax> formats{ this, "Audio Formats", static_cast<u32>(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 };

View File

@ -538,12 +538,8 @@ void fmt_class_string<audio_format>::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;

View File

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

View File

@ -1143,12 +1143,18 @@ QString emu_settings::GetLocalizedSetting(const QString& original, emu_settings_
case emu_settings_type::AudioFormat:
switch (static_cast<audio_format>(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<audio_format_flag>(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:

View File

@ -122,6 +122,7 @@ enum class emu_settings_type
DumpToFile,
ConvertTo16Bit,
AudioFormat,
AudioFormats,
AudioProvider,
AudioAvport,
MasterVolume,
@ -292,6 +293,7 @@ inline static const QMap<emu_settings_type, cfg_location> 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"}},

View File

@ -111,6 +111,17 @@ settings_dialog::settings_dialog(std::shared_ptr<gui_settings> 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<std::string> selected;
for (int i = 0; i < ui->lleList->count(); ++i)
{
@ -956,65 +967,65 @@ settings_dialog::settings_dialog(std::shared_ptr<gui_settings> gui_settings, std
#else
SubscribeTooltip(ui->gb_audio_out, tooltips.settings.audio_out_linux);
#endif
connect(ui->audioOutBox, QOverload<int>::of(&QComboBox::currentIndexChanged), enable_buffering);
connect(ui->audioOutBox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, enable_buffering);
connect(ui->combo_audio_format, QOverload<int>::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<int>());
ui->list_audio_formats->setEnabled(static_cast<audio_format>(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<u32, std::vector<audio_format>> formats
{
{ 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 } },
cfg_log.error("Can not interpret AudioFormats value '%s' as number", audio_formats_str);
}
const std::array<audio_format_flag, 5> 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,
};
const int saved_index = ui->combo_audio_format->currentIndex();
for (int i = ui->combo_audio_format->count() - 1; i >= 0; i--)
for (const audio_format_flag& audio_fmt : audio_formats)
{
const QVariantList var_list = ui->combo_audio_format->itemData(i).toList();
ensure(var_list.size() == 2 && var_list[1].canConvert<int>());
const audio_format format = static_cast<audio_format>(var_list[1].toInt());
bool has_format = false;
for (const auto& entry : formats)
const QString audio_format_name = m_emu_settings->GetLocalizedSetting("", emu_settings_type::AudioFormats, static_cast<int>(audio_fmt));
QListWidgetItem* item = new QListWidgetItem(audio_format_name, ui->list_audio_formats);
item->setData(Qt::UserRole, static_cast<u32>(audio_fmt));
if (audio_fmt == audio_format_flag::lpcm_2_48khz)
{
if ((game->sound_format & entry.first) && std::find(entry.second.cbegin(), entry.second.cend(), format) != entry.second.cend())
item->setFlags(item->flags() & ~Qt::ItemIsEnabled);
item->setCheckState(Qt::Checked);
}
else
{
has_format = true;
break;
item->setFlags(item->flags() | Qt::ItemIsUserCheckable);
item->setCheckState(!!(selected_audio_formats & static_cast<u32>(audio_fmt)) ? Qt::Checked : Qt::Unchecked);
}
ui->list_audio_formats->addItem(item);
}
if (!has_format)
connect(this, &settings_dialog::signal_restore_dependant_defaults, this, [this]()
{
ui->combo_audio_format->removeItem(i);
if (i == saved_index)
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)
{
saved_audio_format_index_removed = true;
}
}
}
}
// Set the current selection to the default if the original setting wasn't valid
if (saved_audio_format_index_removed)
const auto& item = ui->list_audio_formats->item(i);
const u32 audio_fmt = item->data(Qt::UserRole).toUInt();
if (audio_fmt == static_cast<u32>(audio_format_flag::lpcm_2_48khz))
{
for (int i = 0; i < ui->combo_audio_format->count(); i++)
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<int>());
if (var_list[1].toInt() == static_cast<int>(g_cfg.audio.format.def))
{
ui->combo_audio_format->setCurrentIndex(i);
break;
}
item->setCheckState(!!(default_audio_formats & audio_fmt) ? Qt::Checked : Qt::Unchecked);
}
}
});
m_emu_settings->EnhanceComboBox(ui->audioProviderBox, emu_settings_type::AudioProvider);
SubscribeTooltip(ui->gb_audio_provider, tooltips.settings.audio_provider);

View File

@ -1039,6 +1039,19 @@
<item>
<widget class="QComboBox" name="combo_audio_format"/>
</item>
<item>
<widget class="QListWidget" name="list_audio_formats">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::ExtendedSelection</enum>
</property>
</widget>
</item>
</layout>
</widget>
</item>
@ -1081,18 +1094,6 @@
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="gb_music_handler">
<property name="title">
<string>Music Handler</string>
</property>
<layout class="QVBoxLayout" name="gb_music_handler_layout">
<item>
<widget class="QComboBox" name="musicHandlerBox"/>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacerAudioLeft">
<property name="orientation">
@ -1137,6 +1138,18 @@
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="gb_music_handler">
<property name="title">
<string>Music Handler</string>
</property>
<layout class="QVBoxLayout" name="gb_music_handler_layout">
<item>
<widget class="QComboBox" name="musicHandlerBox"/>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="gb_audio_volume">
<property name="title">
@ -2308,9 +2321,6 @@
<property name="selectionMode">
<enum>QAbstractItemView::ExtendedSelection</enum>
</property>
<property name="viewMode">
<enum>QListView::ListMode</enum>
</property>
</widget>
</item>
<item>
@ -2324,9 +2334,6 @@
<property name="selectionMode">
<enum>QAbstractItemView::ExtendedSelection</enum>
</property>
<property name="viewMode">
<enum>QListView::ListMode</enum>
</property>
</widget>
</item>
<item>

View File

@ -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.");