+static bool
+AudioTrack_GetChanOrder( int i_mask, uint32_t p_chans_out[] )
+{
+#define HAS_CHAN( x ) ( ( i_mask & (jfields.AudioFormat.x) ) == (jfields.AudioFormat.x) )
+ const int i_sides = jfields.AudioFormat.CHANNEL_OUT_SIDE_LEFT |
+ jfields.AudioFormat.CHANNEL_OUT_SIDE_RIGHT;
+ const int i_backs = jfields.AudioFormat.CHANNEL_OUT_BACK_LEFT |
+ jfields.AudioFormat.CHANNEL_OUT_BACK_RIGHT;
+
+ /* verify has FL/FR */
+ if ( !HAS_CHAN( CHANNEL_OUT_STEREO ) )
+ return false;
+
+ /* verify uses SIDE as a pair (ok if not using SIDE at all) */
+ bool b_has_sides = false;
+ if( jfields.AudioFormat.has_CHANNEL_OUT_SIDE && ( i_mask & i_sides ) != 0 )
+ {
+ if( ( i_mask & i_sides ) != i_sides )
+ return false;
+ b_has_sides = true;
+ }
+ /* verify uses BACK as a pair (ok if not using BACK at all) */
+ bool b_has_backs = false;
+ if( ( i_mask & i_backs ) != 0 )
+ {
+ if( ( i_mask & i_backs ) != i_backs )
+ return false;
+ b_has_backs = true;
+ }
+
+ const bool b_has_FC = HAS_CHAN( CHANNEL_OUT_FRONT_CENTER );
+ const bool b_has_LFE = HAS_CHAN( CHANNEL_OUT_LOW_FREQUENCY );
+ const bool b_has_BC = HAS_CHAN( CHANNEL_OUT_BACK_CENTER );
+
+ /* compute at what index each channel is: samples will be in the following
+ * order: FL FR FC LFE BL BR BC SL SR
+ * when a channel is not present, its index is set to the same as the index
+ * of the preceding channel. */
+
+ const int i_FC = b_has_FC ? 2 : 1;
+ const int i_LFE = b_has_LFE ? i_FC + 1 : i_FC;
+ const int i_BL = b_has_backs ? i_LFE + 1 : i_LFE;
+ const int i_BR = b_has_backs ? i_BL + 1 : i_BL;
+ const int i_BC = b_has_BC ? i_BR + 1 : i_BR;
+ const int i_SL = b_has_sides ? i_BC + 1 : i_BC;
+ const int i_SR = b_has_sides ? i_SL + 1 : i_SL;
+
+ p_chans_out[0] = AOUT_CHAN_LEFT;
+ p_chans_out[1] = AOUT_CHAN_RIGHT;
+ if( b_has_FC )
+ p_chans_out[i_FC] = AOUT_CHAN_CENTER;
+ if( b_has_LFE )
+ p_chans_out[i_LFE] = AOUT_CHAN_LFE;
+ if( b_has_backs )
+ {
+ p_chans_out[i_BL] = AOUT_CHAN_REARLEFT;
+ p_chans_out[i_BR] = AOUT_CHAN_REARRIGHT;
+ }
+ if( b_has_BC )
+ p_chans_out[i_BC] = AOUT_CHAN_REARCENTER;
+ if( b_has_sides )
+ {
+ p_chans_out[i_SL] = AOUT_CHAN_MIDDLELEFT;
+ p_chans_out[i_SR] = AOUT_CHAN_MIDDLERIGHT;
+ }
+
+#undef HAS_CHAN
+ return true;
+}
+
+
+/**
+ * Configure and create an Android AudioTrack.
+ * returns -1 on critical error, 0 on success, 1 on configuration error
+ */