diff --git a/rpcs3/Emu/Cell/Modules/cellAudio.cpp b/rpcs3/Emu/Cell/Modules/cellAudio.cpp index 409646a53e..10bd68e82f 100644 --- a/rpcs3/Emu/Cell/Modules/cellAudio.cpp +++ b/rpcs3/Emu/Cell/Modules/cellAudio.cpp @@ -82,7 +82,8 @@ void cell_audio_config::reset(bool backend_changed) } audio_downmix = downmix; - audio_channels = ch_cnt; + backend_ch_cnt = AudioChannelCnt{ch_cnt}; + audio_channels = static_cast(req_ch_cnt); audio_sampling_rate = static_cast(freq); audio_block_period = AUDIO_BUFFER_SAMPLES * 1'000'000 / audio_sampling_rate; audio_sample_size = static_cast(sample_size); @@ -155,7 +156,7 @@ audio_ringbuffer::audio_ringbuffer(cell_audio_config& _cfg) return cfg.audio_min_buffer_duration; }(); - cb_ringbuf.set_buf_size(static_cast(cfg.audio_channels * cfg.audio_sampling_rate * cfg.audio_sample_size * buffer_dur_mult)); + cb_ringbuf.set_buf_size(static_cast(static_cast(cfg.backend_ch_cnt) * cfg.audio_sampling_rate * cfg.audio_sample_size * buffer_dur_mult)); backend->SetWriteCallback(std::bind(&audio_ringbuffer::backend_write_callback, this, std::placeholders::_1, std::placeholders::_2)); } @@ -203,7 +204,7 @@ float* audio_ringbuffer::get_current_buffer() const u64 audio_ringbuffer::get_enqueued_samples() const { AUDIT(cfg.buffering_enabled); - const u64 ringbuf_samples = cb_ringbuf.get_used_size() / (cfg.audio_sample_size * cfg.audio_channels); + const u64 ringbuf_samples = cb_ringbuf.get_used_size() / (cfg.audio_sample_size * static_cast(cfg.backend_ch_cnt)); if (cfg.time_stretching_enabled) { @@ -264,7 +265,7 @@ void audio_ringbuffer::process_resampled_data() { if (!cfg.time_stretching_enabled) return; - const auto samples = resampler.get_samples(static_cast(cb_ringbuf.get_free_size() / (cfg.audio_sample_size * cfg.audio_channels))); + const auto samples = resampler.get_samples(static_cast(cb_ringbuf.get_free_size() / (cfg.audio_sample_size * static_cast(cfg.backend_ch_cnt)))); commit_data(samples.first, samples.second); } @@ -275,12 +276,48 @@ void audio_ringbuffer::commit_data(f32* buf, u32 sample_cnt) // Dump audio if enabled m_dump.WriteData(buf, sample_cnt * static_cast(AudioSampleSize::FLOAT)); - if (cfg.backend->get_convert_to_s16()) + if (cfg.backend_ch_cnt < AudioChannelCnt{cfg.audio_channels}) { - AudioBackend::convert_to_s16(sample_cnt, buf, buf); + if (AudioChannelCnt{cfg.audio_channels} == AudioChannelCnt::SURROUND_7_1) + { + if (cfg.backend_ch_cnt == AudioChannelCnt::SURROUND_5_1) + { + AudioBackend::downmix(sample_cnt, buf, buf); + } + else if (cfg.backend_ch_cnt == AudioChannelCnt::STEREO) + { + AudioBackend::downmix(sample_cnt, buf, buf); + } + else + { + fmt::throw_exception("Invalid downmix combination: %u -> %u", cfg.audio_channels, static_cast(cfg.backend_ch_cnt)); + } + } + else if (AudioChannelCnt{cfg.audio_channels} == AudioChannelCnt::SURROUND_5_1) + { + if (cfg.backend_ch_cnt == AudioChannelCnt::STEREO) + { + AudioBackend::downmix(sample_cnt, buf, buf); + } + else + { + fmt::throw_exception("Invalid downmix combination: %u -> %u", cfg.audio_channels, static_cast(cfg.backend_ch_cnt)); + } + } + else + { + fmt::throw_exception("Invalid downmix combination: %u -> %u", cfg.audio_channels, static_cast(cfg.backend_ch_cnt)); + } } - cb_ringbuf.push(buf, sample_cnt * cfg.audio_sample_size); + const u32 sample_cnt_out = sample_cnt / cfg.audio_channels * static_cast(cfg.backend_ch_cnt); + + if (cfg.backend->get_convert_to_s16()) + { + AudioBackend::convert_to_s16(sample_cnt_out, buf, buf); + } + + cb_ringbuf.push(buf, sample_cnt_out * cfg.audio_sample_size); } void audio_ringbuffer::play() diff --git a/rpcs3/Emu/Cell/Modules/cellAudio.h b/rpcs3/Emu/Cell/Modules/cellAudio.h index 7feb4e3dc4..ffc67106c4 100644 --- a/rpcs3/Emu/Cell/Modules/cellAudio.h +++ b/rpcs3/Emu/Cell/Modules/cellAudio.h @@ -222,6 +222,7 @@ struct cell_audio_config std::shared_ptr backend = nullptr; AudioChannelCnt audio_downmix = AudioChannelCnt::SURROUND_7_1; + AudioChannelCnt backend_ch_cnt = AudioChannelCnt::SURROUND_7_1; u32 audio_channels = 0; u32 audio_sampling_rate = 0; u32 audio_block_period = 0;