From 2393edc06c2e511e2391847eebe6616b0de84f93 Mon Sep 17 00:00:00 2001 From: Sergii Pylypenko Date: Fri, 15 Mar 2013 19:12:56 +0200 Subject: [PATCH] Fixed audio recording --- project/java/Audio.java | 14 ++--- .../openarena/AndroidAppSettings.cfg | 4 +- project/jni/application/openarena/engine | 2 +- .../src/audio/android/SDL_androidaudio.c | 51 +++++++++++++------ 4 files changed, 46 insertions(+), 25 deletions(-) diff --git a/project/java/Audio.java b/project/java/Audio.java index d5d131aec..e35e3aea9 100644 --- a/project/java/Audio.java +++ b/project/java/Audio.java @@ -164,7 +164,7 @@ class AudioThread private AudioRecord mRecorder = null; private int mRecorderBufferSize = 0; - private int startRecording(int rate, int channels, int encoding, int bufsize) + private byte[] startRecording(int rate, int channels, int encoding, int bufsize) { if( mRecordThread == null ) { @@ -174,7 +174,7 @@ class AudioThread if( !mRecordThread.isStopped() ) { System.out.println("SDL: error: application already opened audio recording device"); - return 0; + return null; } mRecordThread.init(bufsize); @@ -200,7 +200,7 @@ class AudioThread mRecorderBufferSize = minBufferSize; } catch (IllegalArgumentException e) { System.out.println("SDL: error: failed to open recording device!"); - return 0; + return null; } } else @@ -208,7 +208,7 @@ class AudioThread System.out.println("SDL: reusing old recording device"); } mRecordThread.startRecording(); - return minBufferSize; + return mRecordThread.mRecordBuffer; } private void stopRecording() @@ -225,7 +225,7 @@ class AudioThread private class RecordingThread extends Thread { private boolean stopped = true; - private byte[] mRecordBuffer; + byte[] mRecordBuffer; private Semaphore waitStarted = new Semaphore(0); private boolean sleep = false; @@ -258,7 +258,7 @@ class AudioThread // TODO: record in a loop? } //System.out.println("SDL: nativeAudioRecordCallback with len " + mRecordBuffer.length); - nativeAudioRecordCallback(mRecordBuffer); + nativeAudioRecordCallback(); //System.out.println("SDL: nativeAudioRecordCallback returned"); } @@ -298,5 +298,5 @@ class AudioThread } } - private native void nativeAudioRecordCallback(byte[] buffer); + private native void nativeAudioRecordCallback(); } diff --git a/project/jni/application/openarena/AndroidAppSettings.cfg b/project/jni/application/openarena/AndroidAppSettings.cfg index c6005cf64..a7e9bf37a 100644 --- a/project/jni/application/openarena/AndroidAppSettings.cfg +++ b/project/jni/application/openarena/AndroidAppSettings.cfg @@ -43,8 +43,8 @@ HiddenMenuOptions='OptionalDownloadConfig DisplaySizeConfig' FirstStartMenuOptions='' MultiABI=y AppMinimumRAM=300 -AppVersionCode=08821 -AppVersionName="0.8.8.21" +AppVersionCode=08822 +AppVersionName="0.8.8.22" ResetSdlConfigForThisVersion=n DeleteFilesOnUpgrade="libsdl-DownloadFinished-10.flag" CompiledLibraries="sdl_mixer sdl_image freetype curl vorbis ogg" diff --git a/project/jni/application/openarena/engine b/project/jni/application/openarena/engine index 4667cd792..043cd637b 160000 --- a/project/jni/application/openarena/engine +++ b/project/jni/application/openarena/engine @@ -1 +1 @@ -Subproject commit 4667cd792e8b29a0ca51418e7b9853cf721ccc10 +Subproject commit 043cd637b92b8f2ca148198347d463a6c5cde409 diff --git a/project/jni/sdl-1.2/src/audio/android/SDL_androidaudio.c b/project/jni/sdl-1.2/src/audio/android/SDL_androidaudio.c index 862f7986a..ae0b4d58c 100644 --- a/project/jni/sdl-1.2/src/audio/android/SDL_androidaudio.c +++ b/project/jni/sdl-1.2/src/audio/android/SDL_androidaudio.c @@ -151,6 +151,8 @@ static jmethodID JavaResumeAudioPlayback = NULL; static SDL_AudioSpec recording; static jmethodID JavaStartRecording = NULL; static jmethodID JavaStopRecording = NULL; +static jbyteArray recordingBufferJNI = NULL; +static size_t recordingBufferSize = 0; static Uint8 *ANDROIDAUD_GetAudioBuf(_THIS) @@ -320,7 +322,7 @@ static void ANDROIDAUD_ThreadInit(_THIS) SDL_memset(audioBuffer, this->spec.silence, this->spec.size); // Audio recording - JavaStartRecording = (*jniEnvPlaying)->GetMethodID(jniEnvPlaying, JavaAudioThreadClass, "startRecording", "(IIII)I"); + JavaStartRecording = (*jniEnvPlaying)->GetMethodID(jniEnvPlaying, JavaAudioThreadClass, "startRecording", "(IIII)[B"); JavaStopRecording = (*jniEnvPlaying)->GetMethodID(jniEnvPlaying, JavaAudioThreadClass, "stopRecording", "()V"); }; @@ -415,21 +417,26 @@ JNIEXPORT void JNICALL JNI_OnUnload(JavaVM *vm, void *reserved) // ----- Audio recording ----- -JNIEXPORT void JNICALL JAVA_EXPORT_NAME(AudioThread_nativeAudioRecordCallback) (JNIEnv * jniEnv, jobject thiz, jbyteArray jbuffer) +JNIEXPORT void JNICALL JAVA_EXPORT_NAME(AudioThread_nativeAudioRecordCallback) (JNIEnv * jniEnv, jobject thiz) { - int len = (*jniEnv)->GetArrayLength(jniEnv, jbuffer); - Uint8 *buffer = (Uint8 *) (*jniEnv)->GetByteArrayElements(jniEnv, jbuffer, NULL); - if( !buffer ) + if( !recordingBufferJNI || !recordingBufferSize ) { - __android_log_print(ANDROID_LOG_ERROR, "libSDL", "AudioThread_nativeAudioRecordCallbacks() JNI::GetByteArrayElements() failed! we will crash now"); + __android_log_print(ANDROID_LOG_ERROR, "libSDL", "AudioThread_nativeAudioRecordCallbacks(): error: recording buffer is NULL"); return; } - __android_log_print(ANDROID_LOG_INFO, "libSDL", "AudioThread_nativeAudioRecordCallbacks(): got buffer %p len %d", buffer, len); + Uint8 *buffer = (Uint8 *) (*jniEnv)->GetByteArrayElements(jniEnv, recordingBufferJNI, NULL); + if( !buffer ) + { + __android_log_print(ANDROID_LOG_ERROR, "libSDL", "AudioThread_nativeAudioRecordCallbacks(): error: JNI::GetByteArrayElements() failed!"); + return; + } - recording.callback(recording.userdata, buffer, len); + //__android_log_print(ANDROID_LOG_INFO, "libSDL", "AudioThread_nativeAudioRecordCallbacks(): got buffer %p len %d", buffer, recordingBufferSize); - (*jniEnv)->ReleaseByteArrayElements(jniEnv, jbuffer, (jbyte *)buffer, 0); + recording.callback(recording.userdata, buffer, recordingBufferSize); + + (*jniEnv)->ReleaseByteArrayElements(jniEnv, recordingBufferJNI, (jbyte *)buffer, 0); } extern DECLSPEC int SDLCALL SDL_ANDROID_OpenAudioRecording(SDL_AudioSpec *spec) @@ -440,27 +447,41 @@ extern DECLSPEC int SDLCALL SDL_ANDROID_OpenAudioRecording(SDL_AudioSpec *spec) if( ! (recording.format == AUDIO_S8 || recording.format == AUDIO_S16) ) { - __android_log_print(ANDROID_LOG_ERROR, "libSDL", "Application requested unsupported audio format - only S8 and S16 are supported"); + __android_log_print(ANDROID_LOG_ERROR, "libSDL", "SDL_ANDROID_OpenAudioRecording(): Application requested unsupported audio format - only S8 and S16 are supported"); return 0; } if( ! recording.callback ) { - __android_log_print(ANDROID_LOG_ERROR, "libSDL", "Application did not provide callback"); + __android_log_print(ANDROID_LOG_ERROR, "libSDL", "SDL_ANDROID_OpenAudioRecording(): Application did not provide callback"); return 0; } - (*jniVM)->AttachCurrentThread(jniVM, &jniEnv, NULL); + (*jniVM)->AttachCurrentThread( jniVM, &jniEnv, NULL ); - return (*jniEnv)->CallIntMethod( jniEnv, JavaAudioThread, JavaStartRecording, (jint)recording.freq, (jint)recording.channels, - (jint)(recording.format == AUDIO_S16 ? 1 : 0), (jint)recording.size ); + recordingBufferJNI = (*jniEnv)->CallObjectMethod( jniEnv, JavaAudioThread, JavaStartRecording, + (jint)recording.freq, (jint)recording.channels, + (jint)(recording.format == AUDIO_S16 ? 1 : 0), (jint)recording.size ); + if( !recordingBufferJNI ) + { + __android_log_print(ANDROID_LOG_ERROR, "libSDL", "SDL_ANDROID_OpenAudioRecording(): Java did not return audio buffer"); + return 0; + } + recordingBufferJNI = (*jniEnv)->NewGlobalRef( jniEnv, recordingBufferJNI ); + recordingBufferSize = (*jniEnv)->GetArrayLength( jniEnv, recordingBufferJNI ); + //__android_log_print(ANDROID_LOG_ERROR, "libSDL", "SDL_ANDROID_OpenAudioRecording(): JNI buffer %p len %d", recordingBufferJNI, recordingBufferSize); + return 1; } extern DECLSPEC void SDLCALL SDL_ANDROID_CloseAudioRecording(void) { JNIEnv * jniEnv = NULL; - (*jniVM)->AttachCurrentThread(jniVM, &jniEnv, NULL); + (*jniVM)->AttachCurrentThread( jniVM, &jniEnv, NULL ); (*jniEnv)->CallVoidMethod( jniEnv, JavaAudioThread, JavaStopRecording ); + if( recordingBufferJNI ) + (*jniEnv)->DeleteGlobalRef( jniEnv, recordingBufferJNI ); + recordingBufferJNI = NULL; + recordingBufferSize = 0; }