mirror of
https://github.com/moonlight-stream/moonlight-qt
synced 2024-11-10 13:44:17 +00:00
Audio latency tweaks and fix for PulseAudio with A2DP
This commit is contained in:
parent
8612e6726d
commit
d1640e3bb8
2 changed files with 30 additions and 10 deletions
|
@ -4,13 +4,21 @@
|
|||
|
||||
#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.
|
||||
// GFE sends us packets in 5 ms chunks
|
||||
const double SoundIoAudioRenderer::k_RawSampleLengthSec = 0.005;
|
||||
|
||||
#ifdef Q_OS_LINUX
|
||||
// PulseAudio and ALSA require more than just 5 ms samples
|
||||
// for some reason, so write a minimum of 20 ms each time to
|
||||
// prevent underruns on Bluetooth.
|
||||
const double SoundIoAudioRenderer::k_MinSampleLengthSec = 0.020;
|
||||
#else
|
||||
// This determines the size of the buffers we'll
|
||||
// get from CoreAudio. It is also the minimum
|
||||
// size that we will write when called to fill a buffer.
|
||||
const double SoundIoAudioRenderer::k_MinSampleLengthSec = k_RawSampleLengthSec;
|
||||
#endif
|
||||
|
||||
SoundIoAudioRenderer::SoundIoAudioRenderer()
|
||||
: m_OpusChannelCount(0),
|
||||
m_SoundIo(nullptr),
|
||||
|
@ -164,7 +172,7 @@ bool SoundIoAudioRenderer::prepareForPlayback(const OPUS_MULTISTREAM_CONFIGURATI
|
|||
|
||||
m_OutputStream->format = SoundIoFormatS16NE;
|
||||
m_OutputStream->sample_rate = opusConfig->sampleRate;
|
||||
m_OutputStream->software_latency = k_RawSampleLengthSec;
|
||||
m_OutputStream->software_latency = k_MinSampleLengthSec;
|
||||
m_OutputStream->name = "Moonlight";
|
||||
m_OutputStream->userdata = this;
|
||||
m_OutputStream->error_callback = sioErrorCallback;
|
||||
|
@ -225,12 +233,18 @@ bool SoundIoAudioRenderer::prepareForPlayback(const OPUS_MULTISTREAM_CONFIGURATI
|
|||
}
|
||||
}
|
||||
|
||||
// Buffer up to 6 packets of audio (30 ms) to smooth
|
||||
// out network packet delivery jitter
|
||||
// Buffer at least 2 audio packets to smooth out network packet delivery jitter or
|
||||
// 15 ms, whichever is greater.
|
||||
int packetsToBuffer = qMax((int)(k_MinSampleLengthSec / k_RawSampleLengthSec) * 2, 3);
|
||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"Audio buffer size: %d packets",
|
||||
packetsToBuffer);
|
||||
|
||||
m_RingBuffer = soundio_ring_buffer_create(m_SoundIo,
|
||||
m_OutputStream->bytes_per_sample *
|
||||
m_OpusChannelCount *
|
||||
SAMPLES_PER_FRAME * 6);
|
||||
SAMPLES_PER_FRAME *
|
||||
packetsToBuffer);
|
||||
if (m_RingBuffer == nullptr) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"soundio_ring_buffer_create() failed");
|
||||
|
@ -245,6 +259,11 @@ bool SoundIoAudioRenderer::prepareForPlayback(const OPUS_MULTISTREAM_CONFIGURATI
|
|||
return false;
|
||||
}
|
||||
|
||||
// HACK: For some reason, a constant latency hangs around in the audio pipeline
|
||||
// unless we wait for the audio stream to drain before actually submitting any samples.
|
||||
// This is a gross hack, but it works remarkably well.
|
||||
SDL_Delay(500);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -338,7 +357,7 @@ void SoundIoAudioRenderer::sioWriteCallback(SoundIoOutStream* stream, int frameC
|
|||
// 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 = qMax(frameCountMin, (int)(stream->sample_rate * k_MinSampleLengthSec));
|
||||
frameCountMin = qMin(frameCountMin, frameCountMax);
|
||||
|
||||
// Clamp framesLeft to frameCountMin to ensure that we never write more than one sample.
|
||||
|
|
|
@ -36,4 +36,5 @@ private:
|
|||
bool m_Errored;
|
||||
|
||||
static const double k_RawSampleLengthSec;
|
||||
static const double k_MinSampleLengthSec;
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue