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