mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-10 00:41:26 +12:00
cellAudioOut: fix sound_mode exception
Turns out some games don't configure proper channel counts after all, which triggers an ensure in cellAudioOutGetState. Let's select the current sound_mode in cellAudioOutConfigure. Keep the old one if no match was found. Also moves some code from AudioBackend to cellAudioOut for thread safety (see mutex).
This commit is contained in:
parent
11c5230628
commit
ebabdd37b4
3 changed files with 81 additions and 63 deletions
|
@ -106,43 +106,7 @@ std::pair<AudioChannelCnt, AudioChannelCnt> AudioBackend::get_channel_count_and_
|
||||||
std::lock_guard lock(audio_out_cfg.mtx);
|
std::lock_guard lock(audio_out_cfg.mtx);
|
||||||
ensure(device_index < audio_out_cfg.out.size());
|
ensure(device_index < audio_out_cfg.out.size());
|
||||||
const audio_out_configuration::audio_out& out = audio_out_cfg.out.at(device_index);
|
const audio_out_configuration::audio_out& out = audio_out_cfg.out.at(device_index);
|
||||||
|
return out.get_channel_count_and_downmixer();
|
||||||
switch (out.downmixer)
|
|
||||||
{
|
|
||||||
case CELL_AUDIO_OUT_DOWNMIXER_NONE:
|
|
||||||
{
|
|
||||||
switch (out.channels)
|
|
||||||
{
|
|
||||||
case 2: return { AudioChannelCnt::STEREO, AudioChannelCnt::STEREO };
|
|
||||||
case 6: return { AudioChannelCnt::SURROUND_5_1, AudioChannelCnt::SURROUND_5_1 };
|
|
||||||
case 8: return { AudioChannelCnt::SURROUND_7_1, AudioChannelCnt::SURROUND_7_1 };
|
|
||||||
default:
|
|
||||||
fmt::throw_exception("Unsupported channel count in cellAudioOut config: %d", out.channels);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case CELL_AUDIO_OUT_DOWNMIXER_TYPE_A:
|
|
||||||
{
|
|
||||||
switch (out.channels)
|
|
||||||
{
|
|
||||||
case 2:
|
|
||||||
return { AudioChannelCnt::SURROUND_7_1, AudioChannelCnt::STEREO };
|
|
||||||
default:
|
|
||||||
fmt::throw_exception("Unsupported channel count for CELL_AUDIO_OUT_DOWNMIXER_TYPE_A in cellAudioOut config: %d", out.channels);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case CELL_AUDIO_OUT_DOWNMIXER_TYPE_B:
|
|
||||||
{
|
|
||||||
switch (out.channels)
|
|
||||||
{
|
|
||||||
case 6:
|
|
||||||
return { AudioChannelCnt::SURROUND_7_1, AudioChannelCnt::SURROUND_5_1 };
|
|
||||||
default:
|
|
||||||
fmt::throw_exception("Unsupported channel count for CELL_AUDIO_OUT_DOWNMIXER_TYPE_B in cellAudioOut config: %d", out.channels);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
fmt::throw_exception("Unknown downmixer in cellAudioOut config: %d", out.downmixer);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
AudioChannelCnt AudioBackend::get_max_channel_count(u32 device_index)
|
AudioChannelCnt AudioBackend::get_max_channel_count(u32 device_index)
|
||||||
|
|
|
@ -73,6 +73,7 @@ audio_out_configuration::audio_out_configuration()
|
||||||
// Pre-select the first available sound mode
|
// Pre-select the first available sound mode
|
||||||
output.channels = channel;
|
output.channels = channel;
|
||||||
output.encoder = type;
|
output.encoder = type;
|
||||||
|
output.sound_mode = output.sound_modes.back();
|
||||||
|
|
||||||
selected = true;
|
selected = true;
|
||||||
}
|
}
|
||||||
|
@ -177,6 +178,46 @@ audio_out_configuration::audio_out_configuration()
|
||||||
cellSysutil.notice("cellAudioOut: initial secondary output configuration: channels=%d, encoder=%d, downmixer=%d", secondary_output.channels, secondary_output.encoder, secondary_output.downmixer);
|
cellSysutil.notice("cellAudioOut: initial secondary output configuration: channels=%d, encoder=%d, downmixer=%d", secondary_output.channels, secondary_output.encoder, secondary_output.downmixer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::pair<AudioChannelCnt, AudioChannelCnt> audio_out_configuration::audio_out::get_channel_count_and_downmixer() const
|
||||||
|
{
|
||||||
|
switch (downmixer)
|
||||||
|
{
|
||||||
|
case CELL_AUDIO_OUT_DOWNMIXER_NONE:
|
||||||
|
{
|
||||||
|
switch (channels)
|
||||||
|
{
|
||||||
|
case 2: return { AudioChannelCnt::STEREO, AudioChannelCnt::STEREO };
|
||||||
|
case 6: return { AudioChannelCnt::SURROUND_5_1, AudioChannelCnt::SURROUND_5_1 };
|
||||||
|
case 8: return { AudioChannelCnt::SURROUND_7_1, AudioChannelCnt::SURROUND_7_1 };
|
||||||
|
default:
|
||||||
|
fmt::throw_exception("Unsupported channel count in cellAudioOut config: %d", channels);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case CELL_AUDIO_OUT_DOWNMIXER_TYPE_A:
|
||||||
|
{
|
||||||
|
switch (channels)
|
||||||
|
{
|
||||||
|
case 2:
|
||||||
|
return { AudioChannelCnt::SURROUND_7_1, AudioChannelCnt::STEREO };
|
||||||
|
default:
|
||||||
|
fmt::throw_exception("Unsupported channel count for CELL_AUDIO_OUT_DOWNMIXER_TYPE_A in cellAudioOut config: %d", channels);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case CELL_AUDIO_OUT_DOWNMIXER_TYPE_B:
|
||||||
|
{
|
||||||
|
switch (channels)
|
||||||
|
{
|
||||||
|
case 6:
|
||||||
|
return { AudioChannelCnt::SURROUND_7_1, AudioChannelCnt::SURROUND_5_1 };
|
||||||
|
default:
|
||||||
|
fmt::throw_exception("Unsupported channel count for CELL_AUDIO_OUT_DOWNMIXER_TYPE_B in cellAudioOut config: %d", channels);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
fmt::throw_exception("Unknown downmixer in cellAudioOut config: %d", downmixer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
error_code cellAudioOutGetNumberOfDevice(u32 audioOut);
|
error_code cellAudioOutGetNumberOfDevice(u32 audioOut);
|
||||||
|
|
||||||
error_code cellAudioOutGetSoundAvailability(u32 audioOut, u32 type, u32 fs, u32 option)
|
error_code cellAudioOutGetSoundAvailability(u32 audioOut, u32 type, u32 fs, u32 option)
|
||||||
|
@ -274,38 +315,14 @@ error_code cellAudioOutGetState(u32 audioOut, u32 deviceIndex, vm::ptr<CellAudio
|
||||||
case CELL_AUDIO_OUT_PRIMARY:
|
case CELL_AUDIO_OUT_PRIMARY:
|
||||||
case CELL_AUDIO_OUT_SECONDARY:
|
case CELL_AUDIO_OUT_SECONDARY:
|
||||||
{
|
{
|
||||||
const auto [channels, downmixer] = AudioBackend::get_channel_count_and_downmixer(audioOut);
|
|
||||||
|
|
||||||
audio_out_configuration& cfg = g_fxo->get<audio_out_configuration>();
|
audio_out_configuration& cfg = g_fxo->get<audio_out_configuration>();
|
||||||
std::lock_guard lock(cfg.mtx);
|
std::lock_guard lock(cfg.mtx);
|
||||||
const audio_out_configuration::audio_out& out = cfg.out.at(audioOut);
|
const audio_out_configuration::audio_out& out = cfg.out.at(audioOut);
|
||||||
|
|
||||||
const auto it = std::find_if(out.sound_modes.cbegin(), out.sound_modes.cend(), [channels = channels, &out](const CellAudioOutSoundMode& mode)
|
|
||||||
{
|
|
||||||
if (mode.type != out.encoder)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (out.downmixer == CELL_AUDIO_OUT_DOWNMIXER_TYPE_A)
|
|
||||||
{
|
|
||||||
return mode.channel == CELL_AUDIO_OUT_CHNUM_2;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (out.downmixer == CELL_AUDIO_OUT_DOWNMIXER_TYPE_B)
|
|
||||||
{
|
|
||||||
return mode.channel == CELL_AUDIO_OUT_CHNUM_6;
|
|
||||||
}
|
|
||||||
|
|
||||||
return mode.channel == static_cast<u8>(channels);
|
|
||||||
});
|
|
||||||
|
|
||||||
ensure(it != out.sound_modes.cend());
|
|
||||||
|
|
||||||
_state.state = out.state;
|
_state.state = out.state;
|
||||||
_state.encoder = out.encoder;
|
_state.encoder = out.encoder;
|
||||||
_state.downMixer = out.downmixer;
|
_state.downMixer = out.downmixer;
|
||||||
_state.soundMode = *it;
|
_state.soundMode = out.sound_mode;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
@ -352,6 +369,38 @@ error_code cellAudioOutConfigure(u32 audioOut, vm::ptr<CellAudioOutConfiguration
|
||||||
out.encoder = config->encoder;
|
out.encoder = config->encoder;
|
||||||
out.downmixer = config->downMixer;
|
out.downmixer = config->downMixer;
|
||||||
|
|
||||||
|
// Try to find the best sound mode for this configuration
|
||||||
|
const auto [channels, downmixer] = out.get_channel_count_and_downmixer();
|
||||||
|
const auto it = std::find_if(out.sound_modes.cbegin(), out.sound_modes.cend(), [channels = channels, &out](const CellAudioOutSoundMode& mode)
|
||||||
|
{
|
||||||
|
if (mode.type != out.encoder)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (out.downmixer == CELL_AUDIO_OUT_DOWNMIXER_TYPE_A)
|
||||||
|
{
|
||||||
|
return mode.channel == CELL_AUDIO_OUT_CHNUM_2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (out.downmixer == CELL_AUDIO_OUT_DOWNMIXER_TYPE_B)
|
||||||
|
{
|
||||||
|
return mode.channel == CELL_AUDIO_OUT_CHNUM_6;
|
||||||
|
}
|
||||||
|
|
||||||
|
return mode.channel == static_cast<u8>(channels);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (it != out.sound_modes.cend())
|
||||||
|
{
|
||||||
|
out.sound_mode = *it;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cellSysutil.warning("cellAudioOutConfigure: Could not find an ideal sound mode for %d channel output. Keeping old mode: channels=%d, encoder=%d, fs=%d",
|
||||||
|
static_cast<u32>(channels), out.sound_mode.channel, out.sound_mode.type, out.sound_mode.fs);
|
||||||
|
}
|
||||||
|
|
||||||
needs_reset = true;
|
needs_reset = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "Emu/Audio/AudioBackend.h"
|
||||||
|
|
||||||
// Error codes
|
// Error codes
|
||||||
enum CellAudioOutError : u32
|
enum CellAudioOutError : u32
|
||||||
{
|
{
|
||||||
|
@ -194,7 +196,7 @@ struct CellAudioOutDeviceConfiguration
|
||||||
|
|
||||||
struct audio_out_configuration
|
struct audio_out_configuration
|
||||||
{
|
{
|
||||||
std::mutex mtx;
|
shared_mutex mtx;
|
||||||
|
|
||||||
struct audio_out
|
struct audio_out
|
||||||
{
|
{
|
||||||
|
@ -204,6 +206,9 @@ struct audio_out_configuration
|
||||||
u32 downmixer = CELL_AUDIO_OUT_DOWNMIXER_NONE;
|
u32 downmixer = CELL_AUDIO_OUT_DOWNMIXER_NONE;
|
||||||
u32 copy_control = CELL_AUDIO_OUT_COPY_CONTROL_COPY_FREE;
|
u32 copy_control = CELL_AUDIO_OUT_COPY_CONTROL_COPY_FREE;
|
||||||
std::vector<CellAudioOutSoundMode> sound_modes;
|
std::vector<CellAudioOutSoundMode> sound_modes;
|
||||||
|
CellAudioOutSoundMode sound_mode{};
|
||||||
|
|
||||||
|
std::pair<AudioChannelCnt, AudioChannelCnt> get_channel_count_and_downmixer() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::array<audio_out, 2> out;
|
std::array<audio_out, 2> out;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue