From e16e2269b6a18c960a25d58f43ffad5ed408bee9 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 15 Sep 2019 20:46:37 -0700 Subject: [PATCH] Add a fallback if SLAndroidDataFormat_PCM_EX isn't available --- alc/backends/opensl.cpp | 151 +++++++++++++++++++++++++--------------- 1 file changed, 93 insertions(+), 58 deletions(-) diff --git a/alc/backends/opensl.cpp b/alc/backends/opensl.cpp index 0f1d8a21..ec32c295 100644 --- a/alc/backends/opensl.cpp +++ b/alc/backends/opensl.cpp @@ -349,10 +349,6 @@ ALCenum OpenSLPlayback::open(const ALCchar *name) bool OpenSLPlayback::reset() { - SLDataLocator_AndroidSimpleBufferQueue loc_bufq; - SLDataLocator_OutputMix loc_outmix; - SLDataSource audioSrc; - SLDataSink audioSnk; SLresult result; if(mBufferQueueObj) @@ -439,44 +435,68 @@ bool OpenSLPlayback::reset() const std::array ids{{ SL_IID_ANDROIDSIMPLEBUFFERQUEUE, SL_IID_ANDROIDCONFIGURATION }}; const std::array reqs{{ SL_BOOLEAN_TRUE, SL_BOOLEAN_FALSE }}; - loc_bufq.locatorType = SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE; - loc_bufq.numBuffers = mDevice->BufferSize / mDevice->UpdateSize; - -#ifdef SL_ANDROID_DATAFORMAT_PCM_EX - SLAndroidDataFormat_PCM_EX format_pcm{}; - format_pcm.formatType = SL_ANDROID_DATAFORMAT_PCM_EX; - format_pcm.numChannels = mDevice->channelsFromFmt(); - format_pcm.sampleRate = mDevice->Frequency * 1000; - format_pcm.bitsPerSample = mDevice->bytesFromFmt() * 8; - format_pcm.containerSize = format_pcm.bitsPerSample; - format_pcm.channelMask = GetChannelMask(mDevice->FmtChans); - format_pcm.endianness = IS_LITTLE_ENDIAN ? SL_BYTEORDER_LITTLEENDIAN : - SL_BYTEORDER_BIGENDIAN; - format_pcm.representation = GetTypeRepresentation(mDevice->FmtType); -#else - SLDataFormat_PCM format_pcm{}; - format_pcm.formatType = SL_DATAFORMAT_PCM; - format_pcm.numChannels = mDevice->channelsFromFmt(); - format_pcm.samplesPerSec = mDevice->Frequency * 1000; - format_pcm.bitsPerSample = mDevice->bytesFromFmt() * 8; - format_pcm.containerSize = format_pcm.bitsPerSample; - format_pcm.channelMask = GetChannelMask(mDevice->FmtChans); - format_pcm.endianness = IS_LITTLE_ENDIAN ? SL_BYTEORDER_LITTLEENDIAN : - SL_BYTEORDER_BIGENDIAN; -#endif - - audioSrc.pLocator = &loc_bufq; - audioSrc.pFormat = &format_pcm; - + SLDataLocator_OutputMix loc_outmix{}; loc_outmix.locatorType = SL_DATALOCATOR_OUTPUTMIX; loc_outmix.outputMix = mOutputMix; + + SLDataSink audioSnk{}; audioSnk.pLocator = &loc_outmix; audioSnk.pFormat = nullptr; + SLDataLocator_AndroidSimpleBufferQueue loc_bufq{}; + loc_bufq.locatorType = SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE; + loc_bufq.numBuffers = mDevice->BufferSize / mDevice->UpdateSize; + + SLDataSource audioSrc{}; +#ifdef SL_ANDROID_DATAFORMAT_PCM_EX + SLAndroidDataFormat_PCM_EX format_pcm_ex{}; + format_pcm_ex.formatType = SL_ANDROID_DATAFORMAT_PCM_EX; + format_pcm_ex.numChannels = mDevice->channelsFromFmt(); + format_pcm_ex.sampleRate = mDevice->Frequency * 1000; + format_pcm_ex.bitsPerSample = mDevice->bytesFromFmt() * 8; + format_pcm_ex.containerSize = format_pcm_ex.bitsPerSample; + format_pcm_ex.channelMask = GetChannelMask(mDevice->FmtChans); + format_pcm_ex.endianness = IS_LITTLE_ENDIAN ? SL_BYTEORDER_LITTLEENDIAN : SL_BYTEORDER_BIGENDIAN; + format_pcm_ex.representation = GetTypeRepresentation(mDevice->FmtType); + + audioSrc.pLocator = &loc_bufq; + audioSrc.pFormat = &format_pcm_ex; result = VCALL(mEngine,CreateAudioPlayer)(&mBufferQueueObj, &audioSrc, &audioSnk, ids.size(), ids.data(), reqs.data()); - PRINTERR(result, "engine->CreateAudioPlayer"); + if(SL_RESULT_SUCCESS != result) +#endif + { + /* Alter sample type according to what SLDataFormat_PCM can support. */ + switch(mDevice->FmtType) + { + case DevFmtByte: mDevice->FmtType = DevFmtUByte; break; + case DevFmtUInt: mDevice->FmtType = DevFmtInt; break; + case DevFmtFloat: + case DevFmtUShort: mDevice->FmtType = DevFmtShort; break; + case DevFmtUByte: + case DevFmtShort: + case DevFmtInt: + break; + } + + SLDataFormat_PCM format_pcm{}; + format_pcm.formatType = SL_DATAFORMAT_PCM; + format_pcm.numChannels = mDevice->channelsFromFmt(); + format_pcm.samplesPerSec = mDevice->Frequency * 1000; + format_pcm.bitsPerSample = mDevice->bytesFromFmt() * 8; + format_pcm.containerSize = format_pcm.bitsPerSample; + format_pcm.channelMask = GetChannelMask(mDevice->FmtChans); + format_pcm.endianness = IS_LITTLE_ENDIAN ? SL_BYTEORDER_LITTLEENDIAN : + SL_BYTEORDER_BIGENDIAN; + + audioSrc.pLocator = &loc_bufq; + audioSrc.pFormat = &format_pcm; + + result = VCALL(mEngine,CreateAudioPlayer)(&mBufferQueueObj, &audioSrc, &audioSnk, ids.size(), + ids.data(), reqs.data()); + PRINTERR(result, "engine->CreateAudioPlayer"); + } if(SL_RESULT_SUCCESS == result) { /* Set the stream type to "media" (games, music, etc), if possible. */ @@ -717,34 +737,49 @@ ALCenum OpenSLCapture::open(const ALCchar* name) loc_bq.locatorType = SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE; loc_bq.numBuffers = mDevice->BufferSize / mDevice->UpdateSize; -#ifdef SL_ANDROID_DATAFORMAT_PCM_EX - SLAndroidDataFormat_PCM_EX format_pcm{}; - format_pcm.formatType = SL_ANDROID_DATAFORMAT_PCM_EX; - format_pcm.numChannels = mDevice->channelsFromFmt(); - format_pcm.sampleRate = mDevice->Frequency * 1000; - format_pcm.bitsPerSample = mDevice->bytesFromFmt() * 8; - format_pcm.containerSize = format_pcm.bitsPerSample; - format_pcm.channelMask = GetChannelMask(mDevice->FmtChans); - format_pcm.endianness = IS_LITTLE_ENDIAN ? SL_BYTEORDER_LITTLEENDIAN : SL_BYTEORDER_BIGENDIAN; - format_pcm.representation = GetTypeRepresentation(mDevice->FmtType); -#else - SLDataFormat_PCM format_pcm{}; - format_pcm.formatType = SL_DATAFORMAT_PCM; - format_pcm.numChannels = mDevice->channelsFromFmt(); - format_pcm.samplesPerSec = mDevice->Frequency * 1000; - format_pcm.bitsPerSample = mDevice->bytesFromFmt() * 8; - format_pcm.containerSize = format_pcm.bitsPerSample; - format_pcm.channelMask = GetChannelMask(mDevice->FmtChans); - format_pcm.endianness = IS_LITTLE_ENDIAN ? SL_BYTEORDER_LITTLEENDIAN : SL_BYTEORDER_BIGENDIAN; -#endif - SLDataSink audioSnk{}; - audioSnk.pLocator = &loc_bq; - audioSnk.pFormat = &format_pcm; +#ifdef SL_ANDROID_DATAFORMAT_PCM_EX + SLAndroidDataFormat_PCM_EX format_pcm_ex{}; + format_pcm_ex.formatType = SL_ANDROID_DATAFORMAT_PCM_EX; + format_pcm_ex.numChannels = mDevice->channelsFromFmt(); + format_pcm_ex.sampleRate = mDevice->Frequency * 1000; + format_pcm_ex.bitsPerSample = mDevice->bytesFromFmt() * 8; + format_pcm_ex.containerSize = format_pcm_ex.bitsPerSample; + format_pcm_ex.channelMask = GetChannelMask(mDevice->FmtChans); + format_pcm_ex.endianness = IS_LITTLE_ENDIAN ? SL_BYTEORDER_LITTLEENDIAN : + SL_BYTEORDER_BIGENDIAN; + format_pcm_ex.representation = GetTypeRepresentation(mDevice->FmtType); + audioSnk.pLocator = &loc_bq; + audioSnk.pFormat = &format_pcm_ex; result = VCALL(mEngine,CreateAudioRecorder)(&mRecordObj, &audioSrc, &audioSnk, ids.size(), ids.data(), reqs.data()); - PRINTERR(result, "engine->CreateAudioRecorder"); + if(SL_RESULT_SUCCESS != result) +#endif + { + /* Fallback to SLDataFormat_PCM only if it supports the desired + * sample type. + */ + if(mDevice->FmtType == DevFmtUByte || mDevice->FmtType == DevFmtShort + || mDevice->FmtType == DevFmtInt) + { + SLDataFormat_PCM format_pcm{}; + format_pcm.formatType = SL_DATAFORMAT_PCM; + format_pcm.numChannels = mDevice->channelsFromFmt(); + format_pcm.samplesPerSec = mDevice->Frequency * 1000; + format_pcm.bitsPerSample = mDevice->bytesFromFmt() * 8; + format_pcm.containerSize = format_pcm.bitsPerSample; + format_pcm.channelMask = GetChannelMask(mDevice->FmtChans); + format_pcm.endianness = IS_LITTLE_ENDIAN ? SL_BYTEORDER_LITTLEENDIAN : + SL_BYTEORDER_BIGENDIAN; + + audioSnk.pLocator = &loc_bq; + audioSnk.pFormat = &format_pcm; + result = VCALL(mEngine,CreateAudioRecorder)(&mRecordObj, &audioSrc, &audioSnk, + ids.size(), ids.data(), reqs.data()); + } + PRINTERR(result, "engine->CreateAudioRecorder"); + } } if(SL_RESULT_SUCCESS == result) {