mirror of
https://github.com/moonlight-stream/moonlight-qt.git
synced 2025-07-18 10:32:38 +00:00
Fix busy looping in libsoundio audio renderer when no audio is playing
This commit is contained in:
parent
b26df787cd
commit
d1fe752028
@ -4,6 +4,13 @@
|
|||||||
|
|
||||||
#include <QtGlobal>
|
#include <QtGlobal>
|
||||||
|
|
||||||
|
// This determines the size of the buffers we'll
|
||||||
|
// get from CoreAudio. Since GFE sends us packets
|
||||||
|
// in 5 ms chunks, we'll give them to the OS in
|
||||||
|
// buffers of the same size. It is also the minimum
|
||||||
|
// size that we will write when called to fill a buffer.
|
||||||
|
const double SoundIoAudioRenderer::k_RawSampleLengthSec = 0.005;
|
||||||
|
|
||||||
SoundIoAudioRenderer::SoundIoAudioRenderer()
|
SoundIoAudioRenderer::SoundIoAudioRenderer()
|
||||||
: m_OpusChannelCount(0),
|
: m_OpusChannelCount(0),
|
||||||
m_SoundIo(nullptr),
|
m_SoundIo(nullptr),
|
||||||
@ -152,17 +159,12 @@ bool SoundIoAudioRenderer::prepareForPlayback(const OPUS_MULTISTREAM_CONFIGURATI
|
|||||||
|
|
||||||
m_OutputStream->format = SoundIoFormatS16NE;
|
m_OutputStream->format = SoundIoFormatS16NE;
|
||||||
m_OutputStream->sample_rate = opusConfig->sampleRate;
|
m_OutputStream->sample_rate = opusConfig->sampleRate;
|
||||||
|
m_OutputStream->software_latency = k_RawSampleLengthSec;
|
||||||
m_OutputStream->name = "Moonlight";
|
m_OutputStream->name = "Moonlight";
|
||||||
m_OutputStream->userdata = this;
|
m_OutputStream->userdata = this;
|
||||||
m_OutputStream->error_callback = sioErrorCallback;
|
m_OutputStream->error_callback = sioErrorCallback;
|
||||||
m_OutputStream->write_callback = sioWriteCallback;
|
m_OutputStream->write_callback = sioWriteCallback;
|
||||||
|
|
||||||
// This determines the size of the buffers we'll
|
|
||||||
// get from CoreAudio. Since GFE sends us packets
|
|
||||||
// in 5 ms chunks, we'll give them to the OS in
|
|
||||||
// buffers of the same size.
|
|
||||||
m_OutputStream->software_latency = 0.005;
|
|
||||||
|
|
||||||
SoundIoChannelLayout bestLayout = m_Device->current_layout;
|
SoundIoChannelLayout bestLayout = m_Device->current_layout;
|
||||||
for (int i = 0; i < m_Device->layout_count; i++) {
|
for (int i = 0; i < m_Device->layout_count; i++) {
|
||||||
if (scoreChannelLayout(&bestLayout, opusConfig) <
|
if (scoreChannelLayout(&bestLayout, opusConfig) <
|
||||||
@ -331,6 +333,12 @@ void SoundIoAudioRenderer::sioWriteCallback(SoundIoOutStream* stream, int frameC
|
|||||||
// Clamp framesLeft to frameCountMax
|
// Clamp framesLeft to frameCountMax
|
||||||
framesLeft = qMin(framesLeft, frameCountMax);
|
framesLeft = qMin(framesLeft, frameCountMax);
|
||||||
|
|
||||||
|
// Ensure we always write at least a buffer, even if it's silence, to avoid
|
||||||
|
// busy looping when no audio data is available while libsoundio tries to keep
|
||||||
|
// us from starving the output device.
|
||||||
|
frameCountMin = qMax(frameCountMin, (int)(stream->sample_rate * k_RawSampleLengthSec));
|
||||||
|
frameCountMin = qMin(frameCountMin, frameCountMax);
|
||||||
|
|
||||||
// Place an upper-bound on audio stream latency to
|
// Place an upper-bound on audio stream latency to
|
||||||
// avoid accumulating packets in queue-based backends
|
// avoid accumulating packets in queue-based backends
|
||||||
// like WASAPI. This bound was set by testing on several
|
// like WASAPI. This bound was set by testing on several
|
||||||
|
@ -33,4 +33,6 @@ private:
|
|||||||
struct SoundIoRingBuffer* m_RingBuffer;
|
struct SoundIoRingBuffer* m_RingBuffer;
|
||||||
struct SoundIoChannelLayout m_EffectiveLayout;
|
struct SoundIoChannelLayout m_EffectiveLayout;
|
||||||
bool m_Errored;
|
bool m_Errored;
|
||||||
|
|
||||||
|
static const double k_RawSampleLengthSec;
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user