Home | History | Annotate | Download | only in alsa_sound
      1 /* AudioUtil.cpp
      2  *
      3  * Copyright (C) 2012 The Android Open Source Project
      4  *
      5  * Licensed under the Apache License, Version 2.0 (the "License");
      6  * you may not use this file except in compliance with the License.
      7  * You may obtain a copy of the License at
      8  *
      9  *      http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  * Unless required by applicable law or agreed to in writing, software
     12  * distributed under the License is distributed on an "AS IS" BASIS,
     13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  * See the License for the specific language governing permissions and
     15  * limitations under the License.
     16  */
     17 
     18 #define LOG_TAG "AudioUtil"
     19 //#define LOG_NDEBUG 0
     20 #include <utils/Log.h>
     21 
     22 #include "AudioUtil.h"
     23 
     24 int AudioUtil::printFormatFromEDID(unsigned char format) {
     25     switch (format) {
     26     case LPCM:
     27         ALOGV("Format:LPCM");
     28         break;
     29     case AC3:
     30         ALOGV("Format:AC-3");
     31         break;
     32     case MPEG1:
     33         ALOGV("Format:MPEG1 (Layers 1 & 2)");
     34         break;
     35     case MP3:
     36         ALOGV("Format:MP3 (MPEG1 Layer 3)");
     37         break;
     38     case MPEG2_MULTI_CHANNEL:
     39         ALOGV("Format:MPEG2 (multichannel)");
     40         break;
     41     case AAC:
     42         ALOGV("Format:AAC");
     43         break;
     44     case DTS:
     45         ALOGV("Format:DTS");
     46         break;
     47     case ATRAC:
     48         ALOGV("Format:ATRAC");
     49         break;
     50     case SACD:
     51         ALOGV("Format:One-bit audio aka SACD");
     52         break;
     53     case DOLBY_DIGITAL_PLUS:
     54         ALOGV("Format:Dolby Digital +");
     55         break;
     56     case DTS_HD:
     57         ALOGV("Format:DTS-HD");
     58         break;
     59     case MAT:
     60         ALOGV("Format:MAT (MLP)");
     61         break;
     62     case DST:
     63         ALOGV("Format:DST");
     64         break;
     65     case WMA_PRO:
     66         ALOGV("Format:WMA Pro");
     67         break;
     68     default:
     69         ALOGV("Invalid format ID....");
     70         break;
     71     }
     72     return format;
     73 }
     74 
     75 int AudioUtil::getSamplingFrequencyFromEDID(unsigned char byte) {
     76     int nFreq = 0;
     77 
     78     if (byte & BIT(6)) {
     79         ALOGV("192kHz");
     80         nFreq = 192000;
     81     } else if (byte & BIT(5)) {
     82         ALOGV("176kHz");
     83         nFreq = 176000;
     84     } else if (byte & BIT(4)) {
     85         ALOGV("96kHz");
     86         nFreq = 96000;
     87     } else if (byte & BIT(3)) {
     88         ALOGV("88.2kHz");
     89         nFreq = 88200;
     90     } else if (byte & BIT(2)) {
     91         ALOGV("48kHz");
     92         nFreq = 48000;
     93     } else if (byte & BIT(1)) {
     94         ALOGV("44.1kHz");
     95         nFreq = 44100;
     96     } else if (byte & BIT(0)) {
     97         ALOGV("32kHz");
     98         nFreq = 32000;
     99     }
    100     return nFreq;
    101 }
    102 
    103 int AudioUtil::getBitsPerSampleFromEDID(unsigned char byte,
    104     unsigned char format) {
    105     int nBitsPerSample = 0;
    106     if (format == 1) {
    107         if (byte & BIT(2)) {
    108             ALOGV("24bit");
    109             nBitsPerSample = 24;
    110         } else if (byte & BIT(1)) {
    111             ALOGV("20bit");
    112             nBitsPerSample = 20;
    113         } else if (byte & BIT(0)) {
    114             ALOGV("16bit");
    115             nBitsPerSample = 16;
    116         }
    117     } else {
    118         ALOGV("not lpcm format, return 0");
    119         return 0;
    120     }
    121     return nBitsPerSample;
    122 }
    123 
    124 bool AudioUtil::getHDMIAudioSinkCaps(EDID_AUDIO_INFO* pInfo) {
    125     unsigned char channels[16];
    126     unsigned char formats[16];
    127     unsigned char frequency[16];
    128     unsigned char bitrate[16];
    129     unsigned char* data = NULL;
    130     unsigned char* original_data_ptr = NULL;
    131     int count = 0;
    132     bool bRet = false;
    133     const char* file = "/sys/class/graphics/fb1/audio_data_block";
    134     FILE* fpaudiocaps = fopen(file, "rb");
    135     if (fpaudiocaps) {
    136         ALOGV("opened audio_caps successfully...");
    137         fseek(fpaudiocaps, 0, SEEK_END);
    138         long size = ftell(fpaudiocaps);
    139         ALOGV("audiocaps size is %ld\n",size);
    140         data = (unsigned char*) malloc(size);
    141         if (data) {
    142             fseek(fpaudiocaps, 0, SEEK_SET);
    143             original_data_ptr = data;
    144             fread(data, 1, size, fpaudiocaps);
    145         }
    146         fclose(fpaudiocaps);
    147     } else {
    148         ALOGE("failed to open audio_caps");
    149     }
    150 
    151     if (pInfo && data) {
    152         int length = 0;
    153         memcpy(&count,  data, sizeof(int));
    154         data+= sizeof(int);
    155         ALOGV("#Audio Block Count is %d",count);
    156         memcpy(&length, data, sizeof(int));
    157         data += sizeof(int);
    158         ALOGV("Total length is %d",length);
    159         unsigned int sad[MAX_SHORT_AUDIO_DESC_CNT];
    160         int nblockindex = 0;
    161         int nCountDesc = 0;
    162         while (length >= MIN_AUDIO_DESC_LENGTH && count < MAX_SHORT_AUDIO_DESC_CNT) {
    163             sad[nblockindex] = (unsigned int)data[0] + ((unsigned int)data[1] << 8)
    164                                + ((unsigned int)data[2] << 16);
    165             nblockindex+=1;
    166             nCountDesc++;
    167             length -= MIN_AUDIO_DESC_LENGTH;
    168             data += MIN_AUDIO_DESC_LENGTH;
    169         }
    170         memset(pInfo, 0, sizeof(EDID_AUDIO_INFO));
    171         pInfo->nAudioBlocks = nCountDesc;
    172         ALOGV("Total # of audio descriptors %d",nCountDesc);
    173         int nIndex = 0;
    174         while (nCountDesc--) {
    175               channels [nIndex]   = (sad[nIndex] & 0x7) + 1;
    176               formats  [nIndex]   = (sad[nIndex] & 0xFF) >> 3;
    177               frequency[nIndex]   = (sad[nIndex] >> 8) & 0xFF;
    178               bitrate  [nIndex]   = (sad[nIndex] >> 16) & 0xFF;
    179               nIndex++;
    180         }
    181         bRet = true;
    182         for (int i = 0; i < pInfo->nAudioBlocks; i++) {
    183             ALOGV("AUDIO DESC BLOCK # %d\n",i);
    184 
    185             pInfo->AudioBlocksArray[i].nChannels = channels[i];
    186             ALOGV("pInfo->AudioBlocksArray[i].nChannels %d\n", pInfo->AudioBlocksArray[i].nChannels);
    187 
    188             ALOGV("Format Byte %d\n", formats[i]);
    189             pInfo->AudioBlocksArray[i].nFormatId = (EDID_AUDIO_FORMAT_ID)printFormatFromEDID(formats[i]);
    190             ALOGV("pInfo->AudioBlocksArray[i].nFormatId %d",pInfo->AudioBlocksArray[i].nFormatId);
    191 
    192             ALOGV("Frequency Byte %d\n", frequency[i]);
    193             pInfo->AudioBlocksArray[i].nSamplingFreq = getSamplingFrequencyFromEDID(frequency[i]);
    194             ALOGV("pInfo->AudioBlocksArray[i].nSamplingFreq %d",pInfo->AudioBlocksArray[i].nSamplingFreq);
    195 
    196             ALOGV("BitsPerSample Byte %d\n", bitrate[i]);
    197             pInfo->AudioBlocksArray[i].nBitsPerSample = getBitsPerSampleFromEDID(bitrate[i],formats[i]);
    198             ALOGV("pInfo->AudioBlocksArray[i].nBitsPerSample %d",pInfo->AudioBlocksArray[i].nBitsPerSample);
    199         }
    200             getSpeakerAllocation(pInfo);
    201     }
    202     if (original_data_ptr)
    203         free(original_data_ptr);
    204 
    205     return bRet;
    206 }
    207 
    208 bool AudioUtil::getSpeakerAllocation(EDID_AUDIO_INFO* pInfo) {
    209     int count = 0;
    210     bool bRet = false;
    211     unsigned char* data = NULL;
    212     unsigned char* original_data_ptr = NULL;
    213     const char* spkrfile = "/sys/class/graphics/fb1/spkr_alloc_data_block";
    214     FILE* fpspkrfile = fopen(spkrfile, "rb");
    215     if(fpspkrfile) {
    216         ALOGV("opened spkr_alloc_data_block successfully...");
    217         fseek(fpspkrfile,0,SEEK_END);
    218         long size = ftell(fpspkrfile);
    219         ALOGV("fpspkrfile size is %ld\n",size);
    220         data = (unsigned char*)malloc(size);
    221         if(data) {
    222             original_data_ptr = data;
    223             fseek(fpspkrfile,0,SEEK_SET);
    224             fread(data,1,size,fpspkrfile);
    225         }
    226         fclose(fpspkrfile);
    227     } else {
    228         ALOGE("failed to open fpspkrfile");
    229     }
    230 
    231     if(pInfo && data) {
    232         int length = 0;
    233         memcpy(&count,  data, sizeof(int));
    234         ALOGV("Count is %d",count);
    235         data += sizeof(int);
    236         memcpy(&length, data, sizeof(int));
    237         ALOGV("Total length is %d",length);
    238         data+= sizeof(int);
    239         ALOGV("Total speaker allocation Block count # %d\n",count);
    240         bRet = true;
    241         for (int i = 0; i < count; i++) {
    242             ALOGV("Speaker Allocation BLOCK # %d\n",i);
    243             pInfo->nSpeakerAllocation[0] = data[0];
    244             pInfo->nSpeakerAllocation[1] = data[1];
    245             pInfo->nSpeakerAllocation[2] = data[2];
    246             ALOGV("pInfo->nSpeakerAllocation %x %x %x\n", data[0],data[1],data[2]);
    247 
    248 
    249             if (pInfo->nSpeakerAllocation[0] & BIT(7)) {
    250                  ALOGV("FLW/FRW");
    251             } else if (pInfo->nSpeakerAllocation[0] & BIT(6)) {
    252                  ALOGV("RLC/RRC");
    253             } else if (pInfo->nSpeakerAllocation[0] & BIT(5)) {
    254                  ALOGV("FLC/FRC");
    255             } else if (pInfo->nSpeakerAllocation[0] & BIT(4)) {
    256                 ALOGV("RC");
    257             } else if (pInfo->nSpeakerAllocation[0] & BIT(3)) {
    258                 ALOGV("RL/RR");
    259             } else if (pInfo->nSpeakerAllocation[0] & BIT(2)) {
    260                 ALOGV("FC");
    261             } else if (pInfo->nSpeakerAllocation[0] & BIT(1)) {
    262                 ALOGV("LFE");
    263             } else if (pInfo->nSpeakerAllocation[0] & BIT(0)) {
    264                 ALOGV("FL/FR");
    265             }
    266 
    267             if (pInfo->nSpeakerAllocation[1] & BIT(2)) {
    268                 ALOGV("FCH");
    269             } else if (pInfo->nSpeakerAllocation[1] & BIT(1)) {
    270                 ALOGV("TC");
    271             } else if (pInfo->nSpeakerAllocation[1] & BIT(0)) {
    272                 ALOGV("FLH/FRH");
    273             }
    274         }
    275     }
    276     if (original_data_ptr)
    277         free(original_data_ptr);
    278     return bRet;
    279 }
    280