From 1990cc568ad46d74f9751cda260bc090364b2852 Mon Sep 17 00:00:00 2001 From: Megamouse Date: Sun, 5 Mar 2023 23:33:35 +0100 Subject: [PATCH] cellAudio: silence cellAudioSendAck and add pseudo code for it --- rpcs3/Emu/Cell/Modules/cellAudio.cpp | 44 +++++++++++++++++++++++++--- rpcs3/Emu/Cell/Modules/cellAudio.h | 2 ++ 2 files changed, 42 insertions(+), 4 deletions(-) diff --git a/rpcs3/Emu/Cell/Modules/cellAudio.cpp b/rpcs3/Emu/Cell/Modules/cellAudio.cpp index f1d4a9a240ca..1454c4a41800 100644 --- a/rpcs3/Emu/Cell/Modules/cellAudio.cpp +++ b/rpcs3/Emu/Cell/Modules/cellAudio.cpp @@ -606,6 +606,7 @@ void cell_audio_thread::advance(u64 timestamp) } event_sources[queue_count] = key_inf.source; + event_data3[queue_count] = (key_inf.flags & CELL_AUDIO_EVENTFLAG_BEFOREMIX) ? key_inf.source : 0; queue_count++; } } @@ -615,7 +616,7 @@ void cell_audio_thread::advance(u64 timestamp) for (u32 i = 0; i < queue_count; i++) { lv2_obj::notify_all_t notify; - queues[i]->send(event_sources[i], 0, 0, 0); + queues[i]->send(event_sources[i], CELL_AUDIO_EVENT_MIX, 0, event_data3[i]); } } @@ -757,7 +758,15 @@ void cell_audio_thread::operator()() continue; } - // TODO: send beforemix event (in ~2,6 ms before mixing) + // TODO: (no idea how much of this is already implemented) + // The hardware heartbeat interval of libaudio is ~5.3ms. + // As soon as one interval starts, libaudio waits for ~2.6ms (half of the interval) before it mixes the audio. + // There are 2 different types of games: + // - Normal games: + // Once the audio was mixed, we send the CELL_AUDIO_EVENT_MIX event and the game can process audio. + // - Latency sensitive games: + // If CELL_AUDIO_EVENTFLAG_BEFOREMIX is specified, we immediately send the CELL_AUDIO_EVENT_MIX event and the game can process audio. + // We then have to wait for a maximum of ~2.6ms for cellAudioSendAck and then mix immediately. const u64 time_since_last_period = timestamp - m_last_period_end; @@ -1678,7 +1687,13 @@ error_code AudioSetNotifyEventQueue(u64 key, u32 iFlags) } // Set unique source associated with the key - g_audio.keys.push_back({g_audio.event_period, iFlags, ((process_getpid() + u64{}) << 32) + lv2_event_port::id_base + (g_audio.key_count++ * lv2_event_port::id_step), std::move(q)}); + g_audio.keys.push_back({ + .start_period = g_audio.event_period, + .flags = iFlags, + .source = ((process_getpid() + u64{}) << 32) + lv2_event_port::id_base + (g_audio.key_count++ * lv2_event_port::id_step), + .ack_timestamp = 0, + .port = std::move(q) + }); g_audio.key_count %= lv2_event_port::id_count; return CELL_OK; @@ -1910,7 +1925,28 @@ error_code cellAudioMiscSetAccessoryVolume(u32 devNum, float volume) error_code cellAudioSendAck(u64 data3) { - cellAudio.todo("cellAudioSendAck(data3=0x%llx)", data3); + cellAudio.trace("cellAudioSendAck(data3=0x%llx)", data3); + + auto& g_audio = g_fxo->get(); + + std::unique_lock lock(g_audio.mutex); + + if (!g_audio.init) + { + return CELL_AUDIO_ERROR_NOT_INIT; + } + + // TODO: error checks + + for (cell_audio_thread::key_info& k : g_audio.keys) + { + if (k.source == data3) + { + k.ack_timestamp = get_system_time(); + break; + } + } + return CELL_OK; } diff --git a/rpcs3/Emu/Cell/Modules/cellAudio.h b/rpcs3/Emu/Cell/Modules/cellAudio.h index 69780c82fd96..0f2bfe7d523d 100644 --- a/rpcs3/Emu/Cell/Modules/cellAudio.h +++ b/rpcs3/Emu/Cell/Modules/cellAudio.h @@ -390,12 +390,14 @@ class cell_audio_thread u32 key_count = 0; u8 event_period = 0; std::array event_sources{}; + std::array event_data3{}; struct key_info { u8 start_period = 0; // Starting event_period u32 flags = 0; // iFlags u64 source = 0; // Event source + u64 ack_timestamp = 0; // timestamp of last call of cellAudioSendAck std::shared_ptr port{}; // Underlying event port };