diff --git a/rpcs3/Emu/Cell/Modules/cellMic.cpp b/rpcs3/Emu/Cell/Modules/cellMic.cpp index f4c9a942ac..cecf866520 100644 --- a/rpcs3/Emu/Cell/Modules/cellMic.cpp +++ b/rpcs3/Emu/Cell/Modules/cellMic.cpp @@ -70,74 +70,64 @@ void fmt_class_string::format(std::string& out, u64 arg) void mic_context::operator()() { + // Timestep in microseconds + constexpr u64 TIMESTEP = 256ull * 1'000'000ull / 48000ull; + u64 timeout = 0; + u64 oldvalue = 0; + while (thread_ctrl::state() != thread_state::aborting) { - // The time between processing is copied from audio thread - // Might be inaccurate for mic thread - if (Emu.IsPaused()) + if (timeout != 0) { - thread_ctrl::wait_for(1000); // hack - continue; + thread_ctrl::wait_on(wakey, oldvalue, timeout); + oldvalue = wakey; } - const u64 stamp0 = get_guest_system_time(); - const u64 time_pos = stamp0 - start_time - Emu.GetPauseTime(); + std::lock_guard lock(mutex); - const u64 expected_time = m_counter * 256 * 1000000 / 48000; - if (expected_time >= time_pos) + if (std::none_of(mic_list.begin(), mic_list.end(), [](const microphone_device& dev) { return dev.is_registered(); })) { - thread_ctrl::wait_for(1000); // hack + timeout = umax; continue; } - m_counter++; - - // Process signals - const auto process_signals = [this]() -> bool + else { - std::lock_guard lock(mutex); + timeout = TIMESTEP - (std::chrono::duration_cast(steady_clock::now().time_since_epoch()).count() % TIMESTEP); + } - if (std::none_of(mic_list.begin(), mic_list.end(), [](const microphone_device& dev) { return dev.is_registered(); })) - { - return false; - } - - for (auto& mic_entry : mic_list) - { - mic_entry.update_audio(); - } - - auto mic_queue = lv2_event_queue::find(event_queue_key); - if (!mic_queue) - { - return true; - } - - for (usz dev_num = 0; dev_num < mic_list.size(); dev_num++) - { - microphone_device& device = ::at32(mic_list, dev_num); - if (device.has_data()) - { - mic_queue->send(event_queue_source, CELLMIC_DATA, dev_num, 0); - } - } - - return true; - }; - - // Get mic input and sleep if mics are idle - if (!process_signals()) + for (auto& mic_entry : mic_list) { - thread_ctrl::wait_for(100000); + mic_entry.update_audio(); + } + + auto mic_queue = lv2_event_queue::find(event_queue_key); + if (!mic_queue) + continue; + + for (usz dev_num = 0; dev_num < mic_list.size(); dev_num++) + { + microphone_device& device = ::at32(mic_list, dev_num); + if (device.has_data()) + { + mic_queue->send(event_queue_source, CELLMIC_DATA, dev_num, 0); + } } } // Cleanup + std::lock_guard lock(mutex); for (auto& mic_entry : mic_list) { mic_entry.close_microphone(); } } +void mic_context::wake_up() +{ + wakey++; + wakey.notify_one(); +} + void mic_context::load_config_and_init() { mic_list = {}; @@ -214,6 +204,8 @@ u32 mic_context::register_device(const std::string& device_name) break; } + wake_up(); + return ::narrow(index); } diff --git a/rpcs3/Emu/Cell/Modules/cellMic.h b/rpcs3/Emu/Cell/Modules/cellMic.h index 660bf786e0..aba0d8bbfa 100644 --- a/rpcs3/Emu/Cell/Modules/cellMic.h +++ b/rpcs3/Emu/Cell/Modules/cellMic.h @@ -356,6 +356,7 @@ class mic_context public: void operator()(); void load_config_and_init(); + void wake_up(); // Returns index of registered device u32 register_device(const std::string& name); @@ -373,8 +374,7 @@ public: static constexpr auto thread_name = "Microphone Thread"sv; protected: - const u64 start_time = get_guest_system_time(); - u64 m_counter = 0; + atomic_t wakey = 0; // u32 signalStateLocalTalk = 9; // value is in range 0-10. 10 indicates talking, 0 indicating none. // u32 signalStateFarTalk = 0; // value is in range 0-10. 10 indicates talking from far away, 0 indicating none. diff --git a/rpcs3/Emu/Cell/lv2/sys_usbd.cpp b/rpcs3/Emu/Cell/lv2/sys_usbd.cpp index e285acaac0..0c698056bd 100644 --- a/rpcs3/Emu/Cell/lv2/sys_usbd.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_usbd.cpp @@ -398,7 +398,7 @@ void usb_handler_thread::operator()() if (handled_devices.empty()) thread_ctrl::wait_for(500'000); else - std::this_thread::yield(); + thread_ctrl::wait_for(1'000); } } diff --git a/rpcs3/Emu/Io/usio.cpp b/rpcs3/Emu/Io/usio.cpp index 5c237c793b..4c5ee572e3 100644 --- a/rpcs3/Emu/Io/usio.cpp +++ b/rpcs3/Emu/Io/usio.cpp @@ -487,7 +487,7 @@ void usb_device_usio::interrupt_transfer(u32 buf_size, u8* buf, u32 endpoint, Us transfer->fake = true; transfer->expected_result = HC_CC_NOERR; // The latency varies per operation but it doesn't seem to matter for this device so let's go fast! - transfer->expected_time = get_timestamp(); + transfer->expected_time = get_timestamp() + 1'000; is_used = true;