# HG changeset patch # User Sam Lantinga # Date 1294950775 28800 # Node ID 8d7315668e35d2501e7147428733fab30a72dc72 # Parent 9f9bea41e88f8ff32368f5b887edcaf5c78e195f Fixed audio buffer lifecycle and implemented audio shutdown diff -r 9f9bea41e88f -r 8d7315668e35 android-project/src/org/libsdl/app/SDLActivity.java --- a/android-project/src/org/libsdl/app/SDLActivity.java Thu Jan 13 11:14:20 2011 -0800 +++ b/android-project/src/org/libsdl/app/SDLActivity.java Thu Jan 13 12:32:55 2011 -0800 @@ -139,7 +139,7 @@ i += result; } else if (result == 0) { try { - Thread.sleep(10); + Thread.sleep(1); } catch(InterruptedException e) { // Nom nom } @@ -157,7 +157,7 @@ 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 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 @@ // 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 -r 9f9bea41e88f -r 8d7315668e35 src/SDL_android.cpp --- a/src/SDL_android.cpp Thu Jan 13 11:14:20 2011 -0800 +++ b/src/SDL_android.cpp Thu Jan 13 12:32:55 2011 -0800 @@ -55,6 +55,7 @@ static jmethodID midAudioInit; static jmethodID midAudioWriteShortBuffer; static jmethodID midAudioWriteByteBuffer; +static jmethodID midAudioQuit; // Accelerometer data storage float fLastAccelerometer[3]; @@ -83,13 +84,14 @@ 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_nativeRunAudioThread( JNIEnv* env) { - mVM->AttachCurrentThread(&mAudioEnv, NULL); - Android_RunAudioThread(); + mVM->AttachCurrentThread(&mAudioEnv, NULL); + Android_RunAudioThread(); } @@ -171,78 +173,69 @@ // // 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; + + __android_log_print(ANDROID_LOG_VERBOSE, "SDL", "SDL audio: opening device"); + audioBuffer16Bit = is16Bit; + audioBufferStereo = channelCount > 1; - audioBuffer = mEnv->CallStaticObjectMethod(mActivityInstance, midAudioInit, sampleRate, audioBuffer16Bit, audioBufferStereo, desiredBufferFrames); - audioBuffer = mEnv->NewGlobalRef(audioBuffer); + audioBuffer = mEnv->CallStaticObjectMethod(mActivityInstance, midAudioInit, sampleRate, audioBuffer16Bit, audioBufferStereo, desiredBufferFrames); + + 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); - if (audioBuffer == NULL) { - __android_log_print(ANDROID_LOG_WARN, "SDL", "SDL audio: didn't get back a good audio buffer!"); - return 0; - } + 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; + } - if (audioBufferStereo) { - audioBufferFrames = mEnv->GetArrayLength((jshortArray)audioBuffer) / 2; - } else { - audioBufferFrames = mEnv->GetArrayLength((jbyteArray)audioBuffer); - } - - 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; - } + //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); + } - 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; + /* 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 -r 9f9bea41e88f -r 8d7315668e35 src/SDL_android.h --- a/src/SDL_android.h Thu Jan 13 11:14:20 2011 -0800 +++ b/src/SDL_android.h Thu Jan 13 12:32:55 2011 -0800 @@ -34,8 +34,8 @@ // 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 -r 9f9bea41e88f -r 8d7315668e35 src/audio/android/SDL_androidaudio.c --- a/src/audio/android/SDL_androidaudio.c Thu Jan 13 11:14:20 2011 -0800 +++ b/src/audio/android/SDL_androidaudio.c Thu Jan 13 12:32:55 2011 -0800 @@ -103,26 +103,19 @@ 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 -r 9f9bea41e88f -r 8d7315668e35 src/audio/android/SDL_androidaudio.h --- a/src/audio/android/SDL_androidaudio.h Thu Jan 13 11:14:20 2011 -0800 +++ b/src/audio/android/SDL_androidaudio.h Thu Jan 13 12:32:55 2011 -0800 @@ -31,9 +31,6 @@ struct SDL_PrivateAudioData { - /* The file descriptor for the audio device */ - Uint8 *mixbuf; - Uint32 mixlen; }; #endif /* _SDL_androidaudio_h */