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
printFormatFromEDID(unsigned char format)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
getSamplingFrequencyFromEDID(unsigned char byte)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
getBitsPerSampleFromEDID(unsigned char byte,unsigned char format)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
getHDMIAudioSinkCaps(EDID_AUDIO_INFO * pInfo)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
getSpeakerAllocation(EDID_AUDIO_INFO * pInfo)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