diff --git a/app/streaming/audio/audio.cpp b/app/streaming/audio/audio.cpp index 48a9660e..b41c60ec 100644 --- a/app/streaming/audio/audio.cpp +++ b/app/streaming/audio/audio.cpp @@ -156,16 +156,22 @@ void Session::arDecodeAndPlaySample(char* sampleData, int sampleLength) (short*)buffer, desiredSize / sizeof(short) / s_ActiveSession->m_AudioConfig.channelCount, 0); + + // Update desiredSize with the number of bytes actually populated by the decoding operation if (samplesDecoded > 0) { SDL_assert(desiredSize >= sizeof(short) * samplesDecoded * s_ActiveSession->m_AudioConfig.channelCount); desiredSize = sizeof(short) * samplesDecoded * s_ActiveSession->m_AudioConfig.channelCount; - if (!s_ActiveSession->m_AudioRenderer->submitAudio(desiredSize)) { - SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, - "Reinitializing audio renderer after failure"); + } + else { + desiredSize = 0; + } - delete s_ActiveSession->m_AudioRenderer; - s_ActiveSession->m_AudioRenderer = nullptr; - } + if (!s_ActiveSession->m_AudioRenderer->submitAudio(desiredSize)) { + SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, + "Reinitializing audio renderer after failure"); + + delete s_ActiveSession->m_AudioRenderer; + s_ActiveSession->m_AudioRenderer = nullptr; } } diff --git a/app/streaming/audio/renderers/renderer.h b/app/streaming/audio/renderers/renderer.h index 25059cca..52880c73 100644 --- a/app/streaming/audio/renderers/renderer.h +++ b/app/streaming/audio/renderers/renderer.h @@ -2,9 +2,6 @@ #include -#define MAX_CHANNELS 6 -#define SAMPLES_PER_FRAME 240 - class IAudioRenderer { public: diff --git a/app/streaming/audio/renderers/sdlaud.cpp b/app/streaming/audio/renderers/sdlaud.cpp index 551d0896..e8ceb828 100644 --- a/app/streaming/audio/renderers/sdlaud.cpp +++ b/app/streaming/audio/renderers/sdlaud.cpp @@ -87,6 +87,11 @@ void* SdlAudioRenderer::getAudioBuffer(int*) bool SdlAudioRenderer::submitAudio(int bytesWritten) { + if (bytesWritten == 0) { + // Nothing to do + return true; + } + if (SDL_QueueAudio(m_AudioDevice, m_AudioBuffer, bytesWritten) < 0) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to queue audio sample: %s", diff --git a/app/streaming/audio/renderers/slaud.cpp b/app/streaming/audio/renderers/slaud.cpp index e24428d6..115c6d8e 100644 --- a/app/streaming/audio/renderers/slaud.cpp +++ b/app/streaming/audio/renderers/slaud.cpp @@ -4,7 +4,8 @@ SLAudioRenderer::SLAudioRenderer() : m_AudioContext(nullptr), - m_AudioStream(nullptr) + m_AudioStream(nullptr), + m_AudioBuffer(nullptr) { SLAudio_SetLogFunction(SLAudioRenderer::slLogCallback, nullptr); } @@ -18,6 +19,7 @@ bool SLAudioRenderer::prepareForPlayback(const OPUS_MULTISTREAM_CONFIGURATION* o return false; } + m_FrameDuration = opusConfig->samplesPerFrame / 48; m_AudioBufferSize = opusConfig->samplesPerFrame * sizeof(short) * opusConfig->channelCount; m_AudioStream = SLAudio_CreateStream(m_AudioContext, opusConfig->sampleRate, @@ -31,7 +33,8 @@ bool SLAudioRenderer::prepareForPlayback(const OPUS_MULTISTREAM_CONFIGURATION* o } SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, - "Using SLAudio renderer"); + "Using SLAudio renderer with %d ms frames", + m_FrameDuration); return true; } @@ -39,11 +42,21 @@ bool SLAudioRenderer::prepareForPlayback(const OPUS_MULTISTREAM_CONFIGURATION* o void* SLAudioRenderer::getAudioBuffer(int* size) { SDL_assert(*size == m_AudioBufferSize); - return SLAudio_BeginFrame(m_AudioStream); + + if (m_AudioBuffer == nullptr) { + m_AudioBuffer = SLAudio_BeginFrame(m_AudioStream); + } + + return m_AudioBuffer; } SLAudioRenderer::~SLAudioRenderer() { + if (m_AudioBuffer != nullptr) { + memset(m_AudioBuffer, 0, m_AudioBufferSize); + SLAudio_SubmitFrame(m_AudioStream); + } + if (m_AudioStream != nullptr) { SLAudio_FreeStream(m_AudioStream); } @@ -53,9 +66,24 @@ SLAudioRenderer::~SLAudioRenderer() } } -bool SLAudioRenderer::submitAudio(int) +bool SLAudioRenderer::submitAudio(int bytesWritten) { - SLAudio_SubmitFrame(m_AudioStream); + if (bytesWritten == 0) { + // This buffer will be reused next time + return true; + } + + // Only allow up to 40 ms of queued audio + if (LiGetPendingAudioFrames() * m_FrameDuration < 40) { + SLAudio_SubmitFrame(m_AudioStream); + m_AudioBuffer = nullptr; + } + else { + SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, + "Too many queued audio frames: %d", + LiGetPendingAudioFrames()); + } + return true; } diff --git a/app/streaming/audio/renderers/slaud.h b/app/streaming/audio/renderers/slaud.h index bfe8c275..5debd129 100644 --- a/app/streaming/audio/renderers/slaud.h +++ b/app/streaming/audio/renderers/slaud.h @@ -22,5 +22,7 @@ private: CSLAudioContext* m_AudioContext; CSLAudioStream* m_AudioStream; + void* m_AudioBuffer; int m_AudioBufferSize; + int m_FrameDuration; }; diff --git a/app/streaming/audio/renderers/soundioaudiorenderer.cpp b/app/streaming/audio/renderers/soundioaudiorenderer.cpp index fe8982bf..2e18ec74 100644 --- a/app/streaming/audio/renderers/soundioaudiorenderer.cpp +++ b/app/streaming/audio/renderers/soundioaudiorenderer.cpp @@ -303,6 +303,11 @@ bool SoundIoAudioRenderer::submitAudio(int bytesWritten) return false; } + if (bytesWritten == 0) { + // Nothing to do + return true; + } + // Flush events to update with new device arrivals soundio_flush_events(m_SoundIo); diff --git a/moonlight-common-c/moonlight-common-c b/moonlight-common-c/moonlight-common-c index 59481c08..dffe51e8 160000 --- a/moonlight-common-c/moonlight-common-c +++ b/moonlight-common-c/moonlight-common-c @@ -1 +1 @@ -Subproject commit 59481c085a7f774c5d30374636f8bc75da7c676c +Subproject commit dffe51e885bcb5e09f90288f30268846f08c25de