AudioGain.cpp revision dfd7409c1b708f6c429aa43722ca8493a91d8df0
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::AudioGain" 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 "AudioGain.h" 28#include "StreamDescriptor.h" 29#include <utils/Log.h> 30#include <utils/String8.h> 31 32#include <math.h> 33 34namespace android { 35 36const VolumeCurvePoint 37ApmGains::sDefaultVolumeCurve[Volume::VOLCNT] = { 38 {1, -49.5f}, {33, -33.5f}, {66, -17.0f}, {100, 0.0f} 39}; 40 41 42const VolumeCurvePoint 43ApmGains::sDefaultMediaVolumeCurve[Volume::VOLCNT] = { 44 {1, -58.0f}, {20, -40.0f}, {60, -17.0f}, {100, 0.0f} 45}; 46 47const VolumeCurvePoint 48ApmGains::sExtMediaSystemVolumeCurve[Volume::VOLCNT] = { 49 {1, -58.0f}, {20, -40.0f}, {60, -21.0f}, {100, -10.0f} 50}; 51 52const VolumeCurvePoint 53ApmGains::sSpeakerMediaVolumeCurve[Volume::VOLCNT] = { 54 {1, -56.0f}, {20, -34.0f}, {60, -11.0f}, {100, 0.0f} 55}; 56 57const VolumeCurvePoint 58ApmGains::sSpeakerMediaVolumeCurveDrc[Volume::VOLCNT] = { 59 {1, -55.0f}, {20, -43.0f}, {86, -12.0f}, {100, 0.0f} 60}; 61 62const VolumeCurvePoint 63ApmGains::sSpeakerSonificationVolumeCurve[Volume::VOLCNT] = { 64 {1, -29.7f}, {33, -20.1f}, {66, -10.2f}, {100, 0.0f} 65}; 66 67const VolumeCurvePoint 68ApmGains::sSpeakerSonificationVolumeCurveDrc[Volume::VOLCNT] = { 69 {1, -35.7f}, {33, -26.1f}, {66, -13.2f}, {100, 0.0f} 70}; 71 72// AUDIO_STREAM_SYSTEM, AUDIO_STREAM_ENFORCED_AUDIBLE and AUDIO_STREAM_DTMF volume tracks 73// AUDIO_STREAM_RING on phones and AUDIO_STREAM_MUSIC on tablets. 74// AUDIO_STREAM_DTMF tracks AUDIO_STREAM_VOICE_CALL while in call (See AudioService.java). 75// The range is constrained between -24dB and -6dB over speaker and -30dB and -18dB over headset. 76 77const VolumeCurvePoint 78ApmGains::sDefaultSystemVolumeCurve[Volume::VOLCNT] = { 79 {1, -24.0f}, {33, -18.0f}, {66, -12.0f}, {100, -6.0f} 80}; 81 82const VolumeCurvePoint 83ApmGains::sDefaultSystemVolumeCurveDrc[Volume::VOLCNT] = { 84 {1, -34.0f}, {33, -24.0f}, {66, -15.0f}, {100, -6.0f} 85}; 86 87const VolumeCurvePoint 88ApmGains::sHeadsetSystemVolumeCurve[Volume::VOLCNT] = { 89 {1, -30.0f}, {33, -26.0f}, {66, -22.0f}, {100, -18.0f} 90}; 91 92const VolumeCurvePoint 93ApmGains::sDefaultVoiceVolumeCurve[Volume::VOLCNT] = { 94 {0, -42.0f}, {33, -28.0f}, {66, -14.0f}, {100, 0.0f} 95}; 96 97const VolumeCurvePoint 98ApmGains::sSpeakerVoiceVolumeCurve[Volume::VOLCNT] = { 99 {0, -24.0f}, {33, -16.0f}, {66, -8.0f}, {100, 0.0f} 100}; 101 102const VolumeCurvePoint 103ApmGains::sLinearVolumeCurve[Volume::VOLCNT] = { 104 {0, -96.0f}, {33, -68.0f}, {66, -34.0f}, {100, 0.0f} 105}; 106 107const VolumeCurvePoint 108ApmGains::sSilentVolumeCurve[Volume::VOLCNT] = { 109 {0, -96.0f}, {1, -96.0f}, {2, -96.0f}, {100, -96.0f} 110}; 111 112const VolumeCurvePoint 113ApmGains::sFullScaleVolumeCurve[Volume::VOLCNT] = { 114 {0, 0.0f}, {1, 0.0f}, {2, 0.0f}, {100, 0.0f} 115}; 116 117const VolumeCurvePoint *ApmGains::sVolumeProfiles[AUDIO_STREAM_CNT] 118 [Volume::DEVICE_CATEGORY_CNT] = { 119 { // AUDIO_STREAM_VOICE_CALL 120 ApmGains::sDefaultVoiceVolumeCurve, // DEVICE_CATEGORY_HEADSET 121 ApmGains::sSpeakerVoiceVolumeCurve, // DEVICE_CATEGORY_SPEAKER 122 ApmGains::sSpeakerVoiceVolumeCurve, // DEVICE_CATEGORY_EARPIECE 123 ApmGains::sDefaultMediaVolumeCurve // DEVICE_CATEGORY_EXT_MEDIA 124 }, 125 { // AUDIO_STREAM_SYSTEM 126 ApmGains::sHeadsetSystemVolumeCurve, // DEVICE_CATEGORY_HEADSET 127 ApmGains::sDefaultSystemVolumeCurve, // DEVICE_CATEGORY_SPEAKER 128 ApmGains::sDefaultSystemVolumeCurve, // DEVICE_CATEGORY_EARPIECE 129 ApmGains::sExtMediaSystemVolumeCurve // DEVICE_CATEGORY_EXT_MEDIA 130 }, 131 { // AUDIO_STREAM_RING 132 ApmGains::sDefaultVolumeCurve, // DEVICE_CATEGORY_HEADSET 133 ApmGains::sSpeakerSonificationVolumeCurve, // DEVICE_CATEGORY_SPEAKER 134 ApmGains::sDefaultVolumeCurve, // DEVICE_CATEGORY_EARPIECE 135 ApmGains::sExtMediaSystemVolumeCurve // DEVICE_CATEGORY_EXT_MEDIA 136 }, 137 { // AUDIO_STREAM_MUSIC 138 ApmGains::sDefaultMediaVolumeCurve, // DEVICE_CATEGORY_HEADSET 139 ApmGains::sSpeakerMediaVolumeCurve, // DEVICE_CATEGORY_SPEAKER 140 ApmGains::sDefaultMediaVolumeCurve, // DEVICE_CATEGORY_EARPIECE 141 ApmGains::sDefaultMediaVolumeCurve // DEVICE_CATEGORY_EXT_MEDIA 142 }, 143 { // AUDIO_STREAM_ALARM 144 ApmGains::sDefaultVolumeCurve, // DEVICE_CATEGORY_HEADSET 145 ApmGains::sSpeakerSonificationVolumeCurve, // DEVICE_CATEGORY_SPEAKER 146 ApmGains::sDefaultVolumeCurve, // DEVICE_CATEGORY_EARPIECE 147 ApmGains::sExtMediaSystemVolumeCurve // DEVICE_CATEGORY_EXT_MEDIA 148 }, 149 { // AUDIO_STREAM_NOTIFICATION 150 ApmGains::sDefaultVolumeCurve, // DEVICE_CATEGORY_HEADSET 151 ApmGains::sSpeakerSonificationVolumeCurve, // DEVICE_CATEGORY_SPEAKER 152 ApmGains::sDefaultVolumeCurve, // DEVICE_CATEGORY_EARPIECE 153 ApmGains::sExtMediaSystemVolumeCurve // DEVICE_CATEGORY_EXT_MEDIA 154 }, 155 { // AUDIO_STREAM_BLUETOOTH_SCO 156 ApmGains::sDefaultVoiceVolumeCurve, // DEVICE_CATEGORY_HEADSET 157 ApmGains::sSpeakerVoiceVolumeCurve, // DEVICE_CATEGORY_SPEAKER 158 ApmGains::sDefaultVoiceVolumeCurve, // DEVICE_CATEGORY_EARPIECE 159 ApmGains::sDefaultMediaVolumeCurve // DEVICE_CATEGORY_EXT_MEDIA 160 }, 161 { // AUDIO_STREAM_ENFORCED_AUDIBLE 162 ApmGains::sHeadsetSystemVolumeCurve, // DEVICE_CATEGORY_HEADSET 163 ApmGains::sDefaultSystemVolumeCurve, // DEVICE_CATEGORY_SPEAKER 164 ApmGains::sDefaultSystemVolumeCurve, // DEVICE_CATEGORY_EARPIECE 165 ApmGains::sExtMediaSystemVolumeCurve // DEVICE_CATEGORY_EXT_MEDIA 166 }, 167 { // AUDIO_STREAM_DTMF 168 ApmGains::sHeadsetSystemVolumeCurve, // DEVICE_CATEGORY_HEADSET 169 ApmGains::sDefaultSystemVolumeCurve, // DEVICE_CATEGORY_SPEAKER 170 ApmGains::sDefaultSystemVolumeCurve, // DEVICE_CATEGORY_EARPIECE 171 ApmGains::sExtMediaSystemVolumeCurve // DEVICE_CATEGORY_EXT_MEDIA 172 }, 173 { // AUDIO_STREAM_TTS 174 // "Transmitted Through Speaker": always silent except on DEVICE_CATEGORY_SPEAKER 175 ApmGains::sSilentVolumeCurve, // DEVICE_CATEGORY_HEADSET 176 ApmGains::sLinearVolumeCurve, // DEVICE_CATEGORY_SPEAKER 177 ApmGains::sSilentVolumeCurve, // DEVICE_CATEGORY_EARPIECE 178 ApmGains::sSilentVolumeCurve // DEVICE_CATEGORY_EXT_MEDIA 179 }, 180 { // AUDIO_STREAM_ACCESSIBILITY 181 ApmGains::sDefaultMediaVolumeCurve, // DEVICE_CATEGORY_HEADSET 182 ApmGains::sSpeakerMediaVolumeCurve, // DEVICE_CATEGORY_SPEAKER 183 ApmGains::sDefaultMediaVolumeCurve, // DEVICE_CATEGORY_EARPIECE 184 ApmGains::sDefaultMediaVolumeCurve // DEVICE_CATEGORY_EXT_MEDIA 185 }, 186 { // AUDIO_STREAM_REROUTING 187 ApmGains::sFullScaleVolumeCurve, // DEVICE_CATEGORY_HEADSET 188 ApmGains::sFullScaleVolumeCurve, // DEVICE_CATEGORY_SPEAKER 189 ApmGains::sFullScaleVolumeCurve, // DEVICE_CATEGORY_EARPIECE 190 ApmGains::sFullScaleVolumeCurve // DEVICE_CATEGORY_EXT_MEDIA 191 }, 192 { // AUDIO_STREAM_PATCH 193 ApmGains::sFullScaleVolumeCurve, // DEVICE_CATEGORY_HEADSET 194 ApmGains::sFullScaleVolumeCurve, // DEVICE_CATEGORY_SPEAKER 195 ApmGains::sFullScaleVolumeCurve, // DEVICE_CATEGORY_EARPIECE 196 ApmGains::sFullScaleVolumeCurve // DEVICE_CATEGORY_EXT_MEDIA 197 }, 198}; 199 200//static 201float ApmGains::volIndexToAmpl(audio_devices_t device, const StreamDescriptor& streamDesc, 202 int indexInUi) 203{ 204 Volume::device_category deviceCategory = Volume::getDeviceCategory(device); 205 const VolumeCurvePoint *curve = streamDesc.getVolumeCurvePoint(deviceCategory); 206 207 // the volume index in the UI is relative to the min and max volume indices for this stream type 208 int nbSteps = 1 + curve[Volume::VOLMAX].mIndex - 209 curve[Volume::VOLMIN].mIndex; 210 int volIdx = (nbSteps * (indexInUi - streamDesc.getVolumeIndexMin())) / 211 (streamDesc.getVolumeIndexMax() - streamDesc.getVolumeIndexMin()); 212 213 // find what part of the curve this index volume belongs to, or if it's out of bounds 214 int segment = 0; 215 if (volIdx < curve[Volume::VOLMIN].mIndex) { // out of bounds 216 return 0.0f; 217 } else if (volIdx < curve[Volume::VOLKNEE1].mIndex) { 218 segment = 0; 219 } else if (volIdx < curve[Volume::VOLKNEE2].mIndex) { 220 segment = 1; 221 } else if (volIdx <= curve[Volume::VOLMAX].mIndex) { 222 segment = 2; 223 } else { // out of bounds 224 return 1.0f; 225 } 226 227 // linear interpolation in the attenuation table in dB 228 float decibels = curve[segment].mDBAttenuation + 229 ((float)(volIdx - curve[segment].mIndex)) * 230 ( (curve[segment+1].mDBAttenuation - 231 curve[segment].mDBAttenuation) / 232 ((float)(curve[segment+1].mIndex - 233 curve[segment].mIndex)) ); 234 235 float amplification = exp( decibels * 0.115129f); // exp( dB * ln(10) / 20 ) 236 237 ALOGVV("VOLUME vol index=[%d %d %d], dB=[%.1f %.1f %.1f] ampl=%.5f", 238 curve[segment].mIndex, volIdx, 239 curve[segment+1].mIndex, 240 curve[segment].mDBAttenuation, 241 decibels, 242 curve[segment+1].mDBAttenuation, 243 amplification); 244 245 return amplification; 246} 247 248 249 250AudioGain::AudioGain(int index, bool useInChannelMask) 251{ 252 mIndex = index; 253 mUseInChannelMask = useInChannelMask; 254 memset(&mGain, 0, sizeof(struct audio_gain)); 255} 256 257void AudioGain::getDefaultConfig(struct audio_gain_config *config) 258{ 259 config->index = mIndex; 260 config->mode = mGain.mode; 261 config->channel_mask = mGain.channel_mask; 262 if ((mGain.mode & AUDIO_GAIN_MODE_JOINT) == AUDIO_GAIN_MODE_JOINT) { 263 config->values[0] = mGain.default_value; 264 } else { 265 uint32_t numValues; 266 if (mUseInChannelMask) { 267 numValues = audio_channel_count_from_in_mask(mGain.channel_mask); 268 } else { 269 numValues = audio_channel_count_from_out_mask(mGain.channel_mask); 270 } 271 for (size_t i = 0; i < numValues; i++) { 272 config->values[i] = mGain.default_value; 273 } 274 } 275 if ((mGain.mode & AUDIO_GAIN_MODE_RAMP) == AUDIO_GAIN_MODE_RAMP) { 276 config->ramp_duration_ms = mGain.min_ramp_ms; 277 } 278} 279 280status_t AudioGain::checkConfig(const struct audio_gain_config *config) 281{ 282 if ((config->mode & ~mGain.mode) != 0) { 283 return BAD_VALUE; 284 } 285 if ((config->mode & AUDIO_GAIN_MODE_JOINT) == AUDIO_GAIN_MODE_JOINT) { 286 if ((config->values[0] < mGain.min_value) || 287 (config->values[0] > mGain.max_value)) { 288 return BAD_VALUE; 289 } 290 } else { 291 if ((config->channel_mask & ~mGain.channel_mask) != 0) { 292 return BAD_VALUE; 293 } 294 uint32_t numValues; 295 if (mUseInChannelMask) { 296 numValues = audio_channel_count_from_in_mask(config->channel_mask); 297 } else { 298 numValues = audio_channel_count_from_out_mask(config->channel_mask); 299 } 300 for (size_t i = 0; i < numValues; i++) { 301 if ((config->values[i] < mGain.min_value) || 302 (config->values[i] > mGain.max_value)) { 303 return BAD_VALUE; 304 } 305 } 306 } 307 if ((config->mode & AUDIO_GAIN_MODE_RAMP) == AUDIO_GAIN_MODE_RAMP) { 308 if ((config->ramp_duration_ms < mGain.min_ramp_ms) || 309 (config->ramp_duration_ms > mGain.max_ramp_ms)) { 310 return BAD_VALUE; 311 } 312 } 313 return NO_ERROR; 314} 315 316void AudioGain::dump(int fd, int spaces, int index) const 317{ 318 const size_t SIZE = 256; 319 char buffer[SIZE]; 320 String8 result; 321 322 snprintf(buffer, SIZE, "%*sGain %d:\n", spaces, "", index+1); 323 result.append(buffer); 324 snprintf(buffer, SIZE, "%*s- mode: %08x\n", spaces, "", mGain.mode); 325 result.append(buffer); 326 snprintf(buffer, SIZE, "%*s- channel_mask: %08x\n", spaces, "", mGain.channel_mask); 327 result.append(buffer); 328 snprintf(buffer, SIZE, "%*s- min_value: %d mB\n", spaces, "", mGain.min_value); 329 result.append(buffer); 330 snprintf(buffer, SIZE, "%*s- max_value: %d mB\n", spaces, "", mGain.max_value); 331 result.append(buffer); 332 snprintf(buffer, SIZE, "%*s- default_value: %d mB\n", spaces, "", mGain.default_value); 333 result.append(buffer); 334 snprintf(buffer, SIZE, "%*s- step_value: %d mB\n", spaces, "", mGain.step_value); 335 result.append(buffer); 336 snprintf(buffer, SIZE, "%*s- min_ramp_ms: %d ms\n", spaces, "", mGain.min_ramp_ms); 337 result.append(buffer); 338 snprintf(buffer, SIZE, "%*s- max_ramp_ms: %d ms\n", spaces, "", mGain.max_ramp_ms); 339 result.append(buffer); 340 341 write(fd, result.string(), result.size()); 342} 343 344}; // namespace android 345