|
@@ -61,6 +61,10 @@
|
|
|
#define SDL_JAVA_CONTROLLER_INTERFACE(function) CONCAT1(SDL_JAVA_PREFIX, SDLControllerManager, function)
|
|
|
#define SDL_JAVA_INTERFACE_INPUT_CONNECTION(function) CONCAT1(SDL_JAVA_PREFIX, SDLInputConnection, function)
|
|
|
|
|
|
+/* Audio encoding definitions */
|
|
|
+#define ENCODING_PCM_8BIT 3
|
|
|
+#define ENCODING_PCM_16BIT 2
|
|
|
+#define ENCODING_PCM_FLOAT 4
|
|
|
|
|
|
/* Java class SDLActivity */
|
|
|
JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativeSetupJNI)(
|
|
@@ -77,7 +81,7 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativeDropFile)(
|
|
|
JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativeResize)(
|
|
|
JNIEnv* env, jclass jcls,
|
|
|
jint surfaceWidth, jint surfaceHeight,
|
|
|
- jint deviceWidth, jint deviceHeight, jint format, jfloat rate);
|
|
|
+ jint deviceWidth, jint deviceHeight, jint format, jfloat rate);
|
|
|
|
|
|
JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativeSurfaceChanged)(
|
|
|
JNIEnv* env, jclass jcls);
|
|
@@ -144,6 +148,10 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE_INPUT_CONNECTION(nativeCommitText)(
|
|
|
JNIEnv* env, jclass cls,
|
|
|
jstring text, jint newCursorPosition);
|
|
|
|
|
|
+JNIEXPORT void JNICALL SDL_JAVA_INTERFACE_INPUT_CONNECTION(nativeGenerateScancodeForUnichar)(
|
|
|
+ JNIEnv* env, jclass cls,
|
|
|
+ jchar chUnicode);
|
|
|
+
|
|
|
JNIEXPORT void JNICALL SDL_JAVA_INTERFACE_INPUT_CONNECTION(nativeSetComposingText)(
|
|
|
JNIEnv* env, jclass cls,
|
|
|
jstring text, jint newCursorPosition);
|
|
@@ -195,6 +203,7 @@ JNIEXPORT jint JNICALL SDL_JAVA_CONTROLLER_INTERFACE(nativeRemoveHaptic)(
|
|
|
/* #define DEBUG_JNI */
|
|
|
|
|
|
static void Android_JNI_ThreadDestroyed(void*);
|
|
|
+static void checkJNIReady(void);
|
|
|
|
|
|
/*******************************************************************************
|
|
|
This file links the Java side of Android with libsdl
|
|
@@ -243,12 +252,14 @@ static jclass mAudioManagerClass;
|
|
|
|
|
|
/* method signatures */
|
|
|
static jmethodID midAudioOpen;
|
|
|
-static jmethodID midAudioWriteShortBuffer;
|
|
|
static jmethodID midAudioWriteByteBuffer;
|
|
|
+static jmethodID midAudioWriteShortBuffer;
|
|
|
+static jmethodID midAudioWriteFloatBuffer;
|
|
|
static jmethodID midAudioClose;
|
|
|
static jmethodID midCaptureOpen;
|
|
|
-static jmethodID midCaptureReadShortBuffer;
|
|
|
static jmethodID midCaptureReadByteBuffer;
|
|
|
+static jmethodID midCaptureReadShortBuffer;
|
|
|
+static jmethodID midCaptureReadFloatBuffer;
|
|
|
static jmethodID midCaptureClose;
|
|
|
|
|
|
/* controller manager */
|
|
@@ -392,24 +403,28 @@ JNIEXPORT void JNICALL SDL_JAVA_AUDIO_INTERFACE(nativeSetupJNI)(JNIEnv* mEnv, jc
|
|
|
mAudioManagerClass = (jclass)((*mEnv)->NewGlobalRef(mEnv, cls));
|
|
|
|
|
|
midAudioOpen = (*mEnv)->GetStaticMethodID(mEnv, mAudioManagerClass,
|
|
|
- "audioOpen", "(IZZI)I");
|
|
|
- midAudioWriteShortBuffer = (*mEnv)->GetStaticMethodID(mEnv, mAudioManagerClass,
|
|
|
- "audioWriteShortBuffer", "([S)V");
|
|
|
+ "audioOpen", "(IIII)[I");
|
|
|
midAudioWriteByteBuffer = (*mEnv)->GetStaticMethodID(mEnv, mAudioManagerClass,
|
|
|
"audioWriteByteBuffer", "([B)V");
|
|
|
+ midAudioWriteShortBuffer = (*mEnv)->GetStaticMethodID(mEnv, mAudioManagerClass,
|
|
|
+ "audioWriteShortBuffer", "([S)V");
|
|
|
+ midAudioWriteFloatBuffer = (*mEnv)->GetStaticMethodID(mEnv, mAudioManagerClass,
|
|
|
+ "audioWriteFloatBuffer", "([F)V");
|
|
|
midAudioClose = (*mEnv)->GetStaticMethodID(mEnv, mAudioManagerClass,
|
|
|
"audioClose", "()V");
|
|
|
midCaptureOpen = (*mEnv)->GetStaticMethodID(mEnv, mAudioManagerClass,
|
|
|
- "captureOpen", "(IZZI)I");
|
|
|
- midCaptureReadShortBuffer = (*mEnv)->GetStaticMethodID(mEnv, mAudioManagerClass,
|
|
|
- "captureReadShortBuffer", "([SZ)I");
|
|
|
+ "captureOpen", "(IIII)[I");
|
|
|
midCaptureReadByteBuffer = (*mEnv)->GetStaticMethodID(mEnv, mAudioManagerClass,
|
|
|
"captureReadByteBuffer", "([BZ)I");
|
|
|
+ midCaptureReadShortBuffer = (*mEnv)->GetStaticMethodID(mEnv, mAudioManagerClass,
|
|
|
+ "captureReadShortBuffer", "([SZ)I");
|
|
|
+ midCaptureReadFloatBuffer = (*mEnv)->GetStaticMethodID(mEnv, mAudioManagerClass,
|
|
|
+ "captureReadFloatBuffer", "([FZ)I");
|
|
|
midCaptureClose = (*mEnv)->GetStaticMethodID(mEnv, mAudioManagerClass,
|
|
|
"captureClose", "()V");
|
|
|
|
|
|
- if (!midAudioOpen || !midAudioWriteShortBuffer || !midAudioWriteByteBuffer || !midAudioClose ||
|
|
|
- !midCaptureOpen || !midCaptureReadShortBuffer || !midCaptureReadByteBuffer || !midCaptureClose) {
|
|
|
+ if (!midAudioOpen || !midAudioWriteByteBuffer || !midAudioWriteShortBuffer || !midAudioWriteFloatBuffer || !midAudioClose ||
|
|
|
+ !midCaptureOpen || !midCaptureReadByteBuffer || !midCaptureReadShortBuffer || !midCaptureReadFloatBuffer || !midCaptureClose) {
|
|
|
__android_log_print(ANDROID_LOG_WARN, "SDL", "Missing some Java callbacks, do you have the latest version of SDLAudioManager.java?");
|
|
|
}
|
|
|
|
|
@@ -430,7 +445,7 @@ JNIEXPORT void JNICALL SDL_JAVA_CONTROLLER_INTERFACE(nativeSetupJNI)(JNIEnv* mEn
|
|
|
midPollHapticDevices = (*mEnv)->GetStaticMethodID(mEnv, mControllerManagerClass,
|
|
|
"pollHapticDevices", "()V");
|
|
|
midHapticRun = (*mEnv)->GetStaticMethodID(mEnv, mControllerManagerClass,
|
|
|
- "hapticRun", "(II)V");
|
|
|
+ "hapticRun", "(IFI)V");
|
|
|
midHapticStop = (*mEnv)->GetStaticMethodID(mEnv, mControllerManagerClass,
|
|
|
"hapticStop", "(I)V");
|
|
|
|
|
@@ -538,7 +553,7 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativeDropFile)(
|
|
|
JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativeResize)(
|
|
|
JNIEnv* env, jclass jcls,
|
|
|
jint surfaceWidth, jint surfaceHeight,
|
|
|
- jint deviceWidth, jint deviceHeight, jint format, jfloat rate)
|
|
|
+ jint deviceWidth, jint deviceHeight, jint format, jfloat rate)
|
|
|
{
|
|
|
Android_SetScreenResolution(surfaceWidth, surfaceHeight, deviceWidth, deviceHeight, format, rate);
|
|
|
}
|
|
@@ -1039,17 +1054,19 @@ int Android_JNI_SetupThread(void)
|
|
|
/*
|
|
|
* Audio support
|
|
|
*/
|
|
|
-static jboolean audioBuffer16Bit = JNI_FALSE;
|
|
|
+static int audioBufferFormat = 0;
|
|
|
static jobject audioBuffer = NULL;
|
|
|
static void* audioBufferPinned = NULL;
|
|
|
-static jboolean captureBuffer16Bit = JNI_FALSE;
|
|
|
+static int captureBufferFormat = 0;
|
|
|
static jobject captureBuffer = NULL;
|
|
|
|
|
|
-int Android_JNI_OpenAudioDevice(int iscapture, int sampleRate, int is16Bit, int channelCount, int desiredBufferFrames)
|
|
|
+int Android_JNI_OpenAudioDevice(int iscapture, SDL_AudioSpec *spec)
|
|
|
{
|
|
|
- jboolean audioBufferStereo;
|
|
|
- int audioBufferFrames;
|
|
|
+ int audioformat;
|
|
|
+ int numBufferFrames;
|
|
|
jobject jbufobj = NULL;
|
|
|
+ jobject result;
|
|
|
+ int *resultElements;
|
|
|
jboolean isCopy;
|
|
|
|
|
|
JNIEnv *env = Android_JNI_GetEnv();
|
|
@@ -1059,74 +1076,123 @@ int Android_JNI_OpenAudioDevice(int iscapture, int sampleRate, int is16Bit, int
|
|
|
}
|
|
|
Android_JNI_SetupThread();
|
|
|
|
|
|
- audioBufferStereo = channelCount > 1;
|
|
|
+ switch (spec->format) {
|
|
|
+ case AUDIO_U8:
|
|
|
+ audioformat = ENCODING_PCM_8BIT;
|
|
|
+ break;
|
|
|
+ case AUDIO_S16:
|
|
|
+ audioformat = ENCODING_PCM_16BIT;
|
|
|
+ break;
|
|
|
+ case AUDIO_F32:
|
|
|
+ audioformat = ENCODING_PCM_FLOAT;
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ return SDL_SetError("Unsupported audio format: 0x%x", spec->format);
|
|
|
+ }
|
|
|
|
|
|
if (iscapture) {
|
|
|
__android_log_print(ANDROID_LOG_VERBOSE, "SDL", "SDL audio: opening device for capture");
|
|
|
- captureBuffer16Bit = is16Bit;
|
|
|
- if ((*env)->CallStaticIntMethod(env, mAudioManagerClass, midCaptureOpen, sampleRate, audioBuffer16Bit, audioBufferStereo, desiredBufferFrames) != 0) {
|
|
|
- /* Error during audio initialization */
|
|
|
- __android_log_print(ANDROID_LOG_WARN, "SDL", "SDL audio: error on AudioRecord initialization!");
|
|
|
- return 0;
|
|
|
- }
|
|
|
+ result = (*env)->CallStaticObjectMethod(env, mAudioManagerClass, midCaptureOpen, spec->freq, audioformat, spec->channels, spec->samples);
|
|
|
} else {
|
|
|
__android_log_print(ANDROID_LOG_VERBOSE, "SDL", "SDL audio: opening device for output");
|
|
|
- audioBuffer16Bit = is16Bit;
|
|
|
- if ((*env)->CallStaticIntMethod(env, mAudioManagerClass, midAudioOpen, sampleRate, audioBuffer16Bit, audioBufferStereo, desiredBufferFrames) != 0) {
|
|
|
- /* Error during audio initialization */
|
|
|
- __android_log_print(ANDROID_LOG_WARN, "SDL", "SDL audio: error on AudioTrack initialization!");
|
|
|
- return 0;
|
|
|
- }
|
|
|
+ result = (*env)->CallStaticObjectMethod(env, mAudioManagerClass, midAudioOpen, spec->freq, audioformat, spec->channels, spec->samples);
|
|
|
+ }
|
|
|
+ if (result == NULL) {
|
|
|
+ /* Error during audio initialization, error printed from Java */
|
|
|
+ return SDL_SetError("Java-side initialization failed");
|
|
|
}
|
|
|
|
|
|
+ if ((*env)->GetArrayLength(env, (jintArray)result) != 4) {
|
|
|
+ return SDL_SetError("Unexpected results from Java, expected 4, got %d", (*env)->GetArrayLength(env, (jintArray)result));
|
|
|
+ }
|
|
|
+ isCopy = JNI_FALSE;
|
|
|
+ resultElements = (*env)->GetIntArrayElements(env, (jintArray)result, &isCopy);
|
|
|
+ spec->freq = resultElements[0];
|
|
|
+ audioformat = resultElements[1];
|
|
|
+ switch (audioformat) {
|
|
|
+ case ENCODING_PCM_8BIT:
|
|
|
+ spec->format = AUDIO_U8;
|
|
|
+ break;
|
|
|
+ case ENCODING_PCM_16BIT:
|
|
|
+ spec->format = AUDIO_S16;
|
|
|
+ break;
|
|
|
+ case ENCODING_PCM_FLOAT:
|
|
|
+ spec->format = AUDIO_F32;
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ return SDL_SetError("Unexpected audio format from Java: %d\n", audioformat);
|
|
|
+ }
|
|
|
+ spec->channels = resultElements[2];
|
|
|
+ spec->samples = resultElements[3];
|
|
|
+ (*env)->ReleaseIntArrayElements(env, (jintArray)result, resultElements, JNI_ABORT);
|
|
|
+ (*env)->DeleteLocalRef(env, result);
|
|
|
+
|
|
|
/* Allocating the audio buffer from the Java side and passing it as the return value for audioInit no longer works on
|
|
|
* Android >= 4.2 due to a "stale global reference" error. So now we allocate this buffer directly from this side. */
|
|
|
-
|
|
|
- if (is16Bit) {
|
|
|
- jshortArray audioBufferLocal = (*env)->NewShortArray(env, desiredBufferFrames * (audioBufferStereo ? 2 : 1));
|
|
|
- if (audioBufferLocal) {
|
|
|
- jbufobj = (*env)->NewGlobalRef(env, audioBufferLocal);
|
|
|
- (*env)->DeleteLocalRef(env, audioBufferLocal);
|
|
|
+ switch (audioformat) {
|
|
|
+ case ENCODING_PCM_8BIT:
|
|
|
+ {
|
|
|
+ jbyteArray audioBufferLocal = (*env)->NewByteArray(env, spec->samples * spec->channels);
|
|
|
+ if (audioBufferLocal) {
|
|
|
+ jbufobj = (*env)->NewGlobalRef(env, audioBufferLocal);
|
|
|
+ (*env)->DeleteLocalRef(env, audioBufferLocal);
|
|
|
+ }
|
|
|
}
|
|
|
- }
|
|
|
- else {
|
|
|
- jbyteArray audioBufferLocal = (*env)->NewByteArray(env, desiredBufferFrames * (audioBufferStereo ? 2 : 1));
|
|
|
- if (audioBufferLocal) {
|
|
|
- jbufobj = (*env)->NewGlobalRef(env, audioBufferLocal);
|
|
|
- (*env)->DeleteLocalRef(env, audioBufferLocal);
|
|
|
+ break;
|
|
|
+ case ENCODING_PCM_16BIT:
|
|
|
+ {
|
|
|
+ jshortArray audioBufferLocal = (*env)->NewShortArray(env, spec->samples * spec->channels);
|
|
|
+ if (audioBufferLocal) {
|
|
|
+ jbufobj = (*env)->NewGlobalRef(env, audioBufferLocal);
|
|
|
+ (*env)->DeleteLocalRef(env, audioBufferLocal);
|
|
|
+ }
|
|
|
}
|
|
|
+ break;
|
|
|
+ case ENCODING_PCM_FLOAT:
|
|
|
+ {
|
|
|
+ jfloatArray audioBufferLocal = (*env)->NewFloatArray(env, spec->samples * spec->channels);
|
|
|
+ if (audioBufferLocal) {
|
|
|
+ jbufobj = (*env)->NewGlobalRef(env, audioBufferLocal);
|
|
|
+ (*env)->DeleteLocalRef(env, audioBufferLocal);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ return SDL_SetError("Unexpected audio format from Java: %d\n", audioformat);
|
|
|
}
|
|
|
|
|
|
if (jbufobj == NULL) {
|
|
|
- __android_log_print(ANDROID_LOG_WARN, "SDL", "SDL audio: could not allocate an audio buffer!");
|
|
|
- return 0;
|
|
|
+ __android_log_print(ANDROID_LOG_WARN, "SDL", "SDL audio: could not allocate an audio buffer");
|
|
|
+ return SDL_OutOfMemory();
|
|
|
}
|
|
|
|
|
|
if (iscapture) {
|
|
|
+ captureBufferFormat = audioformat;
|
|
|
captureBuffer = jbufobj;
|
|
|
} else {
|
|
|
+ audioBufferFormat = audioformat;
|
|
|
audioBuffer = jbufobj;
|
|
|
}
|
|
|
+ numBufferFrames = (*env)->GetArrayLength(env, (jarray)jbufobj);
|
|
|
|
|
|
- isCopy = JNI_FALSE;
|
|
|
+ if (!iscapture) {
|
|
|
+ isCopy = JNI_FALSE;
|
|
|
|
|
|
- if (is16Bit) {
|
|
|
- if (!iscapture) {
|
|
|
- audioBufferPinned = (*env)->GetShortArrayElements(env, (jshortArray)audioBuffer, &isCopy);
|
|
|
- }
|
|
|
- audioBufferFrames = (*env)->GetArrayLength(env, (jshortArray)audioBuffer);
|
|
|
- } else {
|
|
|
- if (!iscapture) {
|
|
|
+ switch (audioformat) {
|
|
|
+ case ENCODING_PCM_8BIT:
|
|
|
audioBufferPinned = (*env)->GetByteArrayElements(env, (jbyteArray)audioBuffer, &isCopy);
|
|
|
+ break;
|
|
|
+ case ENCODING_PCM_16BIT:
|
|
|
+ audioBufferPinned = (*env)->GetShortArrayElements(env, (jshortArray)audioBuffer, &isCopy);
|
|
|
+ break;
|
|
|
+ case ENCODING_PCM_FLOAT:
|
|
|
+ audioBufferPinned = (*env)->GetFloatArrayElements(env, (jfloatArray)audioBuffer, &isCopy);
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ return SDL_SetError("Unexpected audio format from Java: %d\n", audioformat);
|
|
|
}
|
|
|
- audioBufferFrames = (*env)->GetArrayLength(env, (jbyteArray)audioBuffer);
|
|
|
- }
|
|
|
-
|
|
|
- if (audioBufferStereo) {
|
|
|
- audioBufferFrames /= 2;
|
|
|
}
|
|
|
-
|
|
|
- return audioBufferFrames;
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
int Android_JNI_GetDisplayDPI(float *ddpi, float *xdpi, float *ydpi)
|
|
@@ -1170,12 +1236,22 @@ void Android_JNI_WriteAudioBuffer(void)
|
|
|
{
|
|
|
JNIEnv *mAudioEnv = Android_JNI_GetEnv();
|
|
|
|
|
|
- if (audioBuffer16Bit) {
|
|
|
- (*mAudioEnv)->ReleaseShortArrayElements(mAudioEnv, (jshortArray)audioBuffer, (jshort *)audioBufferPinned, JNI_COMMIT);
|
|
|
- (*mAudioEnv)->CallStaticVoidMethod(mAudioEnv, mAudioManagerClass, midAudioWriteShortBuffer, (jshortArray)audioBuffer);
|
|
|
- } else {
|
|
|
+ switch (audioBufferFormat) {
|
|
|
+ case ENCODING_PCM_8BIT:
|
|
|
(*mAudioEnv)->ReleaseByteArrayElements(mAudioEnv, (jbyteArray)audioBuffer, (jbyte *)audioBufferPinned, JNI_COMMIT);
|
|
|
(*mAudioEnv)->CallStaticVoidMethod(mAudioEnv, mAudioManagerClass, midAudioWriteByteBuffer, (jbyteArray)audioBuffer);
|
|
|
+ break;
|
|
|
+ case ENCODING_PCM_16BIT:
|
|
|
+ (*mAudioEnv)->ReleaseShortArrayElements(mAudioEnv, (jshortArray)audioBuffer, (jshort *)audioBufferPinned, JNI_COMMIT);
|
|
|
+ (*mAudioEnv)->CallStaticVoidMethod(mAudioEnv, mAudioManagerClass, midAudioWriteShortBuffer, (jshortArray)audioBuffer);
|
|
|
+ break;
|
|
|
+ case ENCODING_PCM_FLOAT:
|
|
|
+ (*mAudioEnv)->ReleaseFloatArrayElements(mAudioEnv, (jfloatArray)audioBuffer, (jfloat *)audioBufferPinned, JNI_COMMIT);
|
|
|
+ (*mAudioEnv)->CallStaticVoidMethod(mAudioEnv, mAudioManagerClass, midAudioWriteFloatBuffer, (jfloatArray)audioBuffer);
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ __android_log_print(ANDROID_LOG_WARN, "SDL", "SDL audio: unhandled audio buffer format");
|
|
|
+ break;
|
|
|
}
|
|
|
|
|
|
/* JNI_COMMIT means the changes are committed to the VM but the buffer remains pinned */
|
|
@@ -1187,44 +1263,84 @@ int Android_JNI_CaptureAudioBuffer(void *buffer, int buflen)
|
|
|
jboolean isCopy = JNI_FALSE;
|
|
|
jint br;
|
|
|
|
|
|
- if (captureBuffer16Bit) {
|
|
|
- SDL_assert((*env)->GetArrayLength(env, (jshortArray)captureBuffer) == (buflen / 2));
|
|
|
+ switch (captureBufferFormat) {
|
|
|
+ case ENCODING_PCM_8BIT:
|
|
|
+ SDL_assert((*env)->GetArrayLength(env, (jshortArray)captureBuffer) == buflen);
|
|
|
+ br = (*env)->CallStaticIntMethod(env, mAudioManagerClass, midCaptureReadByteBuffer, (jbyteArray)captureBuffer, JNI_TRUE);
|
|
|
+ if (br > 0) {
|
|
|
+ jbyte *ptr = (*env)->GetByteArrayElements(env, (jbyteArray)captureBuffer, &isCopy);
|
|
|
+ SDL_memcpy(buffer, ptr, br);
|
|
|
+ (*env)->ReleaseByteArrayElements(env, (jbyteArray)captureBuffer, (jbyte *)ptr, JNI_ABORT);
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case ENCODING_PCM_16BIT:
|
|
|
+ SDL_assert((*env)->GetArrayLength(env, (jshortArray)captureBuffer) == (buflen / sizeof(Sint16)));
|
|
|
br = (*env)->CallStaticIntMethod(env, mAudioManagerClass, midCaptureReadShortBuffer, (jshortArray)captureBuffer, JNI_TRUE);
|
|
|
if (br > 0) {
|
|
|
jshort *ptr = (*env)->GetShortArrayElements(env, (jshortArray)captureBuffer, &isCopy);
|
|
|
- br *= 2;
|
|
|
+ br *= sizeof(Sint16);
|
|
|
SDL_memcpy(buffer, ptr, br);
|
|
|
(*env)->ReleaseShortArrayElements(env, (jshortArray)captureBuffer, (jshort *)ptr, JNI_ABORT);
|
|
|
}
|
|
|
- } else {
|
|
|
- SDL_assert((*env)->GetArrayLength(env, (jshortArray)captureBuffer) == buflen);
|
|
|
- br = (*env)->CallStaticIntMethod(env, mAudioManagerClass, midCaptureReadByteBuffer, (jbyteArray)captureBuffer, JNI_TRUE);
|
|
|
+ break;
|
|
|
+ case ENCODING_PCM_FLOAT:
|
|
|
+ SDL_assert((*env)->GetArrayLength(env, (jfloatArray)captureBuffer) == (buflen / sizeof(float)));
|
|
|
+ br = (*env)->CallStaticIntMethod(env, mAudioManagerClass, midCaptureReadFloatBuffer, (jfloatArray)captureBuffer, JNI_TRUE);
|
|
|
if (br > 0) {
|
|
|
- jbyte *ptr = (*env)->GetByteArrayElements(env, (jbyteArray)captureBuffer, &isCopy);
|
|
|
+ jfloat *ptr = (*env)->GetFloatArrayElements(env, (jfloatArray)captureBuffer, &isCopy);
|
|
|
+ br *= sizeof(float);
|
|
|
SDL_memcpy(buffer, ptr, br);
|
|
|
- (*env)->ReleaseByteArrayElements(env, (jbyteArray)captureBuffer, (jbyte *)ptr, JNI_ABORT);
|
|
|
+ (*env)->ReleaseFloatArrayElements(env, (jfloatArray)captureBuffer, (jfloat *)ptr, JNI_ABORT);
|
|
|
}
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ __android_log_print(ANDROID_LOG_WARN, "SDL", "SDL audio: unhandled capture buffer format");
|
|
|
+ break;
|
|
|
}
|
|
|
-
|
|
|
- return (int) br;
|
|
|
+ return br;
|
|
|
}
|
|
|
|
|
|
void Android_JNI_FlushCapturedAudio(void)
|
|
|
{
|
|
|
JNIEnv *env = Android_JNI_GetEnv();
|
|
|
#if 0 /* !!! FIXME: this needs API 23, or it'll do blocking reads and never end. */
|
|
|
- if (captureBuffer16Bit) {
|
|
|
- const jint len = (*env)->GetArrayLength(env, (jshortArray)captureBuffer);
|
|
|
- while ((*env)->CallStaticIntMethod(env, mActivityClass, midCaptureReadShortBuffer, (jshortArray)captureBuffer, JNI_FALSE) == len) { /* spin */ }
|
|
|
- } else {
|
|
|
- const jint len = (*env)->GetArrayLength(env, (jbyteArray)captureBuffer);
|
|
|
- while ((*env)->CallStaticIntMethod(env, mActivityClass, midCaptureReadByteBuffer, (jbyteArray)captureBuffer, JNI_FALSE) == len) { /* spin */ }
|
|
|
+ switch (captureBufferFormat) {
|
|
|
+ case ENCODING_PCM_8BIT:
|
|
|
+ {
|
|
|
+ const jint len = (*env)->GetArrayLength(env, (jbyteArray)captureBuffer);
|
|
|
+ while ((*env)->CallStaticIntMethod(env, mActivityClass, midCaptureReadByteBuffer, (jbyteArray)captureBuffer, JNI_FALSE) == len) { /* spin */ }
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case ENCODING_PCM_16BIT:
|
|
|
+ {
|
|
|
+ const jint len = (*env)->GetArrayLength(env, (jshortArray)captureBuffer);
|
|
|
+ while ((*env)->CallStaticIntMethod(env, mActivityClass, midCaptureReadShortBuffer, (jshortArray)captureBuffer, JNI_FALSE) == len) { /* spin */ }
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case ENCODING_PCM_FLOAT:
|
|
|
+ {
|
|
|
+ const jint len = (*env)->GetArrayLength(env, (jfloatArray)captureBuffer);
|
|
|
+ while ((*env)->CallStaticIntMethod(env, mActivityClass, midCaptureReadFloatBuffer, (jfloatArray)captureBuffer, JNI_FALSE) == len) { /* spin */ }
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ __android_log_print(ANDROID_LOG_WARN, "SDL", "SDL audio: flushing unhandled capture buffer format");
|
|
|
+ break;
|
|
|
}
|
|
|
#else
|
|
|
- if (captureBuffer16Bit) {
|
|
|
- (*env)->CallStaticIntMethod(env, mAudioManagerClass, midCaptureReadShortBuffer, (jshortArray)captureBuffer, JNI_FALSE);
|
|
|
- } else {
|
|
|
+ switch (captureBufferFormat) {
|
|
|
+ case ENCODING_PCM_8BIT:
|
|
|
(*env)->CallStaticIntMethod(env, mAudioManagerClass, midCaptureReadByteBuffer, (jbyteArray)captureBuffer, JNI_FALSE);
|
|
|
+ break;
|
|
|
+ case ENCODING_PCM_16BIT:
|
|
|
+ (*env)->CallStaticIntMethod(env, mAudioManagerClass, midCaptureReadShortBuffer, (jshortArray)captureBuffer, JNI_FALSE);
|
|
|
+ break;
|
|
|
+ case ENCODING_PCM_FLOAT:
|
|
|
+ (*env)->CallStaticIntMethod(env, mAudioManagerClass, midCaptureReadFloatBuffer, (jfloatArray)captureBuffer, JNI_FALSE);
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ __android_log_print(ANDROID_LOG_WARN, "SDL", "SDL audio: flushing unhandled capture buffer format");
|
|
|
+ break;
|
|
|
}
|
|
|
#endif
|
|
|
}
|
|
@@ -1890,10 +2006,10 @@ void Android_JNI_PollHapticDevices(void)
|
|
|
(*env)->CallStaticVoidMethod(env, mControllerManagerClass, midPollHapticDevices);
|
|
|
}
|
|
|
|
|
|
-void Android_JNI_HapticRun(int device_id, int length)
|
|
|
+void Android_JNI_HapticRun(int device_id, float intensity, int length)
|
|
|
{
|
|
|
JNIEnv *env = Android_JNI_GetEnv();
|
|
|
- (*env)->CallStaticVoidMethod(env, mControllerManagerClass, midHapticRun, device_id, length);
|
|
|
+ (*env)->CallStaticVoidMethod(env, mControllerManagerClass, midHapticRun, device_id, intensity, length);
|
|
|
}
|
|
|
|
|
|
void Android_JNI_HapticStop(int device_id)
|