1 /* 2 * Copyright (C) 2012 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 #include <errno.h> 18 #include <fcntl.h> 19 20 #define LOG_TAG "eS305VoiceProcessing" 21 //#define LOG_NDEBUG 0 22 #include <cutils/log.h> 23 24 #include "eS305VoiceProcessing.h" 25 #include <audio_effects/effect_aec.h> 26 #include <audio_effects/effect_ns.h> 27 #include <audio_effects/effect_agc.h> 28 29 extern "C" { 30 31 //------------------------------------------------------------------------------ 32 // local definitions 33 //------------------------------------------------------------------------------ 34 35 // number of sessions this effect bundle can be used for 36 #define ADNC_PFX_NUM_SESSION 8 37 38 // types of pre processing modules 39 enum adnc_pfx_id 40 { 41 PFX_ID_AEC = 0, // Acoustic Echo Cancellation 42 PFX_ID_NS, // Noise Suppression 43 PFX_ID_AGC, // Automatic Gain Control 44 PFX_ID_CNT 45 }; 46 47 // Session state 48 enum adnc_pfx_session_state { 49 PFX_SESSION_STATE_INIT, // initialized 50 PFX_SESSION_STATE_CONFIG // configuration received 51 }; 52 53 // Effect/Preprocessor state 54 enum adnc_pfx_effect_state { 55 PFX_EFFECT_STATE_INIT, // initialized 56 PFX_EFFECT_STATE_CREATED, // effect created 57 PFX_EFFECT_STATE_CONFIG, // configuration received/disabled 58 PFX_EFFECT_STATE_ACTIVE // active/enabled 59 }; 60 61 typedef struct adnc_pfx_session_s adnc_pfx_session_t; 62 typedef struct adnc_pfx_effect_s adnc_pfx_effect_t; 63 typedef struct adnc_pfx_ops_s adnc_pfx_ops_t; 64 65 // Effect operation table. Functions for all pre processors are declared in sPreProcOps[] table. 66 // Function pointer can be null if no action required. 67 struct adnc_pfx_ops_s { 68 int (* create)(adnc_pfx_effect_t *fx); 69 int (* init)(adnc_pfx_effect_t *fx); 70 int (* reset)(adnc_pfx_effect_t *fx); 71 void (* enable)(adnc_pfx_effect_t *fx); 72 void (* disable)(adnc_pfx_effect_t *fx); 73 int (* set_parameter)(adnc_pfx_effect_t *fx, void *param, void *value); 74 int (* get_parameter)(adnc_pfx_effect_t *fx, void *param, size_t *size, void *value); 75 int (* set_device)(adnc_pfx_effect_t *fx, uint32_t device); 76 }; 77 78 // Effect context 79 struct adnc_pfx_effect_s { 80 const struct effect_interface_s *itfe; 81 uint32_t procId; // type of pre processor (enum adnc_pfx_id) 82 uint32_t state; // current state (enum adnc_pfx_effect_state) 83 adnc_pfx_session_t *session; // session the effect is on 84 const adnc_pfx_ops_t *ops; // effect ops table 85 }; 86 87 // Session context 88 struct adnc_pfx_session_s { 89 uint32_t state; // current state (enum adnc_pfx_session_state) 90 audio_source_t audioSource; 91 // FIXME not used, delete? 92 //int audioSessionId; // audio session ID 93 int ioHandle; // handle of input stream this session is on 94 uint32_t createdMsk; // bit field containing IDs of created pre processors 95 uint32_t activeMsk; // bit field containing IDs of pre processors currently active 96 struct adnc_pfx_effect_s effects[PFX_ID_CNT]; // effects in this session 97 98 // effect settings 99 // none controllable from public API here 100 }; 101 102 //----------------------------------------- 103 // forward declarations 104 //----------------------------------------- 105 int Adnc_SetNoiseSuppressionInt_l(bool); 106 int Adnc_SetAutomaticGainControlInt_l(bool); 107 int Adnc_SetEchoCancellationInt_l(bool); 108 int Adnc_ReevaluateUsageInt_l(audio_io_handle_t); 109 int Adnc_SleepInt_l(); 110 111 //------------------------------------------------------------------------------ 112 // eS305 control 113 //------------------------------------------------------------------------------ 114 #define ES305_SYSFS_PATH "/sys/class/i2c-dev/i2c-4/device/4-003e/" 115 #define ES305_VOICE_PROCESSING_PATH ES305_SYSFS_PATH "voice_processing" 116 #define ES305_PRESET_PATH ES305_SYSFS_PATH "preset" 117 #define ES305_TX_NS_LEVEL_PATH ES305_SYSFS_PATH "tx_ns_level" 118 #define ES305_TX_AGC_ENABLE_PATH ES305_SYSFS_PATH "tx_agc_enable" 119 #define ES305_AEC_ENABLE_PATH ES305_SYSFS_PATH "aec_enable" 120 #define ES305_SLEEP_PATH ES305_SYSFS_PATH "sleep" 121 122 enum eS305_controls { 123 ES305_CTRL_VOICE_PROCESSING = 0, 124 ES305_CTRL_PRESET, 125 ES305_CTRL_TX_NS_LEVEL, 126 ES305_CTRL_TX_AGC_ENABLE, 127 ES305_CTRL_AEC_ENABLE, 128 ES305_CTRL_SLEEP, 129 ES305_NUM_CTRL 130 }; 131 132 struct eS305_ctrl_s { 133 int fd[ES305_NUM_CTRL]; 134 int current_preset; 135 int requested_preset; 136 int ioHandle; 137 }; 138 typedef struct eS305_ctrl_s eS305_ctrl_t; 139 140 static eS305_ctrl_t eS305_ctrl = { 141 { -1/*vp*/, -1/*preset*/, -1/*ns*/, -1/*agc*/, -1/*aec*/, -1/*sleep*/}, 142 ES305_PRESET_OFF /*current_preset*/, 143 ES305_PRESET_INIT /*requested_preset, an invalid preset, different from current_preset*/, 144 ES305_IO_HANDLE_NONE 145 }; 146 147 //------------------------------------------------------------------------------ 148 // Effect descriptors 149 //------------------------------------------------------------------------------ 150 151 // UUIDs for effect types have been generated from http://www.itu.int/ITU-T/asn1/uuid.html 152 // as the pre processing effects are not defined by OpenSL ES 153 154 // Acoustic Echo Cancellation 155 static const effect_descriptor_t aec_descriptor = { 156 FX_IID_AEC_, // type 157 { 0xfd90ff00, 0x0b55, 0x11e2, 0x892e, { 0x08, 0x00, 0x20, 0x0c, 0x9a, 0x66 } }, // uuid 158 EFFECT_CONTROL_API_VERSION, 159 (EFFECT_FLAG_TYPE_PRE_PROC|EFFECT_FLAG_DEVICE_IND), 160 0, //FIXME indicate CPU load 161 0, //FIXME indicate memory usage 162 "Acoustic Echo Canceler", 163 "Audience" 164 }; 165 166 // Noise suppression 167 static const effect_descriptor_t ns_descriptor = { 168 FX_IID_NS_, // type 169 { 0x08fa98b0, 0x0b56, 0x11e2, 0x892e, { 0x08, 0x00, 0x20, 0x0c, 0x9a, 0x66 } }, // uuid 170 EFFECT_CONTROL_API_VERSION, 171 (EFFECT_FLAG_TYPE_PRE_PROC|EFFECT_FLAG_DEVICE_IND), 172 0, //FIXME indicate CPU load 173 0, //FIXME indicate memory usage 174 "Noise Suppression", 175 "Audience" 176 }; 177 178 // Automatic Gain Control 179 static const effect_descriptor_t agc_descriptor = { 180 FX_IID_AGC_, // type 181 { 0xe9e87eb0, 0x0b55, 0x11e2, 0x892e, { 0x08, 0x00, 0x20, 0x0c, 0x9a, 0x66 } }, // uuid 182 EFFECT_CONTROL_API_VERSION, 183 (EFFECT_FLAG_TYPE_PRE_PROC|EFFECT_FLAG_DEVICE_IND), 184 0, //FIXME indicate CPU load 185 0, //FIXME indicate memory usage 186 "Automatic Gain Control", 187 "Audience" 188 }; 189 190 static const effect_descriptor_t *adnc_pfx_descriptors[PFX_ID_CNT] = { 191 &aec_descriptor, 192 &ns_descriptor, 193 &agc_descriptor 194 }; 195 196 197 //------------------------------------------------------------------------------ 198 // Helper functions 199 //------------------------------------------------------------------------------ 200 static const effect_uuid_t * const sAdncUuidTable[PFX_ID_CNT] = { 201 FX_IID_AEC, 202 FX_IID_NS, 203 FX_IID_AGC 204 }; 205 206 const effect_uuid_t * Adnc_ProcIdToUuid(int procId) 207 { 208 if (procId >= PFX_ID_CNT) { 209 return EFFECT_UUID_NULL; 210 } 211 return sAdncUuidTable[procId]; 212 } 213 214 uint32_t Adnc_UuidToProcId(const effect_uuid_t * uuid) 215 { 216 size_t i; 217 for (i = 0; i < PFX_ID_CNT; i++) { 218 if (memcmp(uuid, sAdncUuidTable[i], sizeof(*uuid)) == 0) { 219 break; 220 } 221 } 222 return i; 223 } 224 225 226 //------------------------------------------------------------------------------ 227 // Acoustic Echo Canceler (AEC) 228 //------------------------------------------------------------------------------ 229 int aec_init (adnc_pfx_effect_t *effect) 230 { 231 ALOGV("aec_init [noop]"); 232 return 0; 233 } 234 235 int aec_create(adnc_pfx_effect_t *effect) 236 { 237 ALOGV("aec_create [noop]"); 238 return aec_init (effect); 239 } 240 241 int aec_reset(adnc_pfx_effect_t *effect) 242 { 243 ALOGV("aec_reset [noop]"); 244 return 0; 245 } 246 247 int aec_get_parameter(adnc_pfx_effect_t *effect, 248 void *pParam, 249 size_t *pValueSize, 250 void *pValue) 251 { 252 int status = 0; 253 uint32_t param = *(uint32_t *)pParam; 254 255 if (*pValueSize < sizeof(uint32_t)) { 256 return -EINVAL; 257 } 258 /* NOT SUPPORTED 259 switch (param) { 260 case AEC_PARAM_ECHO_DELAY: 261 case AEC_PARAM_PROPERTIES: 262 break; 263 default: 264 ALOGW("aec_get_parameter() unknown param %08x value %08x", param, *(uint32_t *)pValue); 265 status = -EINVAL; 266 break; 267 } 268 return status; 269 */ 270 return -EINVAL; 271 } 272 273 int aec_set_parameter (adnc_pfx_effect_t *effect, void *pParam, void *pValue) 274 { 275 int status = 0; 276 uint32_t param = *(uint32_t *)pParam; 277 uint32_t value = *(uint32_t *)pValue; 278 279 /* NOT SUPPORTED 280 switch (param) { 281 case AEC_PARAM_ECHO_DELAY: 282 case AEC_PARAM_PROPERTIES: 283 ALOGV("aec_setParameter() echo delay %d us, status %d", value, status); 284 break; 285 default: 286 ALOGW("aec_setParameter() unknown param %08x value %08x", param, *(uint32_t *)pValue); 287 status = -EINVAL; 288 break; 289 } 290 */ 291 return status; 292 } 293 294 void aec_enable(adnc_pfx_effect_t *effect) 295 { 296 ALOGV("aec_enable [noop]"); 297 } 298 299 void aec_disable(adnc_pfx_effect_t *effect) 300 { 301 ALOGV("aec_disable [noop]"); 302 } 303 304 int aec_set_device(adnc_pfx_effect_t *effect, uint32_t device) 305 { 306 ALOGV("aec_set_device(device=%08x) [noop]", device); 307 308 /* 309 switch(device) { 310 case AUDIO_DEVICE_OUT_EARPIECE: 311 break; 312 case AUDIO_DEVICE_OUT_SPEAKER: 313 break; 314 case AUDIO_DEVICE_OUT_WIRED_HEADSET: 315 case AUDIO_DEVICE_OUT_WIRED_HEADPHONE: 316 default: 317 break; 318 } 319 */ 320 321 return 0; 322 } 323 324 static const adnc_pfx_ops_t aec_ops = { 325 aec_create, 326 aec_init, 327 aec_reset, 328 aec_enable, 329 aec_disable, 330 aec_set_parameter, 331 aec_get_parameter, 332 aec_set_device, 333 }; 334 335 336 //------------------------------------------------------------------------------ 337 // Noise Suppression (NS) 338 //------------------------------------------------------------------------------ 339 int ns_init (adnc_pfx_effect_t *effect) 340 { 341 ALOGV("ns_init [noop]"); 342 343 return 0; 344 } 345 346 int ns_create(adnc_pfx_effect_t *effect) 347 { 348 ALOGV("ns_create %p", effect); 349 350 return ns_init (effect); 351 } 352 353 int ns_get_parameter(adnc_pfx_effect_t *effect, 354 void *pParam, 355 size_t *pValueSize, 356 void *pValue) 357 { 358 int status = 0; 359 return status; 360 } 361 362 int ns_set_parameter(adnc_pfx_effect_t *effect, void *pParam, void *pValue) 363 { 364 int status = 0; 365 return status; 366 } 367 368 void ns_enable(adnc_pfx_effect_t *effect) 369 { 370 ALOGV("ns_enable [noop]"); 371 } 372 373 void ns_disable(adnc_pfx_effect_t *effect) 374 { 375 ALOGV("ns_disable [noop]"); 376 } 377 378 static const adnc_pfx_ops_t ns_ops = { 379 ns_create, 380 ns_init, 381 NULL, 382 ns_enable, 383 ns_disable, 384 ns_set_parameter, 385 ns_get_parameter, 386 NULL, 387 }; 388 389 390 //------------------------------------------------------------------------------ 391 // Automatic Gain Control (AGC) 392 //------------------------------------------------------------------------------ 393 int agc_init (adnc_pfx_effect_t *effect) 394 { 395 ALOGV("agc_init [noop]"); 396 397 return 0; 398 } 399 400 int agc_create(adnc_pfx_effect_t *effect) 401 { 402 ALOGV("agc_create %p", effect); 403 404 return agc_init (effect); 405 } 406 407 int agc_get_parameter(adnc_pfx_effect_t *effect, 408 void *pParam, 409 size_t *pValueSize, 410 void *pValue) 411 { 412 int status = 0; 413 return status; 414 } 415 416 int agc_set_parameter(adnc_pfx_effect_t *effect, void *pParam, void *pValue) 417 { 418 int status = 0; 419 return status; 420 } 421 422 void agc_enable(adnc_pfx_effect_t *effect) 423 { 424 ALOGV("agc_enable [noop]"); 425 } 426 427 void agc_disable(adnc_pfx_effect_t *effect) 428 { 429 ALOGV("agc_disable [noop]"); 430 } 431 432 static const adnc_pfx_ops_t agc_ops = { 433 agc_create, 434 agc_init, 435 NULL, 436 agc_enable, 437 agc_disable, 438 agc_set_parameter, 439 agc_get_parameter, 440 NULL, 441 }; 442 443 //------------------------------------------------------------------------------ 444 // 445 //------------------------------------------------------------------------------ 446 static const adnc_pfx_ops_t *sPreProcOps[PFX_ID_CNT] = { 447 &aec_ops, 448 &ns_ops, 449 &agc_ops 450 }; 451 452 //------------------------------------------------------------------------------ 453 // Pre-processing effect functions 454 //------------------------------------------------------------------------------ 455 extern const struct effect_interface_s sEffectInterface; 456 457 #define BAD_STATE_ABORT(from, to) \ 458 LOG_ALWAYS_FATAL("Bad state transition from %d to %d", from, to); 459 460 void AdncSession_SetProcEnabled(adnc_pfx_session_t *session, uint32_t procId, bool enabled); 461 462 int AdncPreProFx_SetState(adnc_pfx_effect_t *effect, uint32_t state) 463 { 464 int status = 0; 465 ALOGV("AdncPreProFx_SetState procId %d, new %d old %d", effect->procId, state, effect->state); 466 switch(state) { 467 case PFX_EFFECT_STATE_INIT: 468 switch(effect->state) { 469 case PFX_EFFECT_STATE_ACTIVE: 470 effect->ops->disable(effect); 471 AdncSession_SetProcEnabled(effect->session, effect->procId, false); 472 case PFX_EFFECT_STATE_CONFIG: 473 case PFX_EFFECT_STATE_CREATED: 474 case PFX_EFFECT_STATE_INIT: 475 break; 476 default: 477 BAD_STATE_ABORT(effect->state, state); 478 } 479 break; 480 case PFX_EFFECT_STATE_CREATED: 481 switch(effect->state) { 482 case PFX_EFFECT_STATE_INIT: 483 status = effect->ops->create(effect); 484 break; 485 case PFX_EFFECT_STATE_CREATED: 486 case PFX_EFFECT_STATE_ACTIVE: 487 case PFX_EFFECT_STATE_CONFIG: 488 ALOGE("Effect_SetState invalid transition"); 489 status = -ENOSYS; 490 break; 491 default: 492 BAD_STATE_ABORT(effect->state, state); 493 } 494 break; 495 case PFX_EFFECT_STATE_CONFIG: 496 switch(effect->state) { 497 case PFX_EFFECT_STATE_INIT: 498 ALOGE("Effect_SetState invalid transition"); 499 status = -ENOSYS; 500 break; 501 case PFX_EFFECT_STATE_ACTIVE: 502 effect->ops->disable(effect); 503 AdncSession_SetProcEnabled(effect->session, effect->procId, false); 504 break; 505 case PFX_EFFECT_STATE_CREATED: 506 case PFX_EFFECT_STATE_CONFIG: 507 break; 508 default: 509 BAD_STATE_ABORT(effect->state, state); 510 } 511 break; 512 case PFX_EFFECT_STATE_ACTIVE: 513 switch(effect->state) { 514 case PFX_EFFECT_STATE_INIT: 515 case PFX_EFFECT_STATE_CREATED: 516 ALOGE("Effect_SetState invalid transition"); 517 status = -ENOSYS; 518 break; 519 case PFX_EFFECT_STATE_ACTIVE: 520 // enabling an already enabled effect is just ignored 521 break; 522 case PFX_EFFECT_STATE_CONFIG: 523 effect->ops->enable(effect); 524 AdncSession_SetProcEnabled(effect->session, effect->procId, true); 525 break; 526 default: 527 BAD_STATE_ABORT(effect->state, state); 528 } 529 break; 530 default: 531 BAD_STATE_ABORT(effect->state, state); 532 } 533 if (status == 0) { 534 effect->state = state; 535 } 536 return status; 537 } 538 539 int AdncPreProFx_Init(adnc_pfx_effect_t *effect, uint32_t procId) 540 { 541 ALOGV(" AdncPreProFx_Init(procId=%d)", procId); 542 effect->itfe = &sEffectInterface; 543 effect->ops = sPreProcOps[procId]; 544 effect->procId = procId; 545 effect->state = PFX_EFFECT_STATE_INIT; 546 return 0; 547 } 548 549 int AdncPreProFx_Create(adnc_pfx_effect_t *effect, 550 adnc_pfx_session_t *session, 551 effect_handle_t *interface) 552 { 553 ALOGV(" AdncPreProFx_Create(effect=%p)", effect); 554 effect->session = session; 555 *interface = (effect_handle_t)&effect->itfe; 556 return AdncPreProFx_SetState(effect, PFX_EFFECT_STATE_CREATED); 557 } 558 559 int AdncPreProFx_Release(adnc_pfx_effect_t *effect) 560 { 561 return AdncPreProFx_SetState(effect, PFX_EFFECT_STATE_INIT); 562 } 563 564 565 //------------------------------------------------------------------------------ 566 // Session functions 567 //------------------------------------------------------------------------------ 568 /* 569 * Initialize a session context. 570 * Must be called with a lock on sAdncBundleLock. 571 */ 572 int AdncSession_Init_l(adnc_pfx_session_t *session) 573 { 574 ALOGV("AdncSession_Init()"); 575 size_t i; 576 int status = 0; 577 578 session->state = PFX_SESSION_STATE_INIT; 579 session->audioSource = AUDIO_SOURCE_DEFAULT; 580 //session->audioSessionId = ES305_SESSION_ID_NONE; // FIXME not used delete? 581 session->ioHandle = ES305_IO_HANDLE_NONE; 582 session->createdMsk = 0; 583 session->activeMsk = 0; 584 // initialize each effect for this session context 585 for (i = 0; i < PFX_ID_CNT && status == 0; i++) { 586 status = AdncPreProFx_Init(&session->effects[i], i); 587 } 588 return status; 589 } 590 591 /* 592 * Must be called with a lock on sAdncBundleLock. 593 */ 594 int AdncSession_CreateEffect_l(adnc_pfx_session_t *session, 595 int32_t procId, 596 effect_handle_t *interface) 597 { 598 int status = -ENOMEM; 599 ALOGV("AdncSession_CreateEffect handle=%d procId %d, old createdMsk %08x", 600 session->ioHandle, procId, session->createdMsk); 601 602 status = AdncPreProFx_Create(&session->effects[procId], session, interface); 603 if (status >= 0) { 604 ALOGV(" AdncSession_CreateEffect OK"); 605 session->createdMsk |= (1 << procId); 606 } 607 return status; 608 } 609 610 int AdncSession_SetConfig(adnc_pfx_session_t *session, effect_config_t *config) 611 { 612 ALOGV("AdncSession_SetConfig [noop]"); 613 return 0; 614 } 615 616 void AdncSession_GetConfig(adnc_pfx_session_t *session, effect_config_t *config) 617 { 618 ALOGV("AdncSession_GetConfig [noop]"); 619 } 620 621 int AdncSession_SetReverseConfig(adnc_pfx_session_t *session, effect_config_t *config) 622 { 623 ALOGV("AdncSession_SetReverseConfig [noop]"); 624 return 0; 625 } 626 627 void AdncSession_GetReverseConfig(adnc_pfx_session_t *session, effect_config_t *config) 628 { 629 ALOGV("AdncSession_GetReverseConfig [noop]"); 630 } 631 632 void AdncSession_SetProcEnabled(adnc_pfx_session_t *session, uint32_t procId, bool enabled) 633 { 634 ALOGV("AdncSession_SetProcEnabled [noop] proc %d, enabled %d", procId, enabled); 635 //no need to reevaluate session settings, if recording is currently ongoing, we'll reevaluate 636 // through eS305_AddEffect() 637 } 638 639 int AdncSession_SetSource(adnc_pfx_session_t *session, audio_source_t source) 640 { 641 session->audioSource = source; 642 return 0; 643 } 644 645 //------------------------------------------------------------------------------ 646 // Bundle functions 647 //------------------------------------------------------------------------------ 648 #define ADNC_BUNDLE_NO_INIT 1 649 static int sAdncBundleInitStatus = ADNC_BUNDLE_NO_INIT; 650 static adnc_pfx_session_t sAdncSessions[ADNC_PFX_NUM_SESSION]; 651 static pthread_mutex_t sAdncBundleLock; 652 653 /* Returns a session context for the given IO handle 654 * Returns an existing session context if the IO handle matches, initializes a new one otherwise. 655 * Returns NULL if no more session contexts are available 656 * Must be called with a lock on sAdncBundleLock 657 */ 658 adnc_pfx_session_t *AdncBundle_GetSession_l(int32_t procId, int32_t sessionId, int32_t ioId) 659 { 660 size_t i; 661 for (i = 0; i < ADNC_PFX_NUM_SESSION; i++) { 662 if (sAdncSessions[i].ioHandle == ioId) { 663 return &sAdncSessions[i]; 664 } 665 } 666 for (i = 0; i < ADNC_PFX_NUM_SESSION; i++) { 667 if (sAdncSessions[i].ioHandle == ES305_IO_HANDLE_NONE) { 668 //sAdncSessions[i].audioSessionId = sessionId; // FIXME not used delete? 669 sAdncSessions[i].ioHandle = ioId; 670 return &sAdncSessions[i]; 671 } 672 } 673 ALOGV("AdncBundle_GetSession_l"); 674 return NULL; 675 } 676 677 /* 678 * Must be called with a lock on sAdncBundleLock. 679 */ 680 int AdncBundle_Init_l() { 681 size_t i; 682 int status = 0; 683 684 if (sAdncBundleInitStatus <= 0) { 685 return sAdncBundleInitStatus; 686 } 687 // initialize all the session contexts that this bundle supports 688 for (i = 0; i < ADNC_PFX_NUM_SESSION && status == 0; i++) { 689 status = AdncSession_Init_l(&sAdncSessions[i]); 690 } 691 sAdncBundleInitStatus = status; 692 return sAdncBundleInitStatus; 693 } 694 695 /* 696 * Must be called with a lock on sAdncBundleLock. 697 */ 698 int AdncBundle_Release_l() { 699 ALOGV("AdncBundle_Release_l()"); 700 701 Adnc_SleepInt_l(); 702 703 for (int i = 0 ; i < ES305_NUM_CTRL ; i++) { 704 if (eS305_ctrl.fd[i] >= 0) { 705 close(eS305_ctrl.fd[i]); 706 } 707 eS305_ctrl.fd[i] = -1; 708 } 709 return 0; 710 } 711 712 const effect_descriptor_t *AdncBundle_GetDescriptor(const effect_uuid_t *uuid) 713 { 714 size_t i; 715 for (i = 0; i < PFX_ID_CNT; i++) { 716 if (memcmp(&adnc_pfx_descriptors[i]->uuid, uuid, sizeof(effect_uuid_t)) == 0) { 717 return adnc_pfx_descriptors[i]; 718 } 719 } 720 return NULL; 721 } 722 723 /* 724 * Debug only: display session contexts 725 */ 726 void AdncBundle_logv_dumpSessions() { 727 ALOGV("Sessions:"); 728 for (int i=0 ; i<ADNC_PFX_NUM_SESSION ; i++) { 729 ALOGV(" session %d handle=%d cre=%2x act=%2x", 730 i, sAdncSessions[i].ioHandle, sAdncSessions[i].createdMsk, sAdncSessions[i].activeMsk); 731 } 732 } 733 734 //------------------------------------------------------------------------------ 735 // Effect Control Interface Implementation 736 //------------------------------------------------------------------------------ 737 int AdncVoiceProcessingFx_Command(effect_handle_t self, 738 uint32_t cmdCode, 739 uint32_t cmdSize, 740 void *pCmdData, 741 uint32_t *replySize, 742 void *pReplyData) 743 { 744 adnc_pfx_effect_t * effect = (adnc_pfx_effect_t *) self; 745 int retsize; 746 int status; 747 748 if (effect == NULL){ 749 return -EINVAL; 750 } 751 752 ALOGV("AdncVoiceProcessingFx_Command: command %d cmdSize %d",cmdCode, cmdSize); 753 754 switch (cmdCode){ 755 case EFFECT_CMD_INIT: 756 if (pReplyData == NULL || *replySize != sizeof(int)){ 757 return -EINVAL; 758 } 759 if (effect->ops->init) { 760 effect->ops->init(effect); 761 } 762 *(int *)pReplyData = 0; 763 break; 764 765 case EFFECT_CMD_SET_CONFIG: { 766 if (pCmdData == NULL|| 767 cmdSize != sizeof(effect_config_t)|| 768 pReplyData == NULL|| 769 *replySize != sizeof(int)){ 770 ALOGV("AdncVoiceProcessingFx_Command cmdCode Case: " 771 "EFFECT_CMD_SET_CONFIG: ERROR"); 772 return -EINVAL; 773 } 774 775 *(int *)pReplyData = AdncSession_SetConfig(effect->session, (effect_config_t *)pCmdData); 776 777 if (*(int *)pReplyData != 0) { 778 break; 779 } 780 if (effect->state != PFX_EFFECT_STATE_ACTIVE) { 781 *(int *)pReplyData = AdncPreProFx_SetState(effect, PFX_EFFECT_STATE_CONFIG); 782 } 783 } break; 784 785 case EFFECT_CMD_GET_CONFIG: 786 if (pReplyData == NULL || 787 *replySize != sizeof(effect_config_t)) { 788 ALOGV("\tLVM_ERROR : AdncVoiceProcessingFx_Command cmdCode Case: " 789 "EFFECT_CMD_GET_CONFIG: ERROR"); 790 return -EINVAL; 791 } 792 793 AdncSession_GetConfig(effect->session, (effect_config_t *)pReplyData); 794 break; 795 796 case EFFECT_CMD_SET_CONFIG_REVERSE: 797 if (pCmdData == NULL || 798 cmdSize != sizeof(effect_config_t) || 799 pReplyData == NULL || 800 *replySize != sizeof(int)) { 801 ALOGV("AdncVoiceProcessingFx_Command cmdCode Case: " 802 "EFFECT_CMD_SET_CONFIG_REVERSE: ERROR"); 803 return -EINVAL; 804 } 805 *(int *)pReplyData = AdncSession_SetReverseConfig(effect->session, 806 (effect_config_t *)pCmdData); 807 if (*(int *)pReplyData != 0) { 808 break; 809 } 810 break; 811 812 case EFFECT_CMD_GET_CONFIG_REVERSE: 813 if (pReplyData == NULL || 814 *replySize != sizeof(effect_config_t)){ 815 ALOGV("AdncVoiceProcessingFx_Command cmdCode Case: " 816 "EFFECT_CMD_GET_CONFIG_REVERSE: ERROR"); 817 return -EINVAL; 818 } 819 AdncSession_GetReverseConfig(effect->session, (effect_config_t *)pCmdData); 820 break; 821 822 case EFFECT_CMD_RESET: 823 if (effect->ops->reset) { 824 effect->ops->reset(effect); 825 } 826 break; 827 828 case EFFECT_CMD_GET_PARAM:{ 829 if (pCmdData == NULL || 830 cmdSize < (int)sizeof(effect_param_t) || 831 pReplyData == NULL || 832 *replySize < (int)sizeof(effect_param_t)){ 833 ALOGV("AdncVoiceProcessingFx_Command cmdCode Case: " 834 "EFFECT_CMD_GET_PARAM: ERROR"); 835 return -EINVAL; 836 } 837 effect_param_t *p = (effect_param_t *)pCmdData; 838 839 memcpy(pReplyData, pCmdData, sizeof(effect_param_t) + p->psize); 840 841 p = (effect_param_t *)pReplyData; 842 843 int voffset = ((p->psize - 1) / sizeof(int32_t) + 1) * sizeof(int32_t); 844 845 if (effect->ops->get_parameter) { 846 p->status = effect->ops->get_parameter(effect, p->data, 847 (size_t *)&p->vsize, 848 p->data + voffset); 849 *replySize = sizeof(effect_param_t) + voffset + p->vsize; 850 } 851 } break; 852 853 case EFFECT_CMD_SET_PARAM:{ 854 if (pCmdData == NULL|| 855 cmdSize < (int)sizeof(effect_param_t) || 856 pReplyData == NULL || 857 *replySize != sizeof(int32_t)){ 858 ALOGV("AdncVoiceProcessingFx_Command cmdCode Case: " 859 "EFFECT_CMD_SET_PARAM: ERROR"); 860 return -EINVAL; 861 } 862 effect_param_t *p = (effect_param_t *) pCmdData; 863 864 if (p->psize != sizeof(int32_t)){ 865 ALOGV("AdncVoiceProcessingFx_Command cmdCode Case: " 866 "EFFECT_CMD_SET_PARAM: ERROR, psize is not sizeof(int32_t)"); 867 return -EINVAL; 868 } 869 if (effect->ops->set_parameter) { 870 *(int *)pReplyData = effect->ops->set_parameter(effect, 871 (void *)p->data, 872 p->data + p->psize); 873 } 874 } break; 875 876 case EFFECT_CMD_ENABLE: 877 if (pReplyData == NULL || *replySize != sizeof(int)){ 878 ALOGV("AdncVoiceProcessingFx_Command cmdCode Case: EFFECT_CMD_ENABLE: ERROR"); 879 return -EINVAL; 880 } 881 *(int *)pReplyData = AdncPreProFx_SetState(effect, PFX_EFFECT_STATE_ACTIVE); 882 break; 883 884 case EFFECT_CMD_DISABLE: 885 if (pReplyData == NULL || *replySize != sizeof(int)){ 886 ALOGV("AdncVoiceProcessingFx_Command cmdCode Case: EFFECT_CMD_DISABLE: ERROR"); 887 return -EINVAL; 888 } 889 *(int *)pReplyData = AdncPreProFx_SetState(effect, PFX_EFFECT_STATE_CONFIG); 890 break; 891 892 case EFFECT_CMD_SET_DEVICE: 893 case EFFECT_CMD_SET_INPUT_DEVICE: 894 if (pCmdData == NULL || 895 cmdSize != sizeof(uint32_t)) { 896 ALOGV("AdncVoiceProcessingFx_Command cmdCode Case: EFFECT_CMD_SET_DEVICE: ERROR"); 897 return -EINVAL; 898 } 899 900 if (effect->ops->set_device) { 901 effect->ops->set_device(effect, *(uint32_t *)pCmdData); 902 } 903 break; 904 905 case EFFECT_CMD_SET_VOLUME: 906 case EFFECT_CMD_SET_AUDIO_MODE: 907 case EFFECT_CMD_SET_FEATURE_CONFIG: 908 break; 909 910 case EFFECT_CMD_SET_AUDIO_SOURCE: 911 if (pCmdData == NULL || 912 cmdSize != sizeof(uint32_t)) { 913 ALOGV("AdncVoiceProcessingFx_Command cmdCode Case: EFFECT_CMD_SET_AUDIO_SOURCE: ERROR"); 914 return -EINVAL; 915 } 916 return AdncSession_SetSource(effect->session, (audio_source_t) *(uint32_t *)pCmdData); 917 break; 918 919 default: 920 return -EINVAL; 921 } 922 return 0; 923 } 924 925 926 int AdncVoiceProcessingFx_GetDescriptor(effect_handle_t self, 927 effect_descriptor_t *pDescriptor) 928 { 929 adnc_pfx_effect_t * effect = (adnc_pfx_effect_t *) self; 930 931 if (effect == NULL || pDescriptor == NULL) { 932 return -EINVAL; 933 } 934 935 memcpy(pDescriptor, adnc_pfx_descriptors[effect->procId], sizeof(effect_descriptor_t)); 936 937 return 0; 938 } 939 940 941 // effect_handle_t interface implementation for effect 942 const struct effect_interface_s sEffectInterface = { 943 NULL, /* Process */ 944 AdncVoiceProcessingFx_Command, 945 AdncVoiceProcessingFx_GetDescriptor, 946 NULL 947 }; 948 //------------------------------------------------------------------------------ 949 // Effect Library Interface Implementation 950 //------------------------------------------------------------------------------ 951 int adnc_query_number_effects(uint32_t *pNumEffects) 952 { 953 if (pNumEffects == NULL) { 954 return -EINVAL; 955 } 956 *pNumEffects = PFX_ID_CNT; 957 return sAdncBundleInitStatus; 958 } 959 960 int adnc_query_effect(uint32_t index, effect_descriptor_t *pDescriptor) 961 { 962 int status = 0; 963 964 pthread_mutex_lock(&sAdncBundleLock); 965 966 if (AdncBundle_Init_l() != 0) { 967 status = sAdncBundleInitStatus; 968 goto exit; 969 } 970 if (index >= PFX_ID_CNT) { 971 status = -EINVAL; 972 goto exit; 973 } 974 memcpy(pDescriptor, adnc_pfx_descriptors[index], sizeof(effect_descriptor_t)); 975 976 exit: 977 pthread_mutex_unlock(&sAdncBundleLock); 978 return status; 979 } 980 981 int adnc_create(const effect_uuid_t *uuid, 982 int32_t sessionId, 983 int32_t ioId, 984 effect_handle_t *pInterface) 985 { 986 ALOGV("adnc_create: uuid: %08x session %d IO: %d", uuid->timeLow, sessionId, ioId); 987 988 int status = 0; 989 const effect_descriptor_t *desc; 990 adnc_pfx_session_t *session; 991 uint32_t procId; 992 993 pthread_mutex_lock(&sAdncBundleLock); 994 995 if (AdncBundle_Init_l() != 0) { 996 status = sAdncBundleInitStatus; 997 goto exit; 998 } 999 1000 desc = AdncBundle_GetDescriptor(uuid); 1001 if (desc == NULL) { 1002 ALOGW(" adnc_create: fx not found uuid: %08x", uuid->timeLow); 1003 status = -EINVAL; 1004 goto exit; 1005 } 1006 procId = Adnc_UuidToProcId(&desc->type); 1007 1008 session = AdncBundle_GetSession_l(procId, sessionId, ioId); 1009 if (session == NULL) { 1010 ALOGW(" adnc_create: no more session available"); 1011 status = -EINVAL; 1012 goto exit; 1013 } 1014 1015 status = AdncSession_CreateEffect_l(session, procId, pInterface); 1016 1017 if (status < 0 && session->createdMsk == 0) { 1018 session->ioHandle = ES305_IO_HANDLE_NONE; 1019 } 1020 1021 exit: 1022 pthread_mutex_unlock(&sAdncBundleLock); 1023 return status; 1024 } 1025 1026 int adnc_release(effect_handle_t interface) 1027 { 1028 int i, status = 0; 1029 ALOGV("adnc_release %p", interface); 1030 1031 // the effect handle comes from the effect framework, ok to cast 1032 const adnc_pfx_effect_t * fx = (adnc_pfx_effect_t *) interface; 1033 1034 const uint32_t removalMsk = ~(1 << fx->procId); 1035 1036 pthread_mutex_lock(&sAdncBundleLock); 1037 1038 if (AdncBundle_Init_l() != 0) { 1039 status = sAdncBundleInitStatus; 1040 goto exit; 1041 } 1042 1043 if (fx->session->ioHandle == 0) { 1044 status = -EINVAL; 1045 goto exit; 1046 } 1047 1048 // effect is released, flag it as inactive and not created 1049 fx->session->createdMsk &= removalMsk; 1050 fx->session->activeMsk &= removalMsk; 1051 1052 // configuration has changed, reevaluate 1053 status = Adnc_ReevaluateUsageInt_l(fx->session->ioHandle); 1054 // not checking the return status here: if there was an error, 1055 // we still need to free the session and wouldn't exit here 1056 1057 // free session if it has no more effects 1058 if (fx->session->createdMsk == 0) { 1059 ALOGV(" resetting session on handle %d after effect release", fx->session->ioHandle); 1060 const int statusInit = AdncSession_Init_l(fx->session); 1061 if (status == 0) { 1062 status = statusInit; 1063 } 1064 } 1065 1066 exit: 1067 pthread_mutex_unlock(&sAdncBundleLock); 1068 return status; 1069 } 1070 1071 int adnc_get_descriptor(const effect_uuid_t *uuid, effect_descriptor_t *pDescriptor) { 1072 if (pDescriptor == NULL || uuid == NULL){ 1073 ALOGV("adnc_get_descriptor() invalid params"); 1074 return -EINVAL; 1075 } 1076 1077 const effect_descriptor_t *desc = AdncBundle_GetDescriptor(uuid); 1078 if (desc == NULL) { 1079 ALOGV("adnc_get_descriptor() not found"); 1080 return -EINVAL; 1081 } 1082 1083 ALOGV("adnc_get_descriptor() got fx %s", desc->name); 1084 1085 memcpy(pDescriptor, desc, sizeof(effect_descriptor_t)); 1086 return 0; 1087 } 1088 1089 audio_effect_library_t AUDIO_EFFECT_LIBRARY_INFO_SYM = { 1090 tag : AUDIO_EFFECT_LIBRARY_TAG, 1091 version : EFFECT_LIBRARY_API_VERSION, 1092 name : "Audience Voice Preprocessing Library", 1093 implementor : "The Android Open Source Project", 1094 query_num_effects : adnc_query_number_effects, 1095 query_effect : adnc_query_effect, 1096 create_effect : adnc_create, 1097 release_effect : adnc_release, 1098 get_descriptor : adnc_get_descriptor 1099 }; 1100 1101 //------------------------------------------------------- 1102 // eS305 control interface 1103 //------------------------------------------------------- 1104 int Adnc_SetAutomaticGainControlInt_l(bool agc_on) 1105 { 1106 ALOGV("Adnc_SetAutomaticGainControlInt_l(%d)", agc_on); 1107 1108 if (eS305_ctrl.fd[ES305_CTRL_TX_AGC_ENABLE] < 0) { 1109 ALOGV(" opening eS305 path for agc"); 1110 eS305_ctrl.fd[ES305_CTRL_TX_AGC_ENABLE] = open(ES305_TX_AGC_ENABLE_PATH, O_RDWR); 1111 if (eS305_ctrl.fd[ES305_CTRL_TX_AGC_ENABLE] < 0) { 1112 ALOGE(" Cannot open eS305 path for agc: %s", strerror(errno)); 1113 return -ENODEV; 1114 } 1115 } 1116 1117 if (agc_on) { 1118 write(eS305_ctrl.fd[ES305_CTRL_TX_AGC_ENABLE], ES305_AGC_ON, strlen(ES305_AGC_ON)); 1119 } else { 1120 write(eS305_ctrl.fd[ES305_CTRL_TX_AGC_ENABLE], ES305_AEC_OFF, strlen(ES305_AGC_OFF)); 1121 } 1122 return 0; 1123 } 1124 1125 int Adnc_SetEchoCancellationInt_l(bool aec_on) 1126 { 1127 ALOGV("Adnc_SetEchoCancellationInt_l(%d)", aec_on); 1128 1129 if (eS305_ctrl.fd[ES305_CTRL_AEC_ENABLE] < 0) { 1130 ALOGV(" opening eS305 path for aec"); 1131 eS305_ctrl.fd[ES305_CTRL_AEC_ENABLE] = open(ES305_AEC_ENABLE_PATH, O_RDWR); 1132 if (eS305_ctrl.fd[ES305_CTRL_AEC_ENABLE] < 0) { 1133 ALOGE(" Cannot open eS305 path for aec: %s", strerror(errno)); 1134 return -ENODEV; 1135 } 1136 } 1137 1138 if (aec_on) { 1139 write(eS305_ctrl.fd[ES305_CTRL_AEC_ENABLE], ES305_AEC_ON, strlen(ES305_AEC_ON)); 1140 } else { 1141 write(eS305_ctrl.fd[ES305_CTRL_AEC_ENABLE], ES305_AEC_OFF, strlen(ES305_AEC_OFF)); 1142 } 1143 return 0; 1144 } 1145 1146 int Adnc_SetNoiseSuppressionInt_l(bool ns_on) 1147 { 1148 ALOGV("Adnc_SetNoiseSuppressionInt(%d)", ns_on); 1149 1150 if (eS305_ctrl.fd[ES305_CTRL_TX_NS_LEVEL] < 0) { 1151 ALOGV(" opening eS305 path for ns"); 1152 eS305_ctrl.fd[ES305_CTRL_TX_NS_LEVEL] = open(ES305_TX_NS_LEVEL_PATH, O_RDWR); 1153 if (eS305_ctrl.fd[ES305_CTRL_TX_NS_LEVEL] < 0) { 1154 ALOGE(" Cannot open eS305 path for ns: %s", strerror(errno)); 1155 return -ENODEV; 1156 } 1157 } 1158 1159 if (ns_on) { 1160 if (eS305_ctrl.requested_preset == ES305_PRESET_ASRA_HANDHELD) { 1161 ALOGV(" setting ns to %s", ES305_NS_VOICE_REC_HANDHELD_ON); 1162 write(eS305_ctrl.fd[ES305_CTRL_TX_NS_LEVEL], 1163 ES305_NS_VOICE_REC_HANDHELD_ON, strlen(ES305_NS_VOICE_REC_HANDHELD_ON)); 1164 } else if ((eS305_ctrl.requested_preset == ES305_PRESET_ASRA_DESKTOP) 1165 || (eS305_ctrl.requested_preset == ES305_PRESET_ASRA_HEADSET)) { 1166 ALOGV(" setting ns to %s", ES305_NS_VOICE_REC_SINGLE_MIC_ON); 1167 write(eS305_ctrl.fd[ES305_CTRL_TX_NS_LEVEL], 1168 ES305_NS_VOICE_REC_SINGLE_MIC_ON, strlen(ES305_NS_VOICE_REC_SINGLE_MIC_ON)); 1169 } else { 1170 ALOGV(" setting ns to %s", ES305_NS_DEFAULT_ON); 1171 write(eS305_ctrl.fd[ES305_CTRL_TX_NS_LEVEL], 1172 ES305_NS_DEFAULT_ON, strlen(ES305_NS_DEFAULT_ON)); 1173 } 1174 } else { 1175 ALOGV(" setting ns to %s", ES305_NS_OFF); 1176 write(eS305_ctrl.fd[ES305_CTRL_TX_NS_LEVEL], ES305_NS_OFF, strlen(ES305_NS_OFF)); 1177 } 1178 return 0; 1179 } 1180 1181 int Adnc_SetVoiceProcessingInt_l(bool vp_on) 1182 { 1183 if (eS305_ctrl.fd[ES305_CTRL_VOICE_PROCESSING] < 0) { 1184 ALOGV(" opening eS305 path for VP"); 1185 eS305_ctrl.fd[ES305_CTRL_VOICE_PROCESSING] = open(ES305_VOICE_PROCESSING_PATH, O_RDWR); 1186 if (eS305_ctrl.fd[ES305_CTRL_VOICE_PROCESSING] < 0) { 1187 ALOGE(" cannot open eS305 path for VP: %s", strerror(errno)); 1188 return -ENODEV; 1189 } 1190 } 1191 if (vp_on) { 1192 write(eS305_ctrl.fd[ES305_CTRL_VOICE_PROCESSING], ES305_ON, strlen(ES305_ON)); 1193 } else { 1194 write(eS305_ctrl.fd[ES305_CTRL_VOICE_PROCESSING], ES305_OFF, strlen(ES305_OFF)); 1195 } 1196 return 0; 1197 } 1198 1199 /* 1200 * Put the eS305 to sleep 1201 * Post condition when no error: eS305_ctrl.current_preset == ES305_PRESET_OFF 1202 */ 1203 int Adnc_SleepInt_l() 1204 { 1205 if (eS305_ctrl.current_preset == ES305_PRESET_OFF) { 1206 return 0; 1207 } 1208 1209 ALOGV(" Adnc_SleepInt()_l setting VP off + sleep 1"); 1210 1211 Adnc_SetVoiceProcessingInt_l(false /*vp_on*/); 1212 1213 ALOGV(" Adnc_SetSleepInt_l"); 1214 if (eS305_ctrl.fd[ES305_CTRL_SLEEP] < 0) { 1215 ALOGV(" opening eS305 path for sleep"); 1216 eS305_ctrl.fd[ES305_CTRL_SLEEP] = open(ES305_SLEEP_PATH, O_RDWR); 1217 if (eS305_ctrl.fd[ES305_CTRL_SLEEP] < 0) { 1218 ALOGE(" cannot open eS305 path for sleep: %s", strerror(errno)); 1219 return -ENODEV; 1220 } 1221 } 1222 1223 write(eS305_ctrl.fd[ES305_CTRL_SLEEP], ES305_ON, strlen(ES305_ON)); 1224 1225 eS305_ctrl.current_preset = ES305_PRESET_OFF; 1226 1227 return 0; 1228 } 1229 1230 /* 1231 * Apply the eS305_ctrl.requested_preset preset after turning VP on 1232 * Post condition when no error: eS305_ctrl.current_preset == eS305_ctrl.requested_preset 1233 */ 1234 int Adnc_ApplyPresetInt_l() 1235 { 1236 ALOGV("Adnc_ApplyPresetInt() current_preset=%d, requested_preset=%d", 1237 eS305_ctrl.current_preset, eS305_ctrl.requested_preset); 1238 1239 if (eS305_ctrl.requested_preset == eS305_ctrl.current_preset) { 1240 ALOGV(" nothing to do, preset %d is current", eS305_ctrl.requested_preset); 1241 return 0; 1242 } 1243 1244 // preset off implies going to sleep 1245 if (eS305_ctrl.requested_preset == ES305_PRESET_OFF) { 1246 return Adnc_SleepInt_l(); 1247 } 1248 1249 // voice processing must be on before setting the preset 1250 if ((eS305_ctrl.current_preset == ES305_PRESET_OFF) 1251 || (eS305_ctrl.current_preset == ES305_PRESET_INIT)) { 1252 const int status = Adnc_SetVoiceProcessingInt_l(true /*vp_on*/); 1253 if (status != 0) { 1254 return status; 1255 } 1256 } 1257 1258 if (eS305_ctrl.fd[ES305_CTRL_PRESET] < 0) { 1259 ALOGV(" opening eS305 path for PRESET"); 1260 eS305_ctrl.fd[ES305_CTRL_PRESET] = open(ES305_PRESET_PATH, O_RDWR); 1261 } 1262 if (eS305_ctrl.fd[ES305_CTRL_PRESET] < 0) { 1263 ALOGE(" Cannot open eS305 path for PRESET: %s", strerror(errno)); 1264 return -ENODEV; 1265 } 1266 1267 char str[8]; 1268 sprintf(str, "%d", eS305_ctrl.requested_preset); 1269 write(eS305_ctrl.fd[ES305_CTRL_PRESET], str, strlen(str)); 1270 1271 eS305_ctrl.current_preset = eS305_ctrl.requested_preset; 1272 1273 return 0; 1274 } 1275 1276 1277 /* 1278 * Apply the settings of given the session context 1279 */ 1280 int Adnc_ApplySettingsFromSessionContextInt_l(adnc_pfx_session_t * session) 1281 { 1282 ALOGV("Adnc_ApplySettingsFromSessionContextInt_l cre=%2x ac=%2x handle=%d", 1283 session->createdMsk, session->activeMsk, session->ioHandle); 1284 int status = 0; 1285 1286 if (session->ioHandle != eS305_ctrl.ioHandle) { 1287 return status; 1288 } 1289 1290 // NS: special case of noise suppression, always reset according to effect state 1291 // as default desirable value might differ from the preset 1292 const bool ns_on = ((session->activeMsk & (1 << PFX_ID_NS)) != 0); 1293 status = Adnc_SetNoiseSuppressionInt_l(ns_on /*ns_on*/); 1294 1295 // AEC 1296 if ((session->createdMsk & (1 << PFX_ID_AEC)) /* the effect has been created */ 1297 && (session->activeMsk & (1 << PFX_ID_AEC))) /* the effect is active */ 1298 { 1299 Adnc_SetEchoCancellationInt_l(true /*aec_on*/); 1300 } 1301 1302 // AGC 1303 if ((session->createdMsk & (1 << PFX_ID_AGC)) /* the effect has been created */ 1304 && (session->activeMsk & (1 << PFX_ID_AGC))) /* the effect is active */ 1305 { 1306 Adnc_SetAutomaticGainControlInt_l(true /*agc_on*/); 1307 } 1308 1309 return status; 1310 } 1311 1312 /* 1313 * Return a value between 0 and ADNC_PFX_NUM_SESSION-1 if a session context has the given handle, 1314 * -1 if the handle isn't in handled by one of the sessions. 1315 * Must be called with a lock on sAdncBundleLock 1316 */ 1317 int Adnc_SessionNumberForHandle_l(audio_io_handle_t handle) 1318 { 1319 for (int i = 0 ; i < ADNC_PFX_NUM_SESSION ; i++) { 1320 if (sAdncSessions[i].ioHandle == handle) { 1321 return i; 1322 } 1323 } 1324 return -1; 1325 } 1326 1327 1328 /* 1329 * Apply the settings of the session matching the given IO handle. 1330 * Must be called with a lock on sAdncBundleLock 1331 */ 1332 int Adnc_ApplySettingsForHandleInt_l(audio_io_handle_t handle) 1333 { 1334 ALOGV(" Adnc_ApplySettingsForHandleInt_l(handle=%d)", handle); 1335 // indicates whether this effect bundle currently has a session context for this IO handle 1336 bool hasSession = false; 1337 int status = 0; 1338 int i; 1339 1340 if (sAdncBundleInitStatus != 0) { 1341 // This assumes that the default config of the eS305 after setting a preset 1342 // is the correct configuration. 1343 ALOGV(" no effect settings to apply for IO handle %d, no effect bundle", handle); 1344 return status; 1345 } 1346 1347 const int sessionId = Adnc_SessionNumberForHandle_l(handle); 1348 if (sessionId >= 0) { 1349 ALOGV(" applying settings from session num %d", sessionId); 1350 status = Adnc_ApplySettingsFromSessionContextInt_l( &sAdncSessions[sessionId] ); 1351 } 1352 else { 1353 ALOGV(" no session found for handle %d", handle); 1354 } 1355 1356 return status; 1357 } 1358 1359 /* 1360 * Reevaluate the usage of the eS305 based on the given IO handle. 1361 * Must be called with a lock on sAdncBundleLock 1362 */ 1363 int Adnc_ReevaluateUsageInt_l(audio_io_handle_t handle) 1364 { 1365 ALOGV(" Adnc_ReevaluateUsageInt_l(handle=%d) current_preset=%d requested_preset=%d", 1366 handle, eS305_ctrl.current_preset, eS305_ctrl.requested_preset); 1367 int status = 0; 1368 if ((eS305_ctrl.requested_preset == ES305_PRESET_OFF) || (handle == ES305_IO_HANDLE_NONE)) { 1369 status = Adnc_SleepInt_l(); 1370 } else { 1371 const int sessionId = Adnc_SessionNumberForHandle_l(handle); 1372 if (sessionId >= 0) { 1373 // recording active, use the preset only if there is an effect, 1374 // reset preset to off otherwise 1375 if (sAdncSessions[sessionId].activeMsk != 0) { 1376 status = Adnc_ApplyPresetInt_l(); 1377 if (status == 0) { 1378 //apply the settings of the session associated with the handle (if any) 1379 status = Adnc_ApplySettingsForHandleInt_l(handle); 1380 } 1381 } else { 1382 status = Adnc_SleepInt_l(); 1383 } 1384 } 1385 } 1386 return status; 1387 } 1388 1389 1390 //------------------------------------------------------- 1391 // eS305 public control interface from HAL 1392 //------------------------------------------------------- 1393 int eS305_UsePreset(int preset) 1394 { 1395 ALOGV("eS305_UsePreset(%d) current=%d handle=%d", 1396 preset, eS305_ctrl.current_preset, eS305_ctrl.ioHandle); 1397 1398 int status = 0; 1399 1400 pthread_mutex_lock(&sAdncBundleLock); 1401 1402 //if (preset != -1) { AdncBundle_logv_dumpSessions(); } 1403 1404 // allow preset transition from any preset to any other during recording, 1405 // except from one ASRA preset to another 1406 if (eS305_ctrl.ioHandle != ES305_IO_HANDLE_NONE) { 1407 switch(eS305_ctrl.current_preset) { 1408 case ES305_PRESET_ASRA_HANDHELD: 1409 case ES305_PRESET_ASRA_DESKTOP: 1410 case ES305_PRESET_ASRA_HEADSET: 1411 switch(preset) { 1412 case ES305_PRESET_ASRA_HANDHELD: 1413 case ES305_PRESET_ASRA_DESKTOP: 1414 case ES305_PRESET_ASRA_HEADSET: 1415 ALOGV(" not switching from ASRA preset %d to %d during voice recognition", 1416 eS305_ctrl.current_preset, preset); 1417 status = -EINVAL; 1418 goto exit; 1419 default: 1420 // transitioning from ASRA to non-ASRA: valid 1421 break; 1422 } 1423 break; 1424 default: 1425 // transitioning from non-ASRA: valid 1426 break; 1427 } 1428 } 1429 1430 eS305_ctrl.requested_preset = preset; 1431 1432 status = AdncBundle_Init_l(); 1433 if (status != 0) { 1434 ALOGE(" error applying preset, bundle failed to initialize"); 1435 goto exit; 1436 } 1437 1438 status = Adnc_ReevaluateUsageInt_l(eS305_ctrl.ioHandle); 1439 1440 exit: 1441 pthread_mutex_unlock(&sAdncBundleLock); 1442 return status; 1443 } 1444 1445 1446 int eS305_SetActiveIoHandle(audio_io_handle_t handle) 1447 { 1448 ALOGV("eS305_SetActiveIoHandle(%d)", handle); 1449 1450 pthread_mutex_lock(&sAdncBundleLock); 1451 1452 int status = AdncBundle_Init_l(); 1453 if (status != 0) { 1454 ALOGE(" error setting active handle, bundle failed to initialize"); 1455 pthread_mutex_unlock(&sAdncBundleLock); 1456 return status; 1457 } 1458 1459 status = Adnc_ReevaluateUsageInt_l(handle); 1460 1461 if (status == 0) { 1462 eS305_ctrl.ioHandle = handle; 1463 } else { 1464 ALOGE(" failed to update for new handle %d (current preset = %d)", 1465 handle, eS305_ctrl.current_preset); 1466 } 1467 1468 pthread_mutex_unlock(&sAdncBundleLock); 1469 1470 return status; 1471 } 1472 1473 1474 int eS305_AddEffect(effect_descriptor_t * descr, audio_io_handle_t handle) 1475 { 1476 ALOGV("eS305_AddEffect(handle=%d)", handle); 1477 1478 pthread_mutex_lock(&sAdncBundleLock); 1479 1480 int status = AdncBundle_Init_l(); 1481 if (status != 0) { 1482 ALOGE(" error setting adding effect, bundle failed to initialize"); 1483 pthread_mutex_unlock(&sAdncBundleLock); 1484 return status; 1485 } 1486 1487 if (descr == NULL){ 1488 ALOGV(" eS305_AddEffect() ERROR effect descriptor is NULL"); 1489 pthread_mutex_unlock(&sAdncBundleLock); 1490 return -EINVAL; 1491 } 1492 1493 uint32_t procId = Adnc_UuidToProcId(&descr->type); 1494 1495 adnc_pfx_session_t * session = AdncBundle_GetSession_l( 1496 procId, ES305_SESSION_ID_NONE, handle/*ioId*/); 1497 1498 if (session != NULL) { 1499 // mark the effect as active 1500 session->activeMsk |= (1 << procId); 1501 1502 // update settings if necessary 1503 Adnc_ReevaluateUsageInt_l(session->ioHandle); 1504 } 1505 1506 pthread_mutex_unlock(&sAdncBundleLock); 1507 1508 return status; 1509 } 1510 1511 1512 int eS305_RemoveEffect(effect_descriptor_t * descr, audio_io_handle_t handle) 1513 { 1514 ALOGV("eS305_RemoveEffect()"); 1515 1516 pthread_mutex_lock(&sAdncBundleLock); 1517 1518 int status = AdncBundle_Init_l(); 1519 if (status != 0) { 1520 ALOGE(" error setting removing effect, bundle failed to initialize"); 1521 pthread_mutex_unlock(&sAdncBundleLock); 1522 return status; 1523 } 1524 1525 if (descr == NULL){ 1526 ALOGV(" eS305_AddEffect() ERROR effect descriptor is NULL"); 1527 pthread_mutex_unlock(&sAdncBundleLock); 1528 return -EINVAL; 1529 } 1530 1531 uint32_t procId = Adnc_UuidToProcId(&descr->type); 1532 1533 adnc_pfx_session_t * session = AdncBundle_GetSession_l( 1534 procId, ES305_SESSION_ID_NONE, handle/*ioId*/); 1535 1536 if (session != NULL) { 1537 // mark the effect as inactive 1538 session->activeMsk &= ~(1 << procId); 1539 1540 // update settings if necessary 1541 Adnc_ReevaluateUsageInt_l(session->ioHandle); 1542 } 1543 1544 pthread_mutex_unlock(&sAdncBundleLock); 1545 1546 return status; 1547 } 1548 1549 1550 int eS305_Release() { 1551 ALOGV("eS305_Release()"); 1552 1553 pthread_mutex_lock(&sAdncBundleLock); 1554 1555 AdncBundle_Release_l(); 1556 1557 pthread_mutex_unlock(&sAdncBundleLock); 1558 1559 return 0; 1560 } 1561 1562 } // extern "C" 1563