From 1febe32e736290fb042524e8ecc4d3e5289a0f4b Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Sun, 17 Nov 2019 12:22:57 -0800 Subject: [PATCH] Fix 5.1 channel mapping on Steam Link --- app/streaming/audio/audio.cpp | 29 ++++++++++++++---------- app/streaming/audio/renderers/renderer.h | 10 ++++++++ app/streaming/audio/renderers/slaud.cpp | 23 +++++++++++++++++++ app/streaming/audio/renderers/slaud.h | 2 ++ 4 files changed, 52 insertions(+), 12 deletions(-) diff --git a/app/streaming/audio/audio.cpp b/app/streaming/audio/audio.cpp index d9a5f1e8..de07fac2 100644 --- a/app/streaming/audio/audio.cpp +++ b/app/streaming/audio/audio.cpp @@ -145,29 +145,34 @@ int Session::arInit(int /* audioConfiguration */, SDL_memcpy(&s_ActiveSession->m_AudioConfig, opusConfig, sizeof(*opusConfig)); + s_ActiveSession->m_AudioRenderer = s_ActiveSession->createAudioRenderer(&s_ActiveSession->m_AudioConfig); + if (s_ActiveSession->m_AudioRenderer == nullptr) { + return -2; + } + + // Allow the chosen renderer to remap Opus channels as needed to ensure proper output + s_ActiveSession->m_AudioRenderer->remapChannels(&s_ActiveSession->m_AudioConfig); + + // Create the Opus decoder with the renderer's preferred channel mapping s_ActiveSession->m_OpusDecoder = - opus_multistream_decoder_create(opusConfig->sampleRate, - opusConfig->channelCount, - opusConfig->streams, - opusConfig->coupledStreams, - opusConfig->mapping, + opus_multistream_decoder_create(s_ActiveSession->m_AudioConfig.sampleRate, + s_ActiveSession->m_AudioConfig.channelCount, + s_ActiveSession->m_AudioConfig.streams, + s_ActiveSession->m_AudioConfig.coupledStreams, + s_ActiveSession->m_AudioConfig.mapping, &error); if (s_ActiveSession->m_OpusDecoder == NULL) { + delete s_ActiveSession->m_AudioRenderer; + s_ActiveSession->m_AudioRenderer = nullptr; SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to create decoder: %d", error); return -1; } - s_ActiveSession->m_AudioRenderer = s_ActiveSession->createAudioRenderer(opusConfig); - if (s_ActiveSession->m_AudioRenderer == nullptr) { - opus_multistream_decoder_destroy(s_ActiveSession->m_OpusDecoder); - return -2; - } - SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "Audio stream has %d channels", - opusConfig->channelCount); + s_ActiveSession->m_AudioConfig.channelCount); return 0; } diff --git a/app/streaming/audio/renderers/renderer.h b/app/streaming/audio/renderers/renderer.h index 1d9901c6..2a3c1030 100644 --- a/app/streaming/audio/renderers/renderer.h +++ b/app/streaming/audio/renderers/renderer.h @@ -15,4 +15,14 @@ public: virtual bool submitAudio(int bytesWritten) = 0; virtual int getCapabilities() = 0; + + virtual void remapChannels(POPUS_MULTISTREAM_CONFIGURATION) { + // Use default channel mapping: + // 0 - Front Left + // 1 - Front Right + // 2 - Center + // 3 - LFE + // 4 - Surround Left + // 5 - Surround Right + } }; diff --git a/app/streaming/audio/renderers/slaud.cpp b/app/streaming/audio/renderers/slaud.cpp index 5e7e1ff4..6bf23eaa 100644 --- a/app/streaming/audio/renderers/slaud.cpp +++ b/app/streaming/audio/renderers/slaud.cpp @@ -43,6 +43,29 @@ bool SLAudioRenderer::prepareForPlayback(const OPUS_MULTISTREAM_CONFIGURATION* o return true; } +#define SWAP_CHANNEL(i, j) \ + tmp = opusConfig->mapping[i]; \ + opusConfig->mapping[i] = opusConfig->mapping[j]; \ + opusConfig->mapping[j] = tmp + +void SLAudioRenderer::remapChannels(POPUS_MULTISTREAM_CONFIGURATION opusConfig) { + unsigned char tmp; + + if (opusConfig->channelCount == 6) { + // The Moonlight's default channel order is FL,FR,C,LFE,RL,RR + // SLAudio expects FL,C,FR,RL,RR,LFE so we swap the channels around to match + + // Swap FR and C - now FL,C,FR,LFE,RL,RR + SWAP_CHANNEL(1, 2); + + // Swap LFE and RR - now FL,C,FR,RR,RL,LFE + SWAP_CHANNEL(3, 5); + + // Swap RR and RL - now FL,C,FR,RL,RR,LFE + SWAP_CHANNEL(4, 5); + } +} + void* SLAudioRenderer::getAudioBuffer(int* size) { SDL_assert(*size == m_AudioBufferSize); diff --git a/app/streaming/audio/renderers/slaud.h b/app/streaming/audio/renderers/slaud.h index 4c2829fc..54f7e7ae 100644 --- a/app/streaming/audio/renderers/slaud.h +++ b/app/streaming/audio/renderers/slaud.h @@ -18,6 +18,8 @@ public: virtual int getCapabilities(); + virtual void remapChannels(POPUS_MULTISTREAM_CONFIGURATION opusConfig); + private: static void slLogCallback(void* context, ESLAudioLog logLevel, const char* message);