aboutsummaryrefslogtreecommitdiffstats
path: root/alc/backends
diff options
context:
space:
mode:
authorChris Robinson <[email protected]>2020-04-18 22:43:20 -0700
committerChris Robinson <[email protected]>2020-04-18 22:43:20 -0700
commit643b192fd593a473c35b44f7b8ccecbcda8b71ad (patch)
treeabfb1778e7445bc894cfb89f1d590ac9059ed0de /alc/backends
parenta387a610f8740b1a66873a37989cd5a11612209a (diff)
Try to be more robust with the Oboe format
Diffstat (limited to 'alc/backends')
-rw-r--r--alc/backends/oboe.cpp53
1 files changed, 45 insertions, 8 deletions
diff --git a/alc/backends/oboe.cpp b/alc/backends/oboe.cpp
index c999df6f..da6bb983 100644
--- a/alc/backends/oboe.cpp
+++ b/alc/backends/oboe.cpp
@@ -36,8 +36,21 @@ oboe::DataCallbackResult OboePlayback::onAudioReady(oboe::AudioStream *oboeStrea
int32_t numFrames)
{
assert(numFrames > 0);
+ const int32_t numChannels{oboeStream->getChannelCount()};
+
+ if UNLIKELY(numChannels > 2 && mDevice->FmtChans == DevFmtStereo)
+ {
+ /* If the device is only mixing stereo but there's more than two
+ * output channels, there are unused channels that need to be silenced.
+ */
+ if(mStream->getFormat() == oboe::AudioFormat::Float)
+ memset(audioData, 0, static_cast<uint32_t>(numFrames*numChannels)*sizeof(float));
+ else
+ memset(audioData, 0, static_cast<uint32_t>(numFrames*numChannels)*sizeof(int16_t));
+ }
+
aluMixData(mDevice, audioData, static_cast<uint32_t>(numFrames),
- static_cast<uint32_t>(oboeStream->getChannelCount()));
+ static_cast<uint32_t>(numChannels));
return oboe::DataCallbackResult::Continue;
}
@@ -61,21 +74,28 @@ void OboePlayback::open(const ALCchar *name)
bool OboePlayback::reset()
{
- mStream = nullptr;
-
+ oboe::AudioFormat format{oboe::AudioFormat::Unspecified};
oboe::AudioStreamBuilder builder;
builder.setDirection(oboe::Direction::Output);
builder.setPerformanceMode(oboe::PerformanceMode::LowLatency);
+ /* Let Oboe convert sample rate as needed. What is medium? Is it better to
+ * use Low or High? What am I picking here?
+ */
+ builder.setSampleRateConversionQuality(oboe::SampleRateConversionQuality::Medium);
builder.setCallback(this);
if(mDevice->Flags.get<FrequencyRequest>())
builder.setSampleRate(static_cast<int32_t>(mDevice->Frequency));
if(mDevice->Flags.get<ChannelsRequest>())
+ {
+ /* Only use mono or stereo at user request. There's no telling what
+ * other counts may be inferred as.
+ */
builder.setChannelCount((mDevice->FmtChans==DevFmtMono) ? oboe::ChannelCount::Mono
: oboe::ChannelCount::Stereo);
+ }
if(mDevice->Flags.get<SampleTypeRequest>())
{
- oboe::AudioFormat format{oboe::AudioFormat::Unspecified};
switch(mDevice->FmtType)
{
case DevFmtByte:
@@ -94,10 +114,19 @@ bool OboePlayback::reset()
}
oboe::Result result{builder.openManagedStream(mStream)};
+ if(result == oboe::Result::ErrorInvalidFormat && format == oboe::AudioFormat::Float)
+ {
+ /* If the format failed with float samples, try int16. */
+ builder.setFormat(oboe::AudioFormat::I16);
+ result = builder.openManagedStream(mStream);
+ }
if(result == oboe::Result::ErrorInvalidFormat)
{
+ /* If the format still fails, let the system pick a sample rate,
+ * channel count and sample type for us.
+ */
builder.setSampleRate(oboe::kUnspecified);
- builder.setChannelCount(oboe::ChannelCount::Stereo);
+ builder.setChannelCount(oboe::ChannelCount::Unspecified);
builder.setFormat(oboe::AudioFormat::Unspecified);
result = builder.openManagedStream(mStream);
}
@@ -113,7 +142,9 @@ bool OboePlayback::reset()
case oboe::ChannelCount::Stereo:
mDevice->FmtChans = DevFmtStereo;
break;
- /* Other potential configurations. Assume WFX channel order. */
+ /* Other potential configurations. Could be wrong, but better than failing.
+ * Assume WFX channel order.
+ */
case 4:
mDevice->FmtChans = DevFmtQuad;
break;
@@ -127,8 +158,14 @@ bool OboePlayback::reset()
mDevice->FmtChans = DevFmtX71;
break;
default:
- throw al::backend_exception{ALC_INVALID_DEVICE, "Got unhandled channel count: %d",
- mStream->getChannelCount()};
+ if(mStream->getChannelCount() < 1)
+ throw al::backend_exception{ALC_INVALID_DEVICE, "Got unhandled channel count: %d",
+ mStream->getChannelCount()};
+ /* Assume first two channels are front left/right. We can do a stereo
+ * mix and keep the other channels silent.
+ */
+ mDevice->FmtChans = DevFmtStereo;
+ break;
}
SetDefaultWFXChannelOrder(mDevice);