blob: 7c8ce83a7cfc8a8a8e41996e5c4d1bcc1c77922f [file] [log] [blame]
François Gaffiedfd74092015-03-19 12:10:59 +01001/*
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
François Gaffieaaac0fd2018-11-22 17:56:39 +010019#include <media/AudioCommonTypes.h>
jiabin9a3361e2019-10-01 09:38:30 -070020#include <media/AudioContainers.h>
François Gaffiedfd74092015-03-19 12:10:59 +010021#include <system/audio.h>
22#include <utils/Log.h>
Eric Laurentffbc80f2015-03-18 18:30:19 -070023#include <math.h>
24
jiabin43810402019-10-24 14:58:31 -070025#include "policy.h"
26
François Gaffie1c878552018-11-22 16:53:21 +010027namespace android {
François Gaffie251c7f02018-11-07 10:41:08 +010028
François Gaffie1c878552018-11-22 16:53:21 +010029/**
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
François Gaffieaaac0fd2018-11-22 17:56:39 +010032 * we allow to have more than one curve per volume group (mandatory to get rid of AudioServer
33 * stream aliases.
François Gaffie1c878552018-11-22 16:53:21 +010034 */
François Gaffieaaac0fd2018-11-22 17:56:39 +010035enum VolumeSource : std::underlying_type<volume_group_t>::type;
36static const VolumeSource VOLUME_SOURCE_NONE = static_cast<VolumeSource>(VOLUME_GROUP_NONE);
François Gaffie1c878552018-11-22 16:53:21 +010037
François Gaffie1c878552018-11-22 16:53:21 +010038} // namespace android
39
Eric Laurentffbc80f2015-03-18 18:30:19 -070040// Absolute min volume in dB (can be represented in single precision normal float value)
41#define VOLUME_MIN_DB (-758)
François Gaffiedfd74092015-03-19 12:10:59 +010042
43class VolumeCurvePoint
44{
45public:
46 int mIndex;
47 float mDBAttenuation;
48};
49
François Gaffied0609ad2015-12-01 17:56:08 +010050/**
51 * device categories used for volume curve management.
52 */
53enum device_category {
54 DEVICE_CATEGORY_HEADSET,
55 DEVICE_CATEGORY_SPEAKER,
56 DEVICE_CATEGORY_EARPIECE,
57 DEVICE_CATEGORY_EXT_MEDIA,
Jakub Pawlowski24b0a892018-04-02 19:17:11 -070058 DEVICE_CATEGORY_HEARING_AID,
François Gaffied0609ad2015-12-01 17:56:08 +010059 DEVICE_CATEGORY_CNT
60};
61
François Gaffiedfd74092015-03-19 12:10:59 +010062class Volume
63{
64public:
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.
Eric Laurentffbc80f2015-03-18 18:30:19 -070068 * we use 100 steps to avoid rounding errors when computing the volume in volIndexToDb()
François Gaffiedfd74092015-03-19 12:10:59 +010069 *
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 /**
François Gaffiedfd74092015-03-19 12:10:59 +010082 * 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 */
jiabin9a3361e2019-10-01 09:38:30 -070088 static audio_devices_t getDeviceForVolume(const android::DeviceTypeSet& deviceTypes)
François Gaffiedfd74092015-03-19 12:10:59 +010089 {
jiabin9a3361e2019-10-01 09:38:30 -070090 if (deviceTypes.empty()) {
François Gaffiedfd74092015-03-19 12:10:59 +010091 // 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.
jiabin43810402019-10-24 14:58:31 -070093 return AUDIO_DEVICE_OUT_SPEAKER;
François Gaffiedfd74092015-03-19 12:10:59 +010094 }
95
jiabin43810402019-10-24 14:58:31 -070096 audio_devices_t deviceType = apm_extract_one_audio_device(deviceTypes);
97
François Gaffiedfd74092015-03-19 12:10:59 +010098 /*SPEAKER_SAFE is an alias of SPEAKER for purposes of volume control*/
jiabin9a3361e2019-10-01 09:38:30 -070099 if (deviceType == AUDIO_DEVICE_OUT_SPEAKER_SAFE) {
100 deviceType = AUDIO_DEVICE_OUT_SPEAKER;
101 }
François Gaffiedfd74092015-03-19 12:10:59 +0100102
jiabin9a3361e2019-10-01 09:38:30 -0700103 ALOGW_IF(deviceType == AUDIO_DEVICE_NONE,
104 "getDeviceForVolume() invalid device combination: %s, returning AUDIO_DEVICE_NONE",
105 android::dumpDeviceTypes(deviceTypes).c_str());
François Gaffiedfd74092015-03-19 12:10:59 +0100106
jiabin9a3361e2019-10-01 09:38:30 -0700107 return deviceType;
François Gaffiedfd74092015-03-19 12:10:59 +0100108 }
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 */
jiabin9a3361e2019-10-01 09:38:30 -0700117 static device_category getDeviceCategory(const android::DeviceTypeSet& deviceTypes)
François Gaffiedfd74092015-03-19 12:10:59 +0100118 {
jiabin9a3361e2019-10-01 09:38:30 -0700119 switch(getDeviceForVolume(deviceTypes)) {
François Gaffiedfd74092015-03-19 12:10:59 +0100120 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:
Eric Laurent904d6322017-03-17 17:20:47 -0700128 case AUDIO_DEVICE_OUT_USB_HEADSET:
François Gaffiedfd74092015-03-19 12:10:59 +0100129 return DEVICE_CATEGORY_HEADSET;
Jakub Pawlowski24b0a892018-04-02 19:17:11 -0700130 case AUDIO_DEVICE_OUT_HEARING_AID:
131 return DEVICE_CATEGORY_HEARING_AID;
François Gaffiedfd74092015-03-19 12:10:59 +0100132 case AUDIO_DEVICE_OUT_LINE:
133 case AUDIO_DEVICE_OUT_AUX_DIGITAL:
Eric Laurent904d6322017-03-17 17:20:47 -0700134 case AUDIO_DEVICE_OUT_USB_DEVICE:
François Gaffiedfd74092015-03-19 12:10:59 +0100135 return DEVICE_CATEGORY_EXT_MEDIA;
136 case AUDIO_DEVICE_OUT_SPEAKER:
Jean-Michel Trivi227342a2018-09-14 11:42:37 -0700137 case AUDIO_DEVICE_OUT_SPEAKER_SAFE:
François Gaffiedfd74092015-03-19 12:10:59 +0100138 case AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT:
139 case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER:
140 case AUDIO_DEVICE_OUT_USB_ACCESSORY:
François Gaffiedfd74092015-03-19 12:10:59 +0100141 case AUDIO_DEVICE_OUT_REMOTE_SUBMIX:
142 default:
143 return DEVICE_CATEGORY_SPEAKER;
144 }
145 }
146
Eric Laurentffbc80f2015-03-18 18:30:19 -0700147 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
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
François Gaffiedfd74092015-03-19 12:10:59 +0100163};