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