1/* 2 * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved. 3 * Not a Contribution. 4 * 5 * Copyright (C) 2013 The Android Open Source Project 6 * 7 * Licensed under the Apache License, Version 2.0 (the "License"); 8 * you may not use this file except in compliance with the License. 9 * You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, software 14 * distributed under the License is distributed on an "AS IS" BASIS, 15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 * See the License for the specific language governing permissions and 17 * limitations under the License. 18 */ 19 20#define LOG_TAG "offload_effect_virtualizer" 21#define LOG_NDEBUG 0 22 23#include <cutils/list.h> 24#include <cutils/log.h> 25#include <tinyalsa/asoundlib.h> 26#include <sound/audio_effects.h> 27#include <audio_effects/effect_virtualizer.h> 28 29#include "effect_api.h" 30#include "virtualizer.h" 31 32/* Offload Virtualizer UUID: 509a4498-561a-4bea-b3b1-0002a5d5c51b */ 33const effect_descriptor_t virtualizer_descriptor = { 34 {0x37cc2c00, 0xdddd, 0x11db, 0x8577, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, 35 {0x509a4498, 0x561a, 0x4bea, 0xb3b1, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, // uuid 36 EFFECT_CONTROL_API_VERSION, 37 (EFFECT_FLAG_TYPE_INSERT | EFFECT_FLAG_DEVICE_IND | EFFECT_FLAG_HW_ACC_TUNNEL), 38 0, /* TODO */ 39 1, 40 "MSM offload virtualizer", 41 "The Android Open Source Project", 42}; 43 44/* 45 * Virtualizer operations 46 */ 47 48int virtualizer_get_strength(virtualizer_context_t *context) 49{ 50 ALOGV("%s: ctxt %p, strength: %d", __func__, context, context->strength); 51 return context->strength; 52} 53 54int virtualizer_set_strength(virtualizer_context_t *context, uint32_t strength) 55{ 56 ALOGV("%s: ctxt %p, strength: %d", __func__, context, strength); 57 context->strength = strength; 58 59 offload_virtualizer_set_strength(&(context->offload_virt), strength); 60 if (context->ctl) 61 offload_virtualizer_send_params(context->ctl, context->offload_virt, 62 OFFLOAD_SEND_VIRTUALIZER_ENABLE_FLAG | 63 OFFLOAD_SEND_VIRTUALIZER_STRENGTH); 64 return 0; 65} 66 67/* 68 * Check if an audio device is supported by this implementation 69 * 70 * [in] 71 * device device that is intented for processing (e.g. for binaural vs transaural) 72 * [out] 73 * false device is not applicable for effect 74 * true device is applicable for effect 75 */ 76bool virtualizer_is_device_supported(audio_devices_t device) { 77 switch (device) { 78 case AUDIO_DEVICE_OUT_SPEAKER: 79 case AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT: 80 case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER: 81#ifdef AFE_PROXY_ENABLED 82 case AUDIO_DEVICE_OUT_PROXY: 83#endif 84 case AUDIO_DEVICE_OUT_AUX_DIGITAL: 85 case AUDIO_DEVICE_OUT_USB_ACCESSORY: 86 case AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET: 87 return false; 88 default : 89 return true; 90 } 91} 92 93/* 94 * Check if a channel mask + audio device is supported by this implementation 95 * 96 * [in] 97 * channel_mask channel mask of input buffer 98 * device device that is intented for processing (e.g. for binaural vs transaural) 99 * [out] 100 * false if the configuration is not supported or it is unknown 101 * true if the configuration is supported 102 */ 103bool virtualizer_is_configuration_supported(audio_channel_mask_t channel_mask, 104 audio_devices_t device) { 105 uint32_t channelCount = audio_channel_count_from_out_mask(channel_mask); 106 if ((channelCount == 0) || (channelCount > 2)) { 107 return false; 108 } 109 110 return virtualizer_is_device_supported(device); 111} 112 113/* 114 * Force the virtualization mode to that of the given audio device 115 * 116 * [in] 117 * context effect engine context 118 * forced_device device whose virtualization mode we'll always use 119 * [out] 120 * -EINVAL if the device is not supported or is unknown 121 * 0 if the device is supported and the virtualization mode forced 122 */ 123int virtualizer_force_virtualization_mode(virtualizer_context_t *context, 124 audio_devices_t forced_device) { 125 virtualizer_context_t *virt_ctxt = (virtualizer_context_t *)context; 126 int status = 0; 127 bool use_virt = false; 128 int is_virt_enabled = 129 offload_virtualizer_get_enable_flag(&(virt_ctxt->offload_virt)); 130 131 ALOGV("%s: ctxt %p, forcedDev=0x%x enabled=%d tmpDisabled=%d", __func__, virt_ctxt, 132 forced_device, is_virt_enabled, virt_ctxt->temp_disabled); 133 134 if (virtualizer_is_device_supported(forced_device) == false) { 135 if (forced_device != AUDIO_DEVICE_NONE) { 136 //forced device is not supported, make it behave as a reset of forced mode 137 forced_device = AUDIO_DEVICE_NONE; 138 // but return an error 139 status = -EINVAL; 140 } 141 } 142 143 if (forced_device == AUDIO_DEVICE_NONE) { 144 // disabling forced virtualization mode: 145 // verify whether the virtualization should be enabled or disabled 146 if (virtualizer_is_device_supported(virt_ctxt->device)) { 147 use_virt = (is_virt_enabled == true); 148 } 149 virt_ctxt->forced_device = AUDIO_DEVICE_NONE; 150 } else { 151 // forcing virtualization mode: 152 // TODO: we assume device is supported, so hard coded a fixed one. 153 virt_ctxt->forced_device = AUDIO_DEVICE_OUT_WIRED_HEADPHONE; 154 // TODO: only enable for a supported mode, when the effect is enabled 155 use_virt = (is_virt_enabled == true); 156 } 157 158 if (use_virt) { 159 if (virt_ctxt->temp_disabled == true) { 160 if (effect_is_active(&virt_ctxt->common)) { 161 offload_virtualizer_set_enable_flag(&(virt_ctxt->offload_virt), true); 162 if (virt_ctxt->ctl) 163 offload_virtualizer_send_params(virt_ctxt->ctl, 164 virt_ctxt->offload_virt, 165 OFFLOAD_SEND_VIRTUALIZER_ENABLE_FLAG); 166 } 167 ALOGV("%s: re-enable VIRTUALIZER", __func__); 168 virt_ctxt->temp_disabled = false; 169 } else { 170 ALOGV("%s: leaving VIRTUALIZER enabled", __func__); 171 } 172 } else { 173 if (virt_ctxt->temp_disabled == false) { 174 if (effect_is_active(&virt_ctxt->common)) { 175 offload_virtualizer_set_enable_flag(&(virt_ctxt->offload_virt), false); 176 if (virt_ctxt->ctl) 177 offload_virtualizer_send_params(virt_ctxt->ctl, 178 virt_ctxt->offload_virt, 179 OFFLOAD_SEND_VIRTUALIZER_ENABLE_FLAG); 180 } 181 ALOGV("%s: disable VIRTUALIZER", __func__); 182 virt_ctxt->temp_disabled = true; 183 } else { 184 ALOGV("%s: leaving VIRTUALIZER disabled", __func__); 185 } 186 } 187 188 ALOGV("after %s: ctxt %p, enabled=%d tmpDisabled=%d", __func__, virt_ctxt, 189 is_virt_enabled, virt_ctxt->temp_disabled); 190 191 return status; 192} 193 194/* 195 * Get the virtual speaker angles for a channel mask + audio device configuration 196 * which is guaranteed to be supported by this implementation 197 * 198 * [in] 199 * channel_mask the channel mask of the input to virtualize 200 * device the type of device that affects the processing (e.g. for binaural vs transaural) 201 * [in/out] 202 * speaker_angles the array of integer where each speaker angle is written as a triplet in the 203 * following format: 204 * int32_t a bit mask with a single value selected for each speaker, following 205 * the convention of the audio_channel_mask_t type 206 * int32_t a value in degrees expressing the speaker azimuth, where 0 is in front 207 * of the user, 180 behind, -90 to the left, 90 to the right of the user 208 * int32_t a value in degrees expressing the speaker elevation, where 0 is the 209 * horizontal plane, +90 is directly above the user, -90 below 210 * 211 */ 212void virtualizer_get_speaker_angles(audio_channel_mask_t channel_mask __unused, 213 audio_devices_t device __unused, int32_t *speaker_angles) { 214 // the channel count is guaranteed to be 1 or 2 215 // the device is guaranteed to be of type headphone 216 // this virtualizer is always 2in with speakers at -90 and 90deg of azimuth, 0deg of elevation 217 *speaker_angles++ = (int32_t) AUDIO_CHANNEL_OUT_FRONT_LEFT; 218 *speaker_angles++ = -90; // azimuth 219 *speaker_angles++ = 0; // elevation 220 *speaker_angles++ = (int32_t) AUDIO_CHANNEL_OUT_FRONT_RIGHT; 221 *speaker_angles++ = 90; // azimuth 222 *speaker_angles = 0; // elevation 223} 224 225/* 226 * Retrieve the current device whose processing mode is used by this effect 227 * 228 * [out] 229 * AUDIO_DEVICE_NONE if the effect is not virtualizing 230 * or the device type if the effect is virtualizing 231 */ 232audio_devices_t virtualizer_get_virtualization_mode(virtualizer_context_t *context) { 233 virtualizer_context_t *virt_ctxt = (virtualizer_context_t *)context; 234 audio_devices_t device = AUDIO_DEVICE_NONE; 235 236 if ((offload_virtualizer_get_enable_flag(&(virt_ctxt->offload_virt))) 237 && (virt_ctxt->temp_disabled == false)) { 238 if (virt_ctxt->forced_device != AUDIO_DEVICE_NONE) { 239 // virtualization mode is forced, return that device 240 device = virt_ctxt->forced_device; 241 } else { 242 // no forced mode, return the current device 243 device = virt_ctxt->device; 244 } 245 } 246 ALOGV("%s: returning 0x%x", __func__, device); 247 return device; 248} 249 250int virtualizer_get_parameter(effect_context_t *context, effect_param_t *p, 251 uint32_t *size) 252{ 253 virtualizer_context_t *virt_ctxt = (virtualizer_context_t *)context; 254 int voffset = ((p->psize - 1) / sizeof(int32_t) + 1) * sizeof(int32_t); 255 int32_t *param_tmp = (int32_t *)p->data; 256 int32_t param = *param_tmp++; 257 void *value = p->data + voffset; 258 int i; 259 260 ALOGV("%s: ctxt %p, param %d", __func__, virt_ctxt, param); 261 262 p->status = 0; 263 264 switch (param) { 265 case VIRTUALIZER_PARAM_STRENGTH_SUPPORTED: 266 if (p->vsize < sizeof(uint32_t)) 267 p->status = -EINVAL; 268 p->vsize = sizeof(uint32_t); 269 break; 270 case VIRTUALIZER_PARAM_STRENGTH: 271 if (p->vsize < sizeof(int16_t)) 272 p->status = -EINVAL; 273 p->vsize = sizeof(int16_t); 274 break; 275 case VIRTUALIZER_PARAM_VIRTUAL_SPEAKER_ANGLES: 276 // return value size can only be interpreted as relative to input value, 277 // deferring validity check to below 278 break; 279 case VIRTUALIZER_PARAM_VIRTUALIZATION_MODE: 280 if (p->vsize != sizeof(uint32_t)) 281 p->status = -EINVAL; 282 p->vsize = sizeof(uint32_t); 283 break; 284 default: 285 p->status = -EINVAL; 286 } 287 288 *size = sizeof(effect_param_t) + voffset + p->vsize; 289 290 if (p->status != 0) 291 return 0; 292 293 switch (param) { 294 case VIRTUALIZER_PARAM_STRENGTH_SUPPORTED: 295 *(uint32_t *)value = 1; 296 break; 297 298 case VIRTUALIZER_PARAM_STRENGTH: 299 *(int16_t *)value = virtualizer_get_strength(virt_ctxt); 300 break; 301 302 case VIRTUALIZER_PARAM_VIRTUAL_SPEAKER_ANGLES: 303 { 304 const audio_channel_mask_t channel_mask = (audio_channel_mask_t) *param_tmp++; 305 const audio_devices_t device = (audio_devices_t) *param_tmp; 306 uint32_t channel_cnt = audio_channel_count_from_out_mask(channel_mask); 307 308 if (p->vsize < 3 * channel_cnt * sizeof(int32_t)){ 309 p->status = -EINVAL; 310 break; 311 } 312 // verify the configuration is supported 313 if(virtualizer_is_configuration_supported(channel_mask, device)) { 314 // configuration is supported, get the angles 315 virtualizer_get_speaker_angles(channel_mask, device, (int32_t *)value); 316 } else { 317 p->status = -EINVAL; 318 } 319 320 break; 321 } 322 323 case VIRTUALIZER_PARAM_VIRTUALIZATION_MODE: 324 *(uint32_t *)value = (uint32_t) virtualizer_get_virtualization_mode(virt_ctxt); 325 break; 326 327 default: 328 p->status = -EINVAL; 329 break; 330 } 331 332 return 0; 333} 334 335int virtualizer_set_parameter(effect_context_t *context, effect_param_t *p, 336 uint32_t size __unused) 337{ 338 virtualizer_context_t *virt_ctxt = (virtualizer_context_t *)context; 339 int voffset = ((p->psize - 1) / sizeof(int32_t) + 1) * sizeof(int32_t); 340 void *value = p->data + voffset; 341 int32_t *param_tmp = (int32_t *)p->data; 342 int32_t param = *param_tmp++; 343 uint32_t strength; 344 345 ALOGV("%s: ctxt %p, param %d", __func__, virt_ctxt, param); 346 347 p->status = 0; 348 349 switch (param) { 350 case VIRTUALIZER_PARAM_STRENGTH: 351 strength = (uint32_t)(*(int16_t *)value); 352 virtualizer_set_strength(virt_ctxt, strength); 353 break; 354 case VIRTUALIZER_PARAM_FORCE_VIRTUALIZATION_MODE: 355 { 356 const audio_devices_t device = *(audio_devices_t *)value; 357 if (0 != virtualizer_force_virtualization_mode(virt_ctxt, device)) { 358 p->status = -EINVAL; 359 } 360 break; 361 } 362 default: 363 p->status = -EINVAL; 364 break; 365 } 366 367 return 0; 368} 369 370int virtualizer_set_device(effect_context_t *context, uint32_t device) 371{ 372 virtualizer_context_t *virt_ctxt = (virtualizer_context_t *)context; 373 374 ALOGV("%s: ctxt %p, device: 0x%x", __func__, virt_ctxt, device); 375 virt_ctxt->device = device; 376 377 if (virt_ctxt->forced_device == AUDIO_DEVICE_NONE) { 378 // default case unless configuration is forced 379 if (virtualizer_is_device_supported(device) == false) { 380 if (!virt_ctxt->temp_disabled) { 381 if (effect_is_active(&virt_ctxt->common)) { 382 offload_virtualizer_set_enable_flag(&(virt_ctxt->offload_virt), false); 383 if (virt_ctxt->ctl) 384 offload_virtualizer_send_params(virt_ctxt->ctl, 385 virt_ctxt->offload_virt, 386 OFFLOAD_SEND_VIRTUALIZER_ENABLE_FLAG); 387 } 388 ALOGI("%s: ctxt %p, disabled based on device", __func__, virt_ctxt); 389 virt_ctxt->temp_disabled = true; 390 } 391 } else { 392 if (virt_ctxt->temp_disabled) { 393 if (effect_is_active(&virt_ctxt->common)) { 394 offload_virtualizer_set_enable_flag(&(virt_ctxt->offload_virt), true); 395 if (virt_ctxt->ctl) 396 offload_virtualizer_send_params(virt_ctxt->ctl, 397 virt_ctxt->offload_virt, 398 OFFLOAD_SEND_VIRTUALIZER_ENABLE_FLAG); 399 } 400 virt_ctxt->temp_disabled = false; 401 } 402 } 403 } 404 // else virtualization mode is forced to a certain device, nothing to do 405 406 offload_virtualizer_set_device(&(virt_ctxt->offload_virt), device); 407 return 0; 408} 409 410int virtualizer_reset(effect_context_t *context) 411{ 412 virtualizer_context_t *virt_ctxt = (virtualizer_context_t *)context; 413 414 return 0; 415} 416 417int virtualizer_init(effect_context_t *context) 418{ 419 ALOGV("%s: ctxt %p", __func__, context); 420 virtualizer_context_t *virt_ctxt = (virtualizer_context_t *)context; 421 422 context->config.inputCfg.accessMode = EFFECT_BUFFER_ACCESS_READ; 423 context->config.inputCfg.channels = AUDIO_CHANNEL_OUT_STEREO; 424 context->config.inputCfg.format = AUDIO_FORMAT_PCM_16_BIT; 425 context->config.inputCfg.samplingRate = 44100; 426 context->config.inputCfg.bufferProvider.getBuffer = NULL; 427 context->config.inputCfg.bufferProvider.releaseBuffer = NULL; 428 context->config.inputCfg.bufferProvider.cookie = NULL; 429 context->config.inputCfg.mask = EFFECT_CONFIG_ALL; 430 context->config.outputCfg.accessMode = EFFECT_BUFFER_ACCESS_ACCUMULATE; 431 context->config.outputCfg.channels = AUDIO_CHANNEL_OUT_STEREO; 432 context->config.outputCfg.format = AUDIO_FORMAT_PCM_16_BIT; 433 context->config.outputCfg.samplingRate = 44100; 434 context->config.outputCfg.bufferProvider.getBuffer = NULL; 435 context->config.outputCfg.bufferProvider.releaseBuffer = NULL; 436 context->config.outputCfg.bufferProvider.cookie = NULL; 437 context->config.outputCfg.mask = EFFECT_CONFIG_ALL; 438 439 set_config(context, &context->config); 440 441 virt_ctxt->temp_disabled = false; 442 virt_ctxt->forced_device = AUDIO_DEVICE_NONE; 443 virt_ctxt->device = AUDIO_DEVICE_NONE; 444 memset(&(virt_ctxt->offload_virt), 0, sizeof(struct virtualizer_params)); 445 446 return 0; 447} 448 449int virtualizer_enable(effect_context_t *context) 450{ 451 virtualizer_context_t *virt_ctxt = (virtualizer_context_t *)context; 452 453 ALOGV("%s: ctxt %p, strength %d", __func__, virt_ctxt, virt_ctxt->strength); 454 455 if (!offload_virtualizer_get_enable_flag(&(virt_ctxt->offload_virt)) && 456 !(virt_ctxt->temp_disabled)) { 457 offload_virtualizer_set_enable_flag(&(virt_ctxt->offload_virt), true); 458 if (virt_ctxt->ctl && virt_ctxt->strength) 459 offload_virtualizer_send_params(virt_ctxt->ctl, 460 virt_ctxt->offload_virt, 461 OFFLOAD_SEND_VIRTUALIZER_ENABLE_FLAG | 462 OFFLOAD_SEND_BASSBOOST_STRENGTH); 463 } 464 return 0; 465} 466 467int virtualizer_disable(effect_context_t *context) 468{ 469 virtualizer_context_t *virt_ctxt = (virtualizer_context_t *)context; 470 471 ALOGV("%s: ctxt %p", __func__, virt_ctxt); 472 if (offload_virtualizer_get_enable_flag(&(virt_ctxt->offload_virt))) { 473 offload_virtualizer_set_enable_flag(&(virt_ctxt->offload_virt), false); 474 if (virt_ctxt->ctl) 475 offload_virtualizer_send_params(virt_ctxt->ctl, 476 virt_ctxt->offload_virt, 477 OFFLOAD_SEND_VIRTUALIZER_ENABLE_FLAG); 478 } 479 return 0; 480} 481 482int virtualizer_start(effect_context_t *context, output_context_t *output) 483{ 484 virtualizer_context_t *virt_ctxt = (virtualizer_context_t *)context; 485 486 ALOGV("%s: ctxt %p, ctl %p", __func__, virt_ctxt, output->ctl); 487 virt_ctxt->ctl = output->ctl; 488 if (offload_virtualizer_get_enable_flag(&(virt_ctxt->offload_virt))) 489 if (virt_ctxt->ctl) 490 offload_virtualizer_send_params(virt_ctxt->ctl, virt_ctxt->offload_virt, 491 OFFLOAD_SEND_VIRTUALIZER_ENABLE_FLAG | 492 OFFLOAD_SEND_VIRTUALIZER_STRENGTH); 493 return 0; 494} 495 496int virtualizer_stop(effect_context_t *context, output_context_t *output __unused) 497{ 498 virtualizer_context_t *virt_ctxt = (virtualizer_context_t *)context; 499 500 ALOGV("%s: ctxt %p", __func__, virt_ctxt); 501 virt_ctxt->ctl = NULL; 502 return 0; 503} 504