aboutsummaryrefslogtreecommitdiff
path: root/externals/oboe/src/opensles/AudioOutputStreamOpenSLES.cpp
diff options
context:
space:
mode:
authorcrueter <crueter@eden-emu.dev>2025-08-04 04:50:14 +0200
committercrueter <crueter@eden-emu.dev>2025-08-04 04:50:14 +0200
commit51b170b470ed587f99a7c2a773e4464687f0d07a (patch)
tree4c03c510cfb17a5f5d6233df490d78f06dcfa7f7 /externals/oboe/src/opensles/AudioOutputStreamOpenSLES.cpp
parent04e5e6453875ffa5c79cdb421a29bc19985b1049 (diff)
[cmake] refactor: Use CPM over submodules (#143)
Transfers the majority of submodules and large externals to CPM, using source archives rather than full Git clones. Not only does this save massive amounts of clone and configure time, but dependencies are grabbed on-demand rather than being required by default. Additionally, CPM will (generally) automatically search for system dependencies, though certain dependencies have options to control this. Testing shows gains ranging from 5x to 10x in terms of overall clone/configure time. Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/143 Reviewed-by: CamilleLaVey <camillelavey99@gmail.com>
Diffstat (limited to 'externals/oboe/src/opensles/AudioOutputStreamOpenSLES.cpp')
-rw-r--r--externals/oboe/src/opensles/AudioOutputStreamOpenSLES.cpp457
1 files changed, 0 insertions, 457 deletions
diff --git a/externals/oboe/src/opensles/AudioOutputStreamOpenSLES.cpp b/externals/oboe/src/opensles/AudioOutputStreamOpenSLES.cpp
deleted file mode 100644
index 1b94885711..0000000000
--- a/externals/oboe/src/opensles/AudioOutputStreamOpenSLES.cpp
+++ /dev/null
@@ -1,457 +0,0 @@
-/*
- * Copyright 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <cassert>
-
-#include "common/OboeDebug.h"
-#include "oboe/AudioClock.h"
-#include "oboe/AudioStreamBuilder.h"
-#include "AudioOutputStreamOpenSLES.h"
-#include "AudioStreamOpenSLES.h"
-#include "OpenSLESUtilities.h"
-#include "OutputMixerOpenSLES.h"
-
-using namespace oboe;
-
-static SLuint32 OpenSLES_convertOutputUsage(Usage oboeUsage) {
- SLuint32 openslStream;
- switch(oboeUsage) {
- case Usage::Media:
- case Usage::Game:
- openslStream = SL_ANDROID_STREAM_MEDIA;
- break;
- case Usage::VoiceCommunication:
- case Usage::VoiceCommunicationSignalling:
- openslStream = SL_ANDROID_STREAM_VOICE;
- break;
- case Usage::Alarm:
- openslStream = SL_ANDROID_STREAM_ALARM;
- break;
- case Usage::Notification:
- case Usage::NotificationEvent:
- openslStream = SL_ANDROID_STREAM_NOTIFICATION;
- break;
- case Usage::NotificationRingtone:
- openslStream = SL_ANDROID_STREAM_RING;
- break;
- case Usage::AssistanceAccessibility:
- case Usage::AssistanceNavigationGuidance:
- case Usage::AssistanceSonification:
- case Usage::Assistant:
- default:
- openslStream = SL_ANDROID_STREAM_SYSTEM;
- break;
- }
- return openslStream;
-}
-
-AudioOutputStreamOpenSLES::AudioOutputStreamOpenSLES(const AudioStreamBuilder &builder)
- : AudioStreamOpenSLES(builder) {
-}
-
-// These will wind up in <SLES/OpenSLES_Android.h>
-constexpr int SL_ANDROID_SPEAKER_STEREO = (SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT);
-
-constexpr int SL_ANDROID_SPEAKER_QUAD = (SL_ANDROID_SPEAKER_STEREO
- | SL_SPEAKER_BACK_LEFT | SL_SPEAKER_BACK_RIGHT);
-
-constexpr int SL_ANDROID_SPEAKER_5DOT1 = (SL_ANDROID_SPEAKER_QUAD
- | SL_SPEAKER_FRONT_CENTER | SL_SPEAKER_LOW_FREQUENCY);
-
-constexpr int SL_ANDROID_SPEAKER_7DOT1 = (SL_ANDROID_SPEAKER_5DOT1 | SL_SPEAKER_SIDE_LEFT
- | SL_SPEAKER_SIDE_RIGHT);
-
-SLuint32 AudioOutputStreamOpenSLES::channelCountToChannelMask(int channelCount) const {
- SLuint32 channelMask = 0;
-
- switch (channelCount) {
- case 1:
- channelMask = SL_SPEAKER_FRONT_CENTER;
- break;
-
- case 2:
- channelMask = SL_ANDROID_SPEAKER_STEREO;
- break;
-
- case 4: // Quad
- channelMask = SL_ANDROID_SPEAKER_QUAD;
- break;
-
- case 6: // 5.1
- channelMask = SL_ANDROID_SPEAKER_5DOT1;
- break;
-
- case 8: // 7.1
- channelMask = SL_ANDROID_SPEAKER_7DOT1;
- break;
-
- default:
- channelMask = channelCountToChannelMaskDefault(channelCount);
- break;
- }
- return channelMask;
-}
-
-Result AudioOutputStreamOpenSLES::open() {
- logUnsupportedAttributes();
-
- SLAndroidConfigurationItf configItf = nullptr;
-
-
- if (getSdkVersion() < __ANDROID_API_L__ && mFormat == AudioFormat::Float){
- // TODO: Allow floating point format on API <21 using float->int16 converter
- return Result::ErrorInvalidFormat;
- }
-
- // If audio format is unspecified then choose a suitable default.
- // API 21+: FLOAT
- // API <21: INT16
- if (mFormat == AudioFormat::Unspecified){
- mFormat = (getSdkVersion() < __ANDROID_API_L__) ?
- AudioFormat::I16 : AudioFormat::Float;
- }
-
- Result oboeResult = AudioStreamOpenSLES::open();
- if (Result::OK != oboeResult) return oboeResult;
-
- SLresult result = OutputMixerOpenSL::getInstance().open();
- if (SL_RESULT_SUCCESS != result) {
- AudioStreamOpenSLES::close();
- return Result::ErrorInternal;
- }
-
- SLuint32 bitsPerSample = static_cast<SLuint32>(getBytesPerSample() * kBitsPerByte);
-
- // configure audio source
- mBufferQueueLength = calculateOptimalBufferQueueLength();
- SLDataLocator_AndroidSimpleBufferQueue loc_bufq = {
- SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, // locatorType
- static_cast<SLuint32>(mBufferQueueLength)}; // numBuffers
-
- // Define the audio data format.
- SLDataFormat_PCM format_pcm = {
- SL_DATAFORMAT_PCM, // formatType
- static_cast<SLuint32>(mChannelCount), // numChannels
- static_cast<SLuint32>(mSampleRate * kMillisPerSecond), // milliSamplesPerSec
- bitsPerSample, // mBitsPerSample
- bitsPerSample, // containerSize;
- channelCountToChannelMask(mChannelCount), // channelMask
- getDefaultByteOrder(),
- };
-
- SLDataSource audioSrc = {&loc_bufq, &format_pcm};
-
- /**
- * API 21 (Lollipop) introduced support for floating-point data representation and an extended
- * data format type: SLAndroidDataFormat_PCM_EX. If running on API 21+ use this newer format
- * type, creating it from our original format.
- */
- SLAndroidDataFormat_PCM_EX format_pcm_ex;
- if (getSdkVersion() >= __ANDROID_API_L__) {
- SLuint32 representation = OpenSLES_ConvertFormatToRepresentation(getFormat());
- // Fill in the format structure.
- format_pcm_ex = OpenSLES_createExtendedFormat(format_pcm, representation);
- // Use in place of the previous format.
- audioSrc.pFormat = &format_pcm_ex;
- }
-
- result = OutputMixerOpenSL::getInstance().createAudioPlayer(&mObjectInterface,
- &audioSrc);
- if (SL_RESULT_SUCCESS != result) {
- LOGE("createAudioPlayer() result:%s", getSLErrStr(result));
- goto error;
- }
-
- // Configure the stream.
- result = (*mObjectInterface)->GetInterface(mObjectInterface,
- EngineOpenSLES::getInstance().getIidAndroidConfiguration(),
- (void *)&configItf);
- if (SL_RESULT_SUCCESS != result) {
- LOGW("%s() GetInterface(SL_IID_ANDROIDCONFIGURATION) failed with %s",
- __func__, getSLErrStr(result));
- } else {
- result = configurePerformanceMode(configItf);
- if (SL_RESULT_SUCCESS != result) {
- goto error;
- }
-
- SLuint32 presetValue = OpenSLES_convertOutputUsage(getUsage());
- result = (*configItf)->SetConfiguration(configItf,
- SL_ANDROID_KEY_STREAM_TYPE,
- &presetValue,
- sizeof(presetValue));
- if (SL_RESULT_SUCCESS != result) {
- goto error;
- }
- }
-
- result = (*mObjectInterface)->Realize(mObjectInterface, SL_BOOLEAN_FALSE);
- if (SL_RESULT_SUCCESS != result) {
- LOGE("Realize player object result:%s", getSLErrStr(result));
- goto error;
- }
-
- result = (*mObjectInterface)->GetInterface(mObjectInterface,
- EngineOpenSLES::getInstance().getIidPlay(),
- &mPlayInterface);
- if (SL_RESULT_SUCCESS != result) {
- LOGE("GetInterface PLAY result:%s", getSLErrStr(result));
- goto error;
- }
-
- result = finishCommonOpen(configItf);
- if (SL_RESULT_SUCCESS != result) {
- goto error;
- }
-
- setState(StreamState::Open);
- return Result::OK;
-
-error:
- close(); // Clean up various OpenSL objects and prevent resource leaks.
- return Result::ErrorInternal; // TODO convert error from SLES to OBOE
-}
-
-Result AudioOutputStreamOpenSLES::onAfterDestroy() {
- OutputMixerOpenSL::getInstance().close();
- return Result::OK;
-}
-
-Result AudioOutputStreamOpenSLES::close() {
- LOGD("AudioOutputStreamOpenSLES::%s()", __func__);
- std::lock_guard<std::mutex> lock(mLock);
- Result result = Result::OK;
- if (getState() == StreamState::Closed) {
- result = Result::ErrorClosed;
- } else {
- (void) requestPause_l();
- if (OboeGlobals::areWorkaroundsEnabled()) {
- sleepBeforeClose();
- }
- // invalidate any interfaces
- mPlayInterface = nullptr;
- result = AudioStreamOpenSLES::close_l();
- }
- return result;
-}
-
-Result AudioOutputStreamOpenSLES::setPlayState_l(SLuint32 newState) {
- LOGD("AudioOutputStreamOpenSLES::%s(%d) called", __func__, newState);
- Result result = Result::OK;
-
- if (mPlayInterface == nullptr){
- LOGE("AudioOutputStreamOpenSLES::%s() mPlayInterface is null", __func__);
- return Result::ErrorInvalidState;
- }
-
- SLresult slResult = (*mPlayInterface)->SetPlayState(mPlayInterface, newState);
- if (SL_RESULT_SUCCESS != slResult) {
- LOGW("AudioOutputStreamOpenSLES(): %s() returned %s", __func__, getSLErrStr(slResult));
- result = Result::ErrorInternal; // TODO convert slResult to Result::Error
- }
- return result;
-}
-
-Result AudioOutputStreamOpenSLES::requestStart() {
- LOGD("AudioOutputStreamOpenSLES::%s() called", __func__);
-
- mLock.lock();
- StreamState initialState = getState();
- switch (initialState) {
- case StreamState::Starting:
- case StreamState::Started:
- mLock.unlock();
- return Result::OK;
- case StreamState::Closed:
- mLock.unlock();
- return Result::ErrorClosed;
- default:
- break;
- }
-
- // We use a callback if the user requests one
- // OR if we have an internal callback to read the blocking IO buffer.
- setDataCallbackEnabled(true);
-
- setState(StreamState::Starting);
- closePerformanceHint();
-
- if (getBufferDepth(mSimpleBufferQueueInterface) == 0) {
- // Enqueue the first buffer if needed to start the streaming.
- // We may need to stop the current stream.
- bool shouldStopStream = processBufferCallback(mSimpleBufferQueueInterface);
- if (shouldStopStream) {
- LOGD("Stopping the current stream.");
- if (requestStop_l() != Result::OK) {
- LOGW("Failed to flush the stream. Error %s", convertToText(flush()));
- }
- setState(initialState);
- mLock.unlock();
- return Result::ErrorClosed;
- }
- }
-
- Result result = setPlayState_l(SL_PLAYSTATE_PLAYING);
- if (result == Result::OK) {
- setState(StreamState::Started);
- mLock.unlock();
- } else {
- setState(initialState);
- mLock.unlock();
- }
- return result;
-}
-
-Result AudioOutputStreamOpenSLES::requestPause() {
- LOGD("AudioOutputStreamOpenSLES::%s() called", __func__);
- std::lock_guard<std::mutex> lock(mLock);
- return requestPause_l();
-}
-
-// Call under mLock
-Result AudioOutputStreamOpenSLES::requestPause_l() {
- StreamState initialState = getState();
- switch (initialState) {
- case StreamState::Pausing:
- case StreamState::Paused:
- return Result::OK;
- case StreamState::Uninitialized:
- case StreamState::Closed:
- return Result::ErrorClosed;
- default:
- break;
- }
-
- setState(StreamState::Pausing);
- Result result = setPlayState_l(SL_PLAYSTATE_PAUSED);
- if (result == Result::OK) {
- // Note that OpenSL ES does NOT reset its millisecond position when OUTPUT is paused.
- int64_t framesWritten = getFramesWritten();
- if (framesWritten >= 0) {
- setFramesRead(framesWritten);
- }
- setState(StreamState::Paused);
- } else {
- setState(initialState);
- }
- return result;
-}
-
-/**
- * Flush/clear the queue buffers
- */
-Result AudioOutputStreamOpenSLES::requestFlush() {
- std::lock_guard<std::mutex> lock(mLock);
- return requestFlush_l();
-}
-
-Result AudioOutputStreamOpenSLES::requestFlush_l() {
- LOGD("AudioOutputStreamOpenSLES::%s() called", __func__);
- if (getState() == StreamState::Closed) {
- return Result::ErrorClosed;
- }
-
- Result result = Result::OK;
- if (mPlayInterface == nullptr || mSimpleBufferQueueInterface == nullptr) {
- result = Result::ErrorInvalidState;
- } else {
- SLresult slResult = (*mSimpleBufferQueueInterface)->Clear(mSimpleBufferQueueInterface);
- if (slResult != SL_RESULT_SUCCESS){
- LOGW("Failed to clear buffer queue. OpenSLES error: %s", getSLErrStr(slResult));
- result = Result::ErrorInternal;
- }
- }
- return result;
-}
-
-Result AudioOutputStreamOpenSLES::requestStop() {
- std::lock_guard<std::mutex> lock(mLock);
- return requestStop_l();
-}
-
-Result AudioOutputStreamOpenSLES::requestStop_l() {
- StreamState initialState = getState();
- LOGD("AudioOutputStreamOpenSLES::%s() called, initialState = %d", __func__, initialState);
- switch (initialState) {
- case StreamState::Stopping:
- case StreamState::Stopped:
- return Result::OK;
- case StreamState::Uninitialized:
- case StreamState::Closed:
- return Result::ErrorClosed;
- default:
- break;
- }
-
- setState(StreamState::Stopping);
-
- Result result = setPlayState_l(SL_PLAYSTATE_STOPPED);
- if (result == Result::OK) {
-
- // Also clear the buffer queue so the old data won't be played if the stream is restarted.
- // Call the _l function that expects to already be under a lock.
- if (requestFlush_l() != Result::OK) {
- LOGW("Failed to flush the stream. Error %s", convertToText(flush()));
- }
-
- mPositionMillis.reset32(); // OpenSL ES resets its millisecond position when stopped.
- int64_t framesWritten = getFramesWritten();
- if (framesWritten >= 0) {
- setFramesRead(framesWritten);
- }
- setState(StreamState::Stopped);
- } else {
- setState(initialState);
- }
- return result;
-}
-
-void AudioOutputStreamOpenSLES::setFramesRead(int64_t framesRead) {
- int64_t millisWritten = framesRead * kMillisPerSecond / getSampleRate();
- mPositionMillis.set(millisWritten);
-}
-
-void AudioOutputStreamOpenSLES::updateFramesRead() {
- if (usingFIFO()) {
- AudioStreamBuffered::updateFramesRead();
- } else {
- mFramesRead = getFramesProcessedByServer();
- }
-}
-
-Result AudioOutputStreamOpenSLES::updateServiceFrameCounter() {
- Result result = Result::OK;
- // Avoid deadlock if another thread is trying to stop or close this stream
- // and this is being called from a callback.
- if (mLock.try_lock()) {
-
- if (mPlayInterface == nullptr) {
- mLock.unlock();
- return Result::ErrorNull;
- }
- SLmillisecond msec = 0;
- SLresult slResult = (*mPlayInterface)->GetPosition(mPlayInterface, &msec);
- if (SL_RESULT_SUCCESS != slResult) {
- LOGW("%s(): GetPosition() returned %s", __func__, getSLErrStr(slResult));
- // set result based on SLresult
- result = Result::ErrorInternal;
- } else {
- mPositionMillis.update32(msec);
- }
- mLock.unlock();
- }
- return result;
-}