diff --git a/rpcs3/Emu/Audio/AudioBackend.cpp b/rpcs3/Emu/Audio/AudioBackend.cpp index 2ca44d1dc5..382c1abc5f 100644 --- a/rpcs3/Emu/Audio/AudioBackend.cpp +++ b/rpcs3/Emu/Audio/AudioBackend.cpp @@ -100,7 +100,7 @@ void AudioBackend::normalize(u32 sample_cnt, const f32* src, f32* dst) } } -AudioChannelCnt AudioBackend::get_channel_count(u32 device_index) +std::pair AudioBackend::get_channel_count_and_downmixer(u32 device_index) { audio_out_configuration& audio_out_cfg = g_fxo->get(); std::lock_guard lock(audio_out_cfg.mtx); @@ -113,9 +113,9 @@ AudioChannelCnt AudioBackend::get_channel_count(u32 device_index) { switch (out.channels) { - case 2: return AudioChannelCnt::STEREO; - case 6: return AudioChannelCnt::SURROUND_5_1; - case 8: return AudioChannelCnt::SURROUND_7_1; + 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); } @@ -125,7 +125,7 @@ AudioChannelCnt AudioBackend::get_channel_count(u32 device_index) switch (out.channels) { case 2: - return AudioChannelCnt::STEREO; + 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); } @@ -135,8 +135,7 @@ AudioChannelCnt AudioBackend::get_channel_count(u32 device_index) switch (out.channels) { case 6: - case 8: - return AudioChannelCnt::SURROUND_5_1; + 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); } diff --git a/rpcs3/Emu/Audio/AudioBackend.h b/rpcs3/Emu/Audio/AudioBackend.h index 5d681c8d89..19cfbcd1fc 100644 --- a/rpcs3/Emu/Audio/AudioBackend.h +++ b/rpcs3/Emu/Audio/AudioBackend.h @@ -136,9 +136,9 @@ public: static void normalize(u32 sample_cnt, const f32* src, f32* dst); /* - * Returns the channel count based on the downmix mode. + * Returns the channel count and the downmix mode. */ - static AudioChannelCnt get_channel_count(u32 device_index); + static std::pair get_channel_count_and_downmixer(u32 device_index); /* * Downmix audio stream. diff --git a/rpcs3/Emu/Cell/Modules/cellAudio.cpp b/rpcs3/Emu/Cell/Modules/cellAudio.cpp index ac6d379ff1..bf1dbbeeeb 100644 --- a/rpcs3/Emu/Cell/Modules/cellAudio.cpp +++ b/rpcs3/Emu/Cell/Modules/cellAudio.cpp @@ -66,9 +66,10 @@ void cell_audio_config::reset(bool backend_changed) const AudioFreq freq = AudioFreq::FREQ_48K; const AudioSampleSize sample_size = raw.convert_to_s16 ? AudioSampleSize::S16 : AudioSampleSize::FLOAT; - const AudioChannelCnt ch_cnt = AudioBackend::get_channel_count(0); // CELL_AUDIO_OUT_PRIMARY + const auto [ch_cnt, downmix] = AudioBackend::get_channel_count_and_downmixer(0); // CELL_AUDIO_OUT_PRIMARY const f64 cb_frame_len = backend->Open(freq, sample_size, ch_cnt) ? backend->GetCallbackFrameLen() : 0.0; + audio_downmix = downmix; audio_channels = static_cast(ch_cnt); audio_sampling_rate = static_cast(freq); audio_block_period = AUDIO_BUFFER_SAMPLES * 1'000'000 / audio_sampling_rate; @@ -843,21 +844,19 @@ void cell_audio_thread::operator()() } // Mix - float *buf = ringbuffer->get_current_buffer(); + float* buf = ringbuffer->get_current_buffer(); - switch (cfg.audio_channels) + switch (cfg.audio_downmix) { - case 2: + case AudioChannelCnt::STEREO: mix(buf); break; - case 6: + case AudioChannelCnt::SURROUND_5_1: mix(buf); break; - case 8: + case AudioChannelCnt::SURROUND_7_1: mix(buf); break; - default: - fmt::throw_exception("Unsupported number of audio channels: %u", cfg.audio_channels); } // Enqueue @@ -885,7 +884,7 @@ audio_port* cell_audio_thread::open_port() } template -void cell_audio_thread::mix(float *out_buffer, s32 offset) +void cell_audio_thread::mix(float* out_buffer, s32 offset) { AUDIT(out_buffer != nullptr); diff --git a/rpcs3/Emu/Cell/Modules/cellAudio.h b/rpcs3/Emu/Cell/Modules/cellAudio.h index 560f1455fa..e304158f96 100644 --- a/rpcs3/Emu/Cell/Modules/cellAudio.h +++ b/rpcs3/Emu/Cell/Modules/cellAudio.h @@ -211,6 +211,7 @@ struct cell_audio_config std::shared_ptr backend = nullptr; + AudioChannelCnt audio_downmix = AudioChannelCnt::SURROUND_7_1; u32 audio_channels = 0; u32 audio_sampling_rate = 0; u32 audio_block_period = 0; @@ -349,7 +350,7 @@ private: void advance(u64 timestamp); std::tuple count_port_buffer_tags(); template - void mix(float *out_buffer, s32 offset = 0); + void mix(float* out_buffer, s32 offset = 0); void finish_port_volume_stepping(); constexpr static u64 get_thread_wait_delay(u64 time_left) diff --git a/rpcs3/Emu/Cell/Modules/cellAudioOut.cpp b/rpcs3/Emu/Cell/Modules/cellAudioOut.cpp index 422331433b..0fe14e0041 100644 --- a/rpcs3/Emu/Cell/Modules/cellAudioOut.cpp +++ b/rpcs3/Emu/Cell/Modules/cellAudioOut.cpp @@ -74,11 +74,6 @@ audio_out_configuration::audio_out_configuration() output.channels = channel; output.encoder = type; - // Set the initially selected configuration - output.config.channel = channel; - output.config.encoder = type; - output.config.downMixer = CELL_AUDIO_OUT_DOWNMIXER_NONE; - selected = true; } }; @@ -249,7 +244,6 @@ error_code cellAudioOutGetState(u32 audioOut, u32 deviceIndex, vm::ptrget(); std::lock_guard lock(cfg.mtx); 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, &out](const CellAudioOutSoundMode& mode) + const auto it = std::find_if(out.sound_modes.cbegin(), out.sound_modes.cend(), [channels = channels, &out](const CellAudioOutSoundMode& mode) { - return mode.type == out.encoder && mode.channel == static_cast(channels); + 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(channels); }); ensure(it != out.sound_modes.cend()); @@ -334,12 +343,10 @@ error_code cellAudioOutConfigure(u32 audioOut, vm::ptrchannel && mode.type == config->encoder && config->downMixer <= CELL_AUDIO_OUT_DOWNMIXER_TYPE_B; - })); + // Apparently the set config does not necessarily have to exist in the list of sound modes. + // For example 8 channels are used if the downMixer is set even if the PS3 only supports 2 channel output. - if (found_mode && (out.channels != config->channel || out.encoder != config->encoder || out.downmixer != config->downMixer)) + if (out.channels != config->channel || out.encoder != config->encoder || out.downmixer != config->downMixer) { out.channels = config->channel; out.encoder = config->encoder; @@ -347,9 +354,6 @@ error_code cellAudioOutConfigure(u32 audioOut, vm::ptr sound_modes; - CellAudioOutConfiguration config{}; // Selected by the game. Does not necessarily mean the active config. }; std::array out; diff --git a/rpcs3/Emu/Cell/lv2/sys_rsxaudio.cpp b/rpcs3/Emu/Cell/lv2/sys_rsxaudio.cpp index b6c32628d0..9f3aa6c329 100644 --- a/rpcs3/Emu/Cell/lv2/sys_rsxaudio.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_rsxaudio.cpp @@ -1322,7 +1322,7 @@ void rsxaudio_backend_thread::update_emu_cfg() rsxaudio_backend_thread::emu_audio_cfg rsxaudio_backend_thread::get_emu_cfg() { - const AudioChannelCnt out_ch_cnt = AudioBackend::get_channel_count(0); // CELL_AUDIO_OUT_PRIMARY + const auto [out_ch_cnt, out_downmix] = AudioBackend::get_channel_count_and_downmixer(0); // CELL_AUDIO_OUT_PRIMARY emu_audio_cfg cfg = { @@ -1332,7 +1332,8 @@ rsxaudio_backend_thread::emu_audio_cfg rsxaudio_backend_thread::get_emu_cfg() .convert_to_s16 = static_cast(g_cfg.audio.convert_to_s16), .enable_time_stretching = static_cast(g_cfg.audio.enable_time_stretching), .dump_to_file = static_cast(g_cfg.audio.dump_to_file), - .downmix = out_ch_cnt, + .channels = out_ch_cnt, + .downmix = out_downmix, .renderer = g_cfg.audio.renderer, .provider = g_cfg.audio.provider, .avport = convert_avport(g_cfg.audio.rsxaudio_port) @@ -1671,9 +1672,11 @@ void rsxaudio_backend_thread::backend_init(const rsxaudio_state& ra_state, const backend->SetErrorCallback(std::bind(&rsxaudio_backend_thread::error_callback, this)); } + // TODO: properly handle dowmnix + const port_config& port_cfg = ra_state.port[static_cast(emu_cfg.avport)]; const AudioSampleSize sample_size = emu_cfg.convert_to_s16 ? AudioSampleSize::S16 : AudioSampleSize::FLOAT; - const AudioChannelCnt ch_cnt = static_cast(std::min(static_cast(port_cfg.ch_cnt), static_cast(emu_cfg.downmix))); + const AudioChannelCnt ch_cnt = static_cast(std::min(static_cast(port_cfg.ch_cnt), static_cast(emu_cfg.channels))); static constexpr f64 _10ms = 512.0 / 48000.0; const f64 cb_frame_len = backend->Open(port_cfg.freq, sample_size, ch_cnt) ? backend->GetCallbackFrameLen() : 0.0; diff --git a/rpcs3/Emu/Cell/lv2/sys_rsxaudio.h b/rpcs3/Emu/Cell/lv2/sys_rsxaudio.h index 0aa480f9b1..362dcac60b 100644 --- a/rpcs3/Emu/Cell/lv2/sys_rsxaudio.h +++ b/rpcs3/Emu/Cell/lv2/sys_rsxaudio.h @@ -474,7 +474,8 @@ private: bool convert_to_s16 = false; bool enable_time_stretching = false; bool dump_to_file = false; - AudioChannelCnt downmix = AudioChannelCnt::STEREO; + AudioChannelCnt channels = AudioChannelCnt::STEREO; + AudioChannelCnt downmix = AudioChannelCnt::SURROUND_7_1; audio_renderer renderer = audio_renderer::null; audio_provider provider = audio_provider::none; RsxaudioAvportIdx avport = RsxaudioAvportIdx::HDMI_0;