OSDN Git Service

Move channel index computation to native AudioTrack JNI
authorAndy Hung <hunga@google.com>
Fri, 24 Apr 2015 02:28:38 +0000 (19:28 -0700)
committerAndy Hung <hunga@google.com>
Fri, 24 Apr 2015 23:08:27 +0000 (16:08 -0700)
Change-Id: I047a9dcce13a38c11da165607d668dfb9d7fa335

core/jni/android_media_AudioTrack.cpp
media/java/android/media/AudioTrack.java

index 8b2c269..2f6a69c 100644 (file)
@@ -189,32 +189,44 @@ sp<AudioTrack> android_media_AudioTrack_getAudioTrack(JNIEnv* env, jobject audio
     return getAudioTrack(env, audioTrackObj);
 }
 
+// This function converts Java channel masks to a native channel mask.
+// validity should be checked with audio_is_output_channel().
+static inline audio_channel_mask_t nativeChannelMaskFromJavaChannelMasks(
+        jint channelPositionMask, jint channelIndexMask)
+{
+    if (channelIndexMask != 0) {  // channel index mask takes priority
+        // To convert to a native channel mask, the Java channel index mask
+        // requires adding the index representation.
+        return audio_channel_mask_from_representation_and_bits(
+                        AUDIO_CHANNEL_REPRESENTATION_INDEX,
+                        channelIndexMask);
+    }
+    // To convert to a native channel mask, the Java channel position mask
+    // requires a shift by 2 to skip the two deprecated channel
+    // configurations "default" and "mono".
+    return (audio_channel_mask_t)(channelPositionMask >> 2);
+}
+
 // ----------------------------------------------------------------------------
 static jint
 android_media_AudioTrack_setup(JNIEnv *env, jobject thiz, jobject weak_this,
         jobject jaa,
-        jint sampleRateInHertz, jint javaChannelMask,
+        jint sampleRateInHertz, jint channelPositionMask, jint channelIndexMask,
         jint audioFormat, jint buffSizeInBytes, jint memoryMode, jintArray jSession) {
 
-    ALOGV("sampleRate=%d, audioFormat(from Java)=%d, channel mask=%x, buffSize=%d",
-        sampleRateInHertz, audioFormat, javaChannelMask, buffSizeInBytes);
+    ALOGV("sampleRate=%d, channel mask=%x, index mask=%x, audioFormat(Java)=%d, buffSize=%d",
+        sampleRateInHertz, channelPositionMask, channelIndexMask, audioFormat, buffSizeInBytes);
 
     if (jaa == 0) {
         ALOGE("Error creating AudioTrack: invalid audio attributes");
         return (jint) AUDIO_JAVA_ERROR;
     }
 
-    // Java channel masks don't map directly to the native definition for positional
-    // channel masks: it's a shift by 2 to skip the two deprecated channel
-    // configurations "default" and "mono".
     // Invalid channel representations are caught by !audio_is_output_channel() below.
-    audio_channel_mask_t nativeChannelMask =
-            audio_channel_mask_get_representation(javaChannelMask)
-                == AUDIO_CHANNEL_REPRESENTATION_POSITION
-            ? javaChannelMask >> 2 : javaChannelMask;
-
+    audio_channel_mask_t nativeChannelMask = nativeChannelMaskFromJavaChannelMasks(
+            channelPositionMask, channelIndexMask);
     if (!audio_is_output_channel(nativeChannelMask)) {
-        ALOGE("Error creating AudioTrack: invalid channel mask %#x.", javaChannelMask);
+        ALOGE("Error creating AudioTrack: invalid native channel mask %#x.", nativeChannelMask);
         return (jint) AUDIOTRACK_ERROR_SETUP_INVALIDCHANNELMASK;
     }
 
@@ -982,7 +994,7 @@ static JNINativeMethod gMethods[] = {
     {"native_stop",          "()V",      (void *)android_media_AudioTrack_stop},
     {"native_pause",         "()V",      (void *)android_media_AudioTrack_pause},
     {"native_flush",         "()V",      (void *)android_media_AudioTrack_flush},
-    {"native_setup",     "(Ljava/lang/Object;Ljava/lang/Object;IIIII[I)I",
+    {"native_setup",     "(Ljava/lang/Object;Ljava/lang/Object;IIIIII[I)I",
                                          (void *)android_media_AudioTrack_setup},
     {"native_finalize",      "()V",      (void *)android_media_AudioTrack_finalize},
     {"native_release",       "()V",      (void *)android_media_AudioTrack_release},
index 847bdc2..147d7fc 100644 (file)
@@ -491,7 +491,7 @@ public class AudioTrack
         session[0] = sessionId;
         // native initialization
         int initResult = native_setup(new WeakReference<AudioTrack>(this), mAttributes,
-                mSampleRate, mChannels, mAudioFormat,
+                mSampleRate, mChannels, mChannelIndexMask, mAudioFormat,
                 mNativeBufferSizeInBytes, mDataLoadMode, session);
         if (initResult != SUCCESS) {
             loge("Error code "+initResult+" when initializing AudioTrack.");
@@ -701,48 +701,6 @@ public class AudioTrack
             AudioFormat.CHANNEL_OUT_SIDE_LEFT |
             AudioFormat.CHANNEL_OUT_SIDE_RIGHT;
 
-    // Java channel mask definitions below match those
-    // in /system/core/include/system/audio.h in the JNI code of AudioTrack.
-
-    // internal maximum size for bits parameter, not part of public API
-    private static final int AUDIO_CHANNEL_BITS_LOG2 = 30;
-
-    // log(2) of maximum number of representations, not part of public API
-    private static final int AUDIO_CHANNEL_REPRESENTATION_LOG2 = 2;
-
-    // used to create a channel index mask or channel position mask
-    // with getChannelMaskFromRepresentationAndBits();
-    private static final int CHANNEL_OUT_REPRESENTATION_POSITION = 0;
-    private static final int CHANNEL_OUT_REPRESENTATION_INDEX = 2;
-
-    /**
-     * Return the channel mask from its representation and bits.
-     *
-     * This creates a channel mask for mChannels which combines a
-     * representation field and a bits field.  This is for internal
-     * communication to native code, not part of the public API.
-     *
-     * @param representation the type of channel mask,
-     *   either CHANNEL_OUT_REPRESENTATION_POSITION
-     *   or CHANNEL_OUT_REPRESENTATION_INDEX
-     * @param bits is the channel bits specifying occupancy
-     * @return the channel mask
-     * @throws java.lang.IllegalArgumentException if representation is not recognized or
-     *   the bits field is not acceptable for that representation
-     */
-    private static int getChannelMaskFromRepresentationAndBits(int representation, int bits) {
-        switch (representation) {
-        case CHANNEL_OUT_REPRESENTATION_POSITION:
-        case CHANNEL_OUT_REPRESENTATION_INDEX:
-            if ((bits & ~((1 << AUDIO_CHANNEL_BITS_LOG2) - 1)) != 0) {
-                throw new IllegalArgumentException("invalid bits " + bits);
-            }
-            return representation << AUDIO_CHANNEL_BITS_LOG2 | bits;
-        default:
-            throw new IllegalArgumentException("invalid representation " + representation);
-        }
-    }
-
     // Convenience method for the constructor's parameter checks.
     // This is where constructor IllegalArgumentException-s are thrown
     // postconditions:
@@ -804,11 +762,6 @@ public class AudioTrack
             } else if (mChannelCount != channelIndexCount) {
                 throw new IllegalArgumentException("Channel count must match");
             }
-
-            // AudioTrack prefers to use the channel index configuration
-            // over the channel position configuration if both are specified.
-            mChannels = getChannelMaskFromRepresentationAndBits(
-                    CHANNEL_OUT_REPRESENTATION_INDEX, mChannelIndexMask);
         }
 
         //--------------
@@ -2361,7 +2314,7 @@ public class AudioTrack
     //     AudioAttributes.USAGE_MEDIA will map to AudioManager.STREAM_MUSIC
     private native final int native_setup(Object /*WeakReference<AudioTrack>*/ audiotrack_this,
             Object /*AudioAttributes*/ attributes,
-            int sampleRate, int channelMask, int audioFormat,
+            int sampleRate, int channelMask, int channelIndexMask, int audioFormat,
             int buffSizeInBytes, int mode, int[] sessionId);
 
     private native final void native_finalize();