1 /* 2 * Copyright (C) 2015 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 #pragma once 18 19 #include <media/AudioCommonTypes.h> 20 #include <media/AudioContainers.h> 21 #include <system/audio.h> 22 #include <utils/Log.h> 23 #include <math.h> 24 25 #include "policy.h" 26 27 namespace android { 28 29 /** 30 * VolumeSource is the discriminent for volume management on an output. 31 * It used to be the stream type by legacy, it may be host volume group or a volume curves if 32 * we allow to have more than one curve per volume group (mandatory to get rid of AudioServer 33 * stream aliases. 34 */ 35 enum VolumeSource : std::underlying_type<volume_group_t>::type; 36 static const VolumeSource VOLUME_SOURCE_NONE = static_cast<VolumeSource>(VOLUME_GROUP_NONE); 37 38 } // namespace android 39 40 // Absolute min volume in dB (can be represented in single precision normal float value) 41 #define VOLUME_MIN_DB (-758) 42 43 class VolumeCurvePoint 44 { 45 public: 46 int mIndex; 47 float mDBAttenuation; 48 }; 49 50 /** 51 * device categories used for volume curve management. 52 */ 53 enum device_category { 54 DEVICE_CATEGORY_HEADSET, 55 DEVICE_CATEGORY_SPEAKER, 56 DEVICE_CATEGORY_EARPIECE, 57 DEVICE_CATEGORY_EXT_MEDIA, 58 DEVICE_CATEGORY_HEARING_AID, 59 DEVICE_CATEGORY_CNT 60 }; 61 62 class Volume 63 { 64 public: 65 /** 66 * 4 points to define the volume attenuation curve, each characterized by the volume 67 * index (from 0 to 100) at which they apply, and the attenuation in dB at that index. 68 * we use 100 steps to avoid rounding errors when computing the volume in volIndexToDb() 69 * 70 * @todo shall become configurable 71 */ 72 enum { 73 VOLMIN = 0, 74 VOLKNEE1 = 1, 75 VOLKNEE2 = 2, 76 VOLMAX = 3, 77 78 VOLCNT = 4 79 }; 80 81 /** 82 * extract one device relevant for volume control from multiple device selection 83 * 84 * @param[in] device for which the volume category is associated 85 * 86 * @return subset of device required to limit the number of volume category per device 87 */ getDeviceForVolume(const android::DeviceTypeSet & deviceTypes)88 static audio_devices_t getDeviceForVolume(const android::DeviceTypeSet& deviceTypes) 89 { 90 if (deviceTypes.empty()) { 91 // this happens when forcing a route update and no track is active on an output. 92 // In this case the returned category is not important. 93 return AUDIO_DEVICE_OUT_SPEAKER; 94 } 95 96 audio_devices_t deviceType = apm_extract_one_audio_device(deviceTypes); 97 98 /*SPEAKER_SAFE is an alias of SPEAKER for purposes of volume control*/ 99 if (deviceType == AUDIO_DEVICE_OUT_SPEAKER_SAFE) { 100 deviceType = AUDIO_DEVICE_OUT_SPEAKER; 101 } 102 103 ALOGW_IF(deviceType == AUDIO_DEVICE_NONE, 104 "getDeviceForVolume() invalid device combination: %s, returning AUDIO_DEVICE_NONE", 105 android::dumpDeviceTypes(deviceTypes).c_str()); 106 107 return deviceType; 108 } 109 110 /** 111 * returns the category the device belongs to with regard to volume curve management 112 * 113 * @param[in] device to check upon the category to whom it belongs to. 114 * 115 * @return device category. 116 */ getDeviceCategory(const android::DeviceTypeSet & deviceTypes)117 static device_category getDeviceCategory(const android::DeviceTypeSet& deviceTypes) 118 { 119 switch(getDeviceForVolume(deviceTypes)) { 120 case AUDIO_DEVICE_OUT_EARPIECE: 121 return DEVICE_CATEGORY_EARPIECE; 122 case AUDIO_DEVICE_OUT_WIRED_HEADSET: 123 case AUDIO_DEVICE_OUT_WIRED_HEADPHONE: 124 case AUDIO_DEVICE_OUT_BLUETOOTH_SCO: 125 case AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET: 126 case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP: 127 case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES: 128 case AUDIO_DEVICE_OUT_USB_HEADSET: 129 return DEVICE_CATEGORY_HEADSET; 130 case AUDIO_DEVICE_OUT_HEARING_AID: 131 return DEVICE_CATEGORY_HEARING_AID; 132 case AUDIO_DEVICE_OUT_LINE: 133 case AUDIO_DEVICE_OUT_AUX_DIGITAL: 134 case AUDIO_DEVICE_OUT_USB_DEVICE: 135 return DEVICE_CATEGORY_EXT_MEDIA; 136 case AUDIO_DEVICE_OUT_SPEAKER: 137 case AUDIO_DEVICE_OUT_SPEAKER_SAFE: 138 case AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT: 139 case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER: 140 case AUDIO_DEVICE_OUT_USB_ACCESSORY: 141 case AUDIO_DEVICE_OUT_REMOTE_SUBMIX: 142 default: 143 return DEVICE_CATEGORY_SPEAKER; 144 } 145 } 146 DbToAmpl(float decibels)147 static inline float DbToAmpl(float decibels) 148 { 149 if (decibels <= VOLUME_MIN_DB) { 150 return 0.0f; 151 } 152 return exp( decibels * 0.115129f); // exp( dB * ln(10) / 20 ) 153 } 154 AmplToDb(float amplification)155 static inline float AmplToDb(float amplification) 156 { 157 if (amplification == 0) { 158 return VOLUME_MIN_DB; 159 } 160 return 20 * log10(amplification); 161 } 162 163 }; 164