xref: /aosp_15_r20/frameworks/wilhelm/src/android/channels.cpp (revision bebae9c0e76121f8312ccb50385c080b3a0b023c)
1*bebae9c0SAndroid Build Coastguard Worker /*
2*bebae9c0SAndroid Build Coastguard Worker  * Copyright (C) 2015 The Android Open Source Project
3*bebae9c0SAndroid Build Coastguard Worker  *
4*bebae9c0SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*bebae9c0SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*bebae9c0SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*bebae9c0SAndroid Build Coastguard Worker  *
8*bebae9c0SAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*bebae9c0SAndroid Build Coastguard Worker  *
10*bebae9c0SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*bebae9c0SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*bebae9c0SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*bebae9c0SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*bebae9c0SAndroid Build Coastguard Worker  * limitations under the License.
15*bebae9c0SAndroid Build Coastguard Worker  */
16*bebae9c0SAndroid Build Coastguard Worker 
17*bebae9c0SAndroid Build Coastguard Worker #include "sles_allinclusive.h"
18*bebae9c0SAndroid Build Coastguard Worker #include <cutils/bitops.h>
19*bebae9c0SAndroid Build Coastguard Worker #include <system/audio.h>
20*bebae9c0SAndroid Build Coastguard Worker #include <SLES/OpenSLES_Android.h>
21*bebae9c0SAndroid Build Coastguard Worker #include "channels.h"
22*bebae9c0SAndroid Build Coastguard Worker 
23*bebae9c0SAndroid Build Coastguard Worker 
24*bebae9c0SAndroid Build Coastguard Worker /*
25*bebae9c0SAndroid Build Coastguard Worker  * Return the default OpenSL ES output channel mask (as used in SLDataFormat_PCM.channelMask)
26*bebae9c0SAndroid Build Coastguard Worker  * for the specified channel count.
27*bebae9c0SAndroid Build Coastguard Worker  *
28*bebae9c0SAndroid Build Coastguard Worker  * OpenSL ES makes no distinction between input and output channel masks, but
29*bebae9c0SAndroid Build Coastguard Worker  * Android does. This is the OUTPUT version of this function.
30*bebae9c0SAndroid Build Coastguard Worker  */
sles_channel_out_mask_from_count(unsigned channelCount)31*bebae9c0SAndroid Build Coastguard Worker SLuint32 sles_channel_out_mask_from_count(unsigned channelCount)
32*bebae9c0SAndroid Build Coastguard Worker {
33*bebae9c0SAndroid Build Coastguard Worker     // FIXME channel mask is not yet implemented by Stagefright, so use a reasonable default
34*bebae9c0SAndroid Build Coastguard Worker     //       that is computed from the channel count
35*bebae9c0SAndroid Build Coastguard Worker     if (channelCount > FCC_8) {
36*bebae9c0SAndroid Build Coastguard Worker         return SL_ANDROID_UNKNOWN_CHANNELMASK;
37*bebae9c0SAndroid Build Coastguard Worker     }
38*bebae9c0SAndroid Build Coastguard Worker     switch (channelCount) {
39*bebae9c0SAndroid Build Coastguard Worker     case 1:
40*bebae9c0SAndroid Build Coastguard Worker         // see explanation in data.c re: default channel mask for mono
41*bebae9c0SAndroid Build Coastguard Worker         return SL_SPEAKER_FRONT_LEFT;
42*bebae9c0SAndroid Build Coastguard Worker     case 2:
43*bebae9c0SAndroid Build Coastguard Worker         return SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT;
44*bebae9c0SAndroid Build Coastguard Worker     // Android-specific
45*bebae9c0SAndroid Build Coastguard Worker     case 3:
46*bebae9c0SAndroid Build Coastguard Worker         return SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT | SL_SPEAKER_FRONT_CENTER;
47*bebae9c0SAndroid Build Coastguard Worker     case 4:
48*bebae9c0SAndroid Build Coastguard Worker         return SL_ANDROID_SPEAKER_QUAD;
49*bebae9c0SAndroid Build Coastguard Worker     case 5:
50*bebae9c0SAndroid Build Coastguard Worker         return SL_ANDROID_SPEAKER_QUAD | SL_SPEAKER_FRONT_CENTER;
51*bebae9c0SAndroid Build Coastguard Worker     case 6:
52*bebae9c0SAndroid Build Coastguard Worker         return SL_ANDROID_SPEAKER_5DOT1;
53*bebae9c0SAndroid Build Coastguard Worker     case 7:
54*bebae9c0SAndroid Build Coastguard Worker         return SL_ANDROID_SPEAKER_5DOT1 | SL_SPEAKER_BACK_CENTER;
55*bebae9c0SAndroid Build Coastguard Worker     case 8:
56*bebae9c0SAndroid Build Coastguard Worker         return SL_ANDROID_SPEAKER_7DOT1;
57*bebae9c0SAndroid Build Coastguard Worker     // FIXME FCC_8
58*bebae9c0SAndroid Build Coastguard Worker     default:
59*bebae9c0SAndroid Build Coastguard Worker         return SL_ANDROID_UNKNOWN_CHANNELMASK;
60*bebae9c0SAndroid Build Coastguard Worker     }
61*bebae9c0SAndroid Build Coastguard Worker }
62*bebae9c0SAndroid Build Coastguard Worker 
63*bebae9c0SAndroid Build Coastguard Worker /*
64*bebae9c0SAndroid Build Coastguard Worker  * Return the default OpenSL ES input channel mask (as used in SLDataFormat_PCM.channelMask)
65*bebae9c0SAndroid Build Coastguard Worker  * for the specified channel count.
66*bebae9c0SAndroid Build Coastguard Worker  *
67*bebae9c0SAndroid Build Coastguard Worker  * OpenSL ES makes no distinction between input and output channel masks, but
68*bebae9c0SAndroid Build Coastguard Worker  * Android does. This is the INPUT version of this function.
69*bebae9c0SAndroid Build Coastguard Worker  */
sles_channel_in_mask_from_count(unsigned channelCount)70*bebae9c0SAndroid Build Coastguard Worker SLuint32 sles_channel_in_mask_from_count(unsigned channelCount) {
71*bebae9c0SAndroid Build Coastguard Worker     switch (channelCount) {
72*bebae9c0SAndroid Build Coastguard Worker         case 1:
73*bebae9c0SAndroid Build Coastguard Worker             return SL_SPEAKER_FRONT_LEFT;
74*bebae9c0SAndroid Build Coastguard Worker         case 2:
75*bebae9c0SAndroid Build Coastguard Worker             return SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT;
76*bebae9c0SAndroid Build Coastguard Worker         default: {
77*bebae9c0SAndroid Build Coastguard Worker             if (channelCount > AUDIO_CHANNEL_COUNT_MAX) {
78*bebae9c0SAndroid Build Coastguard Worker                 return SL_ANDROID_UNKNOWN_CHANNELMASK;
79*bebae9c0SAndroid Build Coastguard Worker             } else {
80*bebae9c0SAndroid Build Coastguard Worker                 SLuint32 bitfield = (1 << channelCount) - 1;
81*bebae9c0SAndroid Build Coastguard Worker                 return SL_ANDROID_MAKE_INDEXED_CHANNEL_MASK(bitfield);
82*bebae9c0SAndroid Build Coastguard Worker             }
83*bebae9c0SAndroid Build Coastguard Worker         }
84*bebae9c0SAndroid Build Coastguard Worker 
85*bebae9c0SAndroid Build Coastguard Worker     }
86*bebae9c0SAndroid Build Coastguard Worker }
87*bebae9c0SAndroid Build Coastguard Worker 
88*bebae9c0SAndroid Build Coastguard Worker /*
89*bebae9c0SAndroid Build Coastguard Worker  * Get the number of active channels in an OpenSL ES channel mask.
90*bebae9c0SAndroid Build Coastguard Worker  *
91*bebae9c0SAndroid Build Coastguard Worker  * This function is valid for both input and output
92*bebae9c0SAndroid Build Coastguard Worker  * masks.
93*bebae9c0SAndroid Build Coastguard Worker  */
sles_channel_count_from_mask(SLuint32 mask)94*bebae9c0SAndroid Build Coastguard Worker SLuint32 sles_channel_count_from_mask(SLuint32 mask) {
95*bebae9c0SAndroid Build Coastguard Worker     audio_channel_representation_t rep
96*bebae9c0SAndroid Build Coastguard Worker         = sles_to_audio_channel_mask_representation(mask);
97*bebae9c0SAndroid Build Coastguard Worker 
98*bebae9c0SAndroid Build Coastguard Worker     if (rep == AUDIO_CHANNEL_REPRESENTATION_INDEX) {
99*bebae9c0SAndroid Build Coastguard Worker         mask &= SL_ANDROID_INDEXED_SPEAKER_MASK_ALL;
100*bebae9c0SAndroid Build Coastguard Worker         return popcount(mask);
101*bebae9c0SAndroid Build Coastguard Worker     } else if (rep == AUDIO_CHANNEL_REPRESENTATION_POSITION){
102*bebae9c0SAndroid Build Coastguard Worker         mask &= SL_ANDROID_POSITIONAL_SPEAKER_MASK_ALL;
103*bebae9c0SAndroid Build Coastguard Worker         return popcount(mask);
104*bebae9c0SAndroid Build Coastguard Worker     } else {
105*bebae9c0SAndroid Build Coastguard Worker         return 0;
106*bebae9c0SAndroid Build Coastguard Worker     }
107*bebae9c0SAndroid Build Coastguard Worker }
108*bebae9c0SAndroid Build Coastguard Worker 
109*bebae9c0SAndroid Build Coastguard Worker /*
110*bebae9c0SAndroid Build Coastguard Worker  * Helper to determine whether a channel mask is indexed or not.
111*bebae9c0SAndroid Build Coastguard Worker  *
112*bebae9c0SAndroid Build Coastguard Worker  * This is the OpenSL ES analog to audio_channel_mask_get_representation().
113*bebae9c0SAndroid Build Coastguard Worker  */
sles_to_audio_channel_mask_representation(SLuint32 mask)114*bebae9c0SAndroid Build Coastguard Worker audio_channel_representation_t sles_to_audio_channel_mask_representation(SLuint32 mask) {
115*bebae9c0SAndroid Build Coastguard Worker     if (mask & SL_ANDROID_SPEAKER_NON_POSITIONAL) {
116*bebae9c0SAndroid Build Coastguard Worker         return AUDIO_CHANNEL_REPRESENTATION_INDEX;
117*bebae9c0SAndroid Build Coastguard Worker     } else {
118*bebae9c0SAndroid Build Coastguard Worker         return AUDIO_CHANNEL_REPRESENTATION_POSITION;
119*bebae9c0SAndroid Build Coastguard Worker     }
120*bebae9c0SAndroid Build Coastguard Worker }
121*bebae9c0SAndroid Build Coastguard Worker 
122*bebae9c0SAndroid Build Coastguard Worker // helper struct for the two static arrays which follow.
123*bebae9c0SAndroid Build Coastguard Worker struct channel_map {
124*bebae9c0SAndroid Build Coastguard Worker     SLuint32 sles;
125*bebae9c0SAndroid Build Coastguard Worker     audio_channel_mask_t android;
126*bebae9c0SAndroid Build Coastguard Worker };
127*bebae9c0SAndroid Build Coastguard Worker 
128*bebae9c0SAndroid Build Coastguard Worker // In practice this map is unnecessary, because the SL definitions just
129*bebae9c0SAndroid Build Coastguard Worker // happen to match the android definitions perfectly, but we can't rely
130*bebae9c0SAndroid Build Coastguard Worker // on that fact since the two sets of definitions have different API
131*bebae9c0SAndroid Build Coastguard Worker // contracts.
132*bebae9c0SAndroid Build Coastguard Worker static const struct channel_map output_map[] = {
133*bebae9c0SAndroid Build Coastguard Worker     { SL_SPEAKER_FRONT_LEFT, AUDIO_CHANNEL_OUT_FRONT_LEFT },
134*bebae9c0SAndroid Build Coastguard Worker     { SL_SPEAKER_FRONT_RIGHT, AUDIO_CHANNEL_OUT_FRONT_RIGHT },
135*bebae9c0SAndroid Build Coastguard Worker     { SL_SPEAKER_FRONT_CENTER, AUDIO_CHANNEL_OUT_FRONT_CENTER },
136*bebae9c0SAndroid Build Coastguard Worker     { SL_SPEAKER_LOW_FREQUENCY, AUDIO_CHANNEL_OUT_LOW_FREQUENCY },
137*bebae9c0SAndroid Build Coastguard Worker     { SL_SPEAKER_BACK_LEFT, AUDIO_CHANNEL_OUT_BACK_LEFT },
138*bebae9c0SAndroid Build Coastguard Worker     { SL_SPEAKER_BACK_RIGHT, AUDIO_CHANNEL_OUT_BACK_RIGHT },
139*bebae9c0SAndroid Build Coastguard Worker     { SL_SPEAKER_FRONT_LEFT_OF_CENTER, AUDIO_CHANNEL_OUT_FRONT_LEFT_OF_CENTER },
140*bebae9c0SAndroid Build Coastguard Worker     { SL_SPEAKER_FRONT_RIGHT_OF_CENTER, AUDIO_CHANNEL_OUT_FRONT_RIGHT_OF_CENTER },
141*bebae9c0SAndroid Build Coastguard Worker     { SL_SPEAKER_BACK_CENTER, AUDIO_CHANNEL_OUT_BACK_CENTER },
142*bebae9c0SAndroid Build Coastguard Worker     { SL_SPEAKER_SIDE_LEFT, AUDIO_CHANNEL_OUT_SIDE_LEFT },
143*bebae9c0SAndroid Build Coastguard Worker     { SL_SPEAKER_SIDE_RIGHT, AUDIO_CHANNEL_OUT_SIDE_RIGHT },
144*bebae9c0SAndroid Build Coastguard Worker     { SL_SPEAKER_TOP_CENTER, AUDIO_CHANNEL_OUT_TOP_CENTER },
145*bebae9c0SAndroid Build Coastguard Worker     { SL_SPEAKER_TOP_FRONT_LEFT, AUDIO_CHANNEL_OUT_TOP_FRONT_LEFT },
146*bebae9c0SAndroid Build Coastguard Worker     { SL_SPEAKER_TOP_FRONT_CENTER, AUDIO_CHANNEL_OUT_TOP_FRONT_CENTER },
147*bebae9c0SAndroid Build Coastguard Worker     { SL_SPEAKER_TOP_FRONT_RIGHT, AUDIO_CHANNEL_OUT_TOP_FRONT_RIGHT },
148*bebae9c0SAndroid Build Coastguard Worker     { SL_SPEAKER_TOP_BACK_LEFT, AUDIO_CHANNEL_OUT_TOP_BACK_LEFT },
149*bebae9c0SAndroid Build Coastguard Worker     { SL_SPEAKER_TOP_BACK_CENTER, AUDIO_CHANNEL_OUT_TOP_BACK_CENTER },
150*bebae9c0SAndroid Build Coastguard Worker     { SL_SPEAKER_TOP_BACK_RIGHT, AUDIO_CHANNEL_OUT_TOP_BACK_RIGHT },
151*bebae9c0SAndroid Build Coastguard Worker };
152*bebae9c0SAndroid Build Coastguard Worker static const unsigned int nOutputChannelMappings = sizeof(output_map) / sizeof(output_map[0]);
153*bebae9c0SAndroid Build Coastguard Worker 
154*bebae9c0SAndroid Build Coastguard Worker // This map is quite sparse, because there really isn't a reasonable mapping
155*bebae9c0SAndroid Build Coastguard Worker // between most of the SL_SPEAKER bits and the android input map. It's probably
156*bebae9c0SAndroid Build Coastguard Worker // best to use channel indices instead.
157*bebae9c0SAndroid Build Coastguard Worker static const struct channel_map input_map[] = {
158*bebae9c0SAndroid Build Coastguard Worker         { SL_SPEAKER_FRONT_LEFT, AUDIO_CHANNEL_IN_LEFT },
159*bebae9c0SAndroid Build Coastguard Worker         { SL_SPEAKER_FRONT_RIGHT, AUDIO_CHANNEL_IN_RIGHT },
160*bebae9c0SAndroid Build Coastguard Worker };
161*bebae9c0SAndroid Build Coastguard Worker static const unsigned int nInputChannelMappings = sizeof(input_map) / sizeof(input_map[0]);
162*bebae9c0SAndroid Build Coastguard Worker 
163*bebae9c0SAndroid Build Coastguard Worker // Core channel mask mapper; implementation common to both input and output
sles_to_android_mask_helper(SLuint32 mask,const struct channel_map * map,unsigned int nMappings)164*bebae9c0SAndroid Build Coastguard Worker static audio_channel_mask_t sles_to_android_mask_helper(
165*bebae9c0SAndroid Build Coastguard Worker         SLuint32 mask,
166*bebae9c0SAndroid Build Coastguard Worker         const struct channel_map* map,
167*bebae9c0SAndroid Build Coastguard Worker         unsigned int nMappings) {
168*bebae9c0SAndroid Build Coastguard Worker     if (!sles_is_channel_mask_valid(mask)) {
169*bebae9c0SAndroid Build Coastguard Worker         SL_LOGW("Channel mask %#x is invalid because it uses bits that are undefined.", mask);
170*bebae9c0SAndroid Build Coastguard Worker         return AUDIO_CHANNEL_INVALID;
171*bebae9c0SAndroid Build Coastguard Worker     }
172*bebae9c0SAndroid Build Coastguard Worker 
173*bebae9c0SAndroid Build Coastguard Worker     // determine whether this mask uses positional or indexed representation
174*bebae9c0SAndroid Build Coastguard Worker     audio_channel_representation_t rep = sles_to_audio_channel_mask_representation(mask);
175*bebae9c0SAndroid Build Coastguard Worker 
176*bebae9c0SAndroid Build Coastguard Worker     uint32_t bitsOut = 0;
177*bebae9c0SAndroid Build Coastguard Worker     uint32_t bitsIn = mask;
178*bebae9c0SAndroid Build Coastguard Worker     if (rep == AUDIO_CHANNEL_REPRESENTATION_INDEX) {
179*bebae9c0SAndroid Build Coastguard Worker         // Indexed masks need no mapping
180*bebae9c0SAndroid Build Coastguard Worker         bitsIn &= SL_ANDROID_INDEXED_SPEAKER_MASK_ALL;
181*bebae9c0SAndroid Build Coastguard Worker         bitsOut = bitsIn;
182*bebae9c0SAndroid Build Coastguard Worker     } else if (rep == AUDIO_CHANNEL_REPRESENTATION_POSITION){
183*bebae9c0SAndroid Build Coastguard Worker         // positional masks get mapped from OpenSLES speaker definitions
184*bebae9c0SAndroid Build Coastguard Worker         // to the channel definitions we use internally.
185*bebae9c0SAndroid Build Coastguard Worker         bitsIn &= SL_ANDROID_POSITIONAL_SPEAKER_MASK_ALL;
186*bebae9c0SAndroid Build Coastguard Worker         for (unsigned int i = 0; i < nMappings; ++i) {
187*bebae9c0SAndroid Build Coastguard Worker             if (bitsIn & map[i].sles) {
188*bebae9c0SAndroid Build Coastguard Worker                 bitsOut |= map[i].android;
189*bebae9c0SAndroid Build Coastguard Worker             }
190*bebae9c0SAndroid Build Coastguard Worker         }
191*bebae9c0SAndroid Build Coastguard Worker     } else {
192*bebae9c0SAndroid Build Coastguard Worker         SL_LOGE("Unrecognized channel representation %#x", rep);
193*bebae9c0SAndroid Build Coastguard Worker     }
194*bebae9c0SAndroid Build Coastguard Worker 
195*bebae9c0SAndroid Build Coastguard Worker     audio_channel_mask_t result = audio_channel_mask_from_representation_and_bits(
196*bebae9c0SAndroid Build Coastguard Worker             rep,
197*bebae9c0SAndroid Build Coastguard Worker             bitsOut);
198*bebae9c0SAndroid Build Coastguard Worker 
199*bebae9c0SAndroid Build Coastguard Worker     if (popcount(bitsIn) != popcount(bitsOut)) {
200*bebae9c0SAndroid Build Coastguard Worker         // At this point mask has already been stripped of the
201*bebae9c0SAndroid Build Coastguard Worker         // representation bitsOut, so its bitcount should equal the number
202*bebae9c0SAndroid Build Coastguard Worker         // of channels requested. If the bitcount of 'bitsOut' isn't
203*bebae9c0SAndroid Build Coastguard Worker         // the same, then we're unable to provide the number of
204*bebae9c0SAndroid Build Coastguard Worker         // channels that the app requested. That will cause an
205*bebae9c0SAndroid Build Coastguard Worker         // error downstream if the app doesn't correct it, so
206*bebae9c0SAndroid Build Coastguard Worker         // issue a warning here.
207*bebae9c0SAndroid Build Coastguard Worker         SL_LOGW("Conversion from OpenSL ES %s channel mask %#x to Android mask %#x %s channels",
208*bebae9c0SAndroid Build Coastguard Worker                 (rep == AUDIO_CHANNEL_REPRESENTATION_POSITION) ? "positional" : "indexed",
209*bebae9c0SAndroid Build Coastguard Worker                 mask,
210*bebae9c0SAndroid Build Coastguard Worker                 result,
211*bebae9c0SAndroid Build Coastguard Worker                 (popcount(bitsIn) < popcount(bitsOut)) ? "gains" : "loses");
212*bebae9c0SAndroid Build Coastguard Worker     }
213*bebae9c0SAndroid Build Coastguard Worker 
214*bebae9c0SAndroid Build Coastguard Worker     return result;
215*bebae9c0SAndroid Build Coastguard Worker }
216*bebae9c0SAndroid Build Coastguard Worker 
217*bebae9c0SAndroid Build Coastguard Worker /*
218*bebae9c0SAndroid Build Coastguard Worker  * Return an android output channel mask, as used in the AudioTrack constructor.
219*bebae9c0SAndroid Build Coastguard Worker  */
sles_to_audio_output_channel_mask(SLuint32 mask)220*bebae9c0SAndroid Build Coastguard Worker audio_channel_mask_t sles_to_audio_output_channel_mask(SLuint32 mask) {
221*bebae9c0SAndroid Build Coastguard Worker     return sles_to_android_mask_helper(mask, output_map, nOutputChannelMappings);
222*bebae9c0SAndroid Build Coastguard Worker }
223*bebae9c0SAndroid Build Coastguard Worker 
224*bebae9c0SAndroid Build Coastguard Worker /*
225*bebae9c0SAndroid Build Coastguard Worker  * Return an android input channel mask, as used in the AudioRecord constructor.
226*bebae9c0SAndroid Build Coastguard Worker  */
sles_to_audio_input_channel_mask(SLuint32 mask)227*bebae9c0SAndroid Build Coastguard Worker audio_channel_mask_t sles_to_audio_input_channel_mask(SLuint32 mask) {
228*bebae9c0SAndroid Build Coastguard Worker     return sles_to_android_mask_helper(mask, input_map, nInputChannelMappings);
229*bebae9c0SAndroid Build Coastguard Worker }
230*bebae9c0SAndroid Build Coastguard Worker 
231*bebae9c0SAndroid Build Coastguard Worker /*
232*bebae9c0SAndroid Build Coastguard Worker  * Check the mask for undefined bits (that is, set bits that don't correspond to a channel).
233*bebae9c0SAndroid Build Coastguard Worker  *
234*bebae9c0SAndroid Build Coastguard Worker  * Returns SL_BOOLEAN_TRUE if no undefined bits are set; SL_BOOLEAN_FALSE otherwise.
235*bebae9c0SAndroid Build Coastguard Worker  */
sles_is_channel_mask_valid(SLuint32 mask)236*bebae9c0SAndroid Build Coastguard Worker SLboolean sles_is_channel_mask_valid(SLuint32 mask) {
237*bebae9c0SAndroid Build Coastguard Worker     SLuint32 undefinedMask;
238*bebae9c0SAndroid Build Coastguard Worker     if (sles_to_audio_channel_mask_representation(mask) == AUDIO_CHANNEL_REPRESENTATION_POSITION) {
239*bebae9c0SAndroid Build Coastguard Worker         undefinedMask =  ~SL_ANDROID_POSITIONAL_SPEAKER_MASK_ALL;
240*bebae9c0SAndroid Build Coastguard Worker     } else {
241*bebae9c0SAndroid Build Coastguard Worker         undefinedMask
242*bebae9c0SAndroid Build Coastguard Worker                 = ~(SL_ANDROID_MAKE_INDEXED_CHANNEL_MASK(SL_ANDROID_INDEXED_SPEAKER_MASK_ALL));
243*bebae9c0SAndroid Build Coastguard Worker     }
244*bebae9c0SAndroid Build Coastguard Worker     return (mask & undefinedMask) ? SL_BOOLEAN_FALSE : SL_BOOLEAN_TRUE;
245*bebae9c0SAndroid Build Coastguard Worker }
246