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.
This commit is contained in:
Stenzek 2023-07-07 00:49:28 +10:00 committed by Connor McLaughlin
parent 20420da326
commit b53e9856b8
3 changed files with 8 additions and 8 deletions

View File

@ -162,7 +162,7 @@ void RingBuffer::write(size_t bytes)
// push m_begin forward if m_end overlaps it // push m_begin forward if m_end overlaps it
if ((m_end < m_begin && m_end + bytes > m_begin) || 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_overrun = true;
m_begin = (m_end + bytes) % m_capacity; m_begin = (m_end + bytes) % m_capacity;

View File

@ -150,14 +150,13 @@ namespace usb_mic
params.prefs = CUBEB_STREAM_PREF_NONE; params.prefs = CUBEB_STREAM_PREF_NONE;
// Prefer minimum latency, reduces the chance of dropped samples due to the extra buffer. // Prefer minimum latency, reduces the chance of dropped samples due to the extra buffer.
u32 streamLatency; if (cubeb_get_min_latency(mContext, &params, &mStreamLatency) != CUBEB_OK)
if (cubeb_get_min_latency(mContext, &params, &streamLatency) != CUBEB_OK) mStreamLatency = (mLatency * mSampleRate) / 1000u;
streamLatency = mLatency;
const bool input = (mAudioDir == AUDIODIR_SOURCE); const bool input = (mAudioDir == AUDIODIR_SOURCE);
int res = cubeb_stream_init(mContext, &mStream, fmt::format("{}", (void*)this).c_str(), int res = cubeb_stream_init(mContext, &mStream, fmt::format("{}", (void*)this).c_str(),
input ? mDeviceId : nullptr, input ? &params : nullptr, input ? nullptr : mDeviceId, input ? mDeviceId : nullptr, input ? &params : nullptr, input ? nullptr : mDeviceId,
input ? nullptr : &params, (streamLatency * mSampleRate) / 1000u, input ? nullptr : &params, mStreamLatency,
&CubebAudioDevice::DataCallback, &CubebStateCallback, this); &CubebAudioDevice::DataCallback, &CubebStateCallback, this);
if (res != CUBEB_OK) if (res != CUBEB_OK)
{ {
@ -165,6 +164,8 @@ namespace usb_mic
return false; return false;
} }
ResetBuffers();
res = cubeb_stream_start(mStream); res = cubeb_stream_start(mStream);
if (res != CUBEB_OK) if (res != CUBEB_OK)
{ {
@ -174,7 +175,6 @@ namespace usb_mic
return false; return false;
} }
ResetBuffers();
return true; return true;
} }
@ -252,9 +252,8 @@ namespace usb_mic
void CubebAudioDevice::ResetBuffers() void CubebAudioDevice::ResetBuffers()
{ {
// TODO: Do we want to make the buffer size adjustable? Currently 100ms max.
std::lock_guard<std::mutex> lk(mMutex); std::lock_guard<std::mutex> 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); mBuffer.reserve(sizeof(u16) * samples);
} }

View File

@ -51,6 +51,7 @@ namespace usb_mic
u32 mSampleRate = 48000; u32 mSampleRate = 48000;
u32 mLatency = 50; u32 mLatency = 50;
u32 mStreamLatency = 0;
cubeb* mContext; cubeb* mContext;
cubeb_stream* mStream = nullptr; cubeb_stream* mStream = nullptr;
std::string mDeviceName; std::string mDeviceName;