Commit 5b1882ee authored by Sam Lantinga's avatar Sam Lantinga

Fixed audio buffer lifecycle and implemented audio shutdown

parent 4f9db82a
...@@ -139,7 +139,7 @@ public class SDLActivity extends Activity { ...@@ -139,7 +139,7 @@ public class SDLActivity extends Activity {
i += result; i += result;
} else if (result == 0) { } else if (result == 0) {
try { try {
Thread.sleep(10); Thread.sleep(1);
} catch(InterruptedException e) { } catch(InterruptedException e) {
// Nom nom // Nom nom
} }
...@@ -157,7 +157,7 @@ public class SDLActivity extends Activity { ...@@ -157,7 +157,7 @@ public class SDLActivity extends Activity {
i += result; i += result;
} else if (result == 0) { } else if (result == 0) {
try { try {
Thread.sleep(10); Thread.sleep(1);
} catch(InterruptedException e) { } catch(InterruptedException e) {
// Nom nom // Nom nom
} }
...@@ -168,6 +168,23 @@ public class SDLActivity extends Activity { ...@@ -168,6 +168,23 @@ public class SDLActivity extends Activity {
} }
} }
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 @@ class SDLSurface extends SurfaceView implements SurfaceHolder.Callback, ...@@ -233,13 +250,11 @@ class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
// Now wait for the SDL thread to quit // Now wait for the SDL thread to quit
if (mSDLThread != null) { if (mSDLThread != null) {
//synchronized (mSDLThread) { try {
try { mSDLThread.join();
mSDLThread.join(); } catch(Exception e) {
} catch(Exception e) { Log.v("SDL", "Problem stopping thread: " + e);
Log.v("SDL", "Problem stopping thread: " + e); }
}
//}
mSDLThread = null; mSDLThread = null;
//Log.v("SDL", "Finished waiting for SDL thread"); //Log.v("SDL", "Finished waiting for SDL thread");
......
...@@ -55,6 +55,7 @@ static jmethodID midFlipBuffers; ...@@ -55,6 +55,7 @@ static jmethodID midFlipBuffers;
static jmethodID midAudioInit; static jmethodID midAudioInit;
static jmethodID midAudioWriteShortBuffer; static jmethodID midAudioWriteShortBuffer;
static jmethodID midAudioWriteByteBuffer; static jmethodID midAudioWriteByteBuffer;
static jmethodID midAudioQuit;
// Accelerometer data storage // Accelerometer data storage
float fLastAccelerometer[3]; float fLastAccelerometer[3];
...@@ -83,13 +84,14 @@ extern "C" void SDL_Android_Init(JNIEnv* env) ...@@ -83,13 +84,14 @@ extern "C" void SDL_Android_Init(JNIEnv* env)
mActivityInstance = cls; mActivityInstance = cls;
midCreateGLContext = mEnv->GetStaticMethodID(cls,"createGLContext","()V"); midCreateGLContext = mEnv->GetStaticMethodID(cls,"createGLContext","()V");
midFlipBuffers = mEnv->GetStaticMethodID(cls,"flipBuffers","()V"); midFlipBuffers = mEnv->GetStaticMethodID(cls,"flipBuffers","()V");
midAudioInit = mEnv->GetStaticMethodID(cls, "audioInit", "(IZZI)Ljava/lang/Object;"); midAudioInit = mEnv->GetStaticMethodID(cls, "audioInit", "(IZZI)Ljava/lang/Object;");
midAudioWriteShortBuffer = mEnv->GetStaticMethodID(cls, "audioWriteShortBuffer", "([S)V"); midAudioWriteShortBuffer = mEnv->GetStaticMethodID(cls, "audioWriteShortBuffer", "([S)V");
midAudioWriteByteBuffer = mEnv->GetStaticMethodID(cls, "audioWriteByteBuffer", "([B)V"); midAudioWriteByteBuffer = mEnv->GetStaticMethodID(cls, "audioWriteByteBuffer", "([B)V");
midAudioQuit = mEnv->GetStaticMethodID(cls, "audioQuit", "()V");
if(!midCreateGLContext || !midFlipBuffers || !midAudioInit || if(!midCreateGLContext || !midFlipBuffers || !midAudioInit ||
!midAudioWriteShortBuffer || !midAudioWriteByteBuffer) { !midAudioWriteShortBuffer || !midAudioWriteByteBuffer || !midAudioQuit) {
__android_log_print(ANDROID_LOG_WARN, "SDL", "SDL: Couldn't locate Java callbacks, check that they're named and typed correctly"); __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( ...@@ -150,8 +152,8 @@ extern "C" void Java_org_libsdl_app_SDLActivity_nativeQuit(
extern "C" void Java_org_libsdl_app_SDLActivity_nativeRunAudioThread( extern "C" void Java_org_libsdl_app_SDLActivity_nativeRunAudioThread(
JNIEnv* env) JNIEnv* env)
{ {
mVM->AttachCurrentThread(&mAudioEnv, NULL); mVM->AttachCurrentThread(&mAudioEnv, NULL);
Android_RunAudioThread(); Android_RunAudioThread();
} }
...@@ -171,78 +173,69 @@ extern "C" void Android_JNI_SwapWindow() ...@@ -171,78 +173,69 @@ extern "C" void Android_JNI_SwapWindow()
// //
// Audio support // Audio support
// //
static jint audioBufferFrames = 0; static jboolean audioBuffer16Bit = JNI_FALSE;
static bool audioBuffer16Bit = false; static jboolean audioBufferStereo = JNI_FALSE;
static bool audioBufferStereo = false; static jobject audioBuffer = NULL;
static void* audioBufferPinned = NULL;
static jobject audioBuffer;
static void * audioPinnedBuffer;
extern "C" int Android_JNI_OpenAudioDevice(int sampleRate, int is16Bit, int channelCount, int desiredBufferFrames) 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"); int audioBufferFrames;
audioBuffer16Bit = is16Bit;
audioBufferStereo = channelCount > 1;
audioBuffer = mEnv->CallStaticObjectMethod(mActivityInstance, midAudioInit, sampleRate, audioBuffer16Bit, audioBufferStereo, desiredBufferFrames); __android_log_print(ANDROID_LOG_VERBOSE, "SDL", "SDL audio: opening device");
audioBuffer = mEnv->NewGlobalRef(audioBuffer); audioBuffer16Bit = is16Bit;
audioBufferStereo = channelCount > 1;
if (audioBuffer == NULL) { audioBuffer = mEnv->CallStaticObjectMethod(mActivityInstance, midAudioInit, sampleRate, audioBuffer16Bit, audioBufferStereo, desiredBufferFrames);
__android_log_print(ANDROID_LOG_WARN, "SDL", "SDL audio: didn't get back a good audio buffer!");
return 0;
}
if (audioBufferStereo) { if (audioBuffer == NULL) {
audioBufferFrames = mEnv->GetArrayLength((jshortArray)audioBuffer) / 2; __android_log_print(ANDROID_LOG_WARN, "SDL", "SDL audio: didn't get back a good audio buffer!");
} else { return 0;
audioBufferFrames = mEnv->GetArrayLength((jbyteArray)audioBuffer); }
} 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; //jboolean isCopy = JNI_FALSE;
//audioBufferPinned = mAudioEnv->GetPrimitiveArrayCritical((jarray)audioBuffer, &isCopy);
if (audioPinnedBuffer != NULL) { return audioBufferPinned;
return audioPinnedBuffer;
}
if (audioBuffer16Bit) {
audioPinnedBuffer = mAudioEnv->GetShortArrayElements((jshortArray)audioBuffer, &isCopy);
} else {
audioPinnedBuffer = mAudioEnv->GetByteArrayElements((jbyteArray)audioBuffer, &isCopy);
}
return audioPinnedBuffer;
} }
extern "C" void Android_JNI_WriteAudioBufferAndUnpin() extern "C" void Android_JNI_WriteAudioBuffer()
{ {
if (audioPinnedBuffer == NULL) { //mAudioEnv->ReleasePrimitiveArrayCritical((jarray)audioBuffer, audioBufferPinned, 0);
return; if (audioBuffer16Bit) {
} mAudioEnv->ReleaseShortArrayElements((jshortArray)audioBuffer, (jshort *)audioBufferPinned, JNI_COMMIT);
mAudioEnv->CallStaticVoidMethod(mActivityInstance, midAudioWriteShortBuffer, (jshortArray)audioBuffer);
if (audioBuffer16Bit) { } else {
mAudioEnv->ReleaseShortArrayElements((jshortArray)audioBuffer, (jshort *)audioPinnedBuffer, JNI_COMMIT); mAudioEnv->ReleaseByteArrayElements((jbyteArray)audioBuffer, (jbyte *)audioBufferPinned, JNI_COMMIT);
mAudioEnv->CallStaticVoidMethod(mActivityInstance, midAudioWriteShortBuffer, (jshortArray)audioBuffer); mAudioEnv->CallStaticVoidMethod(mActivityInstance, midAudioWriteByteBuffer, (jbyteArray)audioBuffer);
} else { }
mAudioEnv->ReleaseByteArrayElements((jbyteArray)audioBuffer, (jbyte *)audioPinnedBuffer, JNI_COMMIT);
mAudioEnv->CallStaticVoidMethod(mActivityInstance, midAudioWriteByteBuffer, (jbyteArray)audioBuffer); /* JNI_COMMIT means the changes are committed to the VM but the buffer remains pinned */
}
audioPinnedBuffer = NULL;
} }
extern "C" void Android_JNI_CloseAudioDevice() extern "C" void Android_JNI_CloseAudioDevice()
{ {
if (audioBuffer) { mEnv->CallStaticVoidMethod(mActivityInstance, midAudioQuit);
mEnv->DeleteGlobalRef(audioBuffer);
audioBuffer = NULL;
}
// TODO: Implement mEnv->DeleteGlobalRef(audioBuffer);
audioBuffer = NULL;
} }
/* vi: set ts=4 sw=4 expandtab: */ /* vi: set ts=4 sw=4 expandtab: */
...@@ -34,8 +34,8 @@ void Android_JNI_SwapWindow(); ...@@ -34,8 +34,8 @@ void Android_JNI_SwapWindow();
// Audio support // Audio support
int Android_JNI_OpenAudioDevice(int sampleRate, int is16Bit, int channelCount, int desiredBufferFrames); int Android_JNI_OpenAudioDevice(int sampleRate, int is16Bit, int channelCount, int desiredBufferFrames);
void* Android_JNI_PinAudioBuffer(); void* Android_JNI_GetAudioBuffer();
void Android_JNI_WriteAudioBufferAndUnpin(); void Android_JNI_WriteAudioBuffer();
void Android_JNI_CloseAudioDevice(); void Android_JNI_CloseAudioDevice();
/* Ends C function definitions when using C++ */ /* Ends C function definitions when using C++ */
......
...@@ -103,26 +103,19 @@ AndroidAUD_OpenDevice(_THIS, const char *devname, int iscapture) ...@@ -103,26 +103,19 @@ AndroidAUD_OpenDevice(_THIS, const char *devname, int iscapture)
static void static void
AndroidAUD_PlayDevice(_THIS) AndroidAUD_PlayDevice(_THIS)
{ {
Android_JNI_WriteAudioBufferAndUnpin(); Android_JNI_WriteAudioBuffer();
this->hidden->mixbuf = NULL;
} }
static Uint8 * static Uint8 *
AndroidAUD_GetDeviceBuf(_THIS) AndroidAUD_GetDeviceBuf(_THIS)
{ {
if (this->hidden->mixbuf == NULL) { return Android_JNI_GetAudioBuffer();
this->hidden->mixbuf = Android_JNI_PinAudioBuffer();
}
return this->hidden->mixbuf;
} }
static void static void
AndroidAUD_CloseDevice(_THIS) AndroidAUD_CloseDevice(_THIS)
{ {
if (this->hidden != NULL) { if (this->hidden != NULL) {
if (this->hidden->mixbuf != NULL) {
Android_JNI_WriteAudioBufferAndUnpin();
}
SDL_free(this->hidden); SDL_free(this->hidden);
this->hidden = NULL; this->hidden = NULL;
} }
......
...@@ -31,9 +31,6 @@ ...@@ -31,9 +31,6 @@
struct SDL_PrivateAudioData struct SDL_PrivateAudioData
{ {
/* The file descriptor for the audio device */
Uint8 *mixbuf;
Uint32 mixlen;
}; };
#endif /* _SDL_androidaudio_h */ #endif /* _SDL_androidaudio_h */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment