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 audio_channel_mask_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