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 24int 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 75int 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 103int 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 124bool 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 208bool 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