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