diff --git a/Source/Core/Core/IOS/USB/Emulated/Microphone.cpp b/Source/Core/Core/IOS/USB/Emulated/Microphone.cpp index c264eb768f..93e4bcfbc6 100644 --- a/Source/Core/Core/IOS/USB/Emulated/Microphone.cpp +++ b/Source/Core/Core/IOS/USB/Emulated/Microphone.cpp @@ -188,6 +188,7 @@ long Microphone::DataCallback(cubeb_stream* stream, void* user_data, const void* mic->m_samples_avail += nframes; if (mic->m_samples_avail > mic->STREAM_SIZE) { + WARN_LOG_FMT(IOS_USB, "Wii Speak ring buffer is full, data will be lost!"); mic->m_samples_avail = 0; } @@ -196,18 +197,30 @@ long Microphone::DataCallback(cubeb_stream* stream, void* user_data, const void* void Microphone::ReadIntoBuffer(u8* dst, u32 size) { + static constexpr u32 SINGLE_READ_SIZE = BUFF_SIZE_SAMPLES * sizeof(SampleType); + + // Avoid buffer overflow during memcpy + static_assert((STREAM_SIZE % BUFF_SIZE_SAMPLES) == 0, + "The STREAM_SIZE isn't a multiple of BUFF_SIZE_SAMPLES"); + std::lock_guard lk(m_ring_lock); - if (m_samples_avail >= BUFF_SIZE_SAMPLES) + for (u8* end = dst + size; dst < end; dst += SINGLE_READ_SIZE, size -= SINGLE_READ_SIZE) { - u8* last_buffer = reinterpret_cast(&m_stream_buffer[m_stream_rpos]); - std::memcpy(dst, static_cast(last_buffer), 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); 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); + } } 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 a938430dae..1b02e81d42 100644 --- a/Source/Core/Core/IOS/USB/Emulated/Microphone.h +++ b/Source/Core/Core/IOS/USB/Emulated/Microphone.h @@ -34,11 +34,11 @@ private: void StreamStop(); static constexpr u32 SAMPLING_RATE = 8000; - static constexpr u32 BUFFER_SIZE = SAMPLING_RATE / 2; + using SampleType = s16; static constexpr u32 BUFF_SIZE_SAMPLES = 16; static constexpr u32 STREAM_SIZE = BUFF_SIZE_SAMPLES * 500; - std::array m_stream_buffer{}; + std::array m_stream_buffer{}; u32 m_stream_wpos = 0; u32 m_stream_rpos = 0; u32 m_samples_avail = 0;