Fixed audio buffer lifecycle and implemented audio shutdown
This commit is contained in:
parent
4f9db82a4c
commit
5b1882ee17
5 changed files with 81 additions and 83 deletions
|
@ -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 {
|
||||||
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 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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,
|
||||||
|
|
||||||
// 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;
|
||||||
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];
|
||||||
|
@ -86,9 +87,10 @@ extern "C" void SDL_Android_Init(JNIEnv* env)
|
||||||
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");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
{
|
{
|
||||||
|
int audioBufferFrames;
|
||||||
|
|
||||||
__android_log_print(ANDROID_LOG_VERBOSE, "SDL", "SDL audio: opening device");
|
__android_log_print(ANDROID_LOG_VERBOSE, "SDL", "SDL audio: opening device");
|
||||||
audioBuffer16Bit = is16Bit;
|
audioBuffer16Bit = is16Bit;
|
||||||
audioBufferStereo = channelCount > 1;
|
audioBufferStereo = channelCount > 1;
|
||||||
|
|
||||||
audioBuffer = mEnv->CallStaticObjectMethod(mActivityInstance, midAudioInit, sampleRate, audioBuffer16Bit, audioBufferStereo, desiredBufferFrames);
|
audioBuffer = mEnv->CallStaticObjectMethod(mActivityInstance, midAudioInit, sampleRate, audioBuffer16Bit, audioBufferStereo, desiredBufferFrames);
|
||||||
audioBuffer = mEnv->NewGlobalRef(audioBuffer);
|
|
||||||
|
|
||||||
if (audioBuffer == NULL) {
|
if (audioBuffer == NULL) {
|
||||||
__android_log_print(ANDROID_LOG_WARN, "SDL", "SDL audio: didn't get back a good audio buffer!");
|
__android_log_print(ANDROID_LOG_WARN, "SDL", "SDL audio: didn't get back a good audio buffer!");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
audioBuffer = mEnv->NewGlobalRef(audioBuffer);
|
||||||
|
|
||||||
if (audioBufferStereo) {
|
jboolean isCopy = JNI_FALSE;
|
||||||
audioBufferFrames = mEnv->GetArrayLength((jshortArray)audioBuffer) / 2;
|
if (audioBuffer16Bit) {
|
||||||
|
audioBufferPinned = mEnv->GetShortArrayElements((jshortArray)audioBuffer, &isCopy);
|
||||||
|
audioBufferFrames = mEnv->GetArrayLength((jshortArray)audioBuffer);
|
||||||
} else {
|
} else {
|
||||||
|
audioBufferPinned = mEnv->GetByteArrayElements((jbyteArray)audioBuffer, &isCopy);
|
||||||
audioBufferFrames = mEnv->GetArrayLength((jbyteArray)audioBuffer);
|
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) {
|
extern "C" void Android_JNI_WriteAudioBuffer()
|
||||||
audioPinnedBuffer = mAudioEnv->GetShortArrayElements((jshortArray)audioBuffer, &isCopy);
|
|
||||||
} else {
|
|
||||||
audioPinnedBuffer = mAudioEnv->GetByteArrayElements((jbyteArray)audioBuffer, &isCopy);
|
|
||||||
}
|
|
||||||
|
|
||||||
return audioPinnedBuffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" void Android_JNI_WriteAudioBufferAndUnpin()
|
|
||||||
{
|
{
|
||||||
if (audioPinnedBuffer == NULL) {
|
//mAudioEnv->ReleasePrimitiveArrayCritical((jarray)audioBuffer, audioBufferPinned, 0);
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (audioBuffer16Bit) {
|
if (audioBuffer16Bit) {
|
||||||
mAudioEnv->ReleaseShortArrayElements((jshortArray)audioBuffer, (jshort *)audioPinnedBuffer, JNI_COMMIT);
|
mAudioEnv->ReleaseShortArrayElements((jshortArray)audioBuffer, (jshort *)audioBufferPinned, JNI_COMMIT);
|
||||||
mAudioEnv->CallStaticVoidMethod(mActivityInstance, midAudioWriteShortBuffer, (jshortArray)audioBuffer);
|
mAudioEnv->CallStaticVoidMethod(mActivityInstance, midAudioWriteShortBuffer, (jshortArray)audioBuffer);
|
||||||
} else {
|
} else {
|
||||||
mAudioEnv->ReleaseByteArrayElements((jbyteArray)audioBuffer, (jbyte *)audioPinnedBuffer, JNI_COMMIT);
|
mAudioEnv->ReleaseByteArrayElements((jbyteArray)audioBuffer, (jbyte *)audioBufferPinned, JNI_COMMIT);
|
||||||
mAudioEnv->CallStaticVoidMethod(mActivityInstance, midAudioWriteByteBuffer, (jbyteArray)audioBuffer);
|
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()
|
extern "C" void Android_JNI_CloseAudioDevice()
|
||||||
{
|
{
|
||||||
if (audioBuffer) {
|
mEnv->CallStaticVoidMethod(mActivityInstance, midAudioQuit);
|
||||||
|
|
||||||
mEnv->DeleteGlobalRef(audioBuffer);
|
mEnv->DeleteGlobalRef(audioBuffer);
|
||||||
audioBuffer = NULL;
|
audioBuffer = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Implement
|
|
||||||
}
|
|
||||||
|
|
||||||
/* vi: set ts=4 sw=4 expandtab: */
|
/* vi: set ts=4 sw=4 expandtab: */
|
||||||
|
|
|
@ -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)
|
||||||
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 @@
|
||||||
|
|
||||||
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 */
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue