Skip to content
This repository has been archived by the owner on Feb 11, 2021. It is now read-only.

Commit

Permalink
Fixed audio buffer lifecycle and implemented audio shutdown
Browse files Browse the repository at this point in the history
  • Loading branch information
slouken committed Jan 13, 2011
1 parent 0ac2e2a commit 497f696
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 84 deletions.
33 changes: 24 additions & 9 deletions android-project/src/org/libsdl/app/SDLActivity.java
Expand Up @@ -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
}
Expand All @@ -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
}
Expand All @@ -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;
}
}
}

/**
Expand Down Expand Up @@ -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");
Expand Down
115 changes: 54 additions & 61 deletions src/SDL_android.cpp
Expand Up @@ -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];
Expand Down Expand Up @@ -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");
}
}

Expand Down Expand Up @@ -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();
}


Expand All @@ -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: */
4 changes: 2 additions & 2 deletions src/SDL_android.h
Expand Up @@ -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++ */
Expand Down
11 changes: 2 additions & 9 deletions src/audio/android/SDL_androidaudio.c
Expand Up @@ -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;
}
Expand Down
3 changes: 0 additions & 3 deletions src/audio/android/SDL_androidaudio.h
Expand Up @@ -31,9 +31,6 @@

struct SDL_PrivateAudioData
{
/* The file descriptor for the audio device */
Uint8 *mixbuf;
Uint32 mixlen;
};

#endif /* _SDL_androidaudio_h */
Expand Down

0 comments on commit 497f696

Please sign in to comment.