diff --git a/project/java/Audio.java b/project/java/Audio.java index a7d365bdb..d5d131aec 100644 --- a/project/java/Audio.java +++ b/project/java/Audio.java @@ -36,7 +36,8 @@ import android.media.AudioRecord; import android.media.MediaRecorder.AudioSource; import java.io.*; import android.util.Log; -import java.lang.Thread; +import java.util.concurrent.Semaphore; + class AudioThread @@ -135,9 +136,9 @@ class AudioThread { mAudio.pause(); } - if( mRecorder != null ) + if( mRecordThread != null ) { - mRecorder.stop(); + mRecordThread.pauseRecording(); } return 1; } @@ -148,9 +149,9 @@ class AudioThread { mAudio.play(); } - if( mRecorder != null ) + if( mRecordThread != null ) { - mRecorder.startRecording(); + mRecordThread.resumeRecording(); } return 1; } @@ -159,106 +160,143 @@ class AudioThread // ----- Audio recording ----- - private AudioRecord mRecorder = null; private RecordingThread mRecordThread = null; - //private int mRecordSize; - //private int mRecordPos; + private AudioRecord mRecorder = null; + private int mRecorderBufferSize = 0; private int startRecording(int rate, int channels, int encoding, int bufsize) { - //mRecordSize = bufsize; - //mRecordPos = 0; - if( mRecordThread != null ) + if( mRecordThread == null ) + { + mRecordThread = new RecordingThread(); + mRecordThread.start(); + } + if( !mRecordThread.isStopped() ) { System.out.println("SDL: error: application already opened audio recording device"); return 0; } - channels = ( channels == 1 ) ? AudioFormat.CHANNEL_IN_MONO : + + mRecordThread.init(bufsize); + + int channelConfig = ( channels == 1 ) ? AudioFormat.CHANNEL_IN_MONO : AudioFormat.CHANNEL_IN_STEREO; - encoding = ( encoding == 1 ) ? AudioFormat.ENCODING_PCM_16BIT : + int encodingConfig = ( encoding == 1 ) ? AudioFormat.ENCODING_PCM_16BIT : AudioFormat.ENCODING_PCM_8BIT; - int minBufDevice = AudioRecord.getMinBufferSize(rate, channels, encoding); + int minBufDevice = AudioRecord.getMinBufferSize(rate, channelConfig, encodingConfig); int minBufferSize = Math.max(bufsize * 8, minBufDevice + (bufsize - (minBufDevice % bufsize))); System.out.println("SDL: app opened recording device, rate " + rate + " channels " + channels + " sample size " + (encoding+1) + " bufsize " + bufsize + " internal bufsize " + minBufferSize); - try { - mRecorder = new AudioRecord(AudioSource.DEFAULT, rate, channels, encoding, minBufferSize); - } catch (IllegalArgumentException e) { - System.out.println("SDL: error: failed to open recording device!"); - return 0; + if( mRecorder == null || mRecorder.getSampleRate() != rate || + mRecorder.getChannelCount() != channels || + mRecorder.getAudioFormat() != encodingConfig || + mRecorderBufferSize != minBufferSize ) + { + if( mRecorder != null ) + mRecorder.release(); + mRecorder = null; + try { + mRecorder = new AudioRecord(AudioSource.DEFAULT, rate, channelConfig, encodingConfig, minBufferSize); + mRecorderBufferSize = minBufferSize; + } catch (IllegalArgumentException e) { + System.out.println("SDL: error: failed to open recording device!"); + return 0; + } } - mRecordThread = new RecordingThread(bufsize); - mRecorder.startRecording(); - mRecordThread.start(); + else + { + System.out.println("SDL: reusing old recording device"); + } + mRecordThread.startRecording(); return minBufferSize; } private void stopRecording() { - if( mRecordThread == null ) + if( mRecordThread == null || mRecordThread.isStopped() ) { System.out.println("SDL: error: application already closed audio recording device"); return; } - mRecordThread.terminate = true; - while( !mRecordThread.stopped ) - { - try{ - Thread.sleep(100); - } catch (InterruptedException e) {} - } - mRecordThread = null; - mRecorder.stop(); - mRecorder.release(); - mRecorder = null; + mRecordThread.stopRecording(); System.out.println("SDL: app closed recording device"); } private class RecordingThread extends Thread { - public boolean terminate = false; - public boolean stopped = false; + private boolean stopped = true; private byte[] mRecordBuffer; + private Semaphore waitStarted = new Semaphore(0); + private boolean sleep = false; - RecordingThread(int bufsize) + RecordingThread() { super(); - mRecordBuffer = new byte[bufsize]; + } + + void init(int bufsize) + { + if( mRecordBuffer == null || mRecordBuffer.length != bufsize ) + mRecordBuffer = new byte[bufsize]; } public void run() { - while( !terminate ) + while( true ) { - int got = mRecorder.read(mRecordBuffer, 0, mRecordBuffer.length); - if( got != mRecordBuffer.length ) + waitStarted.acquireUninterruptibly(); + waitStarted.drainPermits(); + stopped = false; + sleep = false; + + while( !sleep ) { - System.out.println("SDL: warning: RecordingThread: mRecorder.read returned short byte count " + got + " for bufsize " + mRecordBuffer.length); - // TODO: record in a loop? + int got = mRecorder.read(mRecordBuffer, 0, mRecordBuffer.length); + if( got != mRecordBuffer.length ) + { + System.out.println("SDL: warning: RecordingThread: mRecorder.read returned short byte count " + got + " for bufsize " + mRecordBuffer.length); + // TODO: record in a loop? + } + //System.out.println("SDL: nativeAudioRecordCallback with len " + mRecordBuffer.length); + nativeAudioRecordCallback(mRecordBuffer); + //System.out.println("SDL: nativeAudioRecordCallback returned"); } - System.out.println("SDL: nativeAudioRecordCallback with len " + mRecordBuffer.length); - nativeAudioRecordCallback(mRecordBuffer); - System.out.println("SDL: nativeAudioRecordCallback returned"); + + stopped = true; + mRecorder.stop(); } - stopped = true; + } + + public void startRecording() + { + mRecorder.startRecording(); + waitStarted.release(); + } + public void stopRecording() + { + sleep = true; + while( !stopped ) + { + try{ + Thread.sleep(100); + } catch (InterruptedException e) {} + } + } + public void pauseRecording() + { + if( !stopped ) + mRecorder.stop(); + } + public void resumeRecording() + { + if( !stopped ) + mRecorder.startRecording(); + } + public boolean isStopped() + { + return stopped; } } private native void nativeAudioRecordCallback(byte[] buffer); - - /* - private int recordRead() - { - mRecordPos += mRecordSize; - if( mRecordPos >= mRecordBuffer.length ) - mRecordPos = 0; - mRecorder.read(mRecordBuffer, mRecordPos, mRecordSize); - return mRecordPos; - } - - public byte[] getRecordBuffer() - { - return mRecordBuffer; - } - */ } diff --git a/project/jni/application/commandergenius/commandergenius b/project/jni/application/commandergenius/commandergenius index 6f28771d5..d1b8a7ae0 160000 --- a/project/jni/application/commandergenius/commandergenius +++ b/project/jni/application/commandergenius/commandergenius @@ -1 +1 @@ -Subproject commit 6f28771d57ca7d878e3cfee08014651b854b9c7f +Subproject commit d1b8a7ae03b1a0960722abbab38bbb8fca98e7cd diff --git a/project/jni/application/openarena/AndroidBuild.sh b/project/jni/application/openarena/AndroidBuild.sh index 9d93ed9d0..586d559ec 100755 --- a/project/jni/application/openarena/AndroidBuild.sh +++ b/project/jni/application/openarena/AndroidBuild.sh @@ -23,7 +23,7 @@ env NO_SHARED_LIBS=1 BUILD_EXECUTABLE=1 V=1 ../setEnvironment-armeabi.sh make -C # ../setEnvironment-armeabi.sh sh -c "cd vm/build/release-android-$1/baseq3 && \$STRIP --strip-unneeded *.so && zip ../../../../AndroidData/binaries.zip *.so" ../setEnvironment-$1.sh make -j8 -C engine release \ -PLATFORM=android ARCH=$1 USE_GLES=1 USE_LOCAL_HEADERS=0 \ +PLATFORM=android ARCH=$1 USE_GLES=1 USE_LOCAL_HEADERS=0 BUILD_CLIENT_SMP=0 \ USE_OPENAL=0 USE_VOIP=1 USE_CURL=1 USE_CURL_DLOPEN=0 USE_CODEC_VORBIS=1 USE_MUMBLE=0 USE_FREETYPE=1 \ USE_RENDERER_DLOPEN=0 USE_INTERNAL_ZLIB=0 USE_INTERNAL_JPEG=1 BUILD_RENDERER_REND2=0 && \ echo "Copying engine/build/release-android-$1/openarena.$1 -> libapplication-$1.so" && \ diff --git a/project/jni/application/openarena/engine b/project/jni/application/openarena/engine index cec6cad84..4667cd792 160000 --- a/project/jni/application/openarena/engine +++ b/project/jni/application/openarena/engine @@ -1 +1 @@ -Subproject commit cec6cad84b8e322c06a1ca7b861c86e14a665fae +Subproject commit 4667cd792e8b29a0ca51418e7b9853cf721ccc10 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 f53cc4fa3..c291c0d61 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 @@ -420,9 +420,12 @@ JNIEXPORT void JNICALL JAVA_EXPORT_NAME(AudioThread_nativeAudioRecordCallback) ( int len = (*jniEnv)->GetArrayLength(jniEnv, jbuffer); Uint8 *buffer = (Uint8 *) (*jniEnv)->GetByteArrayElements(jniEnv, jbuffer, NULL); if( !buffer ) + { __android_log_print(ANDROID_LOG_ERROR, "libSDL", "AudioThread_nativeAudioRecordCallbacks() JNI::GetByteArrayElements() failed! we will crash now"); + return; + } - __android_log_print(ANDROID_LOG_INFO, "libSDL", "AudioThread_nativeAudioRecordCallbacks(): got buffer %p len %d", buffer, len); + //__android_log_print(ANDROID_LOG_INFO, "libSDL", "AudioThread_nativeAudioRecordCallbacks(): got buffer %p len %d", buffer, len); recording.callback(recording.userdata, buffer, len);