| /* |
| * Copyright (C) 2018 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package android.media; |
| |
| import android.annotation.IntDef; |
| import android.annotation.NonNull; |
| import android.compat.annotation.UnsupportedAppUsage; |
| import android.os.Build; |
| import android.util.Pair; |
| |
| import java.lang.annotation.Retention; |
| import java.lang.annotation.RetentionPolicy; |
| import java.util.List; |
| |
| /** |
| * Class providing information on a microphone. It indicates the location and orientation of the |
| * microphone on the device as well as useful information like frequency response and sensitivity. |
| * It can be used by applications implementing special pre processing effects like noise suppression |
| * of beam forming that need to know about precise microphone characteristics in order to adapt |
| * their algorithms. |
| */ |
| public final class MicrophoneInfo { |
| |
| /** |
| * A microphone that the location is unknown. |
| */ |
| public static final int LOCATION_UNKNOWN = 0; |
| |
| /** |
| * A microphone that locate on main body of the device. |
| */ |
| public static final int LOCATION_MAINBODY = 1; |
| |
| /** |
| * A microphone that locate on a movable main body of the device. |
| */ |
| public static final int LOCATION_MAINBODY_MOVABLE = 2; |
| |
| /** |
| * A microphone that locate on a peripheral. |
| */ |
| public static final int LOCATION_PERIPHERAL = 3; |
| |
| /** |
| * Unknown microphone directionality. |
| */ |
| public static final int DIRECTIONALITY_UNKNOWN = 0; |
| |
| /** |
| * Microphone directionality type: omni. |
| */ |
| public static final int DIRECTIONALITY_OMNI = 1; |
| |
| /** |
| * Microphone directionality type: bi-directional. |
| */ |
| public static final int DIRECTIONALITY_BI_DIRECTIONAL = 2; |
| |
| /** |
| * Microphone directionality type: cardioid. |
| */ |
| public static final int DIRECTIONALITY_CARDIOID = 3; |
| |
| /** |
| * Microphone directionality type: hyper cardioid. |
| */ |
| public static final int DIRECTIONALITY_HYPER_CARDIOID = 4; |
| |
| /** |
| * Microphone directionality type: super cardioid. |
| */ |
| public static final int DIRECTIONALITY_SUPER_CARDIOID = 5; |
| |
| /** |
| * The channel contains raw audio from this microphone. |
| */ |
| public static final int CHANNEL_MAPPING_DIRECT = 1; |
| |
| /** |
| * The channel contains processed audio from this microphone and possibly another microphone. |
| */ |
| public static final int CHANNEL_MAPPING_PROCESSED = 2; |
| |
| /** |
| * Value used for when the group of the microphone is unknown. |
| */ |
| public static final int GROUP_UNKNOWN = -1; |
| |
| /** |
| * Value used for when the index in the group of the microphone is unknown. |
| */ |
| public static final int INDEX_IN_THE_GROUP_UNKNOWN = -1; |
| |
| /** |
| * Value used for when the position of the microphone is unknown. |
| */ |
| public static final Coordinate3F POSITION_UNKNOWN = new Coordinate3F( |
| -Float.MAX_VALUE, -Float.MAX_VALUE, -Float.MAX_VALUE); |
| |
| /** |
| * Value used for when the orientation of the microphone is unknown. |
| */ |
| public static final Coordinate3F ORIENTATION_UNKNOWN = new Coordinate3F(0.0f, 0.0f, 0.0f); |
| |
| /** |
| * Value used for when the sensitivity of the microphone is unknown. |
| */ |
| public static final float SENSITIVITY_UNKNOWN = -Float.MAX_VALUE; |
| |
| /** |
| * Value used for when the SPL of the microphone is unknown. This value could be used when |
| * maximum SPL or minimum SPL is unknown. |
| */ |
| public static final float SPL_UNKNOWN = -Float.MAX_VALUE; |
| |
| /** @hide */ |
| @IntDef(flag = true, prefix = { "LOCATION_" }, value = { |
| LOCATION_UNKNOWN, |
| LOCATION_MAINBODY, |
| LOCATION_MAINBODY_MOVABLE, |
| LOCATION_PERIPHERAL, |
| }) |
| @Retention(RetentionPolicy.SOURCE) |
| public @interface MicrophoneLocation {} |
| |
| /** @hide */ |
| @IntDef(flag = true, prefix = { "DIRECTIONALITY_" }, value = { |
| DIRECTIONALITY_UNKNOWN, |
| DIRECTIONALITY_OMNI, |
| DIRECTIONALITY_BI_DIRECTIONAL, |
| DIRECTIONALITY_CARDIOID, |
| DIRECTIONALITY_HYPER_CARDIOID, |
| DIRECTIONALITY_SUPER_CARDIOID, |
| }) |
| @Retention(RetentionPolicy.SOURCE) |
| public @interface MicrophoneDirectionality {} |
| |
| private Coordinate3F mPosition; |
| private Coordinate3F mOrientation; |
| private String mDeviceId; |
| private String mAddress; |
| private List<Pair<Float, Float>> mFrequencyResponse; |
| private List<Pair<Integer, Integer>> mChannelMapping; |
| private float mMaxSpl; |
| private float mMinSpl; |
| private float mSensitivity; |
| private int mLocation; |
| private int mGroup; /* Usually 0 will be used for main body. */ |
| private int mIndexInTheGroup; |
| private int mPortId; /* mPortId will correspond to the id in AudioPort */ |
| private int mType; |
| private int mDirectionality; |
| |
| @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) { |
| mDeviceId = deviceId; |
| mType = type; |
| mAddress = address; |
| mLocation = location; |
| mGroup = group; |
| mIndexInTheGroup = indexInTheGroup; |
| mPosition = position; |
| mOrientation = orientation; |
| mFrequencyResponse = frequencyResponse; |
| mChannelMapping = channelMapping; |
| mSensitivity = sensitivity; |
| mMaxSpl = maxSpl; |
| mMinSpl = minSpl; |
| mDirectionality = directionality; |
| } |
| |
| /** |
| * Returns alphanumeric code that uniquely identifies the device. |
| * |
| * @return the description of the microphone |
| */ |
| public String getDescription() { |
| return mDeviceId; |
| } |
| |
| /** |
| * Returns The system unique device ID that corresponds to the id |
| * returned by {@link AudioDeviceInfo#getId()}. |
| * |
| * @return the microphone's id |
| */ |
| public int getId() { |
| return mPortId; |
| } |
| |
| /** |
| * @hide |
| * Returns the internal device type (e.g AudioSystem.DEVICE_IN_BUILTIN_MIC). |
| * The internal device type could be used when getting microphone's port id |
| * by matching type and address. |
| * |
| * @return the internal device type |
| */ |
| public int getInternalDeviceType() { |
| return mType; |
| } |
| |
| /** |
| * Returns the device type identifier of the microphone (e.g AudioDeviceInfo.TYPE_BUILTIN_MIC). |
| * |
| * @return the device type of the microphone |
| */ |
| public int getType() { |
| return AudioDeviceInfo.convertInternalDeviceToDeviceType(mType); |
| } |
| |
| /** |
| * Returns The "address" string of the microphone that corresponds to the |
| * address returned by {@link AudioDeviceInfo#getAddress()} |
| * @return the address of the microphone |
| */ |
| public @NonNull String getAddress() { |
| return mAddress; |
| } |
| |
| /** |
| * Returns the location of the microphone. The return value is |
| * one of {@link #LOCATION_UNKNOWN}, {@link #LOCATION_MAINBODY}, |
| * {@link #LOCATION_MAINBODY_MOVABLE}, or {@link #LOCATION_PERIPHERAL}. |
| * |
| * @return the location of the microphone |
| */ |
| public @MicrophoneLocation int getLocation() { |
| return mLocation; |
| } |
| |
| /** |
| * Returns A device group id that can be used to group together microphones on the same |
| * peripheral, attachments or logical groups. Main body is usually group 0. |
| * |
| * @return the group of the microphone or {@link #GROUP_UNKNOWN} if the group is unknown |
| */ |
| public int getGroup() { |
| return mGroup; |
| } |
| |
| /** |
| * Returns unique index for device within its group. |
| * |
| * @return the microphone's index in its group or {@link #INDEX_IN_THE_GROUP_UNKNOWN} if the |
| * index in the group is unknown |
| */ |
| public int getIndexInTheGroup() { |
| return mIndexInTheGroup; |
| } |
| |
| /** |
| * Returns A {@link Coordinate3F} object that represents the geometric location of microphone |
| * in meters. X-axis, Y-axis and Z-axis show as the x, y, z values. For mobile devices, the axes |
| * originate from the bottom-left-back corner of the appliance. In devices with |
| * {@link android.content.pm.PackageManager#FEATURE_AUTOMOTIVE}, axes are defined with respect |
| * to the vehicle body frame, originating from the center of the vehicle's rear axle. |
| * @see <a href="https://source.android.com/devices/sensors/sensor-types#auto_axes">auto axes</a> |
| * |
| * @return the geometric location of the microphone or {@link #POSITION_UNKNOWN} if the |
| * geometric location is unknown |
| */ |
| public Coordinate3F getPosition() { |
| return mPosition; |
| } |
| |
| /** |
| * Returns A {@link Coordinate3F} object that represents the orientation of microphone. |
| * X-axis, Y-axis and Z-axis show as the x, y, z value. The orientation will be normalized |
| * such as sqrt(x^2 + y^2 + z^2) equals 1. |
| * |
| * @return the orientation of the microphone or {@link #ORIENTATION_UNKNOWN} if orientation |
| * is unknown |
| */ |
| public Coordinate3F getOrientation() { |
| return mOrientation; |
| } |
| |
| /** |
| * Returns a {@link android.util.Pair} list of frequency responses. |
| * For every {@link android.util.Pair} in the list, the first value represents frequency in Hz, |
| * and the second value represents response in dB. |
| * |
| * @return the frequency response of the microphone |
| */ |
| public List<Pair<Float, Float>> getFrequencyResponse() { |
| return mFrequencyResponse; |
| } |
| |
| /** |
| * Returns a {@link android.util.Pair} list for channel mapping, which indicating how this |
| * microphone is used by each channels or a capture stream. For each {@link android.util.Pair}, |
| * the first value is channel index, the second value is channel mapping type, which could be |
| * either {@link #CHANNEL_MAPPING_DIRECT} or {@link #CHANNEL_MAPPING_PROCESSED}. |
| * If a channel has contributions from more than one microphone, it is likely the HAL |
| * did some extra processing to combine the sources, but this is to be inferred by the user. |
| * Empty list when the MicrophoneInfo is returned by AudioManager.getMicrophones(). |
| * At least one entry when the MicrophoneInfo is returned by AudioRecord.getActiveMicrophones(). |
| * |
| * @return a {@link android.util.Pair} list for channel mapping |
| */ |
| public List<Pair<Integer, Integer>> getChannelMapping() { |
| return mChannelMapping; |
| } |
| |
| /** |
| * Returns the level in dBFS produced by a 1000Hz tone at 94 dB SPL. |
| * |
| * @return the sensitivity of the microphone or {@link #SENSITIVITY_UNKNOWN} if the sensitivity |
| * is unknown |
| */ |
| public float getSensitivity() { |
| return mSensitivity; |
| } |
| |
| /** |
| * Returns the level in dB of the maximum SPL supported by the device at 1000Hz. |
| * |
| * @return the maximum level in dB or {@link #SPL_UNKNOWN} if maximum SPL is unknown |
| */ |
| public float getMaxSpl() { |
| return mMaxSpl; |
| } |
| |
| /** |
| * Returns the level in dB of the minimum SPL that can be registered by the device at 1000Hz. |
| * |
| * @return the minimum level in dB or {@link #SPL_UNKNOWN} if minimum SPL is unknown |
| */ |
| public float getMinSpl() { |
| return mMinSpl; |
| } |
| |
| /** |
| * Returns the directionality of microphone. The return value is one of |
| * {@link #DIRECTIONALITY_UNKNOWN}, {@link #DIRECTIONALITY_OMNI}, |
| * {@link #DIRECTIONALITY_BI_DIRECTIONAL}, {@link #DIRECTIONALITY_CARDIOID}, |
| * {@link #DIRECTIONALITY_HYPER_CARDIOID}, or {@link #DIRECTIONALITY_SUPER_CARDIOID}. |
| * |
| * @return the directionality of microphone |
| */ |
| public @MicrophoneDirectionality int getDirectionality() { |
| return mDirectionality; |
| } |
| |
| /** |
| * Set the port id for the device. |
| * @hide |
| */ |
| public void setId(int portId) { |
| mPortId = portId; |
| } |
| |
| /** |
| * Set the channel mapping for the device. |
| * @hide |
| */ |
| public void setChannelMapping(List<Pair<Integer, Integer>> channelMapping) { |
| mChannelMapping = channelMapping; |
| } |
| |
| /* A class containing three float value to represent a 3D coordinate */ |
| public static final class Coordinate3F { |
| public final float x; |
| public final float y; |
| public final float z; |
| |
| Coordinate3F(float x, float y, float z) { |
| this.x = x; |
| this.y = y; |
| this.z = z; |
| } |
| |
| @Override |
| public boolean equals(Object obj) { |
| if (this == obj) { |
| return true; |
| } |
| if (!(obj instanceof Coordinate3F)) { |
| return false; |
| } |
| Coordinate3F other = (Coordinate3F) obj; |
| return this.x == other.x && this.y == other.y && this.z == other.z; |
| } |
| } |
| } |