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