From c1f8b3695f8bee09a96aaac1414151aa8dd6a75d Mon Sep 17 00:00:00 2001 From: Gabriel Jacobo Date: Mon, 7 Jan 2013 12:22:26 -0300 Subject: [PATCH] Fix Audio Buffer allocation on Android >= 4.2 --- .../src/org/libsdl/app/SDLActivity.java | 9 ------- src/core/android/SDL_android.cpp | 25 ++++++++++++++++--- 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/android-project/src/org/libsdl/app/SDLActivity.java b/android-project/src/org/libsdl/app/SDLActivity.java index 2277510bb..18b3f5df3 100644 --- a/android-project/src/org/libsdl/app/SDLActivity.java +++ b/android-project/src/org/libsdl/app/SDLActivity.java @@ -353,8 +353,6 @@ public static void flipEGL() { } // Audio - private static Object buf; - public static Object audioInit(int sampleRate, boolean is16Bit, boolean isStereo, int desiredFrames) { int channelConfig = isStereo ? AudioFormat.CHANNEL_CONFIGURATION_STEREO : AudioFormat.CHANNEL_CONFIGURATION_MONO; int audioFormat = is16Bit ? AudioFormat.ENCODING_PCM_16BIT : AudioFormat.ENCODING_PCM_8BIT; @@ -373,13 +371,6 @@ public static Object audioInit(int sampleRate, boolean is16Bit, boolean isStereo audioStartThread(); Log.v("SDL", "SDL audio: got " + ((mAudioTrack.getChannelCount() >= 2) ? "stereo" : "mono") + " " + ((mAudioTrack.getAudioFormat() == AudioFormat.ENCODING_PCM_16BIT) ? "16-bit" : "8-bit") + " " + ((float)mAudioTrack.getSampleRate() / 1000f) + "kHz, " + desiredFrames + " frames buffer"); - - if (is16Bit) { - buf = new short[desiredFrames * (isStereo ? 2 : 1)]; - } else { - buf = new byte[desiredFrames * (isStereo ? 2 : 1)]; - } - return buf; } public static void audioStartThread() { diff --git a/src/core/android/SDL_android.cpp b/src/core/android/SDL_android.cpp index 3818800ab..c279f64c0 100644 --- a/src/core/android/SDL_android.cpp +++ b/src/core/android/SDL_android.cpp @@ -120,7 +120,7 @@ extern "C" void SDL_Android_Init(JNIEnv* mEnv, jclass cls) midFlipBuffers = mEnv->GetStaticMethodID(mActivityClass, "flipBuffers","()V"); midAudioInit = mEnv->GetStaticMethodID(mActivityClass, - "audioInit", "(IZZI)Ljava/lang/Object;"); + "audioInit", "(IZZI)V"); midAudioWriteShortBuffer = mEnv->GetStaticMethodID(mActivityClass, "audioWriteShortBuffer", "([S)V"); midAudioWriteByteBuffer = mEnv->GetStaticMethodID(mActivityClass, @@ -433,13 +433,30 @@ extern "C" int Android_JNI_OpenAudioDevice(int sampleRate, int is16Bit, int chan audioBuffer16Bit = is16Bit; audioBufferStereo = channelCount > 1; - audioBuffer = env->CallStaticObjectMethod(mActivityClass, midAudioInit, sampleRate, audioBuffer16Bit, audioBufferStereo, desiredBufferFrames); + env->CallStaticObjectMethod(mActivityClass, midAudioInit, sampleRate, audioBuffer16Bit, audioBufferStereo, desiredBufferFrames); + + /* Allocating the audio buffer from the Java side and passing it as the return value for audioInit no longer works on + * Android >= 4.2 due to a "stale global reference" error. So now we allocate this buffer directly from this side. */ + + if (is16Bit) { + jshortArray audioBufferLocal = env->NewShortArray(desiredBufferFrames * (audioBufferStereo ? 2 : 1)); + if (audioBufferLocal) { + audioBuffer = env->NewGlobalRef(audioBufferLocal); + env->DeleteLocalRef(audioBufferLocal); + } + } + else { + jbyteArray audioBufferLocal = env->NewByteArray(desiredBufferFrames * (audioBufferStereo ? 2 : 1)); + if (audioBufferLocal) { + audioBuffer = env->NewGlobalRef(audioBufferLocal); + env->DeleteLocalRef(audioBufferLocal); + } + } if (audioBuffer == NULL) { - __android_log_print(ANDROID_LOG_WARN, "SDL", "SDL audio: didn't get back a good audio buffer!"); + __android_log_print(ANDROID_LOG_WARN, "SDL", "SDL audio: could not allocate an audio buffer!"); return 0; } - audioBuffer = env->NewGlobalRef(audioBuffer); jboolean isCopy = JNI_FALSE; if (audioBuffer16Bit) {