From 951b4518c11af31d9e6a29aa40b9dbeae677f71f Mon Sep 17 00:00:00 2001 From: Aaron Culliney Date: Sun, 28 Jun 2015 12:49:26 -0700 Subject: [PATCH] Expose device-preferred audio parameters to native --- .../org/deadc0de/apple2ix/Apple2Activity.java | 29 +++++++++++++++++-- .../apple2ix/DevicePropertyCalculator.java | 12 ++++---- Android/jni/android_globals.h | 15 ++++++++++ Android/jni/jnihooks.c | 10 ++++++- src/common.h | 4 +++ 5 files changed, 60 insertions(+), 10 deletions(-) create mode 100644 Android/jni/android_globals.h diff --git a/Android/app/src/main/java/org/deadc0de/apple2ix/Apple2Activity.java b/Android/app/src/main/java/org/deadc0de/apple2ix/Apple2Activity.java index a8c33e12..b031243e 100644 --- a/Android/app/src/main/java/org/deadc0de/apple2ix/Apple2Activity.java +++ b/Android/app/src/main/java/org/deadc0de/apple2ix/Apple2Activity.java @@ -49,6 +49,10 @@ public class Apple2Activity extends Activity { private int mWidth = 0; private int mHeight = 0; + private int mSampleRate = 0; + private int mMonoBufferSize = 0; + private int mStereoBufferSize = 0; + private float[] mXCoords = new float[MAX_FINGERS]; private float[] mYCoords = new float[MAX_FINGERS]; @@ -56,7 +60,7 @@ public class Apple2Activity extends Activity { System.loadLibrary("apple2ix"); } - private native void nativeOnCreate(String dataDir); + private native void nativeOnCreate(String dataDir, int sampleRate, int monoBufferSize, int stereoBufferSize); private native void nativeGraphicsInitialized(int width, int height); private native void nativeGraphicsChanged(int width, int height); private native void nativeOnKeyDown(int keyCode, int metaState); @@ -182,6 +186,15 @@ public class Apple2Activity extends Activity { traceBuffer.append("\n"); traceBuffer.append(Build.DEVICE); traceBuffer.append("\n"); + traceBuffer.append("Device sample rate:"); + traceBuffer.append(mSampleRate); + traceBuffer.append("\n"); + traceBuffer.append("Device mono buffer size:"); + traceBuffer.append(mMonoBufferSize); + traceBuffer.append("\n"); + traceBuffer.append("Device stereo buffer size:"); + traceBuffer.append(mStereoBufferSize); + traceBuffer.append("\n"); // now append the actual stack trace traceBuffer.append(t.getClass().getName()); @@ -208,11 +221,22 @@ public class Apple2Activity extends Activity { Log.e(TAG, "onCreate()"); mDataDir = firstTimeInitialization(); - nativeOnCreate(mDataDir); + + // get device audio parameters for native OpenSLES + mSampleRate = DevicePropertyCalculator.getRecommendedSampleRate(this); + mMonoBufferSize = DevicePropertyCalculator.getRecommendedBufferSize(this, /*isStereo:*/false); + mStereoBufferSize = DevicePropertyCalculator.getRecommendedBufferSize(this, /*isStereo:*/true); + Log.d(TAG, "Device sampleRate:"+mSampleRate+" mono bufferSize:"+mMonoBufferSize+" stereo bufferSize:"+mStereoBufferSize); + + nativeOnCreate(mDataDir, mSampleRate, mMonoBufferSize, mStereoBufferSize); mView = new Apple2View(this); setContentView(mView); + // Another Android Annoyance ... + // Even though we no longer use the system soft keyboard (which would definitely trigger width/height changes to our OpenGL canvas), + // we still need to listen to dimension changes, because it seems on some janky devices you have an incorrect width/height set when + // the initial OpenGL onSurfaceChanged() callback occurs. For now, include this defensive coding... mView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { public void onGlobalLayout() { Rect rect = new Rect(); @@ -225,7 +249,6 @@ public class Apple2Activity extends Activity { w = h; h = w_; } - // I actually think this whole observer is now spurious ... but it's triggering SEGFAULT ... should investigate ... nativeGraphicsChanged(w, h); } }); diff --git a/Android/app/src/main/java/org/deadc0de/apple2ix/DevicePropertyCalculator.java b/Android/app/src/main/java/org/deadc0de/apple2ix/DevicePropertyCalculator.java index 4a3528aa..4acb758d 100644 --- a/Android/app/src/main/java/org/deadc0de/apple2ix/DevicePropertyCalculator.java +++ b/Android/app/src/main/java/org/deadc0de/apple2ix/DevicePropertyCalculator.java @@ -108,7 +108,7 @@ public final class DevicePropertyCalculator * @param aContext {Context} * @return {int} */ - public static int getRecommendedBufferSize( Context aContext ) + public static int getRecommendedBufferSize( Context aContext, boolean isStereo) { // prepare Native Audio engine String BS_CHECK = null; @@ -121,14 +121,14 @@ public final class DevicePropertyCalculator BS_CHECK = am.getProperty( AudioManager.PROPERTY_OUTPUT_FRAMES_PER_BUFFER ); } return ( BS_CHECK != null ) ? Integer.parseInt( BS_CHECK ) : AudioTrack.getMinBufferSize( getRecommendedSampleRate( aContext ), - AudioFormat.CHANNEL_OUT_MONO, + isStereo ? AudioFormat.CHANNEL_OUT_STEREO : AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT ); } - public static int getMinimumBufferSize( Context aContext ) + public static int getMinimumBufferSize( Context aContext, boolean isStereo ) { // minimum buffer size we allow is the recommendation divided by four - int min = DevicePropertyCalculator.getRecommendedBufferSize( aContext ) / 4; + int min = DevicePropertyCalculator.getRecommendedBufferSize( aContext, isStereo ) / 4; // however, we'd like to supply tha rea of 64 samples per buffer as an option while ( min > 128 ) min /= 2; // 128 as we do a greater than check @@ -140,9 +140,9 @@ public final class DevicePropertyCalculator return min; } - public static int getMaximumBufferSize( Context aContext ) + public static int getMaximumBufferSize( Context aContext, boolean isStereo ) { - int max = DevicePropertyCalculator.getRecommendedBufferSize( aContext ) * 8; + int max = DevicePropertyCalculator.getRecommendedBufferSize( aContext, isStereo ) * 8; // nothing TOO extravagant... 8192 should be enough... while ( max > 10000 ) diff --git a/Android/jni/android_globals.h b/Android/jni/android_globals.h new file mode 100644 index 00000000..aa522c93 --- /dev/null +++ b/Android/jni/android_globals.h @@ -0,0 +1,15 @@ +/* + * Apple // emulator for *nix + * + * This software package is subject to the GNU General Public License + * version 2 or later (your choice) as published by the Free Software + * Foundation. + * + * THERE ARE NO WARRANTIES WHATSOEVER. + * + */ + +extern unsigned long android_deviceSampleRateHz; +extern unsigned long android_monoBufferSize; +extern unsigned long android_stereoBufferSize; + diff --git a/Android/jni/jnihooks.c b/Android/jni/jnihooks.c index eea9a582..6b4319c4 100644 --- a/Android/jni/jnihooks.c +++ b/Android/jni/jnihooks.c @@ -14,6 +14,10 @@ #include +unsigned long android_deviceSampleRateHz = 0; +unsigned long android_monoBufferSize = 0; +unsigned long android_stereoBufferSize = 0; + enum { ANDROID_ACTION_DOWN = 0x0, ANDROID_ACTION_UP = 0x1, @@ -81,7 +85,7 @@ static void _nativeRequestsShowMainMenu(void) { // ---------------------------------------------------------------------------- // JNI functions -void Java_org_deadc0de_apple2ix_Apple2Activity_nativeOnCreate(JNIEnv *env, jobject obj, jstring j_dataDir) { +void Java_org_deadc0de_apple2ix_Apple2Activity_nativeOnCreate(JNIEnv *env, jobject obj, jstring j_dataDir, jint sampleRate, jint monoBufferSize, jint stereoBufferSize) { const char *dataDir = (*env)->GetStringUTFChars(env, j_dataDir, 0); // Android lifecycle can call onCreate() multiple times... @@ -94,6 +98,10 @@ void Java_org_deadc0de_apple2ix_Apple2Activity_nativeOnCreate(JNIEnv *env, jobje (*env)->ReleaseStringUTFChars(env, j_dataDir, dataDir); LOG("nativeOnCreate(%s)...", data_dir); + android_deviceSampleRateHz = (unsigned long)sampleRate; + android_monoBufferSize = (unsigned long)monoBufferSize; + android_stereoBufferSize = (unsigned long)stereoBufferSize; + #if TESTING _run_tests(); #else diff --git a/src/common.h b/src/common.h index 20c4687c..8420f82a 100644 --- a/src/common.h +++ b/src/common.h @@ -96,6 +96,10 @@ static inline GLenum safeGLGetError(void) { #include "audio/mockingboard.h" #endif +#ifdef ANDROID +#include "../Android/jni/android_globals.h" +#endif + #define PATH_SEPARATOR "/" // =P #if !defined(MIN)