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;
}
{"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},
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.");
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:
} 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);
}
//--------------
// 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();