Fixed audio buffer lifecycle and implemented audio shutdown
authorSam Lantinga
Thu, 13 Jan 2011 12:32:55 -0800
changeset 49968d7315668e35
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
     1.1 --- a/android-project/src/org/libsdl/app/SDLActivity.java	Thu Jan 13 11:14:20 2011 -0800
     1.2 +++ b/android-project/src/org/libsdl/app/SDLActivity.java	Thu Jan 13 12:32:55 2011 -0800
     1.3 @@ -139,7 +139,7 @@
     1.4                  i += result;
     1.5              } else if (result == 0) {
     1.6                  try {
     1.7 -                    Thread.sleep(10);
     1.8 +                    Thread.sleep(1);
     1.9                  } catch(InterruptedException e) {
    1.10                      // Nom nom
    1.11                  }
    1.12 @@ -157,7 +157,7 @@
    1.13                  i += result;
    1.14              } else if (result == 0) {
    1.15                  try {
    1.16 -                    Thread.sleep(10);
    1.17 +                    Thread.sleep(1);
    1.18                  } catch(InterruptedException e) {
    1.19                      // Nom nom
    1.20                  }
    1.21 @@ -168,6 +168,23 @@
    1.22          }
    1.23      }
    1.24  
    1.25 +    public static void audioQuit() {
    1.26 +        if (mAudioThread != null) {
    1.27 +            try {
    1.28 +                mAudioThread.join();
    1.29 +            } catch(Exception e) {
    1.30 +                Log.v("SDL", "Problem stopping audio thread: " + e);
    1.31 +            }
    1.32 +            mAudioThread = null;
    1.33 +
    1.34 +            Log.v("SDL", "Finished waiting for audio thread");
    1.35 +        }
    1.36 +
    1.37 +        if (mAudioTrack != null) {
    1.38 +            mAudioTrack.stop();
    1.39 +            mAudioTrack = null;
    1.40 +        }
    1.41 +    }
    1.42  }
    1.43  
    1.44  /**
    1.45 @@ -233,13 +250,11 @@
    1.46  
    1.47          // Now wait for the SDL thread to quit
    1.48          if (mSDLThread != null) {
    1.49 -            //synchronized (mSDLThread) {
    1.50 -                try {
    1.51 -                    mSDLThread.join();
    1.52 -                } catch(Exception e) {
    1.53 -                    Log.v("SDL", "Problem stopping thread: " + e);
    1.54 -                }
    1.55 -            //}
    1.56 +            try {
    1.57 +                mSDLThread.join();
    1.58 +            } catch(Exception e) {
    1.59 +                Log.v("SDL", "Problem stopping thread: " + e);
    1.60 +            }
    1.61              mSDLThread = null;
    1.62  
    1.63              //Log.v("SDL", "Finished waiting for SDL thread");
     2.1 --- a/src/SDL_android.cpp	Thu Jan 13 11:14:20 2011 -0800
     2.2 +++ b/src/SDL_android.cpp	Thu Jan 13 12:32:55 2011 -0800
     2.3 @@ -55,6 +55,7 @@
     2.4  static jmethodID midAudioInit;
     2.5  static jmethodID midAudioWriteShortBuffer;
     2.6  static jmethodID midAudioWriteByteBuffer;
     2.7 +static jmethodID midAudioQuit;
     2.8  
     2.9  // Accelerometer data storage
    2.10  float fLastAccelerometer[3];
    2.11 @@ -83,13 +84,14 @@
    2.12      mActivityInstance = cls;
    2.13      midCreateGLContext = mEnv->GetStaticMethodID(cls,"createGLContext","()V");
    2.14      midFlipBuffers = mEnv->GetStaticMethodID(cls,"flipBuffers","()V");
    2.15 -	midAudioInit = mEnv->GetStaticMethodID(cls, "audioInit", "(IZZI)Ljava/lang/Object;");
    2.16 -	midAudioWriteShortBuffer = mEnv->GetStaticMethodID(cls, "audioWriteShortBuffer", "([S)V");
    2.17 -	midAudioWriteByteBuffer = mEnv->GetStaticMethodID(cls, "audioWriteByteBuffer", "([B)V");
    2.18 +    midAudioInit = mEnv->GetStaticMethodID(cls, "audioInit", "(IZZI)Ljava/lang/Object;");
    2.19 +    midAudioWriteShortBuffer = mEnv->GetStaticMethodID(cls, "audioWriteShortBuffer", "([S)V");
    2.20 +    midAudioWriteByteBuffer = mEnv->GetStaticMethodID(cls, "audioWriteByteBuffer", "([B)V");
    2.21 +    midAudioQuit = mEnv->GetStaticMethodID(cls, "audioQuit", "()V");
    2.22  
    2.23      if(!midCreateGLContext || !midFlipBuffers || !midAudioInit ||
    2.24 -       !midAudioWriteShortBuffer || !midAudioWriteByteBuffer) {
    2.25 -		__android_log_print(ANDROID_LOG_WARN, "SDL", "SDL: Couldn't locate Java callbacks, check that they're named and typed correctly");
    2.26 +       !midAudioWriteShortBuffer || !midAudioWriteByteBuffer || !midAudioQuit) {
    2.27 +        __android_log_print(ANDROID_LOG_WARN, "SDL", "SDL: Couldn't locate Java callbacks, check that they're named and typed correctly");
    2.28      }
    2.29  }
    2.30  
    2.31 @@ -150,8 +152,8 @@
    2.32  extern "C" void Java_org_libsdl_app_SDLActivity_nativeRunAudioThread(
    2.33                                      JNIEnv* env)
    2.34  {
    2.35 -	mVM->AttachCurrentThread(&mAudioEnv, NULL);
    2.36 -	Android_RunAudioThread();
    2.37 +    mVM->AttachCurrentThread(&mAudioEnv, NULL);
    2.38 +    Android_RunAudioThread();
    2.39  }
    2.40  
    2.41  
    2.42 @@ -171,78 +173,69 @@
    2.43  //
    2.44  // Audio support
    2.45  //
    2.46 -static jint audioBufferFrames = 0;
    2.47 -static bool audioBuffer16Bit = false;
    2.48 -static bool audioBufferStereo = false;
    2.49 -
    2.50 -static jobject audioBuffer;
    2.51 -static void * audioPinnedBuffer;
    2.52 +static jboolean audioBuffer16Bit = JNI_FALSE;
    2.53 +static jboolean audioBufferStereo = JNI_FALSE;
    2.54 +static jobject audioBuffer = NULL;
    2.55 +static void* audioBufferPinned = NULL;
    2.56  
    2.57  extern "C" int Android_JNI_OpenAudioDevice(int sampleRate, int is16Bit, int channelCount, int desiredBufferFrames)
    2.58  {
    2.59 -	__android_log_print(ANDROID_LOG_VERBOSE, "SDL", "SDL audio: opening device");
    2.60 -	audioBuffer16Bit = is16Bit;
    2.61 -	audioBufferStereo = channelCount > 1;
    2.62 +    int audioBufferFrames;
    2.63 +
    2.64 +    __android_log_print(ANDROID_LOG_VERBOSE, "SDL", "SDL audio: opening device");
    2.65 +    audioBuffer16Bit = is16Bit;
    2.66 +    audioBufferStereo = channelCount > 1;
    2.67  
    2.68 -	audioBuffer = mEnv->CallStaticObjectMethod(mActivityInstance, midAudioInit, sampleRate, audioBuffer16Bit, audioBufferStereo, desiredBufferFrames);
    2.69 -	audioBuffer = mEnv->NewGlobalRef(audioBuffer);
    2.70 +    audioBuffer = mEnv->CallStaticObjectMethod(mActivityInstance, midAudioInit, sampleRate, audioBuffer16Bit, audioBufferStereo, desiredBufferFrames);
    2.71 +
    2.72 +    if (audioBuffer == NULL) {
    2.73 +        __android_log_print(ANDROID_LOG_WARN, "SDL", "SDL audio: didn't get back a good audio buffer!");
    2.74 +        return 0;
    2.75 +    }
    2.76 +    audioBuffer = mEnv->NewGlobalRef(audioBuffer);
    2.77  
    2.78 -	if (audioBuffer == NULL) {
    2.79 -		__android_log_print(ANDROID_LOG_WARN, "SDL", "SDL audio: didn't get back a good audio buffer!");
    2.80 -		return 0;
    2.81 -	}
    2.82 +    jboolean isCopy = JNI_FALSE;
    2.83 +    if (audioBuffer16Bit) {
    2.84 +        audioBufferPinned = mEnv->GetShortArrayElements((jshortArray)audioBuffer, &isCopy);
    2.85 +        audioBufferFrames = mEnv->GetArrayLength((jshortArray)audioBuffer);
    2.86 +    } else {
    2.87 +        audioBufferPinned = mEnv->GetByteArrayElements((jbyteArray)audioBuffer, &isCopy);
    2.88 +        audioBufferFrames = mEnv->GetArrayLength((jbyteArray)audioBuffer);
    2.89 +    }
    2.90 +    if (audioBufferStereo) {
    2.91 +        audioBufferFrames /= 2;
    2.92 +    }
    2.93  
    2.94 -	if (audioBufferStereo) {
    2.95 -		audioBufferFrames = mEnv->GetArrayLength((jshortArray)audioBuffer) / 2;
    2.96 -	} else {
    2.97 -		audioBufferFrames = mEnv->GetArrayLength((jbyteArray)audioBuffer);
    2.98 -	}
    2.99 -
   2.100 -	return audioBufferFrames;
   2.101 +    return audioBufferFrames;
   2.102  }
   2.103  
   2.104 -extern "C" void * Android_JNI_PinAudioBuffer()
   2.105 +extern "C" void * Android_JNI_GetAudioBuffer()
   2.106  {
   2.107 -	jboolean isCopy = JNI_FALSE;
   2.108 -
   2.109 -	if (audioPinnedBuffer != NULL) {
   2.110 -		return audioPinnedBuffer;
   2.111 -	}
   2.112 -
   2.113 -	if (audioBuffer16Bit) {
   2.114 -		audioPinnedBuffer = mAudioEnv->GetShortArrayElements((jshortArray)audioBuffer, &isCopy);
   2.115 -	} else {
   2.116 -		audioPinnedBuffer = mAudioEnv->GetByteArrayElements((jbyteArray)audioBuffer, &isCopy);
   2.117 -	}
   2.118 -
   2.119 -	return audioPinnedBuffer;
   2.120 +    //jboolean isCopy = JNI_FALSE;
   2.121 +    //audioBufferPinned = mAudioEnv->GetPrimitiveArrayCritical((jarray)audioBuffer, &isCopy);
   2.122 +    return audioBufferPinned;
   2.123  }
   2.124  
   2.125 -extern "C" void Android_JNI_WriteAudioBufferAndUnpin()
   2.126 +extern "C" void Android_JNI_WriteAudioBuffer()
   2.127  {
   2.128 -	if (audioPinnedBuffer == NULL) {
   2.129 -		return;
   2.130 -	}
   2.131 +    //mAudioEnv->ReleasePrimitiveArrayCritical((jarray)audioBuffer, audioBufferPinned, 0);
   2.132 +    if (audioBuffer16Bit) {
   2.133 +        mAudioEnv->ReleaseShortArrayElements((jshortArray)audioBuffer, (jshort *)audioBufferPinned, JNI_COMMIT);
   2.134 +        mAudioEnv->CallStaticVoidMethod(mActivityInstance, midAudioWriteShortBuffer, (jshortArray)audioBuffer);
   2.135 +    } else {
   2.136 +        mAudioEnv->ReleaseByteArrayElements((jbyteArray)audioBuffer, (jbyte *)audioBufferPinned, JNI_COMMIT);
   2.137 +        mAudioEnv->CallStaticVoidMethod(mActivityInstance, midAudioWriteByteBuffer, (jbyteArray)audioBuffer);
   2.138 +    }
   2.139  
   2.140 -	if (audioBuffer16Bit) {
   2.141 -		mAudioEnv->ReleaseShortArrayElements((jshortArray)audioBuffer, (jshort *)audioPinnedBuffer, JNI_COMMIT);
   2.142 -		mAudioEnv->CallStaticVoidMethod(mActivityInstance, midAudioWriteShortBuffer, (jshortArray)audioBuffer);
   2.143 -	} else {
   2.144 -		mAudioEnv->ReleaseByteArrayElements((jbyteArray)audioBuffer, (jbyte *)audioPinnedBuffer, JNI_COMMIT);
   2.145 -		mAudioEnv->CallStaticVoidMethod(mActivityInstance, midAudioWriteByteBuffer, (jbyteArray)audioBuffer);
   2.146 -	}
   2.147 -
   2.148 -	audioPinnedBuffer = NULL;
   2.149 +    /* JNI_COMMIT means the changes are committed to the VM but the buffer remains pinned */
   2.150  }
   2.151  
   2.152  extern "C" void Android_JNI_CloseAudioDevice()
   2.153  {
   2.154 -    if (audioBuffer) {
   2.155 -        mEnv->DeleteGlobalRef(audioBuffer);
   2.156 -        audioBuffer = NULL;
   2.157 -    }
   2.158 +    mEnv->CallStaticVoidMethod(mActivityInstance, midAudioQuit); 
   2.159  
   2.160 -	// TODO: Implement
   2.161 +    mEnv->DeleteGlobalRef(audioBuffer);
   2.162 +    audioBuffer = NULL;
   2.163  }
   2.164  
   2.165  /* vi: set ts=4 sw=4 expandtab: */
     3.1 --- a/src/SDL_android.h	Thu Jan 13 11:14:20 2011 -0800
     3.2 +++ b/src/SDL_android.h	Thu Jan 13 12:32:55 2011 -0800
     3.3 @@ -34,8 +34,8 @@
     3.4  
     3.5  // Audio support
     3.6  int Android_JNI_OpenAudioDevice(int sampleRate, int is16Bit, int channelCount, int desiredBufferFrames);
     3.7 -void* Android_JNI_PinAudioBuffer();
     3.8 -void Android_JNI_WriteAudioBufferAndUnpin();
     3.9 +void* Android_JNI_GetAudioBuffer();
    3.10 +void Android_JNI_WriteAudioBuffer();
    3.11  void Android_JNI_CloseAudioDevice();
    3.12  
    3.13  /* Ends C function definitions when using C++ */
     4.1 --- a/src/audio/android/SDL_androidaudio.c	Thu Jan 13 11:14:20 2011 -0800
     4.2 +++ b/src/audio/android/SDL_androidaudio.c	Thu Jan 13 12:32:55 2011 -0800
     4.3 @@ -103,26 +103,19 @@
     4.4  static void
     4.5  AndroidAUD_PlayDevice(_THIS)
     4.6  {
     4.7 -    Android_JNI_WriteAudioBufferAndUnpin();
     4.8 -    this->hidden->mixbuf = NULL;
     4.9 +    Android_JNI_WriteAudioBuffer();
    4.10  }
    4.11  
    4.12  static Uint8 *
    4.13  AndroidAUD_GetDeviceBuf(_THIS)
    4.14  {
    4.15 -	if (this->hidden->mixbuf == NULL) {
    4.16 -		this->hidden->mixbuf = Android_JNI_PinAudioBuffer();
    4.17 -	}
    4.18 -    return this->hidden->mixbuf;
    4.19 +    return Android_JNI_GetAudioBuffer();
    4.20  }
    4.21  
    4.22  static void
    4.23  AndroidAUD_CloseDevice(_THIS)
    4.24  {
    4.25      if (this->hidden != NULL) {
    4.26 -    	if (this->hidden->mixbuf != NULL) {
    4.27 -    		Android_JNI_WriteAudioBufferAndUnpin();
    4.28 -    	}
    4.29      	SDL_free(this->hidden);
    4.30      	this->hidden = NULL;
    4.31      }
     5.1 --- a/src/audio/android/SDL_androidaudio.h	Thu Jan 13 11:14:20 2011 -0800
     5.2 +++ b/src/audio/android/SDL_androidaudio.h	Thu Jan 13 12:32:55 2011 -0800
     5.3 @@ -31,9 +31,6 @@
     5.4  
     5.5  struct SDL_PrivateAudioData
     5.6  {
     5.7 -    /* The file descriptor for the audio device */
     5.8 -    Uint8 *mixbuf;
     5.9 -    Uint32 mixlen;
    5.10  };
    5.11  
    5.12  #endif /* _SDL_androidaudio_h */