Fixed audio buffer lifecycle and implemented audio shutdown
authorSam Lantinga <slouken@libsdl.org>
Thu, 13 Jan 2011 12:32:55 -0800
changeset 4996 8d7315668e35
parent 4995 9f9bea41e88f
child 4997 a21501393bef
Fixed audio buffer lifecycle and implemented audio shutdown
android-project/src/org/libsdl/app/SDLActivity.java
src/SDL_android.cpp
src/SDL_android.h
src/audio/android/SDL_androidaudio.c
src/audio/android/SDL_androidaudio.h
--- 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");
--- 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: */
--- 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++ */
--- 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;
     }
--- 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 */