Fix surround sound channel mapping on ALSA

This commit is contained in:
Cameron Gutman 2018-10-01 18:46:16 -07:00
parent b14a0fa2ce
commit 209b4a1b02
6 changed files with 58 additions and 7 deletions

View file

@ -59,23 +59,27 @@ int Session::arInit(int /* audioConfiguration */,
SDL_memcpy(&s_ActiveSession->m_AudioConfig, opusConfig, sizeof(*opusConfig)); SDL_memcpy(&s_ActiveSession->m_AudioConfig, opusConfig, sizeof(*opusConfig));
s_ActiveSession->m_AudioRenderer = s_ActiveSession->createAudioRenderer();
if (s_ActiveSession->m_AudioRenderer == nullptr) {
return -1;
}
// Allow the audio renderer to adjust the channel mapping to fit its
// preferred channel order
s_ActiveSession->m_AudioRenderer->adjustOpusChannelMapping(&s_ActiveSession->m_AudioConfig);
s_ActiveSession->m_OpusDecoder = s_ActiveSession->m_OpusDecoder =
opus_multistream_decoder_create(opusConfig->sampleRate, opus_multistream_decoder_create(opusConfig->sampleRate,
opusConfig->channelCount, opusConfig->channelCount,
opusConfig->streams, opusConfig->streams,
opusConfig->coupledStreams, opusConfig->coupledStreams,
opusConfig->mapping, s_ActiveSession->m_AudioConfig.mapping,
&error); &error);
if (s_ActiveSession->m_OpusDecoder == NULL) { if (s_ActiveSession->m_OpusDecoder == NULL) {
delete s_ActiveSession->m_AudioRenderer;
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"Failed to create decoder: %d", "Failed to create decoder: %d",
error); error);
return -1;
}
s_ActiveSession->m_AudioRenderer = s_ActiveSession->createAudioRenderer();
if (s_ActiveSession->m_AudioRenderer == nullptr) {
opus_multistream_decoder_destroy(s_ActiveSession->m_OpusDecoder);
return -2; return -2;
} }

View file

@ -194,6 +194,42 @@ int PortAudioRenderer::detectAudioConfiguration() const
} }
} }
void PortAudioRenderer::adjustOpusChannelMapping(OPUS_MULTISTREAM_CONFIGURATION* opusConfig) const
{
const OPUS_MULTISTREAM_CONFIGURATION origConfig = *opusConfig;
const PaDeviceInfo* deviceInfo = Pa_GetDeviceInfo(Pa_GetDefaultOutputDevice());
if (deviceInfo == nullptr) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"Pa_GetDeviceInfo() failed");
return;
}
const PaHostApiInfo* hostApiInfo = Pa_GetHostApiInfo(deviceInfo->hostApi);
if (hostApiInfo == nullptr) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"Pa_GetHostApiInfo() failed");
return;
}
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
"PortAudio host API: %s",
hostApiInfo->name);
if (hostApiInfo->type == paALSA) {
// The default mapping array has is: FL-FR-C-LFE-RL-RR
// ALSA expects: FL-FR-RL-RR-C-LFE
opusConfig->mapping[0] = origConfig.mapping[0];
opusConfig->mapping[1] = origConfig.mapping[1];
if (opusConfig->channelCount == 6) {
opusConfig->mapping[2] = origConfig.mapping[4];
opusConfig->mapping[3] = origConfig.mapping[5];
opusConfig->mapping[4] = origConfig.mapping[2];
opusConfig->mapping[5] = origConfig.mapping[3];
}
}
}
int PortAudioRenderer::paStreamCallback(const void*, void* output, unsigned long frameCount, const PaStreamCallbackTimeInfo*, PaStreamCallbackFlags, void* userData) int PortAudioRenderer::paStreamCallback(const void*, void* output, unsigned long frameCount, const PaStreamCallbackTimeInfo*, PaStreamCallbackFlags, void* userData)
{ {
auto me = reinterpret_cast<PortAudioRenderer*>(userData); auto me = reinterpret_cast<PortAudioRenderer*>(userData);

View file

@ -24,6 +24,8 @@ public:
virtual int detectAudioConfiguration() const; virtual int detectAudioConfiguration() const;
virtual void adjustOpusChannelMapping(OPUS_MULTISTREAM_CONFIGURATION* opusConfig) const;
static int paStreamCallback(const void *input, static int paStreamCallback(const void *input,
void *output, void *output,
unsigned long frameCount, unsigned long frameCount,

View file

@ -10,6 +10,8 @@ class IAudioRenderer
public: public:
virtual ~IAudioRenderer() {} virtual ~IAudioRenderer() {}
virtual void adjustOpusChannelMapping(OPUS_MULTISTREAM_CONFIGURATION* opusConfig) const = 0;
virtual bool prepareForPlayback(const OPUS_MULTISTREAM_CONFIGURATION* opusConfig) = 0; virtual bool prepareForPlayback(const OPUS_MULTISTREAM_CONFIGURATION* opusConfig) = 0;
virtual void submitAudio(short* audioBuffer, int audioSize) = 0; virtual void submitAudio(short* audioBuffer, int audioSize) = 0;

View file

@ -23,6 +23,8 @@ public:
virtual int detectAudioConfiguration() const; virtual int detectAudioConfiguration() const;
virtual void adjustOpusChannelMapping(OPUS_MULTISTREAM_CONFIGURATION* opusConfig) const;
private: private:
SDL_AudioDeviceID m_AudioDevice; SDL_AudioDeviceID m_AudioDevice;
Uint32 m_ChannelCount; Uint32 m_ChannelCount;

View file

@ -51,6 +51,11 @@ int SdlAudioRenderer::detectAudioConfiguration() const
} }
} }
void SdlAudioRenderer::adjustOpusChannelMapping(OPUS_MULTISTREAM_CONFIGURATION*) const
{
// The default mapping is fine for SDL
}
bool SdlAudioRenderer::testAudio(int audioConfiguration) const bool SdlAudioRenderer::testAudio(int audioConfiguration) const
{ {
SDL_AudioSpec want, have; SDL_AudioSpec want, have;