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#define LOG_TAG "APM::Gains"
18//#define LOG_NDEBUG 0
19
20//#define VERY_VERBOSE_LOGGING
21#ifdef VERY_VERBOSE_LOGGING
22#define ALOGVV ALOGV
23#else
24#define ALOGVV(a...) do { } while(0)
25#endif
26
27#include "Gains.h"
28#include <Volume.h>
29#include <math.h>
30#include <utils/String8.h>
31
32namespace android {
33
34// Enginedefault
35const VolumeCurvePoint
36Gains::sDefaultVolumeCurve[Volume::VOLCNT] = {
37    {1, -49.5f}, {33, -33.5f}, {66, -17.0f}, {100, 0.0f}
38};
39
40
41const VolumeCurvePoint
42Gains::sDefaultMediaVolumeCurve[Volume::VOLCNT] = {
43    {1, -58.0f}, {20, -40.0f}, {60, -17.0f}, {100, 0.0f}
44};
45
46const VolumeCurvePoint
47Gains::sExtMediaSystemVolumeCurve[Volume::VOLCNT] = {
48    {1, -58.0f}, {20, -40.0f}, {60, -21.0f}, {100, -10.0f}
49};
50
51const VolumeCurvePoint
52Gains::sSpeakerMediaVolumeCurve[Volume::VOLCNT] = {
53    {1, -56.0f}, {20, -34.0f}, {60, -11.0f}, {100, 0.0f}
54};
55
56const VolumeCurvePoint
57Gains::sSpeakerMediaVolumeCurveDrc[Volume::VOLCNT] = {
58    {1, -55.0f}, {20, -43.0f}, {86, -12.0f}, {100, 0.0f}
59};
60
61const VolumeCurvePoint
62Gains::sSpeakerSonificationVolumeCurve[Volume::VOLCNT] = {
63    {1, -29.7f}, {33, -20.1f}, {66, -10.2f}, {100, 0.0f}
64};
65
66const VolumeCurvePoint
67Gains::sSpeakerSonificationVolumeCurveDrc[Volume::VOLCNT] = {
68    {1, -35.7f}, {33, -26.1f}, {66, -13.2f}, {100, 0.0f}
69};
70
71// AUDIO_STREAM_SYSTEM, AUDIO_STREAM_ENFORCED_AUDIBLE and AUDIO_STREAM_DTMF volume tracks
72// AUDIO_STREAM_RING on phones and AUDIO_STREAM_MUSIC on tablets.
73// AUDIO_STREAM_DTMF tracks AUDIO_STREAM_VOICE_CALL while in call (See AudioService.java).
74// The range is constrained between -24dB and -6dB over speaker and -30dB and -18dB over headset.
75
76const VolumeCurvePoint
77Gains::sDefaultSystemVolumeCurve[Volume::VOLCNT] = {
78    {1, -24.0f}, {33, -18.0f}, {66, -12.0f}, {100, -6.0f}
79};
80
81const VolumeCurvePoint
82Gains::sDefaultSystemVolumeCurveDrc[Volume::VOLCNT] = {
83    {1, -34.0f}, {33, -24.0f}, {66, -15.0f}, {100, -6.0f}
84};
85
86const VolumeCurvePoint
87Gains::sHeadsetSystemVolumeCurve[Volume::VOLCNT] = {
88    {1, -30.0f}, {33, -26.0f}, {66, -22.0f}, {100, -18.0f}
89};
90
91const VolumeCurvePoint
92Gains::sDefaultVoiceVolumeCurve[Volume::VOLCNT] = {
93    {0, -42.0f}, {33, -28.0f}, {66, -14.0f}, {100, 0.0f}
94};
95
96const VolumeCurvePoint
97Gains::sSpeakerVoiceVolumeCurve[Volume::VOLCNT] = {
98    {0, -24.0f}, {33, -16.0f}, {66, -8.0f}, {100, 0.0f}
99};
100
101const VolumeCurvePoint
102Gains::sLinearVolumeCurve[Volume::VOLCNT] = {
103    {0, -96.0f}, {33, -68.0f}, {66, -34.0f}, {100, 0.0f}
104};
105
106const VolumeCurvePoint
107Gains::sSilentVolumeCurve[Volume::VOLCNT] = {
108    {0, -96.0f}, {1, -96.0f}, {2, -96.0f}, {100, -96.0f}
109};
110
111const VolumeCurvePoint
112Gains::sFullScaleVolumeCurve[Volume::VOLCNT] = {
113    {0, 0.0f}, {1, 0.0f}, {2, 0.0f}, {100, 0.0f}
114};
115
116const VolumeCurvePoint *Gains::sVolumeProfiles[AUDIO_STREAM_CNT]
117                                                  [DEVICE_CATEGORY_CNT] = {
118    { // AUDIO_STREAM_VOICE_CALL
119        Gains::sDefaultVoiceVolumeCurve, // DEVICE_CATEGORY_HEADSET
120        Gains::sSpeakerVoiceVolumeCurve, // DEVICE_CATEGORY_SPEAKER
121        Gains::sSpeakerVoiceVolumeCurve, // DEVICE_CATEGORY_EARPIECE
122        Gains::sDefaultMediaVolumeCurve  // DEVICE_CATEGORY_EXT_MEDIA
123    },
124    { // AUDIO_STREAM_SYSTEM
125        Gains::sHeadsetSystemVolumeCurve, // DEVICE_CATEGORY_HEADSET
126        Gains::sDefaultSystemVolumeCurve, // DEVICE_CATEGORY_SPEAKER
127        Gains::sDefaultSystemVolumeCurve,  // DEVICE_CATEGORY_EARPIECE
128        Gains::sExtMediaSystemVolumeCurve  // DEVICE_CATEGORY_EXT_MEDIA
129    },
130    { // AUDIO_STREAM_RING
131        Gains::sDefaultVolumeCurve, // DEVICE_CATEGORY_HEADSET
132        Gains::sSpeakerSonificationVolumeCurve, // DEVICE_CATEGORY_SPEAKER
133        Gains::sDefaultVolumeCurve,  // DEVICE_CATEGORY_EARPIECE
134        Gains::sExtMediaSystemVolumeCurve  // DEVICE_CATEGORY_EXT_MEDIA
135    },
136    { // AUDIO_STREAM_MUSIC
137        Gains::sDefaultMediaVolumeCurve, // DEVICE_CATEGORY_HEADSET
138        Gains::sSpeakerMediaVolumeCurve, // DEVICE_CATEGORY_SPEAKER
139        Gains::sDefaultMediaVolumeCurve, // DEVICE_CATEGORY_EARPIECE
140        Gains::sDefaultMediaVolumeCurve  // DEVICE_CATEGORY_EXT_MEDIA
141    },
142    { // AUDIO_STREAM_ALARM
143        Gains::sDefaultVolumeCurve, // DEVICE_CATEGORY_HEADSET
144        Gains::sSpeakerSonificationVolumeCurve, // DEVICE_CATEGORY_SPEAKER
145        Gains::sDefaultVolumeCurve,  // DEVICE_CATEGORY_EARPIECE
146        Gains::sExtMediaSystemVolumeCurve  // DEVICE_CATEGORY_EXT_MEDIA
147    },
148    { // AUDIO_STREAM_NOTIFICATION
149        Gains::sDefaultVolumeCurve, // DEVICE_CATEGORY_HEADSET
150        Gains::sSpeakerSonificationVolumeCurve, // DEVICE_CATEGORY_SPEAKER
151        Gains::sDefaultVolumeCurve,  // DEVICE_CATEGORY_EARPIECE
152        Gains::sExtMediaSystemVolumeCurve  // DEVICE_CATEGORY_EXT_MEDIA
153    },
154    { // AUDIO_STREAM_BLUETOOTH_SCO
155        Gains::sDefaultVoiceVolumeCurve, // DEVICE_CATEGORY_HEADSET
156        Gains::sSpeakerVoiceVolumeCurve, // DEVICE_CATEGORY_SPEAKER
157        Gains::sDefaultVoiceVolumeCurve, // DEVICE_CATEGORY_EARPIECE
158        Gains::sDefaultMediaVolumeCurve  // DEVICE_CATEGORY_EXT_MEDIA
159    },
160    { // AUDIO_STREAM_ENFORCED_AUDIBLE
161        Gains::sHeadsetSystemVolumeCurve, // DEVICE_CATEGORY_HEADSET
162        Gains::sDefaultSystemVolumeCurve, // DEVICE_CATEGORY_SPEAKER
163        Gains::sDefaultSystemVolumeCurve, // DEVICE_CATEGORY_EARPIECE
164        Gains::sExtMediaSystemVolumeCurve  // DEVICE_CATEGORY_EXT_MEDIA
165    },
166    {  // AUDIO_STREAM_DTMF
167        Gains::sHeadsetSystemVolumeCurve, // DEVICE_CATEGORY_HEADSET
168        Gains::sDefaultSystemVolumeCurve, // DEVICE_CATEGORY_SPEAKER
169        Gains::sDefaultSystemVolumeCurve, // DEVICE_CATEGORY_EARPIECE
170        Gains::sExtMediaSystemVolumeCurve  // DEVICE_CATEGORY_EXT_MEDIA
171    },
172    { // AUDIO_STREAM_TTS
173      // "Transmitted Through Speaker": always silent except on DEVICE_CATEGORY_SPEAKER
174        Gains::sSilentVolumeCurve,    // DEVICE_CATEGORY_HEADSET
175        Gains::sFullScaleVolumeCurve, // DEVICE_CATEGORY_SPEAKER
176        Gains::sSilentVolumeCurve,    // DEVICE_CATEGORY_EARPIECE
177        Gains::sSilentVolumeCurve     // DEVICE_CATEGORY_EXT_MEDIA
178    },
179    { // AUDIO_STREAM_ACCESSIBILITY
180        Gains::sDefaultMediaVolumeCurve, // DEVICE_CATEGORY_HEADSET
181        Gains::sSpeakerMediaVolumeCurve, // DEVICE_CATEGORY_SPEAKER
182        Gains::sDefaultMediaVolumeCurve, // DEVICE_CATEGORY_EARPIECE
183        Gains::sDefaultMediaVolumeCurve  // DEVICE_CATEGORY_EXT_MEDIA
184    },
185    { // AUDIO_STREAM_REROUTING
186        Gains::sFullScaleVolumeCurve, // DEVICE_CATEGORY_HEADSET
187        Gains::sFullScaleVolumeCurve, // DEVICE_CATEGORY_SPEAKER
188        Gains::sFullScaleVolumeCurve, // DEVICE_CATEGORY_EARPIECE
189        Gains::sFullScaleVolumeCurve  // DEVICE_CATEGORY_EXT_MEDIA
190    },
191    { // AUDIO_STREAM_PATCH
192        Gains::sFullScaleVolumeCurve, // DEVICE_CATEGORY_HEADSET
193        Gains::sFullScaleVolumeCurve, // DEVICE_CATEGORY_SPEAKER
194        Gains::sFullScaleVolumeCurve, // DEVICE_CATEGORY_EARPIECE
195        Gains::sFullScaleVolumeCurve  // DEVICE_CATEGORY_EXT_MEDIA
196    },
197};
198
199//static
200float Gains::volIndexToDb(const VolumeCurvePoint *curve, int indexMin, int indexMax, int indexInUi)
201{
202    // the volume index in the UI is relative to the min and max volume indices for this stream type
203    int nbSteps = 1 + curve[Volume::VOLMAX].mIndex - curve[Volume::VOLMIN].mIndex;
204    int volIdx = (nbSteps * (indexInUi - indexMin)) / (indexMax - indexMin);
205
206    // find what part of the curve this index volume belongs to, or if it's out of bounds
207    int segment = 0;
208    if (volIdx < curve[Volume::VOLMIN].mIndex) {         // out of bounds
209        return VOLUME_MIN_DB;
210    } else if (volIdx < curve[Volume::VOLKNEE1].mIndex) {
211        segment = 0;
212    } else if (volIdx < curve[Volume::VOLKNEE2].mIndex) {
213        segment = 1;
214    } else if (volIdx <= curve[Volume::VOLMAX].mIndex) {
215        segment = 2;
216    } else {                                                               // out of bounds
217        return 0.0f;
218    }
219
220    // linear interpolation in the attenuation table in dB
221    float decibels = curve[segment].mDBAttenuation +
222            ((float)(volIdx - curve[segment].mIndex)) *
223                ( (curve[segment+1].mDBAttenuation -
224                        curve[segment].mDBAttenuation) /
225                    ((float)(curve[segment+1].mIndex -
226                            curve[segment].mIndex)) );
227
228    ALOGVV("VOLUME vol index=[%d %d %d], dB=[%.1f %.1f %.1f]",
229            curve[segment].mIndex, volIdx,
230            curve[segment+1].mIndex,
231            curve[segment].mDBAttenuation,
232            decibels,
233            curve[segment+1].mDBAttenuation);
234
235    return decibels;
236}
237
238}; // namespace android
239