1 /*
2  * Copyright (C) 2018 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 android.media;
18 
19 import android.annotation.IntDef;
20 import android.annotation.NonNull;
21 import android.util.Pair;
22 
23 import java.lang.annotation.Retention;
24 import java.lang.annotation.RetentionPolicy;
25 import java.util.List;
26 
27 /**
28  * Class providing information on a microphone. It indicates the location and orientation of the
29  * microphone on the device as well as useful information like frequency response and sensitivity.
30  * It can be used by applications implementing special pre processing effects like noise suppression
31  * of beam forming that need to know about precise microphone characteristics in order to adapt
32  * their algorithms.
33  */
34 public final class MicrophoneInfo {
35 
36     /**
37      * A microphone that the location is unknown.
38      */
39     public static final int LOCATION_UNKNOWN = 0;
40 
41     /**
42      * A microphone that locate on main body of the device.
43      */
44     public static final int LOCATION_MAINBODY = 1;
45 
46     /**
47      * A microphone that locate on a movable main body of the device.
48      */
49     public static final int LOCATION_MAINBODY_MOVABLE = 2;
50 
51     /**
52      * A microphone that locate on a peripheral.
53      */
54     public static final int LOCATION_PERIPHERAL = 3;
55 
56     /**
57      * Unknown microphone directionality.
58      */
59     public static final int DIRECTIONALITY_UNKNOWN = 0;
60 
61     /**
62      * Microphone directionality type: omni.
63      */
64     public static final int DIRECTIONALITY_OMNI = 1;
65 
66     /**
67      * Microphone directionality type: bi-directional.
68      */
69     public static final int DIRECTIONALITY_BI_DIRECTIONAL = 2;
70 
71     /**
72      * Microphone directionality type: cardioid.
73      */
74     public static final int DIRECTIONALITY_CARDIOID = 3;
75 
76     /**
77      * Microphone directionality type: hyper cardioid.
78      */
79     public static final int DIRECTIONALITY_HYPER_CARDIOID = 4;
80 
81     /**
82      * Microphone directionality type: super cardioid.
83      */
84     public static final int DIRECTIONALITY_SUPER_CARDIOID = 5;
85 
86     /**
87      * The channel contains raw audio from this microphone.
88      */
89     public static final int CHANNEL_MAPPING_DIRECT = 1;
90 
91     /**
92      * The channel contains processed audio from this microphone and possibly another microphone.
93      */
94     public static final int CHANNEL_MAPPING_PROCESSED = 2;
95 
96     /**
97      * Value used for when the group of the microphone is unknown.
98      */
99     public static final int GROUP_UNKNOWN = -1;
100 
101     /**
102      * Value used for when the index in the group of the microphone is unknown.
103      */
104     public static final int INDEX_IN_THE_GROUP_UNKNOWN = -1;
105 
106     /**
107      * Value used for when the position of the microphone is unknown.
108      */
109     public static final Coordinate3F POSITION_UNKNOWN = new Coordinate3F(
110             -Float.MAX_VALUE, -Float.MAX_VALUE, -Float.MAX_VALUE);
111 
112     /**
113      * Value used for when the orientation of the microphone is unknown.
114      */
115     public static final Coordinate3F ORIENTATION_UNKNOWN = new Coordinate3F(0.0f, 0.0f, 0.0f);
116 
117     /**
118      * Value used for when the sensitivity of the microphone is unknown.
119      */
120     public static final float SENSITIVITY_UNKNOWN = -Float.MAX_VALUE;
121 
122     /**
123      * Value used for when the SPL of the microphone is unknown. This value could be used when
124      * maximum SPL or minimum SPL is unknown.
125      */
126     public static final float SPL_UNKNOWN = -Float.MAX_VALUE;
127 
128     /** @hide */
129     @IntDef(flag = true, prefix = { "LOCATION_" }, value = {
130             LOCATION_UNKNOWN,
131             LOCATION_MAINBODY,
132             LOCATION_MAINBODY_MOVABLE,
133             LOCATION_PERIPHERAL,
134     })
135     @Retention(RetentionPolicy.SOURCE)
136     public @interface MicrophoneLocation {}
137 
138     /** @hide */
139     @IntDef(flag = true, prefix = { "DIRECTIONALITY_" }, value = {
140             DIRECTIONALITY_UNKNOWN,
141             DIRECTIONALITY_OMNI,
142             DIRECTIONALITY_BI_DIRECTIONAL,
143             DIRECTIONALITY_CARDIOID,
144             DIRECTIONALITY_HYPER_CARDIOID,
145             DIRECTIONALITY_SUPER_CARDIOID,
146     })
147     @Retention(RetentionPolicy.SOURCE)
148     public @interface MicrophoneDirectionality {}
149 
150     private Coordinate3F mPosition;
151     private Coordinate3F mOrientation;
152     private String mDeviceId;
153     private String mAddress;
154     private List<Pair<Float, Float>> mFrequencyResponse;
155     private List<Pair<Integer, Integer>> mChannelMapping;
156     private float mMaxSpl;
157     private float mMinSpl;
158     private float mSensitivity;
159     private int mLocation;
160     private int mGroup; /* Usually 0 will be used for main body. */
161     private int mIndexInTheGroup;
162     private int mPortId; /* mPortId will correspond to the id in AudioPort */
163     private int mType;
164     private int mDirectionality;
165 
MicrophoneInfo(String deviceId, int type, String address, int location, int group, int indexInTheGroup, Coordinate3F position, Coordinate3F orientation, List<Pair<Float, Float>> frequencyResponse, List<Pair<Integer, Integer>> channelMapping, float sensitivity, float maxSpl, float minSpl, int directionality)166     MicrophoneInfo(String deviceId, int type, String address, int location,
167             int group, int indexInTheGroup, Coordinate3F position,
168             Coordinate3F orientation, List<Pair<Float, Float>> frequencyResponse,
169             List<Pair<Integer, Integer>> channelMapping, float sensitivity, float maxSpl,
170             float minSpl, int directionality) {
171         mDeviceId = deviceId;
172         mType = type;
173         mAddress = address;
174         mLocation = location;
175         mGroup = group;
176         mIndexInTheGroup = indexInTheGroup;
177         mPosition = position;
178         mOrientation = orientation;
179         mFrequencyResponse = frequencyResponse;
180         mChannelMapping = channelMapping;
181         mSensitivity = sensitivity;
182         mMaxSpl = maxSpl;
183         mMinSpl = minSpl;
184         mDirectionality = directionality;
185     }
186 
187     /**
188      * Returns alphanumeric code that uniquely identifies the device.
189      *
190      * @return the description of the microphone
191      */
getDescription()192     public String getDescription() {
193         return mDeviceId;
194     }
195 
196     /**
197      * Returns The system unique device ID that corresponds to the id
198      * returned by {@link AudioDeviceInfo#getId()}.
199      *
200      * @return the microphone's id
201      */
getId()202     public int getId() {
203         return mPortId;
204     }
205 
206     /**
207      * @hide
208      * Returns the internal device type (e.g AudioSystem.DEVICE_IN_BUILTIN_MIC).
209      * The internal device type could be used when getting microphone's port id
210      * by matching type and address.
211      *
212      * @return the internal device type
213      */
getInternalDeviceType()214     public int getInternalDeviceType() {
215         return mType;
216     }
217 
218     /**
219      * Returns the device type identifier of the microphone (e.g AudioDeviceInfo.TYPE_BUILTIN_MIC).
220      *
221      * @return the device type of the microphone
222      */
getType()223     public int getType() {
224         return AudioDeviceInfo.convertInternalDeviceToDeviceType(mType);
225     }
226 
227     /**
228      * Returns The "address" string of the microphone that corresponds to the
229      * address returned by {@link AudioDeviceInfo#getAddress()}
230      * @return the address of the microphone
231      */
getAddress()232     public @NonNull String getAddress() {
233         return mAddress;
234     }
235 
236     /**
237      * Returns the location of the microphone. The return value is
238      * one of {@link #LOCATION_UNKNOWN}, {@link #LOCATION_MAINBODY},
239      * {@link #LOCATION_MAINBODY_MOVABLE}, or {@link #LOCATION_PERIPHERAL}.
240      *
241      * @return the location of the microphone
242      */
getLocation()243     public @MicrophoneLocation int getLocation() {
244         return mLocation;
245     }
246 
247     /**
248      * Returns A device group id that can be used to group together microphones on the same
249      * peripheral, attachments or logical groups. Main body is usually group 0.
250      *
251      * @return the group of the microphone or {@link #GROUP_UNKNOWN} if the group is unknown
252      */
getGroup()253     public int getGroup() {
254         return mGroup;
255     }
256 
257     /**
258      * Returns unique index for device within its group.
259      *
260      * @return the microphone's index in its group or {@link #INDEX_IN_THE_GROUP_UNKNOWN} if the
261      * index in the group is unknown
262      */
getIndexInTheGroup()263     public int getIndexInTheGroup() {
264         return mIndexInTheGroup;
265     }
266 
267     /**
268      * Returns A {@link Coordinate3F} object that represents the geometric location of microphone
269      * in meters, from bottom-left-back corner of appliance. X-axis, Y-axis and Z-axis show
270      * as the x, y, z values.
271      *
272      * @return the geometric location of the microphone or {@link #POSITION_UNKNOWN} if the
273      * geometric location is unknown
274      */
getPosition()275     public Coordinate3F getPosition() {
276         return mPosition;
277     }
278 
279     /**
280      * Returns A {@link Coordinate3F} object that represents the orientation of microphone.
281      * X-axis, Y-axis and Z-axis show as the x, y, z value. The orientation will be normalized
282      * such as sqrt(x^2 + y^2 + z^2) equals 1.
283      *
284      * @return the orientation of the microphone or {@link #ORIENTATION_UNKNOWN} if orientation
285      * is unknown
286      */
getOrientation()287     public Coordinate3F getOrientation() {
288         return mOrientation;
289     }
290 
291     /**
292      * Returns a {@link android.util.Pair} list of frequency responses.
293      * For every {@link android.util.Pair} in the list, the first value represents frequency in Hz,
294      * and the second value represents response in dB.
295      *
296      * @return the frequency response of the microphone
297      */
getFrequencyResponse()298     public List<Pair<Float, Float>> getFrequencyResponse() {
299         return mFrequencyResponse;
300     }
301 
302     /**
303      * Returns a {@link android.util.Pair} list for channel mapping, which indicating how this
304      * microphone is used by each channels or a capture stream. For each {@link android.util.Pair},
305      * the first value is channel index, the second value is channel mapping type, which could be
306      * either {@link #CHANNEL_MAPPING_DIRECT} or {@link #CHANNEL_MAPPING_PROCESSED}.
307      * If a channel has contributions from more than one microphone, it is likely the HAL
308      * did some extra processing to combine the sources, but this is to be inferred by the user.
309      * Empty list when the MicrophoneInfo is returned by AudioManager.getMicrophones().
310      * At least one entry when the MicrophoneInfo is returned by AudioRecord.getActiveMicrophones().
311      *
312      * @return a {@link android.util.Pair} list for channel mapping
313      */
getChannelMapping()314     public List<Pair<Integer, Integer>> getChannelMapping() {
315         return mChannelMapping;
316     }
317 
318     /**
319      * Returns the level in dBFS produced by a 1000Hz tone at 94 dB SPL.
320      *
321      * @return the sensitivity of the microphone or {@link #SENSITIVITY_UNKNOWN} if the sensitivity
322      * is unknown
323      */
getSensitivity()324     public float getSensitivity() {
325         return mSensitivity;
326     }
327 
328     /**
329      * Returns the level in dB of the maximum SPL supported by the device at 1000Hz.
330      *
331      * @return the maximum level in dB or {@link #SPL_UNKNOWN} if maximum SPL is unknown
332      */
getMaxSpl()333     public float getMaxSpl() {
334         return mMaxSpl;
335     }
336 
337     /**
338      * Returns the level in dB of the minimum SPL that can be registered by the device at 1000Hz.
339      *
340      * @return the minimum level in dB or {@link #SPL_UNKNOWN} if minimum SPL is unknown
341      */
getMinSpl()342     public float getMinSpl() {
343         return mMinSpl;
344     }
345 
346     /**
347      * Returns the directionality of microphone. The return value is one of
348      * {@link #DIRECTIONALITY_UNKNOWN}, {@link #DIRECTIONALITY_OMNI},
349      * {@link #DIRECTIONALITY_BI_DIRECTIONAL}, {@link #DIRECTIONALITY_CARDIOID},
350      * {@link #DIRECTIONALITY_HYPER_CARDIOID}, or {@link #DIRECTIONALITY_SUPER_CARDIOID}.
351      *
352      * @return the directionality of microphone
353      */
getDirectionality()354     public @MicrophoneDirectionality int getDirectionality() {
355         return mDirectionality;
356     }
357 
358     /**
359      * Set the port id for the device.
360      * @hide
361      */
setId(int portId)362     public void setId(int portId) {
363         mPortId = portId;
364     }
365 
366     /**
367      * Set the channel mapping for the device.
368      * @hide
369      */
setChannelMapping(List<Pair<Integer, Integer>> channelMapping)370     public void setChannelMapping(List<Pair<Integer, Integer>> channelMapping) {
371         mChannelMapping = channelMapping;
372     }
373 
374     /* A class containing three float value to represent a 3D coordinate */
375     public static final class Coordinate3F {
376         public final float x;
377         public final float y;
378         public final float z;
379 
Coordinate3F(float x, float y, float z)380         Coordinate3F(float x, float y, float z) {
381             this.x = x;
382             this.y = y;
383             this.z = z;
384         }
385 
386         @Override
equals(Object obj)387         public boolean equals(Object obj) {
388             if (this == obj) {
389                 return true;
390             }
391             if (!(obj instanceof Coordinate3F)) {
392                 return false;
393             }
394             Coordinate3F other = (Coordinate3F) obj;
395             return this.x == other.x && this.y == other.y && this.z == other.z;
396         }
397     }
398 }
399