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