1ff25010cb77455a46357d6dd012631a2599d7bf4Glenn Kasten/*
2ff25010cb77455a46357d6dd012631a2599d7bf4Glenn Kasten * Copyright (C) 2015 The Android Open Source Project
3ff25010cb77455a46357d6dd012631a2599d7bf4Glenn Kasten *
4ff25010cb77455a46357d6dd012631a2599d7bf4Glenn Kasten * Licensed under the Apache License, Version 2.0 (the "License");
5ff25010cb77455a46357d6dd012631a2599d7bf4Glenn Kasten * you may not use this file except in compliance with the License.
6ff25010cb77455a46357d6dd012631a2599d7bf4Glenn Kasten * You may obtain a copy of the License at
7ff25010cb77455a46357d6dd012631a2599d7bf4Glenn Kasten *
8ff25010cb77455a46357d6dd012631a2599d7bf4Glenn Kasten *      http://www.apache.org/licenses/LICENSE-2.0
9ff25010cb77455a46357d6dd012631a2599d7bf4Glenn Kasten *
10ff25010cb77455a46357d6dd012631a2599d7bf4Glenn Kasten * Unless required by applicable law or agreed to in writing, software
11ff25010cb77455a46357d6dd012631a2599d7bf4Glenn Kasten * distributed under the License is distributed on an "AS IS" BASIS,
12ff25010cb77455a46357d6dd012631a2599d7bf4Glenn Kasten * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13ff25010cb77455a46357d6dd012631a2599d7bf4Glenn Kasten * See the License for the specific language governing permissions and
14ff25010cb77455a46357d6dd012631a2599d7bf4Glenn Kasten * limitations under the License.
15ff25010cb77455a46357d6dd012631a2599d7bf4Glenn Kasten */
16ff25010cb77455a46357d6dd012631a2599d7bf4Glenn Kasten
174e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean#include "sles_allinclusive.h"
18680943a4c349712f641b7577e5b0a3fdf49e39d9Glenn Kasten#include <system/audio.h>
194e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean#include <SLES/OpenSLES_Android.h>
20ff25010cb77455a46357d6dd012631a2599d7bf4Glenn Kasten#include "channels.h"
21ff25010cb77455a46357d6dd012631a2599d7bf4Glenn Kasten
224e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean
234e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean/*
244e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean * Return the default OpenSL ES output channel mask (as used in SLDataFormat_PCM.channelMask)
254e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean * for the specified channel count.
264e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean *
274e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean * OpenSL ES makes no distinction between input and output channel masks, but
284e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean * Android does. This is the OUTPUT version of this function.
294e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean */
304e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLeanSLuint32 sles_channel_out_mask_from_count(unsigned channelCount)
31ff25010cb77455a46357d6dd012631a2599d7bf4Glenn Kasten{
32ff25010cb77455a46357d6dd012631a2599d7bf4Glenn Kasten    // FIXME channel mask is not yet implemented by Stagefright, so use a reasonable default
33ff25010cb77455a46357d6dd012631a2599d7bf4Glenn Kasten    //       that is computed from the channel count
34680943a4c349712f641b7577e5b0a3fdf49e39d9Glenn Kasten    if (channelCount > FCC_8) {
354e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean        return SL_ANDROID_UNKNOWN_CHANNELMASK;
36680943a4c349712f641b7577e5b0a3fdf49e39d9Glenn Kasten    }
37ff25010cb77455a46357d6dd012631a2599d7bf4Glenn Kasten    switch (channelCount) {
38ff25010cb77455a46357d6dd012631a2599d7bf4Glenn Kasten    case 1:
39ff25010cb77455a46357d6dd012631a2599d7bf4Glenn Kasten        // see explanation in data.c re: default channel mask for mono
40ff25010cb77455a46357d6dd012631a2599d7bf4Glenn Kasten        return SL_SPEAKER_FRONT_LEFT;
41ff25010cb77455a46357d6dd012631a2599d7bf4Glenn Kasten    case 2:
42ff25010cb77455a46357d6dd012631a2599d7bf4Glenn Kasten        return SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT;
43ff25010cb77455a46357d6dd012631a2599d7bf4Glenn Kasten    // Android-specific
4484bbadf848f606ff28273baf26fc246cf967059aAndy Hung    case 3:
4584bbadf848f606ff28273baf26fc246cf967059aAndy Hung        return SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT | SL_SPEAKER_FRONT_CENTER;
46ff25010cb77455a46357d6dd012631a2599d7bf4Glenn Kasten    case 4:
47ff25010cb77455a46357d6dd012631a2599d7bf4Glenn Kasten        return SL_ANDROID_SPEAKER_QUAD;
4884bbadf848f606ff28273baf26fc246cf967059aAndy Hung    case 5:
4984bbadf848f606ff28273baf26fc246cf967059aAndy Hung        return SL_ANDROID_SPEAKER_QUAD | SL_SPEAKER_FRONT_CENTER;
50ff25010cb77455a46357d6dd012631a2599d7bf4Glenn Kasten    case 6:
51ff25010cb77455a46357d6dd012631a2599d7bf4Glenn Kasten        return SL_ANDROID_SPEAKER_5DOT1;
5284bbadf848f606ff28273baf26fc246cf967059aAndy Hung    case 7:
5384bbadf848f606ff28273baf26fc246cf967059aAndy Hung        return SL_ANDROID_SPEAKER_5DOT1 | SL_SPEAKER_BACK_CENTER;
54ff25010cb77455a46357d6dd012631a2599d7bf4Glenn Kasten    case 8:
55ff25010cb77455a46357d6dd012631a2599d7bf4Glenn Kasten        return SL_ANDROID_SPEAKER_7DOT1;
564e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean    // FIXME FCC_8
57ff25010cb77455a46357d6dd012631a2599d7bf4Glenn Kasten    default:
584e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean        return SL_ANDROID_UNKNOWN_CHANNELMASK;
594e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean    }
604e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean}
614e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean
624e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean/*
634e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean * Return the default OpenSL ES input channel mask (as used in SLDataFormat_PCM.channelMask)
644e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean * for the specified channel count.
654e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean *
664e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean * OpenSL ES makes no distinction between input and output channel masks, but
674e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean * Android does. This is the INPUT version of this function.
684e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean */
694e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLeanSLuint32 sles_channel_in_mask_from_count(unsigned channelCount) {
704e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean    switch (channelCount) {
714e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean        case 1:
724e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean            return SL_SPEAKER_FRONT_LEFT;
734e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean        case 2:
744e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean            return SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT;
754e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean        default: {
764e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean            if (channelCount > AUDIO_CHANNEL_COUNT_MAX) {
774e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean                return SL_ANDROID_UNKNOWN_CHANNELMASK;
784e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean            } else {
794e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean                SLuint32 bitfield = (1 << channelCount) - 1;
804e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean                return SL_ANDROID_MAKE_INDEXED_CHANNEL_MASK(bitfield);
814e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean            }
824e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean        }
834e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean
844e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean    }
854e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean}
864e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean
874e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean/*
884e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean * Get the number of active channels in an OpenSL ES channel mask.
894e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean *
904e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean * This function is valid for both input and output
914e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean * masks.
924e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean */
934e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLeanSLuint32 sles_channel_count_from_mask(SLuint32 mask) {
944e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean    audio_channel_representation_t rep
954e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean        = sles_to_audio_channel_mask_representation(mask);
964e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean
974e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean    if (rep == AUDIO_CHANNEL_REPRESENTATION_INDEX) {
984e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean        mask &= SL_ANDROID_INDEXED_SPEAKER_MASK_ALL;
994e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean        return popcount(mask);
1004e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean    } else if (rep == AUDIO_CHANNEL_REPRESENTATION_POSITION){
1014e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean        mask &= SL_ANDROID_POSITIONAL_SPEAKER_MASK_ALL;
1024e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean        return popcount(mask);
1034e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean    } else {
1044e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean        return 0;
1054e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean    }
1064e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean}
1074e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean
1084e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean/*
1094e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean * Helper to determine whether a channel mask is indexed or not.
1104e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean *
1114e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean * This is the OpenSL ES analog to audio_channel_mask_get_representation().
1124e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean */
1134e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLeanaudio_channel_representation_t sles_to_audio_channel_mask_representation(SLuint32 mask) {
1144e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean    if (mask & SL_ANDROID_SPEAKER_NON_POSITIONAL) {
1154e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean        return AUDIO_CHANNEL_REPRESENTATION_INDEX;
1164e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean    } else {
1174e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean        return AUDIO_CHANNEL_REPRESENTATION_POSITION;
1184e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean    }
1194e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean}
1204e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean
1214e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean// helper struct for the two static arrays which follow.
1224e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLeanstruct channel_map {
1234e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean    SLuint32 sles;
1244e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean    audio_channel_mask_t android;
1254e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean};
1264e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean
1274e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean// In practice this map is unnecessary, because the SL definitions just
1284e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean// happen to match the android definitions perfectly, but we can't rely
1294e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean// on that fact since the two sets of definitions have different API
1304e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean// contracts.
1314e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLeanstatic const struct channel_map output_map[] = {
1324e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean    { SL_SPEAKER_FRONT_LEFT, AUDIO_CHANNEL_OUT_FRONT_LEFT },
1334e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean    { SL_SPEAKER_FRONT_RIGHT, AUDIO_CHANNEL_OUT_FRONT_RIGHT },
1344e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean    { SL_SPEAKER_FRONT_CENTER, AUDIO_CHANNEL_OUT_FRONT_CENTER },
1354e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean    { SL_SPEAKER_LOW_FREQUENCY, AUDIO_CHANNEL_OUT_LOW_FREQUENCY },
1364e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean    { SL_SPEAKER_BACK_LEFT, AUDIO_CHANNEL_OUT_BACK_LEFT },
1374e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean    { SL_SPEAKER_BACK_RIGHT, AUDIO_CHANNEL_OUT_BACK_RIGHT },
1384e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean    { SL_SPEAKER_FRONT_LEFT_OF_CENTER, AUDIO_CHANNEL_OUT_FRONT_LEFT_OF_CENTER },
1394e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean    { SL_SPEAKER_FRONT_RIGHT_OF_CENTER, AUDIO_CHANNEL_OUT_FRONT_RIGHT_OF_CENTER },
1404e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean    { SL_SPEAKER_BACK_CENTER, AUDIO_CHANNEL_OUT_BACK_CENTER },
1414e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean    { SL_SPEAKER_SIDE_LEFT, AUDIO_CHANNEL_OUT_SIDE_LEFT },
1424e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean    { SL_SPEAKER_SIDE_RIGHT, AUDIO_CHANNEL_OUT_SIDE_RIGHT },
1434e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean    { SL_SPEAKER_TOP_CENTER, AUDIO_CHANNEL_OUT_TOP_CENTER },
1444e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean    { SL_SPEAKER_TOP_FRONT_LEFT, AUDIO_CHANNEL_OUT_TOP_FRONT_LEFT },
1454e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean    { SL_SPEAKER_TOP_FRONT_CENTER, AUDIO_CHANNEL_OUT_TOP_FRONT_CENTER },
1464e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean    { SL_SPEAKER_TOP_FRONT_RIGHT, AUDIO_CHANNEL_OUT_TOP_FRONT_RIGHT },
1474e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean    { SL_SPEAKER_TOP_BACK_LEFT, AUDIO_CHANNEL_OUT_TOP_BACK_LEFT },
1484e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean    { SL_SPEAKER_TOP_BACK_CENTER, AUDIO_CHANNEL_OUT_TOP_BACK_CENTER },
1494e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean    { SL_SPEAKER_TOP_BACK_RIGHT, AUDIO_CHANNEL_OUT_TOP_BACK_RIGHT },
1504e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean};
1514e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLeanstatic const unsigned int nOutputChannelMappings = sizeof(output_map) / sizeof(output_map[0]);
1524e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean
1534e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean// This map is quite sparse, because there really isn't a reasonable mapping
1544e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean// between most of the SL_SPEAKER bits and the android input map. It's probably
1554e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean// best to use channel indices instead.
1564e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLeanstatic const struct channel_map input_map[] = {
1574e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean        { SL_SPEAKER_FRONT_LEFT, AUDIO_CHANNEL_IN_LEFT },
1584e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean        { SL_SPEAKER_FRONT_RIGHT, AUDIO_CHANNEL_IN_RIGHT },
1594e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean};
1604e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLeanstatic const unsigned int nInputChannelMappings = sizeof(input_map) / sizeof(input_map[0]);
1614e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean
1624e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean// Core channel mask mapper; implementation common to both input and output
1634e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLeanstatic audio_channel_mask_t sles_to_android_mask_helper(
1644e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean        SLuint32 mask,
1654e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean        const struct channel_map* map,
1664e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean        unsigned int nMappings) {
1674e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean    if (!sles_is_channel_mask_valid(mask)) {
1684e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean        SL_LOGW("Channel mask %#x is invalid because it uses bits that are undefined.", mask);
1694e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean        return AUDIO_CHANNEL_INVALID;
1704e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean    }
1714e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean
1724e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean    // determine whether this mask uses positional or indexed representation
1734e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean    audio_channel_representation_t rep = sles_to_audio_channel_mask_representation(mask);
1744e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean
1754e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean    uint32_t bitsOut = 0;
1764e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean    uint32_t bitsIn = mask;
1774e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean    if (rep == AUDIO_CHANNEL_REPRESENTATION_INDEX) {
1784e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean        // Indexed masks need no mapping
1794e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean        bitsIn &= SL_ANDROID_INDEXED_SPEAKER_MASK_ALL;
1804e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean        bitsOut = bitsIn;
1814e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean    } else if (rep == AUDIO_CHANNEL_REPRESENTATION_POSITION){
1824e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean        // positional masks get mapped from OpenSLES speaker definitions
1834e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean        // to the channel definitions we use internally.
1844e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean        bitsIn &= SL_ANDROID_POSITIONAL_SPEAKER_MASK_ALL;
1854e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean        for (unsigned int i = 0; i < nMappings; ++i) {
1864e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean            if (bitsIn & map[i].sles) {
1874e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean                bitsOut |= map[i].android;
1884e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean            }
1894e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean        }
1904e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean    } else {
1914e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean        SL_LOGE("Unrecognized channel representation %#x", rep);
1924e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean    }
1934e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean
19433f46b8cd9ece650736a4aa5294318c6b51b2ffdilewis    uint32_t result = audio_channel_mask_from_representation_and_bits(
19533f46b8cd9ece650736a4aa5294318c6b51b2ffdilewis            rep,
19633f46b8cd9ece650736a4aa5294318c6b51b2ffdilewis            bitsOut);
19733f46b8cd9ece650736a4aa5294318c6b51b2ffdilewis
1984e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean    if (popcount(bitsIn) != popcount(bitsOut)) {
1994e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean        // At this point mask has already been stripped of the
2004e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean        // representation bitsOut, so its bitcount should equal the number
2014e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean        // of channels requested. If the bitcount of 'bitsOut' isn't
2024e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean        // the same, then we're unable to provide the number of
2034e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean        // channels that the app requested. That will cause an
2044e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean        // error downstream if the app doesn't correct it, so
2054e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean        // issue a warning here.
20633f46b8cd9ece650736a4aa5294318c6b51b2ffdilewis        SL_LOGW("Conversion from OpenSL ES %s channel mask %#x to Android mask %#x %s channels",
20733f46b8cd9ece650736a4aa5294318c6b51b2ffdilewis                (rep == AUDIO_CHANNEL_REPRESENTATION_POSITION) ? "positional" : "indexed",
2084e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean                mask,
20933f46b8cd9ece650736a4aa5294318c6b51b2ffdilewis                result,
21033f46b8cd9ece650736a4aa5294318c6b51b2ffdilewis                (popcount(bitsIn) < popcount(bitsOut)) ? "gains" : "loses");
2114e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean    }
2124e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean
21333f46b8cd9ece650736a4aa5294318c6b51b2ffdilewis    return result;
2144e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean}
2154e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean
2164e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean/*
2174e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean * Return an android output channel mask, as used in the AudioTrack constructor.
2184e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean */
2194e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLeanaudio_channel_mask_t sles_to_audio_output_channel_mask(SLuint32 mask) {
2204e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean    return sles_to_android_mask_helper(mask, output_map, nOutputChannelMappings);
2214e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean}
2224e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean
2234e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean/*
2244e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean * Return an android input channel mask, as used in the AudioRecord constructor.
2254e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean */
2264e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLeanaudio_channel_mask_t sles_to_audio_input_channel_mask(SLuint32 mask) {
2274e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean    return sles_to_android_mask_helper(mask, input_map, nInputChannelMappings);
2284e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean}
2294e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean
2304e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean/*
2314e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean * Check the mask for undefined bits (that is, set bits that don't correspond to a channel).
2324e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean *
2334e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean * Returns SL_BOOLEAN_TRUE if no undefined bits are set; SL_BOOLEAN_FALSE otherwise.
2344e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean */
2354e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLeanSLboolean sles_is_channel_mask_valid(SLuint32 mask) {
2364e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean    SLuint32 undefinedMask;
2374e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean    if (sles_to_audio_channel_mask_representation(mask) == AUDIO_CHANNEL_REPRESENTATION_POSITION) {
2384e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean        undefinedMask =  ~SL_ANDROID_POSITIONAL_SPEAKER_MASK_ALL;
2394e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean    } else {
2404e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean        undefinedMask
2414e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean                = ~(SL_ANDROID_MAKE_INDEXED_CHANNEL_MASK(SL_ANDROID_INDEXED_SPEAKER_MASK_ALL));
242ff25010cb77455a46357d6dd012631a2599d7bf4Glenn Kasten    }
2434e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean    return (mask & undefinedMask) ? SL_BOOLEAN_FALSE : SL_BOOLEAN_TRUE;
244ff25010cb77455a46357d6dd012631a2599d7bf4Glenn Kasten}
245