From 97daea90a7d375bda6fc1911c58168f886993663 Mon Sep 17 00:00:00 2001 From: Sepalani Date: Tue, 14 May 2024 01:52:52 +0400 Subject: [PATCH] IOS/USB: Report Wii Speak packet size properly --- .../Core/Core/IOS/USB/Emulated/Microphone.cpp | 12 +++---- .../Core/Core/IOS/USB/Emulated/Microphone.h | 2 +- .../Core/Core/IOS/USB/Emulated/WiiSpeak.cpp | 32 +++++++++---------- 3 files changed, 22 insertions(+), 24 deletions(-) diff --git a/Source/Core/Core/IOS/USB/Emulated/Microphone.cpp b/Source/Core/Core/IOS/USB/Emulated/Microphone.cpp index 2ff9c29ac154..9aeae218abad 100644 --- a/Source/Core/Core/IOS/USB/Emulated/Microphone.cpp +++ b/Source/Core/Core/IOS/USB/Emulated/Microphone.cpp @@ -206,7 +206,7 @@ long Microphone::DataCallback(cubeb_stream* stream, void* user_data, const void* return nframes; } -void Microphone::ReadIntoBuffer(u8* dst, u32 size) +u16 Microphone::ReadIntoBuffer(u8* ptr, u32 size) { static constexpr u32 SINGLE_READ_SIZE = BUFF_SIZE_SAMPLES * sizeof(SampleType); @@ -216,22 +216,20 @@ void Microphone::ReadIntoBuffer(u8* dst, u32 size) std::lock_guard lk(m_ring_lock); - for (u8* end = dst + size; dst < end; dst += SINGLE_READ_SIZE, size -= SINGLE_READ_SIZE) + u8* begin = ptr; + for (u8* end = begin + size; ptr < end; ptr += SINGLE_READ_SIZE, size -= SINGLE_READ_SIZE) { if (size < SINGLE_READ_SIZE || m_samples_avail < BUFF_SIZE_SAMPLES) break; SampleType* last_buffer = &m_stream_buffer[m_stream_rpos]; - std::memcpy(dst, last_buffer, SINGLE_READ_SIZE); + std::memcpy(ptr, last_buffer, SINGLE_READ_SIZE); m_samples_avail -= BUFF_SIZE_SAMPLES; m_stream_rpos += BUFF_SIZE_SAMPLES; m_stream_rpos %= STREAM_SIZE; } - if (size != 0) - { - std::memset(dst, 0, size); - } + return static_cast(ptr - begin); } bool Microphone::HasData() const diff --git a/Source/Core/Core/IOS/USB/Emulated/Microphone.h b/Source/Core/Core/IOS/USB/Emulated/Microphone.h index d9c16b0c80cb..5c85e612ca50 100644 --- a/Source/Core/Core/IOS/USB/Emulated/Microphone.h +++ b/Source/Core/Core/IOS/USB/Emulated/Microphone.h @@ -24,7 +24,7 @@ class Microphone final ~Microphone(); bool HasData() const; - void ReadIntoBuffer(u8* dst, u32 size); + u16 ReadIntoBuffer(u8* ptr, u32 size); const WiiSpeakState& GetSampler() const; private: diff --git a/Source/Core/Core/IOS/USB/Emulated/WiiSpeak.cpp b/Source/Core/Core/IOS/USB/Emulated/WiiSpeak.cpp index f97cc85bd702..419b4507bab5 100644 --- a/Source/Core/Core/IOS/USB/Emulated/WiiSpeak.cpp +++ b/Source/Core/Core/IOS/USB/Emulated/WiiSpeak.cpp @@ -3,6 +3,8 @@ #include "Core/IOS/USB/Emulated/WiiSpeak.h" +#include + #include "Core/Config/MainSettings.h" #include "Core/HW/Memmap.h" @@ -176,10 +178,18 @@ int WiiSpeak::SubmitTransfer(std::unique_ptr cmd) switch (cmd->endpoint) { case ENDPOINT_AUDIO_IN: + { // Transfer: Wii Speak -> Wii + u16 size = 0; if (m_microphone && m_microphone->HasData()) - m_microphone->ReadIntoBuffer(packets, cmd->length); + size = m_microphone->ReadIntoBuffer(packets, cmd->length); + for (std::size_t i = 0; i < cmd->num_packets; i++) + { + cmd->SetPacketReturnValue(i, std::min(size, cmd->packet_sizes[i])); + size = (size > cmd->packet_sizes[i]) ? (size - cmd->packet_sizes[i]) : 0; + } break; + } case ENDPOINT_AUDIO_OUT: // Transfer: Wii -> Wii Speak break; @@ -202,22 +212,12 @@ int WiiSpeak::SubmitTransfer(std::unique_ptr cmd) // (i.e. 128 samples in 16-bit mono) per frame transfer. The Microphone class is using cubeb // configured with a sample rate of 8000. // - // Based on these numbers, here are some theoretical speeds: - // - fastest transfer speed would be 8000 samples in 63 ms (i.e. 8000 * 1/128 = 62.5) - // * using a timing of 1 ms per frame of 128 samples - // * here cubeb sample rate is the bottleneck - // - slowest transfer speed would be 8000 samples in 1000 ms (i.e. 128 * 1000/8000 = 16) - // * using a timing of 16 ms per frame of 128 samples - // * matching cubeb sampling rate - // - // A decent timing would be 16ms. However, it seems that the Wii Speak Channel record feature is - // broken if the timing is less than 32ms and that the record playback is broken when around 34ms - // and above. Monster Hunter 3 doesn't seem affected by this timing issue. + // Based on USB sniffing using Wireshark + Dolphin USB passthrough: + // - 125 samples are received per second (i.e. timing 8 ms per sample) + // - however, the cmd->length=0x80 which doesn't match the HLE emulation // - // TODO: Investigate and ensure that's the proper way to fix it. - // Maybe it's related to the Wii DSP and its stereo/mono mode? - // If so, what would be the impact of using DSP LLE/HLE in mono/stereo? - const u32 transfer_timing = 32000; + // Let's sample at a reasonable speed. + const u32 transfer_timing = 2000; cmd->ScheduleTransferCompletion(IPC_SUCCESS, transfer_timing); return IPC_SUCCESS; }