From b53e9856b8ef6aa95b3eb5c0654388d7098ab1f3 Mon Sep 17 00:00:00 2001 From: Stenzek Date: Fri, 7 Jul 2023 00:49:28 +1000 Subject: [PATCH] USB/usb-mic: Fix buffer handling - RingBuffer would store a size of zero if you wrote the entire the entire buffer in one call. - ResetBuffers() should be called before starting the stream, otherwise you risk a race where the callback happens before the buffer is allocated. - Fix incorrect latency being passed into Cubeb. --- pcsx2/USB/shared/ringbuffer.cpp | 2 +- pcsx2/USB/usb-mic/audiodev-cubeb.cpp | 13 ++++++------- pcsx2/USB/usb-mic/audiodev-cubeb.h | 1 + 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/pcsx2/USB/shared/ringbuffer.cpp b/pcsx2/USB/shared/ringbuffer.cpp index 588857b621..2b3b1041fc 100644 --- a/pcsx2/USB/shared/ringbuffer.cpp +++ b/pcsx2/USB/shared/ringbuffer.cpp @@ -162,7 +162,7 @@ void RingBuffer::write(size_t bytes) // push m_begin forward if m_end overlaps it if ((m_end < m_begin && m_end + bytes > m_begin) || - m_end + bytes > m_begin + m_capacity) + m_end + bytes >= m_begin + m_capacity) { m_overrun = true; m_begin = (m_end + bytes) % m_capacity; diff --git a/pcsx2/USB/usb-mic/audiodev-cubeb.cpp b/pcsx2/USB/usb-mic/audiodev-cubeb.cpp index 0cd08a2cb0..4e270b331c 100644 --- a/pcsx2/USB/usb-mic/audiodev-cubeb.cpp +++ b/pcsx2/USB/usb-mic/audiodev-cubeb.cpp @@ -150,14 +150,13 @@ namespace usb_mic params.prefs = CUBEB_STREAM_PREF_NONE; // Prefer minimum latency, reduces the chance of dropped samples due to the extra buffer. - u32 streamLatency; - if (cubeb_get_min_latency(mContext, ¶ms, &streamLatency) != CUBEB_OK) - streamLatency = mLatency; + if (cubeb_get_min_latency(mContext, ¶ms, &mStreamLatency) != CUBEB_OK) + mStreamLatency = (mLatency * mSampleRate) / 1000u; const bool input = (mAudioDir == AUDIODIR_SOURCE); int res = cubeb_stream_init(mContext, &mStream, fmt::format("{}", (void*)this).c_str(), input ? mDeviceId : nullptr, input ? ¶ms : nullptr, input ? nullptr : mDeviceId, - input ? nullptr : ¶ms, (streamLatency * mSampleRate) / 1000u, + input ? nullptr : ¶ms, mStreamLatency, &CubebAudioDevice::DataCallback, &CubebStateCallback, this); if (res != CUBEB_OK) { @@ -165,6 +164,8 @@ namespace usb_mic return false; } + ResetBuffers(); + res = cubeb_stream_start(mStream); if (res != CUBEB_OK) { @@ -174,7 +175,6 @@ namespace usb_mic return false; } - ResetBuffers(); return true; } @@ -252,9 +252,8 @@ namespace usb_mic void CubebAudioDevice::ResetBuffers() { - // TODO: Do we want to make the buffer size adjustable? Currently 100ms max. std::lock_guard lk(mMutex); - const u32 samples = ((mSampleRate * mChannels) * mLatency) / 1000u; + const u32 samples = std::max(((mSampleRate * mChannels) * mLatency) / 1000u, mStreamLatency * mChannels); mBuffer.reserve(sizeof(u16) * samples); } diff --git a/pcsx2/USB/usb-mic/audiodev-cubeb.h b/pcsx2/USB/usb-mic/audiodev-cubeb.h index 3dbd063b61..393959b3ac 100644 --- a/pcsx2/USB/usb-mic/audiodev-cubeb.h +++ b/pcsx2/USB/usb-mic/audiodev-cubeb.h @@ -51,6 +51,7 @@ namespace usb_mic u32 mSampleRate = 48000; u32 mLatency = 50; + u32 mStreamLatency = 0; cubeb* mContext; cubeb_stream* mStream = nullptr; std::string mDeviceName;