1 /*
2  * Copyright (C) 2017 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 package com.android.cts.verifier.audio.audiolib;
18 
19 import android.media.AudioFormat;
20 import android.media.AudioRecord;
21 import android.media.AudioTrack;
22 
23 import java.util.HashMap;
24 
25 // TODO - This functionality probably exists in the framework function. Remove this and
26 //    use that instead.
27 public class AudioUtils {
28     @SuppressWarnings("unused")
29     private static final String TAG = "AudioUtils";
30 
countIndexChannels(int chanConfig)31     public static int countIndexChannels(int chanConfig) {
32         return Integer.bitCount(chanConfig & ~0x80000000);
33     }
34 
countToIndexMask(int chanCount)35     public static int countToIndexMask(int chanCount) {
36         return (1 << chanCount) - 1;
37     }
38 
countToOutPositionMask(int channelCount)39     public static int countToOutPositionMask(int channelCount) {
40         switch (channelCount) {
41             case 1:
42                 return AudioFormat.CHANNEL_OUT_MONO;
43 
44             case 2:
45                 return AudioFormat.CHANNEL_OUT_STEREO;
46 
47             case 4:
48                 return AudioFormat.CHANNEL_OUT_QUAD;
49 
50             default:
51                 return AudioTrack.ERROR_BAD_VALUE;
52         }
53     }
54 
countToInPositionMask(int channelCount)55     public static int countToInPositionMask(int channelCount) {
56         switch (channelCount) {
57             case 1:
58                 return AudioFormat.CHANNEL_IN_MONO;
59 
60             case 2:
61                 return AudioFormat.CHANNEL_IN_STEREO;
62 
63             default:
64                 return AudioRecord.ERROR_BAD_VALUE;
65         }
66     }
67 
68     // Encodings
sampleSizeInBytes(int encoding)69     public static int sampleSizeInBytes(int encoding) {
70         switch (encoding) {
71             case AudioFormat.ENCODING_PCM_16BIT:
72                 return 2;
73 
74             case AudioFormat.ENCODING_PCM_FLOAT:
75                 return 4;
76 
77             default:
78                 return 0;
79         }
80     }
81 
calcFrameSizeInBytes(int encoding, int numChannels)82     public static int calcFrameSizeInBytes(int encoding, int numChannels) {
83         return sampleSizeInBytes(encoding) * numChannels;
84     }
85 
isMMapSupported()86     public static native boolean isMMapSupported();
isMMapExclusiveSupported()87     public static native boolean isMMapExclusiveSupported();
88 
89     /*
90      * Channel Mask Utilities
91      */
92     private static final HashMap<Integer, String> sEncodingStrings =
93             new HashMap<Integer, String>();
94     /**
95      * A table of strings corresponding to output channel position masks
96      */
97     private static final HashMap<Integer, String> sOutChanPosStrings =
98             new HashMap<Integer, String>();
99 
100     /**
101      * A table of strings corresponding to output channel position masks
102      */
103     private static final HashMap<Integer, String> sInChanPosStrings =
104             new HashMap<Integer, String>();
105 
initOutChanPositionStrings()106     static void initOutChanPositionStrings() {
107         sOutChanPosStrings.put(AudioFormat.CHANNEL_INVALID, "CHANNEL_INVALID");
108         sOutChanPosStrings.put(AudioFormat.CHANNEL_OUT_DEFAULT, "CHANNEL_OUT_DEFAULT");
109         sOutChanPosStrings.put(AudioFormat.CHANNEL_OUT_FRONT_LEFT,
110                 "CHANNEL_OUT_MONO"/*"CHANNEL_OUT_FRONT_LEFT"*/);
111         sOutChanPosStrings.put(AudioFormat.CHANNEL_OUT_FRONT_RIGHT, "CHANNEL_OUT_FRONT_RIGHT");
112         sOutChanPosStrings.put(AudioFormat.CHANNEL_OUT_FRONT_CENTER, "CHANNEL_OUT_FRONT_CENTER");
113         sOutChanPosStrings.put(AudioFormat.CHANNEL_OUT_LOW_FREQUENCY, "CHANNEL_OUT_LOW_FREQUENCY");
114         sOutChanPosStrings.put(AudioFormat.CHANNEL_OUT_BACK_LEFT, "CHANNEL_OUT_BACK_LEFT");
115         sOutChanPosStrings.put(AudioFormat.CHANNEL_OUT_BACK_RIGHT, "CHANNEL_OUT_BACK_RIGHT");
116         sOutChanPosStrings.put(AudioFormat.CHANNEL_OUT_FRONT_LEFT_OF_CENTER,
117                 "CHANNEL_OUT_FRONT_LEFT_OF_CENTER");
118         sOutChanPosStrings.put(AudioFormat.CHANNEL_OUT_FRONT_RIGHT_OF_CENTER,
119                 "CHANNEL_OUT_FRONT_RIGHT_OF_CENTER");
120         sOutChanPosStrings.put(AudioFormat.CHANNEL_OUT_BACK_CENTER, "CHANNEL_OUT_BACK_CENTER");
121         sOutChanPosStrings.put(AudioFormat.CHANNEL_OUT_SIDE_LEFT, "CHANNEL_OUT_SIDE_LEFT");
122         sOutChanPosStrings.put(AudioFormat.CHANNEL_OUT_SIDE_RIGHT, "CHANNEL_OUT_SIDE_RIGHT");
123         sOutChanPosStrings.put(AudioFormat.CHANNEL_OUT_STEREO, "CHANNEL_OUT_STEREO");
124         sOutChanPosStrings.put(AudioFormat.CHANNEL_OUT_QUAD, "CHANNEL_OUT_QUAD");
125         sOutChanPosStrings.put(AudioFormat.CHANNEL_OUT_SURROUND, "CHANNEL_OUT_SURROUND");
126         sOutChanPosStrings.put(AudioFormat.CHANNEL_OUT_5POINT1, "CHANNEL_OUT_5POINT1");
127         sOutChanPosStrings.put(AudioFormat.CHANNEL_OUT_6POINT1, "CHANNEL_OUT_6POINT1");
128         // Deprecated
129         sOutChanPosStrings.put(AudioFormat.CHANNEL_OUT_7POINT1, "CHANNEL_OUT_7POINT1");
130         sOutChanPosStrings.put(AudioFormat.CHANNEL_OUT_7POINT1_SURROUND,
131                 "CHANNEL_OUT_7POINT1_SURROUND");
132         sOutChanPosStrings.put(AudioFormat.CHANNEL_OUT_7POINT1POINT4,
133                 "CHANNEL_OUT_7POINT1POINT4");
134     }
135 
initInChanPositionStrings()136     static void initInChanPositionStrings() {
137         sInChanPosStrings.put(AudioFormat.CHANNEL_INVALID, "CHANNEL_INVALID");
138         sInChanPosStrings.put(AudioFormat.CHANNEL_IN_DEFAULT, "CHANNEL_IN_DEFAULT");
139         sInChanPosStrings.put(AudioFormat.CHANNEL_IN_LEFT, "CHANNEL_IN_LEFT");
140         sInChanPosStrings.put(AudioFormat.CHANNEL_IN_RIGHT, "CHANNEL_IN_RIGHT");
141         sInChanPosStrings.put(AudioFormat.CHANNEL_IN_MONO, "CHANNEL_IN_MONO"/*CHANNEL_IN_FRONT*/);
142         sInChanPosStrings.put(AudioFormat.CHANNEL_IN_BACK, "CHANNEL_IN_BACK");
143         sInChanPosStrings.put(AudioFormat.CHANNEL_IN_LEFT_PROCESSED, "CHANNEL_IN_LEFT_PROCESSED");
144         sInChanPosStrings.put(AudioFormat.CHANNEL_IN_RIGHT_PROCESSED, "CHANNEL_IN_RIGHT_PROCESSED");
145         sInChanPosStrings.put(AudioFormat.CHANNEL_IN_FRONT_PROCESSED, "CHANNEL_IN_FRONT_PROCESSED");
146         sInChanPosStrings.put(AudioFormat.CHANNEL_IN_BACK_PROCESSED, "CHANNEL_IN_BACK_PROCESSED");
147         sInChanPosStrings.put(AudioFormat.CHANNEL_IN_PRESSURE, "CHANNEL_IN_PRESSURE");
148         sInChanPosStrings.put(AudioFormat.CHANNEL_IN_X_AXIS, "CHANNEL_IN_X_AXIS");
149         sInChanPosStrings.put(AudioFormat.CHANNEL_IN_Y_AXIS, "CHANNEL_IN_Y_AXIS");
150         sInChanPosStrings.put(AudioFormat.CHANNEL_IN_Z_AXIS, "CHANNEL_IN_Z_AXIS");
151         sInChanPosStrings.put(AudioFormat.CHANNEL_IN_VOICE_UPLINK, "CHANNEL_IN_VOICE_UPLINK");
152         sInChanPosStrings.put(AudioFormat.CHANNEL_IN_VOICE_DNLINK, "CHANNEL_IN_VOICE_DNLINK");
153         sInChanPosStrings.put(AudioFormat.CHANNEL_IN_STEREO, "CHANNEL_IN_STEREO");
154     }
155 
initEncodingStrings()156     static void initEncodingStrings() {
157         sEncodingStrings.put(AudioFormat.ENCODING_INVALID, "ENCODING_INVALID");
158         sEncodingStrings.put(AudioFormat.ENCODING_DEFAULT, "ENCODING_DEFAULT");
159         sEncodingStrings.put(AudioFormat.ENCODING_PCM_16BIT, "ENCODING_PCM_16BIT");
160         sEncodingStrings.put(AudioFormat.ENCODING_PCM_8BIT, "ENCODING_PCM_8BIT");
161         sEncodingStrings.put(AudioFormat.ENCODING_PCM_FLOAT, "ENCODING_PCM_FLOAT");
162         sEncodingStrings.put(AudioFormat.ENCODING_AC3, "ENCODING_AC3");
163         sEncodingStrings.put(AudioFormat.ENCODING_E_AC3, "ENCODING_E_AC3");
164         sEncodingStrings.put(AudioFormat.ENCODING_DTS, "ENCODING_DTS");
165         sEncodingStrings.put(AudioFormat.ENCODING_DTS_HD, "ENCODING_DTS_HD");
166         sEncodingStrings.put(AudioFormat.ENCODING_MP3, "ENCODING_MP3");
167         sEncodingStrings.put(AudioFormat.ENCODING_AAC_LC, "ENCODING_AAC_LC");
168         sEncodingStrings.put(AudioFormat.ENCODING_AAC_HE_V1, "ENCODING_AAC_HE_V1");
169         sEncodingStrings.put(AudioFormat.ENCODING_AAC_HE_V2, "ENCODING_AAC_HE_V2");
170         sEncodingStrings.put(AudioFormat.ENCODING_IEC61937, "ENCODING_IEC61937");
171         sEncodingStrings.put(AudioFormat.ENCODING_DOLBY_TRUEHD, "ENCODING_DOLBY_TRUEHD");
172         sEncodingStrings.put(AudioFormat.ENCODING_AAC_ELD, "ENCODING_AAC_ELD");
173         sEncodingStrings.put(AudioFormat.ENCODING_AAC_XHE, "ENCODING_AAC_XHE");
174         sEncodingStrings.put(AudioFormat.ENCODING_AC4, "ENCODING_AC4");
175         sEncodingStrings.put(AudioFormat.ENCODING_E_AC3_JOC, "ENCODING_E_AC3_JOC");
176         sEncodingStrings.put(AudioFormat.ENCODING_DOLBY_MAT, "ENCODING_DOLBY_MAT");
177         sEncodingStrings.put(AudioFormat.ENCODING_OPUS, "ENCODING_OPUS");
178         sEncodingStrings.put(AudioFormat.ENCODING_PCM_24BIT_PACKED, "ENCODING_PCM_24BIT_PACKED");
179         sEncodingStrings.put(AudioFormat.ENCODING_PCM_32BIT, "ENCODING_PCM_32BIT");
180         sEncodingStrings.put(AudioFormat.ENCODING_MPEGH_BL_L3, "ENCODING_MPEGH_BL_L3");
181         sEncodingStrings.put(AudioFormat.ENCODING_MPEGH_BL_L4, "ENCODING_MPEGH_BL_L4");
182         sEncodingStrings.put(AudioFormat.ENCODING_MPEGH_LC_L3, "ENCODING_MPEGH_LC_L3");
183         sEncodingStrings.put(AudioFormat.ENCODING_MPEGH_LC_L4, "ENCODING_MPEGH_LC_L4");
184         sEncodingStrings.put(AudioFormat.ENCODING_DTS_UHD, "ENCODING_DTS_UHD");
185         sEncodingStrings.put(AudioFormat.ENCODING_DRA, "ENCODING_DRA");
186     }
187 
188     static {
initOutChanPositionStrings()189         initOutChanPositionStrings();
initInChanPositionStrings()190         initInChanPositionStrings();
initEncodingStrings()191         initEncodingStrings();
192     }
193 
194     /**
195      * @param channelMask An OUTPUT Positional Channel Mask
196      * @return A human-readable string corresponding to the specified channel mask
197      */
channelOutPositionMaskToString(int channelMask)198     public static String channelOutPositionMaskToString(int channelMask) {
199         String maskString = sOutChanPosStrings.get(channelMask);
200         return maskString != null ? maskString : ("0x" + Integer.toHexString(channelMask));
201     }
202 
203     /**
204      * @param channelMask An INPUT Positional Channel Mask
205      * @return A human-readable string corresponding to the specified channel mask
206      */
channelInPositionMaskToString(int channelMask)207     public static String channelInPositionMaskToString(int channelMask) {
208         String maskString = sInChanPosStrings.get(channelMask);
209         return maskString != null ? maskString : ("0x" + Integer.toHexString(channelMask));
210     }
211 
212     /**
213      * @param channelMask An INDEX Channel Mask
214      * @return A human-readable string corresponding to the specified channel mask
215      */
channelIndexMaskToString(int channelMask)216     public static String channelIndexMaskToString(int channelMask) {
217         return "0x" + Integer.toHexString(channelMask);
218     }
219 
220     /**
221      * @param encoding An audio encoding constant
222      * @return A human-readable string corresponding to the specified encoding value
223      */
encodingToString(int encoding)224     public static String encodingToString(int encoding) {
225         String encodingString = sEncodingStrings.get(encoding);
226         return encodingString != null ? encodingString : ("0x" + Integer.toHexString(encoding));
227     }
228 }