diff --git a/CMakeLists.txt b/CMakeLists.txt index 8d4157062c..2b07111e86 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -730,10 +730,10 @@ if(ANDROID) android/jni/AndroidVulkanContext.cpp android/jni/AndroidVulkanContext.h android/jni/AndroidGraphicsContext.h - android/jni/native_audio.cpp - android/jni/native_audio.h - android/jni/native-audio-so.cpp - android/jni/native-audio-so.h + android/jni/AndroidAudio.cpp + android/jni/AndroidAudio.h + android/jni/OpenSLContext.cpp + android/jni/OpenSLContext.h ) # No target elseif(IOS) diff --git a/Windows/PPSSPP.vcxproj b/Windows/PPSSPP.vcxproj index ed8abc3a30..def7547093 100644 --- a/Windows/PPSSPP.vcxproj +++ b/Windows/PPSSPP.vcxproj @@ -600,7 +600,7 @@ true true - + true true true @@ -610,7 +610,7 @@ true true - + true true true @@ -1028,7 +1028,7 @@ - + true true true @@ -1038,7 +1038,7 @@ true true - + true true true diff --git a/Windows/PPSSPP.vcxproj.filters b/Windows/PPSSPP.vcxproj.filters index 451be96f95..ffbdc51429 100644 --- a/Windows/PPSSPP.vcxproj.filters +++ b/Windows/PPSSPP.vcxproj.filters @@ -205,12 +205,6 @@ Other Platforms\Android - - Other Platforms\Android - - - Other Platforms\Android - Other Platforms\iOS @@ -271,6 +265,12 @@ Other Platforms\UWP + + Other Platforms\Android + + + Other Platforms\Android + @@ -430,12 +430,6 @@ Other Platforms\Android - - Other Platforms\Android - - - Other Platforms\Android - Other Platforms\iOS @@ -538,6 +532,12 @@ Other Platforms\UWP + + Other Platforms\Android + + + Other Platforms\Android + diff --git a/android/jni/Android.mk b/android/jni/Android.mk index 510c6a0a1d..3df8536529 100644 --- a/android/jni/Android.mk +++ b/android/jni/Android.mk @@ -499,8 +499,8 @@ LOCAL_SRC_FILES := \ $(SRC)/android/jni/AndroidEGLContext.cpp \ $(SRC)/android/jni/AndroidJavaGLContext.cpp \ $(SRC)/android/jni/AndroidVulkanContext.cpp \ - $(SRC)/android/jni/native_audio.cpp \ - $(SRC)/android/jni/native-audio-so.cpp \ + $(SRC)/android/jni/AndroidAudio.cpp \ + $(SRC)/android/jni/OpenSLContext.cpp \ $(SRC)/UI/BackgroundAudio.cpp \ $(SRC)/UI/DiscordIntegration.cpp \ $(SRC)/UI/ChatScreen.cpp \ diff --git a/android/jni/native_audio.cpp b/android/jni/AndroidAudio.cpp similarity index 79% rename from android/jni/native_audio.cpp rename to android/jni/AndroidAudio.cpp index a06159a89c..98cf3a87be 100644 --- a/android/jni/native_audio.cpp +++ b/android/jni/AndroidAudio.cpp @@ -1,6 +1,18 @@ #include "base/logging.h" -#include "android/jni/native_audio.h" -#include "android/jni/native-audio-so.h" +#include "android/jni/AndroidAudio.h" +#include "android/jni/OpenSLContext.h" + +AudioContext::AudioContext(AndroidAudioCallback cb, int _FramesPerBuffer, int _SampleRate) + : audioCallback(cb), framesPerBuffer(_FramesPerBuffer), sampleRate(_SampleRate) { + if (framesPerBuffer == 0) + framesPerBuffer = 256; + if (framesPerBuffer < 32) + framesPerBuffer = 32; + if (framesPerBuffer > 4096) + framesPerBuffer = 4096; + + sampleRate = _SampleRate; +} struct AndroidAudioState { AudioContext *ctx = nullptr; diff --git a/android/jni/native_audio.h b/android/jni/AndroidAudio.h similarity index 55% rename from android/jni/native_audio.h rename to android/jni/AndroidAudio.h index 427f29ca36..a3d1ab8ee8 100644 --- a/android/jni/native_audio.h +++ b/android/jni/AndroidAudio.h @@ -1,8 +1,22 @@ #pragma once -#include "native-audio-so.h" #include +typedef int (*AndroidAudioCallback)(short *buffer, int num_samples); + +class AudioContext { +public: + AudioContext(AndroidAudioCallback cb, int _FramesPerBuffer, int _SampleRate); + virtual bool Init() { return false; } + virtual ~AudioContext() {} + +protected: + AndroidAudioCallback audioCallback; + + int framesPerBuffer; + int sampleRate; +}; + struct AndroidAudioState; // It's okay for optimalFramesPerBuffer and optimalSampleRate to be 0. Defaults will be used. diff --git a/android/jni/native-audio-so.cpp b/android/jni/OpenSLContext.cpp similarity index 80% rename from android/jni/native-audio-so.cpp rename to android/jni/OpenSLContext.cpp index 17e665d2de..26965a72d5 100644 --- a/android/jni/native-audio-so.cpp +++ b/android/jni/OpenSLContext.cpp @@ -2,8 +2,7 @@ // // Loosely based on the Android NDK sample code. -#include -#include +#include #include // for native audio @@ -11,19 +10,8 @@ #include #include "base/logging.h" -#include "native-audio-so.h" - -AudioContext::AudioContext(AndroidAudioCallback cb, int _FramesPerBuffer, int _SampleRate) - : audioCallback(cb), framesPerBuffer(_FramesPerBuffer), sampleRate(_SampleRate) { - if (framesPerBuffer == 0) - framesPerBuffer = 256; - if (framesPerBuffer < 32) - framesPerBuffer = 32; - if (framesPerBuffer > 4096) - framesPerBuffer = 4096; - - sampleRate = _SampleRate; -} +#include "Common/Log.h" +#include "OpenSLContext.h" // This callback handler is called every time a buffer finishes playing. // The documentation available is very unclear about how to best manage buffers. @@ -36,7 +24,7 @@ void OpenSLContext::bqPlayerCallbackWrap(SLAndroidSimpleBufferQueueItf bq, void void OpenSLContext::BqPlayerCallback(SLAndroidSimpleBufferQueueItf bq) { if (bq != bqPlayerBufferQueue) { - ELOG("Wrong bq!"); + ELOG("OpenSL: Wrong bq!"); return; } @@ -53,7 +41,7 @@ void OpenSLContext::BqPlayerCallback(SLAndroidSimpleBufferQueueItf bq) { // the most likely other result is SL_RESULT_BUFFER_INSUFFICIENT, // which for this code example would indicate a programming error if (result != SL_RESULT_SUCCESS) { - ELOG("OpenSL ES: Failed to enqueue! %i %i", renderedFrames, sizeInBytes); + ELOG("OpenSL: Failed to enqueue! %i %i", renderedFrames, sizeInBytes); } curBuffer += 1; // Switch buffer @@ -70,24 +58,26 @@ bool OpenSLContext::Init() { // create engine result = slCreateEngine(&engineObject, 0, NULL, 0, NULL, NULL); if (result != SL_RESULT_SUCCESS) { - ELOG("OpenSL ES: Failed to create the engine: %d", (int)result); + ELOG("OpenSL: Failed to create the engine: %d", (int)result); engineObject = nullptr; return false; } result = (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE); - assert(SL_RESULT_SUCCESS == result); + _assert_(SL_RESULT_SUCCESS == result); + result = (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineEngine); - assert(SL_RESULT_SUCCESS == result); + _assert_(SL_RESULT_SUCCESS == result); + result = (*engineEngine)->CreateOutputMix(engineEngine, &outputMixObject, 0, 0, 0); if (result != SL_RESULT_SUCCESS) { - ELOG("OpenSL ES: Failed to create output mix: %d", (int)result); + ELOG("OpenSL: Failed to create output mix: %d", (int)result); (*engineObject)->Destroy(engineObject); engineEngine = nullptr; engineObject = nullptr; return false; } result = (*outputMixObject)->Realize(outputMixObject, SL_BOOLEAN_FALSE); - assert(SL_RESULT_SUCCESS == result); + _assert_(SL_RESULT_SUCCESS == result); // The constants, such as SL_SAMPLINGRATE_44_1, are just 44100000. SLuint32 sr = (SLuint32)sampleRate * 1000; @@ -114,7 +104,7 @@ bool OpenSLContext::Init() { const SLboolean req[2] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE}; result = (*engineEngine)->CreateAudioPlayer(engineEngine, &bqPlayerObject, &audioSrc, &audioSnk, 2, ids, req); if (result != SL_RESULT_SUCCESS) { - ELOG("OpenSL ES: CreateAudioPlayer failed: %d", (int)result); + ELOG("OpenSL: CreateAudioPlayer failed: %d", (int)result); (*outputMixObject)->Destroy(outputMixObject); outputMixObject = nullptr; @@ -126,18 +116,18 @@ bool OpenSLContext::Init() { } result = (*bqPlayerObject)->Realize(bqPlayerObject, SL_BOOLEAN_FALSE); - assert(SL_RESULT_SUCCESS == result); + _assert_(SL_RESULT_SUCCESS == result); result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_PLAY, &bqPlayerPlay); - assert(SL_RESULT_SUCCESS == result); + _assert_(SL_RESULT_SUCCESS == result); result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_BUFFERQUEUE, &bqPlayerBufferQueue); - assert(SL_RESULT_SUCCESS == result); + _assert_(SL_RESULT_SUCCESS == result); result = (*bqPlayerBufferQueue)->RegisterCallback(bqPlayerBufferQueue, &bqPlayerCallbackWrap, this); - assert(SL_RESULT_SUCCESS == result); + _assert_(SL_RESULT_SUCCESS == result); result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_VOLUME, &bqPlayerVolume); - assert(SL_RESULT_SUCCESS == result); + _assert_(SL_RESULT_SUCCESS == result); result = (*bqPlayerPlay)->SetPlayState(bqPlayerPlay, SL_PLAYSTATE_PLAYING); - assert(SL_RESULT_SUCCESS == result); + _assert_(SL_RESULT_SUCCESS == result); // Allocate and enqueue N empty buffers. for (int i = 0; i < NUM_BUFFERS; i++) { @@ -159,7 +149,7 @@ bool OpenSLContext::Init() { // shut down the native audio system OpenSLContext::~OpenSLContext() { if (bqPlayerPlay) { - ILOG("OpenSLWrap_Shutdown - stopping playback"); + ILOG("OpenSL: Shutdown - stopping playback"); SLresult result; result = (*bqPlayerPlay)->SetPlayState(bqPlayerPlay, SL_PLAYSTATE_STOPPED); if (SL_RESULT_SUCCESS != result) { @@ -167,7 +157,7 @@ OpenSLContext::~OpenSLContext() { } } - ILOG("OpenSLWrap_Shutdown - deleting player object"); + ILOG("OpenSL: Shutdown - deleting player object"); if (bqPlayerObject) { (*bqPlayerObject)->Destroy(bqPlayerObject); @@ -177,14 +167,14 @@ OpenSLContext::~OpenSLContext() { bqPlayerVolume = nullptr; } - ILOG("OpenSLWrap_Shutdown - deleting mix object"); + ILOG("OpenSL: Shutdown - deleting mix object"); if (outputMixObject) { (*outputMixObject)->Destroy(outputMixObject); outputMixObject = nullptr; } - ILOG("OpenSLWrap_Shutdown - deleting engine object"); + ILOG("OpenSL: Shutdown - deleting engine object"); if (engineObject) { (*engineObject)->Destroy(engineObject); @@ -196,6 +186,6 @@ OpenSLContext::~OpenSLContext() { delete[] buffer[i]; buffer[i] = nullptr; } - ILOG("OpenSLWrap_Shutdown - finished"); + ILOG("OpenSL: Shutdown - finished"); } diff --git a/android/jni/native-audio-so.h b/android/jni/OpenSLContext.h similarity index 73% rename from android/jni/native-audio-so.h rename to android/jni/OpenSLContext.h index 9623e51709..3705f66b82 100644 --- a/android/jni/native-audio-so.h +++ b/android/jni/OpenSLContext.h @@ -3,20 +3,7 @@ #include #include -typedef int (*AndroidAudioCallback)(short *buffer, int num_samples); - -class AudioContext { -public: - AudioContext(AndroidAudioCallback cb, int _FramesPerBuffer, int _SampleRate); - virtual bool Init() { return false; } - virtual ~AudioContext() {} - -protected: - AndroidAudioCallback audioCallback; - - int framesPerBuffer; - int sampleRate; -}; +#include "AndroidAudio.h" class OpenSLContext : public AudioContext { public: diff --git a/android/jni/app-android.cpp b/android/jni/app-android.cpp index 1fafbf5de4..85acaf674f 100644 --- a/android/jni/app-android.cpp +++ b/android/jni/app-android.cpp @@ -63,7 +63,7 @@ struct JNIEnv {}; #include "math/math_util.h" #include "net/resolve.h" #include "util/text/parsers.h" -#include "android/jni/native_audio.h" +#include "android/jni/AndroidAudio.h" #include "gfx/gl_common.h" #include "gfx_es2/gpu_features.h" diff --git a/android/src/org/ppsspp/ppsspp/NativeActivity.java b/android/src/org/ppsspp/ppsspp/NativeActivity.java index 386ed3870f..a06d47fe59 100644 --- a/android/src/org/ppsspp/ppsspp/NativeActivity.java +++ b/android/src/org/ppsspp/ppsspp/NativeActivity.java @@ -630,19 +630,22 @@ public abstract class NativeActivity extends Activity { } Log.i(TAG, "onDestroy"); mGLSurfaceView.onDestroy(); - // Probably vain attempt to help the garbage collector... mGLSurfaceView = null; - audioFocusChangeListener = null; - audioManager = null; } else { mSurfaceView.onDestroy(); mSurfaceView = null; } + + // Probably vain attempt to help the garbage collector... + audioFocusChangeListener = null; + audioManager = null; + sizeManager.setSurfaceView(null); if (mPowerSaveModeReceiver != null) { mPowerSaveModeReceiver.destroy(this); mPowerSaveModeReceiver = null; } + // TODO: Can we ensure that the GL thread has stopped rendering here? // I've seen crashes that seem to indicate that sometimes it hasn't... NativeApp.audioShutdown(); @@ -697,6 +700,7 @@ public abstract class NativeActivity extends Activity { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { updateSystemUiVisibility(); } + // OK, config should be initialized, we can query for screen rotation. if (javaGL || Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) { updateScreenRotation("onResume");