From 497f6961fc71e27856d24519b4b1b1b651b7f568 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Thu, 13 Jan 2011 12:32:55 -0800 Subject: [PATCH] Fixed audio buffer lifecycle and implemented audio shutdown --- .../src/org/libsdl/app/SDLActivity.java | 33 +++-- src/SDL_android.cpp | 115 ++++++++---------- src/SDL_android.h | 4 +- src/audio/android/SDL_androidaudio.c | 11 +- src/audio/android/SDL_androidaudio.h | 3 - 5 files changed, 82 insertions(+), 84 deletions(-) diff --git a/android-project/src/org/libsdl/app/SDLActivity.java b/android-project/src/org/libsdl/app/SDLActivity.java index ca5673e1a..e198156f3 100644 --- a/android-project/src/org/libsdl/app/SDLActivity.java +++ b/android-project/src/org/libsdl/app/SDLActivity.java @@ -139,7 +139,7 @@ public static void audioWriteShortBuffer(short[] buffer) { i += result; } else if (result == 0) { try { - Thread.sleep(10); + Thread.sleep(1); } catch(InterruptedException e) { // Nom nom } @@ -157,7 +157,7 @@ public static void audioWriteByteBuffer(byte[] buffer) { i += result; } else if (result == 0) { try { - Thread.sleep(10); + Thread.sleep(1); } catch(InterruptedException e) { // Nom nom } @@ -168,6 +168,23 @@ public static void audioWriteByteBuffer(byte[] buffer) { } } + public static void audioQuit() { + if (mAudioThread != null) { + try { + mAudioThread.join(); + } catch(Exception e) { + Log.v("SDL", "Problem stopping audio thread: " + e); + } + mAudioThread = null; + + Log.v("SDL", "Finished waiting for audio thread"); + } + + if (mAudioTrack != null) { + mAudioTrack.stop(); + mAudioTrack = null; + } + } } /** @@ -233,13 +250,11 @@ public void surfaceDestroyed(SurfaceHolder holder) { // Now wait for the SDL thread to quit if (mSDLThread != null) { - //synchronized (mSDLThread) { - try { - mSDLThread.join(); - } catch(Exception e) { - Log.v("SDL", "Problem stopping thread: " + e); - } - //} + try { + mSDLThread.join(); + } catch(Exception e) { + Log.v("SDL", "Problem stopping thread: " + e); + } mSDLThread = null; //Log.v("SDL", "Finished waiting for SDL thread"); diff --git a/src/SDL_android.cpp b/src/SDL_android.cpp index 506ad6835..837ec5dca 100644 --- a/src/SDL_android.cpp +++ b/src/SDL_android.cpp @@ -55,6 +55,7 @@ static jmethodID midFlipBuffers; static jmethodID midAudioInit; static jmethodID midAudioWriteShortBuffer; static jmethodID midAudioWriteByteBuffer; +static jmethodID midAudioQuit; // Accelerometer data storage float fLastAccelerometer[3]; @@ -83,13 +84,14 @@ extern "C" void SDL_Android_Init(JNIEnv* env) mActivityInstance = cls; midCreateGLContext = mEnv->GetStaticMethodID(cls,"createGLContext","()V"); midFlipBuffers = mEnv->GetStaticMethodID(cls,"flipBuffers","()V"); - midAudioInit = mEnv->GetStaticMethodID(cls, "audioInit", "(IZZI)Ljava/lang/Object;"); - midAudioWriteShortBuffer = mEnv->GetStaticMethodID(cls, "audioWriteShortBuffer", "([S)V"); - midAudioWriteByteBuffer = mEnv->GetStaticMethodID(cls, "audioWriteByteBuffer", "([B)V"); + midAudioInit = mEnv->GetStaticMethodID(cls, "audioInit", "(IZZI)Ljava/lang/Object;"); + midAudioWriteShortBuffer = mEnv->GetStaticMethodID(cls, "audioWriteShortBuffer", "([S)V"); + midAudioWriteByteBuffer = mEnv->GetStaticMethodID(cls, "audioWriteByteBuffer", "([B)V"); + midAudioQuit = mEnv->GetStaticMethodID(cls, "audioQuit", "()V"); if(!midCreateGLContext || !midFlipBuffers || !midAudioInit || - !midAudioWriteShortBuffer || !midAudioWriteByteBuffer) { - __android_log_print(ANDROID_LOG_WARN, "SDL", "SDL: Couldn't locate Java callbacks, check that they're named and typed correctly"); + !midAudioWriteShortBuffer || !midAudioWriteByteBuffer || !midAudioQuit) { + __android_log_print(ANDROID_LOG_WARN, "SDL", "SDL: Couldn't locate Java callbacks, check that they're named and typed correctly"); } } @@ -150,8 +152,8 @@ extern "C" void Java_org_libsdl_app_SDLActivity_nativeQuit( extern "C" void Java_org_libsdl_app_SDLActivity_nativeRunAudioThread( JNIEnv* env) { - mVM->AttachCurrentThread(&mAudioEnv, NULL); - Android_RunAudioThread(); + mVM->AttachCurrentThread(&mAudioEnv, NULL); + Android_RunAudioThread(); } @@ -171,78 +173,69 @@ extern "C" void Android_JNI_SwapWindow() // // Audio support // -static jint audioBufferFrames = 0; -static bool audioBuffer16Bit = false; -static bool audioBufferStereo = false; - -static jobject audioBuffer; -static void * audioPinnedBuffer; +static jboolean audioBuffer16Bit = JNI_FALSE; +static jboolean audioBufferStereo = JNI_FALSE; +static jobject audioBuffer = NULL; +static void* audioBufferPinned = NULL; extern "C" int Android_JNI_OpenAudioDevice(int sampleRate, int is16Bit, int channelCount, int desiredBufferFrames) { - __android_log_print(ANDROID_LOG_VERBOSE, "SDL", "SDL audio: opening device"); - audioBuffer16Bit = is16Bit; - audioBufferStereo = channelCount > 1; + int audioBufferFrames; - audioBuffer = mEnv->CallStaticObjectMethod(mActivityInstance, midAudioInit, sampleRate, audioBuffer16Bit, audioBufferStereo, desiredBufferFrames); - audioBuffer = mEnv->NewGlobalRef(audioBuffer); + __android_log_print(ANDROID_LOG_VERBOSE, "SDL", "SDL audio: opening device"); + audioBuffer16Bit = is16Bit; + audioBufferStereo = channelCount > 1; - if (audioBuffer == NULL) { - __android_log_print(ANDROID_LOG_WARN, "SDL", "SDL audio: didn't get back a good audio buffer!"); - return 0; - } + audioBuffer = mEnv->CallStaticObjectMethod(mActivityInstance, midAudioInit, sampleRate, audioBuffer16Bit, audioBufferStereo, desiredBufferFrames); - if (audioBufferStereo) { - audioBufferFrames = mEnv->GetArrayLength((jshortArray)audioBuffer) / 2; - } else { - audioBufferFrames = mEnv->GetArrayLength((jbyteArray)audioBuffer); - } + if (audioBuffer == NULL) { + __android_log_print(ANDROID_LOG_WARN, "SDL", "SDL audio: didn't get back a good audio buffer!"); + return 0; + } + audioBuffer = mEnv->NewGlobalRef(audioBuffer); + + jboolean isCopy = JNI_FALSE; + if (audioBuffer16Bit) { + audioBufferPinned = mEnv->GetShortArrayElements((jshortArray)audioBuffer, &isCopy); + audioBufferFrames = mEnv->GetArrayLength((jshortArray)audioBuffer); + } else { + audioBufferPinned = mEnv->GetByteArrayElements((jbyteArray)audioBuffer, &isCopy); + audioBufferFrames = mEnv->GetArrayLength((jbyteArray)audioBuffer); + } + if (audioBufferStereo) { + audioBufferFrames /= 2; + } - return audioBufferFrames; + return audioBufferFrames; } -extern "C" void * Android_JNI_PinAudioBuffer() +extern "C" void * Android_JNI_GetAudioBuffer() { - jboolean isCopy = JNI_FALSE; - - if (audioPinnedBuffer != NULL) { - return audioPinnedBuffer; - } - - if (audioBuffer16Bit) { - audioPinnedBuffer = mAudioEnv->GetShortArrayElements((jshortArray)audioBuffer, &isCopy); - } else { - audioPinnedBuffer = mAudioEnv->GetByteArrayElements((jbyteArray)audioBuffer, &isCopy); - } - - return audioPinnedBuffer; + //jboolean isCopy = JNI_FALSE; + //audioBufferPinned = mAudioEnv->GetPrimitiveArrayCritical((jarray)audioBuffer, &isCopy); + return audioBufferPinned; } -extern "C" void Android_JNI_WriteAudioBufferAndUnpin() +extern "C" void Android_JNI_WriteAudioBuffer() { - if (audioPinnedBuffer == NULL) { - return; - } - - if (audioBuffer16Bit) { - mAudioEnv->ReleaseShortArrayElements((jshortArray)audioBuffer, (jshort *)audioPinnedBuffer, JNI_COMMIT); - mAudioEnv->CallStaticVoidMethod(mActivityInstance, midAudioWriteShortBuffer, (jshortArray)audioBuffer); - } else { - mAudioEnv->ReleaseByteArrayElements((jbyteArray)audioBuffer, (jbyte *)audioPinnedBuffer, JNI_COMMIT); - mAudioEnv->CallStaticVoidMethod(mActivityInstance, midAudioWriteByteBuffer, (jbyteArray)audioBuffer); - } - - audioPinnedBuffer = NULL; + //mAudioEnv->ReleasePrimitiveArrayCritical((jarray)audioBuffer, audioBufferPinned, 0); + if (audioBuffer16Bit) { + mAudioEnv->ReleaseShortArrayElements((jshortArray)audioBuffer, (jshort *)audioBufferPinned, JNI_COMMIT); + mAudioEnv->CallStaticVoidMethod(mActivityInstance, midAudioWriteShortBuffer, (jshortArray)audioBuffer); + } else { + mAudioEnv->ReleaseByteArrayElements((jbyteArray)audioBuffer, (jbyte *)audioBufferPinned, JNI_COMMIT); + mAudioEnv->CallStaticVoidMethod(mActivityInstance, midAudioWriteByteBuffer, (jbyteArray)audioBuffer); + } + + /* JNI_COMMIT means the changes are committed to the VM but the buffer remains pinned */ } extern "C" void Android_JNI_CloseAudioDevice() { - if (audioBuffer) { - mEnv->DeleteGlobalRef(audioBuffer); - audioBuffer = NULL; - } + mEnv->CallStaticVoidMethod(mActivityInstance, midAudioQuit); - // TODO: Implement + mEnv->DeleteGlobalRef(audioBuffer); + audioBuffer = NULL; } /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/SDL_android.h b/src/SDL_android.h index ee5581bb8..ea3a487d7 100644 --- a/src/SDL_android.h +++ b/src/SDL_android.h @@ -34,8 +34,8 @@ void Android_JNI_SwapWindow(); // Audio support int Android_JNI_OpenAudioDevice(int sampleRate, int is16Bit, int channelCount, int desiredBufferFrames); -void* Android_JNI_PinAudioBuffer(); -void Android_JNI_WriteAudioBufferAndUnpin(); +void* Android_JNI_GetAudioBuffer(); +void Android_JNI_WriteAudioBuffer(); void Android_JNI_CloseAudioDevice(); /* Ends C function definitions when using C++ */ diff --git a/src/audio/android/SDL_androidaudio.c b/src/audio/android/SDL_androidaudio.c index b166cec63..5f62339da 100644 --- a/src/audio/android/SDL_androidaudio.c +++ b/src/audio/android/SDL_androidaudio.c @@ -103,26 +103,19 @@ AndroidAUD_OpenDevice(_THIS, const char *devname, int iscapture) static void AndroidAUD_PlayDevice(_THIS) { - Android_JNI_WriteAudioBufferAndUnpin(); - this->hidden->mixbuf = NULL; + Android_JNI_WriteAudioBuffer(); } static Uint8 * AndroidAUD_GetDeviceBuf(_THIS) { - if (this->hidden->mixbuf == NULL) { - this->hidden->mixbuf = Android_JNI_PinAudioBuffer(); - } - return this->hidden->mixbuf; + return Android_JNI_GetAudioBuffer(); } static void AndroidAUD_CloseDevice(_THIS) { if (this->hidden != NULL) { - if (this->hidden->mixbuf != NULL) { - Android_JNI_WriteAudioBufferAndUnpin(); - } SDL_free(this->hidden); this->hidden = NULL; } diff --git a/src/audio/android/SDL_androidaudio.h b/src/audio/android/SDL_androidaudio.h index 867d5181f..e5db41111 100644 --- a/src/audio/android/SDL_androidaudio.h +++ b/src/audio/android/SDL_androidaudio.h @@ -31,9 +31,6 @@ struct SDL_PrivateAudioData { - /* The file descriptor for the audio device */ - Uint8 *mixbuf; - Uint32 mixlen; }; #endif /* _SDL_androidaudio_h */