Home | History | Annotate | Download | only in android
      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  */
     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  */
     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  */
     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  */
    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
    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  */
    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  */
    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  */
    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