1 /* 2 * Copyright (C) 2011 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 <stdlib.h> 18 #include <string.h> 19 #define LOG_TAG "PreProcessing" 20 //#define LOG_NDEBUG 0 21 #include <utils/Log.h> 22 #include <utils/Timers.h> 23 #include <hardware/audio_effect.h> 24 #include <audio_effects/effect_aec.h> 25 #include <audio_effects/effect_agc.h> 26 #include <audio_effects/effect_ns.h> 27 #include <module_common_types.h> 28 #include <audio_processing.h> 29 #include "speex/speex_resampler.h" 30 31 // undefine to perform multi channels API functional tests 32 //#define DUAL_MIC_TEST 33 34 //------------------------------------------------------------------------------ 35 // local definitions 36 //------------------------------------------------------------------------------ 37 38 // maximum number of sessions 39 #define PREPROC_NUM_SESSIONS 8 40 41 // types of pre processing modules 42 enum preproc_id 43 { 44 PREPROC_AGC, // Automatic Gain Control 45 PREPROC_AEC, // Acoustic Echo Canceler 46 PREPROC_NS, // Noise Suppressor 47 PREPROC_NUM_EFFECTS 48 }; 49 50 // Session state 51 enum preproc_session_state { 52 PREPROC_SESSION_STATE_INIT, // initialized 53 PREPROC_SESSION_STATE_CONFIG // configuration received 54 }; 55 56 // Effect/Preprocessor state 57 enum preproc_effect_state { 58 PREPROC_EFFECT_STATE_INIT, // initialized 59 PREPROC_EFFECT_STATE_CREATED, // webRTC engine created 60 PREPROC_EFFECT_STATE_CONFIG, // configuration received/disabled 61 PREPROC_EFFECT_STATE_ACTIVE // active/enabled 62 }; 63 64 // handle on webRTC engine 65 typedef void* preproc_fx_handle_t; 66 67 typedef struct preproc_session_s preproc_session_t; 68 typedef struct preproc_effect_s preproc_effect_t; 69 typedef struct preproc_ops_s preproc_ops_t; 70 71 // Effect operation table. Functions for all pre processors are declared in sPreProcOps[] table. 72 // Function pointer can be null if no action required. 73 struct preproc_ops_s { 74 int (* create)(preproc_effect_t *fx); 75 int (* init)(preproc_effect_t *fx); 76 int (* reset)(preproc_effect_t *fx); 77 void (* enable)(preproc_effect_t *fx); 78 void (* disable)(preproc_effect_t *fx); 79 int (* set_parameter)(preproc_effect_t *fx, void *param, void *value); 80 int (* get_parameter)(preproc_effect_t *fx, void *param, uint32_t *size, void *value); 81 int (* set_device)(preproc_effect_t *fx, uint32_t device); 82 }; 83 84 // Effect context 85 struct preproc_effect_s { 86 const struct effect_interface_s *itfe; 87 uint32_t procId; // type of pre processor (enum preproc_id) 88 uint32_t state; // current state (enum preproc_effect_state) 89 preproc_session_t *session; // session the effect is on 90 const preproc_ops_t *ops; // effect ops table 91 preproc_fx_handle_t engine; // handle on webRTC engine 92 #ifdef DUAL_MIC_TEST 93 bool aux_channels_on; // support auxiliary channels 94 size_t cur_channel_config; // current auciliary channel configuration 95 #endif 96 }; 97 98 // Session context 99 struct preproc_session_s { 100 struct preproc_effect_s effects[PREPROC_NUM_EFFECTS]; // effects in this session 101 uint32_t state; // current state (enum preproc_session_state) 102 int id; // audio session ID 103 int io; // handle of input stream this session is on 104 webrtc::AudioProcessing* apm; // handle on webRTC audio processing module (APM) 105 size_t apmFrameCount; // buffer size for webRTC process (10 ms) 106 uint32_t apmSamplingRate; // webRTC APM sampling rate (8/16 or 32 kHz) 107 size_t frameCount; // buffer size before input resampler ( <=> apmFrameCount) 108 uint32_t samplingRate; // sampling rate at effect process interface 109 uint32_t inChannelCount; // input channel count 110 uint32_t outChannelCount; // output channel count 111 uint32_t createdMsk; // bit field containing IDs of crested pre processors 112 uint32_t enabledMsk; // bit field containing IDs of enabled pre processors 113 uint32_t processedMsk; // bit field containing IDs of pre processors already 114 // processed in current round 115 webrtc::AudioFrame *procFrame; // audio frame passed to webRTC AMP ProcessStream() 116 int16_t *inBuf; // input buffer used when resampling 117 size_t inBufSize; // input buffer size in frames 118 size_t framesIn; // number of frames in input buffer 119 SpeexResamplerState *inResampler; // handle on input speex resampler 120 int16_t *outBuf; // output buffer used when resampling 121 size_t outBufSize; // output buffer size in frames 122 size_t framesOut; // number of frames in output buffer 123 SpeexResamplerState *outResampler; // handle on output speex resampler 124 uint32_t revChannelCount; // number of channels on reverse stream 125 uint32_t revEnabledMsk; // bit field containing IDs of enabled pre processors 126 // with reverse channel 127 uint32_t revProcessedMsk; // bit field containing IDs of pre processors with reverse 128 // channel already processed in current round 129 webrtc::AudioFrame *revFrame; // audio frame passed to webRTC AMP AnalyzeReverseStream() 130 int16_t *revBuf; // reverse channel input buffer 131 size_t revBufSize; // reverse channel input buffer size 132 size_t framesRev; // number of frames in reverse channel input buffer 133 SpeexResamplerState *revResampler; // handle on reverse channel input speex resampler 134 }; 135 136 #ifdef DUAL_MIC_TEST 137 enum { 138 PREPROC_CMD_DUAL_MIC_ENABLE = EFFECT_CMD_FIRST_PROPRIETARY, // enable dual mic mode 139 PREPROC_CMD_DUAL_MIC_PCM_DUMP_START, // start pcm capture 140 PREPROC_CMD_DUAL_MIC_PCM_DUMP_STOP // stop pcm capture 141 }; 142 143 enum { 144 CHANNEL_CFG_MONO, 145 CHANNEL_CFG_STEREO, 146 CHANNEL_CFG_MONO_AUX, 147 CHANNEL_CFG_STEREO_AUX, 148 CHANNEL_CFG_CNT, 149 CHANNEL_CFG_FIRST_AUX = CHANNEL_CFG_MONO_AUX, 150 }; 151 152 const channel_config_t sDualMicConfigs[CHANNEL_CFG_CNT] = { 153 {AUDIO_CHANNEL_IN_MONO , 0}, 154 {AUDIO_CHANNEL_IN_STEREO , 0}, 155 {AUDIO_CHANNEL_IN_FRONT , AUDIO_CHANNEL_IN_BACK}, 156 {AUDIO_CHANNEL_IN_STEREO , AUDIO_CHANNEL_IN_RIGHT} 157 }; 158 159 bool sHasAuxChannels[PREPROC_NUM_EFFECTS] = { 160 false, // PREPROC_AGC 161 true, // PREPROC_AEC 162 true, // PREPROC_NS 163 }; 164 165 bool gDualMicEnabled; 166 FILE *gPcmDumpFh; 167 static pthread_mutex_t gPcmDumpLock = PTHREAD_MUTEX_INITIALIZER; 168 #endif 169 170 171 //------------------------------------------------------------------------------ 172 // Effect descriptors 173 //------------------------------------------------------------------------------ 174 175 // UUIDs for effect types have been generated from http://www.itu.int/ITU-T/asn1/uuid.html 176 // as the pre processing effects are not defined by OpenSL ES 177 178 // Automatic Gain Control 179 static const effect_descriptor_t sAgcDescriptor = { 180 { 0x0a8abfe0, 0x654c, 0x11e0, 0xba26, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } }, // type 181 { 0xaa8130e0, 0x66fc, 0x11e0, 0xbad0, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } }, // 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 "The Android Open Source Project" 188 }; 189 190 // Acoustic Echo Cancellation 191 static const effect_descriptor_t sAecDescriptor = { 192 { 0x7b491460, 0x8d4d, 0x11e0, 0xbd61, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } }, // type 193 { 0xbb392ec0, 0x8d4d, 0x11e0, 0xa896, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } }, // uuid 194 EFFECT_CONTROL_API_VERSION, 195 (EFFECT_FLAG_TYPE_PRE_PROC|EFFECT_FLAG_DEVICE_IND), 196 0, //FIXME indicate CPU load 197 0, //FIXME indicate memory usage 198 "Acoustic Echo Canceler", 199 "The Android Open Source Project" 200 }; 201 202 // Noise suppression 203 static const effect_descriptor_t sNsDescriptor = { 204 { 0x58b4b260, 0x8e06, 0x11e0, 0xaa8e, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } }, // type 205 { 0xc06c8400, 0x8e06, 0x11e0, 0x9cb6, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } }, // uuid 206 EFFECT_CONTROL_API_VERSION, 207 (EFFECT_FLAG_TYPE_PRE_PROC|EFFECT_FLAG_DEVICE_IND), 208 0, //FIXME indicate CPU load 209 0, //FIXME indicate memory usage 210 "Noise Suppression", 211 "The Android Open Source Project" 212 }; 213 214 215 static const effect_descriptor_t *sDescriptors[PREPROC_NUM_EFFECTS] = { 216 &sAgcDescriptor, 217 &sAecDescriptor, 218 &sNsDescriptor 219 }; 220 221 //------------------------------------------------------------------------------ 222 // Helper functions 223 //------------------------------------------------------------------------------ 224 225 const effect_uuid_t * const sUuidToPreProcTable[PREPROC_NUM_EFFECTS] = { 226 FX_IID_AGC, 227 FX_IID_AEC, 228 FX_IID_NS 229 }; 230 231 232 const effect_uuid_t * ProcIdToUuid(int procId) 233 { 234 if (procId >= PREPROC_NUM_EFFECTS) { 235 return EFFECT_UUID_NULL; 236 } 237 return sUuidToPreProcTable[procId]; 238 } 239 240 uint32_t UuidToProcId(const effect_uuid_t * uuid) 241 { 242 size_t i; 243 for (i = 0; i < PREPROC_NUM_EFFECTS; i++) { 244 if (memcmp(uuid, sUuidToPreProcTable[i], sizeof(*uuid)) == 0) { 245 break; 246 } 247 } 248 return i; 249 } 250 251 bool HasReverseStream(uint32_t procId) 252 { 253 if (procId == PREPROC_AEC) { 254 return true; 255 } 256 return false; 257 } 258 259 260 //------------------------------------------------------------------------------ 261 // Automatic Gain Control (AGC) 262 //------------------------------------------------------------------------------ 263 264 static const int kAgcDefaultTargetLevel = 3; 265 static const int kAgcDefaultCompGain = 9; 266 static const bool kAgcDefaultLimiter = true; 267 268 int AgcInit (preproc_effect_t *effect) 269 { 270 ALOGV("AgcInit"); 271 webrtc::GainControl *agc = static_cast<webrtc::GainControl *>(effect->engine); 272 agc->set_mode(webrtc::GainControl::kFixedDigital); 273 agc->set_target_level_dbfs(kAgcDefaultTargetLevel); 274 agc->set_compression_gain_db(kAgcDefaultCompGain); 275 agc->enable_limiter(kAgcDefaultLimiter); 276 return 0; 277 } 278 279 int AgcCreate(preproc_effect_t *effect) 280 { 281 webrtc::GainControl *agc = effect->session->apm->gain_control(); 282 ALOGV("AgcCreate got agc %p", agc); 283 if (agc == NULL) { 284 ALOGW("AgcCreate Error"); 285 return -ENOMEM; 286 } 287 effect->engine = static_cast<preproc_fx_handle_t>(agc); 288 AgcInit(effect); 289 return 0; 290 } 291 292 int AgcGetParameter(preproc_effect_t *effect, 293 void *pParam, 294 uint32_t *pValueSize, 295 void *pValue) 296 { 297 int status = 0; 298 uint32_t param = *(uint32_t *)pParam; 299 t_agc_settings *pProperties = (t_agc_settings *)pValue; 300 webrtc::GainControl *agc = static_cast<webrtc::GainControl *>(effect->engine); 301 302 switch (param) { 303 case AGC_PARAM_TARGET_LEVEL: 304 case AGC_PARAM_COMP_GAIN: 305 if (*pValueSize < sizeof(int16_t)) { 306 *pValueSize = 0; 307 return -EINVAL; 308 } 309 break; 310 case AGC_PARAM_LIMITER_ENA: 311 if (*pValueSize < sizeof(bool)) { 312 *pValueSize = 0; 313 return -EINVAL; 314 } 315 break; 316 case AGC_PARAM_PROPERTIES: 317 if (*pValueSize < sizeof(t_agc_settings)) { 318 *pValueSize = 0; 319 return -EINVAL; 320 } 321 break; 322 323 default: 324 ALOGW("AgcGetParameter() unknown param %08x", param); 325 status = -EINVAL; 326 break; 327 } 328 329 switch (param) { 330 case AGC_PARAM_TARGET_LEVEL: 331 *(int16_t *) pValue = (int16_t)(agc->target_level_dbfs() * -100); 332 ALOGV("AgcGetParameter() target level %d milliBels", *(int16_t *) pValue); 333 break; 334 case AGC_PARAM_COMP_GAIN: 335 *(int16_t *) pValue = (int16_t)(agc->compression_gain_db() * 100); 336 ALOGV("AgcGetParameter() comp gain %d milliBels", *(int16_t *) pValue); 337 break; 338 case AGC_PARAM_LIMITER_ENA: 339 *(bool *) pValue = (bool)agc->is_limiter_enabled(); 340 ALOGV("AgcGetParameter() limiter enabled %s", 341 (*(int16_t *) pValue != 0) ? "true" : "false"); 342 break; 343 case AGC_PARAM_PROPERTIES: 344 pProperties->targetLevel = (int16_t)(agc->target_level_dbfs() * -100); 345 pProperties->compGain = (int16_t)(agc->compression_gain_db() * 100); 346 pProperties->limiterEnabled = (bool)agc->is_limiter_enabled(); 347 break; 348 default: 349 ALOGW("AgcGetParameter() unknown param %d", param); 350 status = -EINVAL; 351 break; 352 } 353 return status; 354 } 355 356 int AgcSetParameter (preproc_effect_t *effect, void *pParam, void *pValue) 357 { 358 int status = 0; 359 uint32_t param = *(uint32_t *)pParam; 360 t_agc_settings *pProperties = (t_agc_settings *)pValue; 361 webrtc::GainControl *agc = static_cast<webrtc::GainControl *>(effect->engine); 362 363 switch (param) { 364 case AGC_PARAM_TARGET_LEVEL: 365 ALOGV("AgcSetParameter() target level %d milliBels", *(int16_t *)pValue); 366 status = agc->set_target_level_dbfs(-(*(int16_t *)pValue / 100)); 367 break; 368 case AGC_PARAM_COMP_GAIN: 369 ALOGV("AgcSetParameter() comp gain %d milliBels", *(int16_t *)pValue); 370 status = agc->set_compression_gain_db(*(int16_t *)pValue / 100); 371 break; 372 case AGC_PARAM_LIMITER_ENA: 373 ALOGV("AgcSetParameter() limiter enabled %s", *(bool *)pValue ? "true" : "false"); 374 status = agc->enable_limiter(*(bool *)pValue); 375 break; 376 case AGC_PARAM_PROPERTIES: 377 ALOGV("AgcSetParameter() properties level %d, gain %d limiter %d", 378 pProperties->targetLevel, 379 pProperties->compGain, 380 pProperties->limiterEnabled); 381 status = agc->set_target_level_dbfs(-(pProperties->targetLevel / 100)); 382 if (status != 0) break; 383 status = agc->set_compression_gain_db(pProperties->compGain / 100); 384 if (status != 0) break; 385 status = agc->enable_limiter(pProperties->limiterEnabled); 386 break; 387 default: 388 ALOGW("AgcSetParameter() unknown param %08x value %08x", param, *(uint32_t *)pValue); 389 status = -EINVAL; 390 break; 391 } 392 393 ALOGV("AgcSetParameter() done status %d", status); 394 395 return status; 396 } 397 398 void AgcEnable(preproc_effect_t *effect) 399 { 400 webrtc::GainControl *agc = static_cast<webrtc::GainControl *>(effect->engine); 401 ALOGV("AgcEnable agc %p", agc); 402 agc->Enable(true); 403 } 404 405 void AgcDisable(preproc_effect_t *effect) 406 { 407 ALOGV("AgcDisable"); 408 webrtc::GainControl *agc = static_cast<webrtc::GainControl *>(effect->engine); 409 agc->Enable(false); 410 } 411 412 413 static const preproc_ops_t sAgcOps = { 414 AgcCreate, 415 AgcInit, 416 NULL, 417 AgcEnable, 418 AgcDisable, 419 AgcSetParameter, 420 AgcGetParameter, 421 NULL 422 }; 423 424 425 //------------------------------------------------------------------------------ 426 // Acoustic Echo Canceler (AEC) 427 //------------------------------------------------------------------------------ 428 429 static const webrtc::EchoControlMobile::RoutingMode kAecDefaultMode = 430 webrtc::EchoControlMobile::kEarpiece; 431 static const bool kAecDefaultComfortNoise = true; 432 433 int AecInit (preproc_effect_t *effect) 434 { 435 ALOGV("AecInit"); 436 webrtc::EchoControlMobile *aec = static_cast<webrtc::EchoControlMobile *>(effect->engine); 437 aec->set_routing_mode(kAecDefaultMode); 438 aec->enable_comfort_noise(kAecDefaultComfortNoise); 439 return 0; 440 } 441 442 int AecCreate(preproc_effect_t *effect) 443 { 444 webrtc::EchoControlMobile *aec = effect->session->apm->echo_control_mobile(); 445 ALOGV("AecCreate got aec %p", aec); 446 if (aec == NULL) { 447 ALOGW("AgcCreate Error"); 448 return -ENOMEM; 449 } 450 effect->engine = static_cast<preproc_fx_handle_t>(aec); 451 AecInit (effect); 452 return 0; 453 } 454 455 int AecGetParameter(preproc_effect_t *effect, 456 void *pParam, 457 uint32_t *pValueSize, 458 void *pValue) 459 { 460 int status = 0; 461 uint32_t param = *(uint32_t *)pParam; 462 463 if (*pValueSize < sizeof(uint32_t)) { 464 return -EINVAL; 465 } 466 switch (param) { 467 case AEC_PARAM_ECHO_DELAY: 468 case AEC_PARAM_PROPERTIES: 469 *(uint32_t *)pValue = 1000 * effect->session->apm->stream_delay_ms(); 470 ALOGV("AecGetParameter() echo delay %d us", *(uint32_t *)pValue); 471 break; 472 default: 473 ALOGW("AecGetParameter() unknown param %08x value %08x", param, *(uint32_t *)pValue); 474 status = -EINVAL; 475 break; 476 } 477 return status; 478 } 479 480 int AecSetParameter (preproc_effect_t *effect, void *pParam, void *pValue) 481 { 482 int status = 0; 483 uint32_t param = *(uint32_t *)pParam; 484 uint32_t value = *(uint32_t *)pValue; 485 486 switch (param) { 487 case AEC_PARAM_ECHO_DELAY: 488 case AEC_PARAM_PROPERTIES: 489 status = effect->session->apm->set_stream_delay_ms(value/1000); 490 ALOGV("AecSetParameter() echo delay %d us, status %d", value, status); 491 break; 492 default: 493 ALOGW("AecSetParameter() unknown param %08x value %08x", param, *(uint32_t *)pValue); 494 status = -EINVAL; 495 break; 496 } 497 return status; 498 } 499 500 void AecEnable(preproc_effect_t *effect) 501 { 502 webrtc::EchoControlMobile *aec = static_cast<webrtc::EchoControlMobile *>(effect->engine); 503 ALOGV("AecEnable aec %p", aec); 504 aec->Enable(true); 505 } 506 507 void AecDisable(preproc_effect_t *effect) 508 { 509 ALOGV("AecDisable"); 510 webrtc::EchoControlMobile *aec = static_cast<webrtc::EchoControlMobile *>(effect->engine); 511 aec->Enable(false); 512 } 513 514 int AecSetDevice(preproc_effect_t *effect, uint32_t device) 515 { 516 ALOGV("AecSetDevice %08x", device); 517 webrtc::EchoControlMobile *aec = static_cast<webrtc::EchoControlMobile *>(effect->engine); 518 webrtc::EchoControlMobile::RoutingMode mode = webrtc::EchoControlMobile::kQuietEarpieceOrHeadset; 519 520 if (audio_is_input_device(device)) { 521 return 0; 522 } 523 524 switch(device) { 525 case AUDIO_DEVICE_OUT_EARPIECE: 526 mode = webrtc::EchoControlMobile::kEarpiece; 527 break; 528 case AUDIO_DEVICE_OUT_SPEAKER: 529 mode = webrtc::EchoControlMobile::kSpeakerphone; 530 break; 531 case AUDIO_DEVICE_OUT_WIRED_HEADSET: 532 case AUDIO_DEVICE_OUT_WIRED_HEADPHONE: 533 default: 534 break; 535 } 536 aec->set_routing_mode(mode); 537 return 0; 538 } 539 540 static const preproc_ops_t sAecOps = { 541 AecCreate, 542 AecInit, 543 NULL, 544 AecEnable, 545 AecDisable, 546 AecSetParameter, 547 AecGetParameter, 548 AecSetDevice 549 }; 550 551 //------------------------------------------------------------------------------ 552 // Noise Suppression (NS) 553 //------------------------------------------------------------------------------ 554 555 static const webrtc::NoiseSuppression::Level kNsDefaultLevel = webrtc::NoiseSuppression::kModerate; 556 557 int NsInit (preproc_effect_t *effect) 558 { 559 ALOGV("NsInit"); 560 webrtc::NoiseSuppression *ns = static_cast<webrtc::NoiseSuppression *>(effect->engine); 561 ns->set_level(kNsDefaultLevel); 562 return 0; 563 } 564 565 int NsCreate(preproc_effect_t *effect) 566 { 567 webrtc::NoiseSuppression *ns = effect->session->apm->noise_suppression(); 568 ALOGV("NsCreate got ns %p", ns); 569 if (ns == NULL) { 570 ALOGW("AgcCreate Error"); 571 return -ENOMEM; 572 } 573 effect->engine = static_cast<preproc_fx_handle_t>(ns); 574 NsInit (effect); 575 return 0; 576 } 577 578 int NsGetParameter(preproc_effect_t *effect __unused, 579 void *pParam __unused, 580 uint32_t *pValueSize __unused, 581 void *pValue __unused) 582 { 583 int status = 0; 584 return status; 585 } 586 587 int NsSetParameter (preproc_effect_t *effect __unused, 588 void *pParam __unused, 589 void *pValue __unused) 590 { 591 int status = 0; 592 return status; 593 } 594 595 void NsEnable(preproc_effect_t *effect) 596 { 597 webrtc::NoiseSuppression *ns = static_cast<webrtc::NoiseSuppression *>(effect->engine); 598 ALOGV("NsEnable ns %p", ns); 599 ns->Enable(true); 600 } 601 602 void NsDisable(preproc_effect_t *effect) 603 { 604 ALOGV("NsDisable"); 605 webrtc::NoiseSuppression *ns = static_cast<webrtc::NoiseSuppression *>(effect->engine); 606 ns->Enable(false); 607 } 608 609 static const preproc_ops_t sNsOps = { 610 NsCreate, 611 NsInit, 612 NULL, 613 NsEnable, 614 NsDisable, 615 NsSetParameter, 616 NsGetParameter, 617 NULL 618 }; 619 620 621 static const preproc_ops_t *sPreProcOps[PREPROC_NUM_EFFECTS] = { 622 &sAgcOps, 623 &sAecOps, 624 &sNsOps 625 }; 626 627 628 //------------------------------------------------------------------------------ 629 // Effect functions 630 //------------------------------------------------------------------------------ 631 632 void Session_SetProcEnabled(preproc_session_t *session, uint32_t procId, bool enabled); 633 634 extern "C" const struct effect_interface_s sEffectInterface; 635 extern "C" const struct effect_interface_s sEffectInterfaceReverse; 636 637 #define BAD_STATE_ABORT(from, to) \ 638 LOG_ALWAYS_FATAL("Bad state transition from %d to %d", from, to); 639 640 int Effect_SetState(preproc_effect_t *effect, uint32_t state) 641 { 642 int status = 0; 643 ALOGV("Effect_SetState proc %d, new %d old %d", effect->procId, state, effect->state); 644 switch(state) { 645 case PREPROC_EFFECT_STATE_INIT: 646 switch(effect->state) { 647 case PREPROC_EFFECT_STATE_ACTIVE: 648 effect->ops->disable(effect); 649 Session_SetProcEnabled(effect->session, effect->procId, false); 650 case PREPROC_EFFECT_STATE_CONFIG: 651 case PREPROC_EFFECT_STATE_CREATED: 652 case PREPROC_EFFECT_STATE_INIT: 653 break; 654 default: 655 BAD_STATE_ABORT(effect->state, state); 656 } 657 break; 658 case PREPROC_EFFECT_STATE_CREATED: 659 switch(effect->state) { 660 case PREPROC_EFFECT_STATE_INIT: 661 status = effect->ops->create(effect); 662 break; 663 case PREPROC_EFFECT_STATE_CREATED: 664 case PREPROC_EFFECT_STATE_ACTIVE: 665 case PREPROC_EFFECT_STATE_CONFIG: 666 ALOGE("Effect_SetState invalid transition"); 667 status = -ENOSYS; 668 break; 669 default: 670 BAD_STATE_ABORT(effect->state, state); 671 } 672 break; 673 case PREPROC_EFFECT_STATE_CONFIG: 674 switch(effect->state) { 675 case PREPROC_EFFECT_STATE_INIT: 676 ALOGE("Effect_SetState invalid transition"); 677 status = -ENOSYS; 678 break; 679 case PREPROC_EFFECT_STATE_ACTIVE: 680 effect->ops->disable(effect); 681 Session_SetProcEnabled(effect->session, effect->procId, false); 682 break; 683 case PREPROC_EFFECT_STATE_CREATED: 684 case PREPROC_EFFECT_STATE_CONFIG: 685 break; 686 default: 687 BAD_STATE_ABORT(effect->state, state); 688 } 689 break; 690 case PREPROC_EFFECT_STATE_ACTIVE: 691 switch(effect->state) { 692 case PREPROC_EFFECT_STATE_INIT: 693 case PREPROC_EFFECT_STATE_CREATED: 694 ALOGE("Effect_SetState invalid transition"); 695 status = -ENOSYS; 696 break; 697 case PREPROC_EFFECT_STATE_ACTIVE: 698 // enabling an already enabled effect is just ignored 699 break; 700 case PREPROC_EFFECT_STATE_CONFIG: 701 effect->ops->enable(effect); 702 Session_SetProcEnabled(effect->session, effect->procId, true); 703 break; 704 default: 705 BAD_STATE_ABORT(effect->state, state); 706 } 707 break; 708 default: 709 BAD_STATE_ABORT(effect->state, state); 710 } 711 if (status == 0) { 712 effect->state = state; 713 } 714 return status; 715 } 716 717 int Effect_Init(preproc_effect_t *effect, uint32_t procId) 718 { 719 if (HasReverseStream(procId)) { 720 effect->itfe = &sEffectInterfaceReverse; 721 } else { 722 effect->itfe = &sEffectInterface; 723 } 724 effect->ops = sPreProcOps[procId]; 725 effect->procId = procId; 726 effect->state = PREPROC_EFFECT_STATE_INIT; 727 return 0; 728 } 729 730 int Effect_Create(preproc_effect_t *effect, 731 preproc_session_t *session, 732 effect_handle_t *interface) 733 { 734 effect->session = session; 735 *interface = (effect_handle_t)&effect->itfe; 736 return Effect_SetState(effect, PREPROC_EFFECT_STATE_CREATED); 737 } 738 739 int Effect_Release(preproc_effect_t *effect) 740 { 741 return Effect_SetState(effect, PREPROC_EFFECT_STATE_INIT); 742 } 743 744 745 //------------------------------------------------------------------------------ 746 // Session functions 747 //------------------------------------------------------------------------------ 748 749 #define RESAMPLER_QUALITY SPEEX_RESAMPLER_QUALITY_VOIP 750 751 static const int kPreprocDefaultSr = 16000; 752 static const int kPreProcDefaultCnl = 1; 753 754 int Session_Init(preproc_session_t *session) 755 { 756 size_t i; 757 int status = 0; 758 759 session->state = PREPROC_SESSION_STATE_INIT; 760 session->id = 0; 761 session->io = 0; 762 session->createdMsk = 0; 763 session->apm = NULL; 764 for (i = 0; i < PREPROC_NUM_EFFECTS && status == 0; i++) { 765 status = Effect_Init(&session->effects[i], i); 766 } 767 return status; 768 } 769 770 771 extern "C" int Session_CreateEffect(preproc_session_t *session, 772 int32_t procId, 773 effect_handle_t *interface) 774 { 775 int status = -ENOMEM; 776 777 ALOGV("Session_CreateEffect procId %d, createdMsk %08x", procId, session->createdMsk); 778 779 if (session->createdMsk == 0) { 780 session->apm = webrtc::AudioProcessing::Create(session->io); 781 if (session->apm == NULL) { 782 ALOGW("Session_CreateEffect could not get apm engine"); 783 goto error; 784 } 785 session->apm->set_sample_rate_hz(kPreprocDefaultSr); 786 session->apm->set_num_channels(kPreProcDefaultCnl, kPreProcDefaultCnl); 787 session->apm->set_num_reverse_channels(kPreProcDefaultCnl); 788 session->procFrame = new webrtc::AudioFrame(); 789 if (session->procFrame == NULL) { 790 ALOGW("Session_CreateEffect could not allocate audio frame"); 791 goto error; 792 } 793 session->revFrame = new webrtc::AudioFrame(); 794 if (session->revFrame == NULL) { 795 ALOGW("Session_CreateEffect could not allocate reverse audio frame"); 796 goto error; 797 } 798 session->apmSamplingRate = kPreprocDefaultSr; 799 session->apmFrameCount = (kPreprocDefaultSr) / 100; 800 session->frameCount = session->apmFrameCount; 801 session->samplingRate = kPreprocDefaultSr; 802 session->inChannelCount = kPreProcDefaultCnl; 803 session->outChannelCount = kPreProcDefaultCnl; 804 session->procFrame->_frequencyInHz = kPreprocDefaultSr; 805 session->procFrame->_audioChannel = kPreProcDefaultCnl; 806 session->revChannelCount = kPreProcDefaultCnl; 807 session->revFrame->_frequencyInHz = kPreprocDefaultSr; 808 session->revFrame->_audioChannel = kPreProcDefaultCnl; 809 session->enabledMsk = 0; 810 session->processedMsk = 0; 811 session->revEnabledMsk = 0; 812 session->revProcessedMsk = 0; 813 session->inResampler = NULL; 814 session->inBuf = NULL; 815 session->inBufSize = 0; 816 session->outResampler = NULL; 817 session->outBuf = NULL; 818 session->outBufSize = 0; 819 session->revResampler = NULL; 820 session->revBuf = NULL; 821 session->revBufSize = 0; 822 } 823 status = Effect_Create(&session->effects[procId], session, interface); 824 if (status < 0) { 825 goto error; 826 } 827 ALOGV("Session_CreateEffect OK"); 828 session->createdMsk |= (1<<procId); 829 return status; 830 831 error: 832 if (session->createdMsk == 0) { 833 delete session->revFrame; 834 session->revFrame = NULL; 835 delete session->procFrame; 836 session->procFrame = NULL; 837 webrtc::AudioProcessing::Destroy(session->apm); 838 session->apm = NULL; 839 } 840 return status; 841 } 842 843 int Session_ReleaseEffect(preproc_session_t *session, 844 preproc_effect_t *fx) 845 { 846 ALOGW_IF(Effect_Release(fx) != 0, " Effect_Release() failed for proc ID %d", fx->procId); 847 session->createdMsk &= ~(1<<fx->procId); 848 if (session->createdMsk == 0) { 849 webrtc::AudioProcessing::Destroy(session->apm); 850 session->apm = NULL; 851 delete session->procFrame; 852 session->procFrame = NULL; 853 delete session->revFrame; 854 session->revFrame = NULL; 855 if (session->inResampler != NULL) { 856 speex_resampler_destroy(session->inResampler); 857 session->inResampler = NULL; 858 } 859 if (session->outResampler != NULL) { 860 speex_resampler_destroy(session->outResampler); 861 session->outResampler = NULL; 862 } 863 if (session->revResampler != NULL) { 864 speex_resampler_destroy(session->revResampler); 865 session->revResampler = NULL; 866 } 867 delete session->inBuf; 868 session->inBuf = NULL; 869 delete session->outBuf; 870 session->outBuf = NULL; 871 delete session->revBuf; 872 session->revBuf = NULL; 873 874 session->io = 0; 875 } 876 877 return 0; 878 } 879 880 881 int Session_SetConfig(preproc_session_t *session, effect_config_t *config) 882 { 883 uint32_t sr; 884 uint32_t inCnl = audio_channel_count_from_out_mask(config->inputCfg.channels); 885 uint32_t outCnl = audio_channel_count_from_out_mask(config->outputCfg.channels); 886 887 if (config->inputCfg.samplingRate != config->outputCfg.samplingRate || 888 config->inputCfg.format != config->outputCfg.format || 889 config->inputCfg.format != AUDIO_FORMAT_PCM_16_BIT) { 890 return -EINVAL; 891 } 892 893 ALOGV("Session_SetConfig sr %d cnl %08x", 894 config->inputCfg.samplingRate, config->inputCfg.channels); 895 int status; 896 897 // if at least one process is enabled, do not accept configuration changes 898 if (session->enabledMsk) { 899 if (session->samplingRate != config->inputCfg.samplingRate || 900 session->inChannelCount != inCnl || 901 session->outChannelCount != outCnl) { 902 return -ENOSYS; 903 } else { 904 return 0; 905 } 906 } 907 908 // AEC implementation is limited to 16kHz 909 if (config->inputCfg.samplingRate >= 32000 && !(session->createdMsk & (1 << PREPROC_AEC))) { 910 session->apmSamplingRate = 32000; 911 } else 912 if (config->inputCfg.samplingRate >= 16000) { 913 session->apmSamplingRate = 16000; 914 } else if (config->inputCfg.samplingRate >= 8000) { 915 session->apmSamplingRate = 8000; 916 } 917 status = session->apm->set_sample_rate_hz(session->apmSamplingRate); 918 if (status < 0) { 919 return -EINVAL; 920 } 921 status = session->apm->set_num_channels(inCnl, outCnl); 922 if (status < 0) { 923 return -EINVAL; 924 } 925 status = session->apm->set_num_reverse_channels(inCnl); 926 if (status < 0) { 927 return -EINVAL; 928 } 929 930 session->samplingRate = config->inputCfg.samplingRate; 931 session->apmFrameCount = session->apmSamplingRate / 100; 932 if (session->samplingRate == session->apmSamplingRate) { 933 session->frameCount = session->apmFrameCount; 934 } else { 935 session->frameCount = (session->apmFrameCount * session->samplingRate) / 936 session->apmSamplingRate + 1; 937 } 938 session->inChannelCount = inCnl; 939 session->outChannelCount = outCnl; 940 session->procFrame->_audioChannel = inCnl; 941 session->procFrame->_frequencyInHz = session->apmSamplingRate; 942 943 session->revChannelCount = inCnl; 944 session->revFrame->_audioChannel = inCnl; 945 session->revFrame->_frequencyInHz = session->apmSamplingRate; 946 947 // force process buffer reallocation 948 session->inBufSize = 0; 949 session->outBufSize = 0; 950 session->framesIn = 0; 951 session->framesOut = 0; 952 953 954 if (session->inResampler != NULL) { 955 speex_resampler_destroy(session->inResampler); 956 session->inResampler = NULL; 957 } 958 if (session->outResampler != NULL) { 959 speex_resampler_destroy(session->outResampler); 960 session->outResampler = NULL; 961 } 962 if (session->revResampler != NULL) { 963 speex_resampler_destroy(session->revResampler); 964 session->revResampler = NULL; 965 } 966 if (session->samplingRate != session->apmSamplingRate) { 967 int error; 968 session->inResampler = speex_resampler_init(session->inChannelCount, 969 session->samplingRate, 970 session->apmSamplingRate, 971 RESAMPLER_QUALITY, 972 &error); 973 if (session->inResampler == NULL) { 974 ALOGW("Session_SetConfig Cannot create speex resampler: %s", 975 speex_resampler_strerror(error)); 976 return -EINVAL; 977 } 978 session->outResampler = speex_resampler_init(session->outChannelCount, 979 session->apmSamplingRate, 980 session->samplingRate, 981 RESAMPLER_QUALITY, 982 &error); 983 if (session->outResampler == NULL) { 984 ALOGW("Session_SetConfig Cannot create speex resampler: %s", 985 speex_resampler_strerror(error)); 986 speex_resampler_destroy(session->inResampler); 987 session->inResampler = NULL; 988 return -EINVAL; 989 } 990 session->revResampler = speex_resampler_init(session->inChannelCount, 991 session->samplingRate, 992 session->apmSamplingRate, 993 RESAMPLER_QUALITY, 994 &error); 995 if (session->revResampler == NULL) { 996 ALOGW("Session_SetConfig Cannot create speex resampler: %s", 997 speex_resampler_strerror(error)); 998 speex_resampler_destroy(session->inResampler); 999 session->inResampler = NULL; 1000 speex_resampler_destroy(session->outResampler); 1001 session->outResampler = NULL; 1002 return -EINVAL; 1003 } 1004 } 1005 1006 session->state = PREPROC_SESSION_STATE_CONFIG; 1007 return 0; 1008 } 1009 1010 void Session_GetConfig(preproc_session_t *session, effect_config_t *config) 1011 { 1012 memset(config, 0, sizeof(effect_config_t)); 1013 config->inputCfg.samplingRate = config->outputCfg.samplingRate = session->samplingRate; 1014 config->inputCfg.format = config->outputCfg.format = AUDIO_FORMAT_PCM_16_BIT; 1015 config->inputCfg.channels = audio_channel_in_mask_from_count(session->inChannelCount); 1016 // "out" doesn't mean output device, so this is the correct API to convert channel count to mask 1017 config->outputCfg.channels = audio_channel_in_mask_from_count(session->outChannelCount); 1018 config->inputCfg.mask = config->outputCfg.mask = 1019 (EFFECT_CONFIG_SMP_RATE | EFFECT_CONFIG_CHANNELS | EFFECT_CONFIG_FORMAT); 1020 } 1021 1022 int Session_SetReverseConfig(preproc_session_t *session, effect_config_t *config) 1023 { 1024 if (config->inputCfg.samplingRate != config->outputCfg.samplingRate || 1025 config->inputCfg.format != config->outputCfg.format || 1026 config->inputCfg.format != AUDIO_FORMAT_PCM_16_BIT) { 1027 return -EINVAL; 1028 } 1029 1030 ALOGV("Session_SetReverseConfig sr %d cnl %08x", 1031 config->inputCfg.samplingRate, config->inputCfg.channels); 1032 1033 if (session->state < PREPROC_SESSION_STATE_CONFIG) { 1034 return -ENOSYS; 1035 } 1036 if (config->inputCfg.samplingRate != session->samplingRate || 1037 config->inputCfg.format != AUDIO_FORMAT_PCM_16_BIT) { 1038 return -EINVAL; 1039 } 1040 uint32_t inCnl = audio_channel_count_from_out_mask(config->inputCfg.channels); 1041 int status = session->apm->set_num_reverse_channels(inCnl); 1042 if (status < 0) { 1043 return -EINVAL; 1044 } 1045 session->revChannelCount = inCnl; 1046 session->revFrame->_audioChannel = inCnl; 1047 session->revFrame->_frequencyInHz = session->apmSamplingRate; 1048 // force process buffer reallocation 1049 session->revBufSize = 0; 1050 session->framesRev = 0; 1051 1052 return 0; 1053 } 1054 1055 void Session_GetReverseConfig(preproc_session_t *session, effect_config_t *config) 1056 { 1057 memset(config, 0, sizeof(effect_config_t)); 1058 config->inputCfg.samplingRate = config->outputCfg.samplingRate = session->samplingRate; 1059 config->inputCfg.format = config->outputCfg.format = AUDIO_FORMAT_PCM_16_BIT; 1060 config->inputCfg.channels = config->outputCfg.channels = 1061 audio_channel_in_mask_from_count(session->revChannelCount); 1062 config->inputCfg.mask = config->outputCfg.mask = 1063 (EFFECT_CONFIG_SMP_RATE | EFFECT_CONFIG_CHANNELS | EFFECT_CONFIG_FORMAT); 1064 } 1065 1066 void Session_SetProcEnabled(preproc_session_t *session, uint32_t procId, bool enabled) 1067 { 1068 if (enabled) { 1069 if(session->enabledMsk == 0) { 1070 session->framesIn = 0; 1071 if (session->inResampler != NULL) { 1072 speex_resampler_reset_mem(session->inResampler); 1073 } 1074 session->framesOut = 0; 1075 if (session->outResampler != NULL) { 1076 speex_resampler_reset_mem(session->outResampler); 1077 } 1078 } 1079 session->enabledMsk |= (1 << procId); 1080 if (HasReverseStream(procId)) { 1081 session->framesRev = 0; 1082 if (session->revResampler != NULL) { 1083 speex_resampler_reset_mem(session->revResampler); 1084 } 1085 session->revEnabledMsk |= (1 << procId); 1086 } 1087 } else { 1088 session->enabledMsk &= ~(1 << procId); 1089 if (HasReverseStream(procId)) { 1090 session->revEnabledMsk &= ~(1 << procId); 1091 } 1092 } 1093 ALOGV("Session_SetProcEnabled proc %d, enabled %d enabledMsk %08x revEnabledMsk %08x", 1094 procId, enabled, session->enabledMsk, session->revEnabledMsk); 1095 session->processedMsk = 0; 1096 if (HasReverseStream(procId)) { 1097 session->revProcessedMsk = 0; 1098 } 1099 } 1100 1101 //------------------------------------------------------------------------------ 1102 // Bundle functions 1103 //------------------------------------------------------------------------------ 1104 1105 static int sInitStatus = 1; 1106 static preproc_session_t sSessions[PREPROC_NUM_SESSIONS]; 1107 1108 preproc_session_t *PreProc_GetSession(int32_t procId, int32_t sessionId, int32_t ioId) 1109 { 1110 size_t i; 1111 int free = -1; 1112 for (i = 0; i < PREPROC_NUM_SESSIONS; i++) { 1113 if (sSessions[i].io == ioId) { 1114 if (sSessions[i].createdMsk & (1 << procId)) { 1115 return NULL; 1116 } 1117 return &sSessions[i]; 1118 } 1119 } 1120 for (i = 0; i < PREPROC_NUM_SESSIONS; i++) { 1121 if (sSessions[i].io == 0) { 1122 sSessions[i].id = sessionId; 1123 sSessions[i].io = ioId; 1124 return &sSessions[i]; 1125 } 1126 } 1127 return NULL; 1128 } 1129 1130 1131 int PreProc_Init() { 1132 size_t i; 1133 int status = 0; 1134 1135 if (sInitStatus <= 0) { 1136 return sInitStatus; 1137 } 1138 for (i = 0; i < PREPROC_NUM_SESSIONS && status == 0; i++) { 1139 status = Session_Init(&sSessions[i]); 1140 } 1141 sInitStatus = status; 1142 return sInitStatus; 1143 } 1144 1145 const effect_descriptor_t *PreProc_GetDescriptor(const effect_uuid_t *uuid) 1146 { 1147 size_t i; 1148 for (i = 0; i < PREPROC_NUM_EFFECTS; i++) { 1149 if (memcmp(&sDescriptors[i]->uuid, uuid, sizeof(effect_uuid_t)) == 0) { 1150 return sDescriptors[i]; 1151 } 1152 } 1153 return NULL; 1154 } 1155 1156 1157 extern "C" { 1158 1159 //------------------------------------------------------------------------------ 1160 // Effect Control Interface Implementation 1161 //------------------------------------------------------------------------------ 1162 1163 int PreProcessingFx_Process(effect_handle_t self, 1164 audio_buffer_t *inBuffer, 1165 audio_buffer_t *outBuffer) 1166 { 1167 preproc_effect_t * effect = (preproc_effect_t *)self; 1168 int status = 0; 1169 1170 if (effect == NULL){ 1171 ALOGV("PreProcessingFx_Process() ERROR effect == NULL"); 1172 return -EINVAL; 1173 } 1174 preproc_session_t * session = (preproc_session_t *)effect->session; 1175 1176 if (inBuffer == NULL || inBuffer->raw == NULL || 1177 outBuffer == NULL || outBuffer->raw == NULL){ 1178 ALOGW("PreProcessingFx_Process() ERROR bad pointer"); 1179 return -EINVAL; 1180 } 1181 1182 session->processedMsk |= (1<<effect->procId); 1183 1184 // ALOGV("PreProcessingFx_Process In %d frames enabledMsk %08x processedMsk %08x", 1185 // inBuffer->frameCount, session->enabledMsk, session->processedMsk); 1186 1187 if ((session->processedMsk & session->enabledMsk) == session->enabledMsk) { 1188 effect->session->processedMsk = 0; 1189 size_t framesRq = outBuffer->frameCount; 1190 size_t framesWr = 0; 1191 if (session->framesOut) { 1192 size_t fr = session->framesOut; 1193 if (outBuffer->frameCount < fr) { 1194 fr = outBuffer->frameCount; 1195 } 1196 memcpy(outBuffer->s16, 1197 session->outBuf, 1198 fr * session->outChannelCount * sizeof(int16_t)); 1199 memcpy(session->outBuf, 1200 session->outBuf + fr * session->outChannelCount, 1201 (session->framesOut - fr) * session->outChannelCount * sizeof(int16_t)); 1202 session->framesOut -= fr; 1203 framesWr += fr; 1204 } 1205 outBuffer->frameCount = framesWr; 1206 if (framesWr == framesRq) { 1207 inBuffer->frameCount = 0; 1208 return 0; 1209 } 1210 1211 if (session->inResampler != NULL) { 1212 size_t fr = session->frameCount - session->framesIn; 1213 if (inBuffer->frameCount < fr) { 1214 fr = inBuffer->frameCount; 1215 } 1216 if (session->inBufSize < session->framesIn + fr) { 1217 session->inBufSize = session->framesIn + fr; 1218 session->inBuf = (int16_t *)realloc(session->inBuf, 1219 session->inBufSize * session->inChannelCount * sizeof(int16_t)); 1220 } 1221 memcpy(session->inBuf + session->framesIn * session->inChannelCount, 1222 inBuffer->s16, 1223 fr * session->inChannelCount * sizeof(int16_t)); 1224 #ifdef DUAL_MIC_TEST 1225 pthread_mutex_lock(&gPcmDumpLock); 1226 if (gPcmDumpFh != NULL) { 1227 fwrite(inBuffer->raw, 1228 fr * session->inChannelCount * sizeof(int16_t), 1, gPcmDumpFh); 1229 } 1230 pthread_mutex_unlock(&gPcmDumpLock); 1231 #endif 1232 1233 session->framesIn += fr; 1234 inBuffer->frameCount = fr; 1235 if (session->framesIn < session->frameCount) { 1236 return 0; 1237 } 1238 spx_uint32_t frIn = session->framesIn; 1239 spx_uint32_t frOut = session->apmFrameCount; 1240 if (session->inChannelCount == 1) { 1241 speex_resampler_process_int(session->inResampler, 1242 0, 1243 session->inBuf, 1244 &frIn, 1245 session->procFrame->_payloadData, 1246 &frOut); 1247 } else { 1248 speex_resampler_process_interleaved_int(session->inResampler, 1249 session->inBuf, 1250 &frIn, 1251 session->procFrame->_payloadData, 1252 &frOut); 1253 } 1254 memcpy(session->inBuf, 1255 session->inBuf + frIn * session->inChannelCount, 1256 (session->framesIn - frIn) * session->inChannelCount * sizeof(int16_t)); 1257 session->framesIn -= frIn; 1258 } else { 1259 size_t fr = session->frameCount - session->framesIn; 1260 if (inBuffer->frameCount < fr) { 1261 fr = inBuffer->frameCount; 1262 } 1263 memcpy(session->procFrame->_payloadData + session->framesIn * session->inChannelCount, 1264 inBuffer->s16, 1265 fr * session->inChannelCount * sizeof(int16_t)); 1266 1267 #ifdef DUAL_MIC_TEST 1268 pthread_mutex_lock(&gPcmDumpLock); 1269 if (gPcmDumpFh != NULL) { 1270 fwrite(inBuffer->raw, 1271 fr * session->inChannelCount * sizeof(int16_t), 1, gPcmDumpFh); 1272 } 1273 pthread_mutex_unlock(&gPcmDumpLock); 1274 #endif 1275 1276 session->framesIn += fr; 1277 inBuffer->frameCount = fr; 1278 if (session->framesIn < session->frameCount) { 1279 return 0; 1280 } 1281 session->framesIn = 0; 1282 } 1283 session->procFrame->_payloadDataLengthInSamples = 1284 session->apmFrameCount * session->inChannelCount; 1285 1286 effect->session->apm->ProcessStream(session->procFrame); 1287 1288 if (session->outBufSize < session->framesOut + session->frameCount) { 1289 session->outBufSize = session->framesOut + session->frameCount; 1290 session->outBuf = (int16_t *)realloc(session->outBuf, 1291 session->outBufSize * session->outChannelCount * sizeof(int16_t)); 1292 } 1293 1294 if (session->outResampler != NULL) { 1295 spx_uint32_t frIn = session->apmFrameCount; 1296 spx_uint32_t frOut = session->frameCount; 1297 if (session->inChannelCount == 1) { 1298 speex_resampler_process_int(session->outResampler, 1299 0, 1300 session->procFrame->_payloadData, 1301 &frIn, 1302 session->outBuf + session->framesOut * session->outChannelCount, 1303 &frOut); 1304 } else { 1305 speex_resampler_process_interleaved_int(session->outResampler, 1306 session->procFrame->_payloadData, 1307 &frIn, 1308 session->outBuf + session->framesOut * session->outChannelCount, 1309 &frOut); 1310 } 1311 session->framesOut += frOut; 1312 } else { 1313 memcpy(session->outBuf + session->framesOut * session->outChannelCount, 1314 session->procFrame->_payloadData, 1315 session->frameCount * session->outChannelCount * sizeof(int16_t)); 1316 session->framesOut += session->frameCount; 1317 } 1318 size_t fr = session->framesOut; 1319 if (framesRq - framesWr < fr) { 1320 fr = framesRq - framesWr; 1321 } 1322 memcpy(outBuffer->s16 + framesWr * session->outChannelCount, 1323 session->outBuf, 1324 fr * session->outChannelCount * sizeof(int16_t)); 1325 memcpy(session->outBuf, 1326 session->outBuf + fr * session->outChannelCount, 1327 (session->framesOut - fr) * session->outChannelCount * sizeof(int16_t)); 1328 session->framesOut -= fr; 1329 outBuffer->frameCount += fr; 1330 1331 return 0; 1332 } else { 1333 return -ENODATA; 1334 } 1335 } 1336 1337 int PreProcessingFx_Command(effect_handle_t self, 1338 uint32_t cmdCode, 1339 uint32_t cmdSize, 1340 void *pCmdData, 1341 uint32_t *replySize, 1342 void *pReplyData) 1343 { 1344 preproc_effect_t * effect = (preproc_effect_t *) self; 1345 int retsize; 1346 int status; 1347 1348 if (effect == NULL){ 1349 return -EINVAL; 1350 } 1351 1352 //ALOGV("PreProcessingFx_Command: command %d cmdSize %d",cmdCode, cmdSize); 1353 1354 switch (cmdCode){ 1355 case EFFECT_CMD_INIT: 1356 if (pReplyData == NULL || *replySize != sizeof(int)){ 1357 return -EINVAL; 1358 } 1359 if (effect->ops->init) { 1360 effect->ops->init(effect); 1361 } 1362 *(int *)pReplyData = 0; 1363 break; 1364 1365 case EFFECT_CMD_SET_CONFIG: { 1366 if (pCmdData == NULL|| 1367 cmdSize != sizeof(effect_config_t)|| 1368 pReplyData == NULL|| 1369 *replySize != sizeof(int)){ 1370 ALOGV("PreProcessingFx_Command cmdCode Case: " 1371 "EFFECT_CMD_SET_CONFIG: ERROR"); 1372 return -EINVAL; 1373 } 1374 #ifdef DUAL_MIC_TEST 1375 // make sure that the config command is accepted by making as if all effects were 1376 // disabled: this is OK for functional tests 1377 uint32_t enabledMsk = effect->session->enabledMsk; 1378 if (gDualMicEnabled) { 1379 effect->session->enabledMsk = 0; 1380 } 1381 #endif 1382 *(int *)pReplyData = Session_SetConfig(effect->session, (effect_config_t *)pCmdData); 1383 #ifdef DUAL_MIC_TEST 1384 if (gDualMicEnabled) { 1385 effect->session->enabledMsk = enabledMsk; 1386 } 1387 #endif 1388 if (*(int *)pReplyData != 0) { 1389 break; 1390 } 1391 if (effect->state != PREPROC_EFFECT_STATE_ACTIVE) { 1392 *(int *)pReplyData = Effect_SetState(effect, PREPROC_EFFECT_STATE_CONFIG); 1393 } 1394 } break; 1395 1396 case EFFECT_CMD_GET_CONFIG: 1397 if (pReplyData == NULL || 1398 *replySize != sizeof(effect_config_t)) { 1399 ALOGV("\tLVM_ERROR : PreProcessingFx_Command cmdCode Case: " 1400 "EFFECT_CMD_GET_CONFIG: ERROR"); 1401 return -EINVAL; 1402 } 1403 1404 Session_GetConfig(effect->session, (effect_config_t *)pReplyData); 1405 break; 1406 1407 case EFFECT_CMD_SET_CONFIG_REVERSE: 1408 if (pCmdData == NULL || 1409 cmdSize != sizeof(effect_config_t) || 1410 pReplyData == NULL || 1411 *replySize != sizeof(int)) { 1412 ALOGV("PreProcessingFx_Command cmdCode Case: " 1413 "EFFECT_CMD_SET_CONFIG_REVERSE: ERROR"); 1414 return -EINVAL; 1415 } 1416 *(int *)pReplyData = Session_SetReverseConfig(effect->session, 1417 (effect_config_t *)pCmdData); 1418 if (*(int *)pReplyData != 0) { 1419 break; 1420 } 1421 break; 1422 1423 case EFFECT_CMD_GET_CONFIG_REVERSE: 1424 if (pReplyData == NULL || 1425 *replySize != sizeof(effect_config_t)){ 1426 ALOGV("PreProcessingFx_Command cmdCode Case: " 1427 "EFFECT_CMD_GET_CONFIG_REVERSE: ERROR"); 1428 return -EINVAL; 1429 } 1430 Session_GetReverseConfig(effect->session, (effect_config_t *)pCmdData); 1431 break; 1432 1433 case EFFECT_CMD_RESET: 1434 if (effect->ops->reset) { 1435 effect->ops->reset(effect); 1436 } 1437 break; 1438 1439 case EFFECT_CMD_GET_PARAM: { 1440 effect_param_t *p = (effect_param_t *)pCmdData; 1441 1442 if (pCmdData == NULL || cmdSize < sizeof(effect_param_t) || 1443 cmdSize < (sizeof(effect_param_t) + p->psize) || 1444 pReplyData == NULL || replySize == NULL || 1445 *replySize < (sizeof(effect_param_t) + p->psize)){ 1446 ALOGV("PreProcessingFx_Command cmdCode Case: " 1447 "EFFECT_CMD_GET_PARAM: ERROR"); 1448 return -EINVAL; 1449 } 1450 1451 memcpy(pReplyData, pCmdData, sizeof(effect_param_t) + p->psize); 1452 1453 p = (effect_param_t *)pReplyData; 1454 1455 int voffset = ((p->psize - 1) / sizeof(int32_t) + 1) * sizeof(int32_t); 1456 1457 if (effect->ops->get_parameter) { 1458 p->status = effect->ops->get_parameter(effect, p->data, 1459 &p->vsize, 1460 p->data + voffset); 1461 *replySize = sizeof(effect_param_t) + voffset + p->vsize; 1462 } 1463 } break; 1464 1465 case EFFECT_CMD_SET_PARAM:{ 1466 if (pCmdData == NULL|| 1467 cmdSize < sizeof(effect_param_t) || 1468 pReplyData == NULL || replySize == NULL || 1469 *replySize != sizeof(int32_t)){ 1470 ALOGV("PreProcessingFx_Command cmdCode Case: " 1471 "EFFECT_CMD_SET_PARAM: ERROR"); 1472 return -EINVAL; 1473 } 1474 effect_param_t *p = (effect_param_t *) pCmdData; 1475 1476 if (p->psize != sizeof(int32_t)){ 1477 ALOGV("PreProcessingFx_Command cmdCode Case: " 1478 "EFFECT_CMD_SET_PARAM: ERROR, psize is not sizeof(int32_t)"); 1479 return -EINVAL; 1480 } 1481 if (effect->ops->set_parameter) { 1482 *(int *)pReplyData = effect->ops->set_parameter(effect, 1483 (void *)p->data, 1484 p->data + p->psize); 1485 } 1486 } break; 1487 1488 case EFFECT_CMD_ENABLE: 1489 if (pReplyData == NULL || replySize == NULL || *replySize != sizeof(int)){ 1490 ALOGV("PreProcessingFx_Command cmdCode Case: EFFECT_CMD_ENABLE: ERROR"); 1491 return -EINVAL; 1492 } 1493 *(int *)pReplyData = Effect_SetState(effect, PREPROC_EFFECT_STATE_ACTIVE); 1494 break; 1495 1496 case EFFECT_CMD_DISABLE: 1497 if (pReplyData == NULL || replySize == NULL || *replySize != sizeof(int)){ 1498 ALOGV("PreProcessingFx_Command cmdCode Case: EFFECT_CMD_DISABLE: ERROR"); 1499 return -EINVAL; 1500 } 1501 *(int *)pReplyData = Effect_SetState(effect, PREPROC_EFFECT_STATE_CONFIG); 1502 break; 1503 1504 case EFFECT_CMD_SET_DEVICE: 1505 case EFFECT_CMD_SET_INPUT_DEVICE: 1506 if (pCmdData == NULL || 1507 cmdSize != sizeof(uint32_t)) { 1508 ALOGV("PreProcessingFx_Command cmdCode Case: EFFECT_CMD_SET_DEVICE: ERROR"); 1509 return -EINVAL; 1510 } 1511 1512 if (effect->ops->set_device) { 1513 effect->ops->set_device(effect, *(uint32_t *)pCmdData); 1514 } 1515 break; 1516 1517 case EFFECT_CMD_SET_VOLUME: 1518 case EFFECT_CMD_SET_AUDIO_MODE: 1519 break; 1520 1521 #ifdef DUAL_MIC_TEST 1522 ///// test commands start 1523 case PREPROC_CMD_DUAL_MIC_ENABLE: { 1524 if (pCmdData == NULL|| cmdSize != sizeof(uint32_t) || 1525 pReplyData == NULL || replySize == NULL) { 1526 ALOGE("PreProcessingFx_Command cmdCode Case: " 1527 "PREPROC_CMD_DUAL_MIC_ENABLE: ERROR"); 1528 *replySize = 0; 1529 return -EINVAL; 1530 } 1531 gDualMicEnabled = *(bool *)pCmdData; 1532 if (gDualMicEnabled) { 1533 effect->aux_channels_on = sHasAuxChannels[effect->procId]; 1534 } else { 1535 effect->aux_channels_on = false; 1536 } 1537 effect->cur_channel_config = (effect->session->inChannelCount == 1) ? 1538 CHANNEL_CFG_MONO : CHANNEL_CFG_STEREO; 1539 1540 ALOGV("PREPROC_CMD_DUAL_MIC_ENABLE: %s", gDualMicEnabled ? "enabled" : "disabled"); 1541 *replySize = sizeof(int); 1542 *(int *)pReplyData = 0; 1543 } break; 1544 case PREPROC_CMD_DUAL_MIC_PCM_DUMP_START: { 1545 if (pCmdData == NULL|| pReplyData == NULL || replySize == NULL) { 1546 ALOGE("PreProcessingFx_Command cmdCode Case: " 1547 "PREPROC_CMD_DUAL_MIC_PCM_DUMP_START: ERROR"); 1548 *replySize = 0; 1549 return -EINVAL; 1550 } 1551 pthread_mutex_lock(&gPcmDumpLock); 1552 if (gPcmDumpFh != NULL) { 1553 fclose(gPcmDumpFh); 1554 gPcmDumpFh = NULL; 1555 } 1556 char *path = strndup((char *)pCmdData, cmdSize); 1557 gPcmDumpFh = fopen((char *)path, "wb"); 1558 pthread_mutex_unlock(&gPcmDumpLock); 1559 ALOGV("PREPROC_CMD_DUAL_MIC_PCM_DUMP_START: path %s gPcmDumpFh %p", 1560 path, gPcmDumpFh); 1561 ALOGE_IF(gPcmDumpFh <= 0, "gPcmDumpFh open error %d %s", errno, strerror(errno)); 1562 free(path); 1563 *replySize = sizeof(int); 1564 *(int *)pReplyData = 0; 1565 } break; 1566 case PREPROC_CMD_DUAL_MIC_PCM_DUMP_STOP: { 1567 if (pReplyData == NULL || replySize == NULL) { 1568 ALOGE("PreProcessingFx_Command cmdCode Case: " 1569 "PREPROC_CMD_DUAL_MIC_PCM_DUMP_STOP: ERROR"); 1570 *replySize = 0; 1571 return -EINVAL; 1572 } 1573 pthread_mutex_lock(&gPcmDumpLock); 1574 if (gPcmDumpFh != NULL) { 1575 fclose(gPcmDumpFh); 1576 gPcmDumpFh = NULL; 1577 } 1578 pthread_mutex_unlock(&gPcmDumpLock); 1579 ALOGV("PREPROC_CMD_DUAL_MIC_PCM_DUMP_STOP"); 1580 *replySize = sizeof(int); 1581 *(int *)pReplyData = 0; 1582 } break; 1583 ///// test commands end 1584 1585 case EFFECT_CMD_GET_FEATURE_SUPPORTED_CONFIGS: { 1586 if(!gDualMicEnabled) { 1587 return -EINVAL; 1588 } 1589 if (pCmdData == NULL|| cmdSize != 2 * sizeof(uint32_t) || 1590 pReplyData == NULL || replySize == NULL) { 1591 ALOGE("PreProcessingFx_Command cmdCode Case: " 1592 "EFFECT_CMD_GET_FEATURE_SUPPORTED_CONFIGS: ERROR"); 1593 *replySize = 0; 1594 return -EINVAL; 1595 } 1596 if (*(uint32_t *)pCmdData != EFFECT_FEATURE_AUX_CHANNELS || 1597 !effect->aux_channels_on) { 1598 ALOGV("PreProcessingFx_Command feature EFFECT_FEATURE_AUX_CHANNELS not supported by" 1599 " fx %d", effect->procId); 1600 *(uint32_t *)pReplyData = -ENOSYS; 1601 *replySize = sizeof(uint32_t); 1602 break; 1603 } 1604 size_t num_configs = *((uint32_t *)pCmdData + 1); 1605 if (*replySize < (2 * sizeof(uint32_t) + 1606 num_configs * sizeof(channel_config_t))) { 1607 *replySize = 0; 1608 return -EINVAL; 1609 } 1610 1611 *((uint32_t *)pReplyData + 1) = CHANNEL_CFG_CNT; 1612 if (num_configs < CHANNEL_CFG_CNT || 1613 *replySize < (2 * sizeof(uint32_t) + 1614 CHANNEL_CFG_CNT * sizeof(channel_config_t))) { 1615 *(uint32_t *)pReplyData = -ENOMEM; 1616 } else { 1617 num_configs = CHANNEL_CFG_CNT; 1618 *(uint32_t *)pReplyData = 0; 1619 } 1620 ALOGV("PreProcessingFx_Command EFFECT_CMD_GET_FEATURE_SUPPORTED_CONFIGS num config %d", 1621 num_configs); 1622 1623 *replySize = 2 * sizeof(uint32_t) + num_configs * sizeof(channel_config_t); 1624 *((uint32_t *)pReplyData + 1) = num_configs; 1625 memcpy((uint32_t *)pReplyData + 2, &sDualMicConfigs, num_configs * sizeof(channel_config_t)); 1626 } break; 1627 case EFFECT_CMD_GET_FEATURE_CONFIG: 1628 if(!gDualMicEnabled) { 1629 return -EINVAL; 1630 } 1631 if (pCmdData == NULL|| cmdSize != sizeof(uint32_t) || 1632 pReplyData == NULL || replySize == NULL || 1633 *replySize < sizeof(uint32_t) + sizeof(channel_config_t)) { 1634 ALOGE("PreProcessingFx_Command cmdCode Case: " 1635 "EFFECT_CMD_GET_FEATURE_CONFIG: ERROR"); 1636 return -EINVAL; 1637 } 1638 if (*(uint32_t *)pCmdData != EFFECT_FEATURE_AUX_CHANNELS || !effect->aux_channels_on) { 1639 *(uint32_t *)pReplyData = -ENOSYS; 1640 *replySize = sizeof(uint32_t); 1641 break; 1642 } 1643 ALOGV("PreProcessingFx_Command EFFECT_CMD_GET_FEATURE_CONFIG"); 1644 *(uint32_t *)pReplyData = 0; 1645 *replySize = sizeof(uint32_t) + sizeof(channel_config_t); 1646 memcpy((uint32_t *)pReplyData + 1, 1647 &sDualMicConfigs[effect->cur_channel_config], 1648 sizeof(channel_config_t)); 1649 break; 1650 case EFFECT_CMD_SET_FEATURE_CONFIG: { 1651 ALOGV("PreProcessingFx_Command EFFECT_CMD_SET_FEATURE_CONFIG: " 1652 "gDualMicEnabled %d effect->aux_channels_on %d", 1653 gDualMicEnabled, effect->aux_channels_on); 1654 if(!gDualMicEnabled) { 1655 return -EINVAL; 1656 } 1657 if (pCmdData == NULL|| cmdSize != (sizeof(uint32_t) + sizeof(channel_config_t)) || 1658 pReplyData == NULL || replySize == NULL || 1659 *replySize < sizeof(uint32_t)) { 1660 ALOGE("PreProcessingFx_Command cmdCode Case: " 1661 "EFFECT_CMD_SET_FEATURE_CONFIG: ERROR\n" 1662 "pCmdData %p cmdSize %d pReplyData %p replySize %p *replySize %d", 1663 pCmdData, cmdSize, pReplyData, replySize, replySize ? *replySize : -1); 1664 return -EINVAL; 1665 } 1666 *replySize = sizeof(uint32_t); 1667 if (*(uint32_t *)pCmdData != EFFECT_FEATURE_AUX_CHANNELS || !effect->aux_channels_on) { 1668 *(uint32_t *)pReplyData = -ENOSYS; 1669 ALOGV("PreProcessingFx_Command cmdCode Case: " 1670 "EFFECT_CMD_SET_FEATURE_CONFIG: ERROR\n" 1671 "CmdData %d effect->aux_channels_on %d", 1672 *(uint32_t *)pCmdData, effect->aux_channels_on); 1673 break; 1674 } 1675 size_t i; 1676 for (i = 0; i < CHANNEL_CFG_CNT;i++) { 1677 if (memcmp((uint32_t *)pCmdData + 1, 1678 &sDualMicConfigs[i], sizeof(channel_config_t)) == 0) { 1679 break; 1680 } 1681 } 1682 if (i == CHANNEL_CFG_CNT) { 1683 *(uint32_t *)pReplyData = -EINVAL; 1684 ALOGW("PreProcessingFx_Command EFFECT_CMD_SET_FEATURE_CONFIG invalid config" 1685 "[%08x].[%08x]", *((uint32_t *)pCmdData + 1), *((uint32_t *)pCmdData + 2)); 1686 } else { 1687 effect->cur_channel_config = i; 1688 *(uint32_t *)pReplyData = 0; 1689 ALOGV("PreProcessingFx_Command EFFECT_CMD_SET_FEATURE_CONFIG New config" 1690 "[%08x].[%08x]", sDualMicConfigs[i].main_channels, sDualMicConfigs[i].aux_channels); 1691 } 1692 } break; 1693 #endif 1694 default: 1695 return -EINVAL; 1696 } 1697 return 0; 1698 } 1699 1700 1701 int PreProcessingFx_GetDescriptor(effect_handle_t self, 1702 effect_descriptor_t *pDescriptor) 1703 { 1704 preproc_effect_t * effect = (preproc_effect_t *) self; 1705 1706 if (effect == NULL || pDescriptor == NULL) { 1707 return -EINVAL; 1708 } 1709 1710 *pDescriptor = *sDescriptors[effect->procId]; 1711 1712 return 0; 1713 } 1714 1715 int PreProcessingFx_ProcessReverse(effect_handle_t self, 1716 audio_buffer_t *inBuffer, 1717 audio_buffer_t *outBuffer __unused) 1718 { 1719 preproc_effect_t * effect = (preproc_effect_t *)self; 1720 int status = 0; 1721 1722 if (effect == NULL){ 1723 ALOGW("PreProcessingFx_ProcessReverse() ERROR effect == NULL"); 1724 return -EINVAL; 1725 } 1726 preproc_session_t * session = (preproc_session_t *)effect->session; 1727 1728 if (inBuffer == NULL || inBuffer->raw == NULL){ 1729 ALOGW("PreProcessingFx_ProcessReverse() ERROR bad pointer"); 1730 return -EINVAL; 1731 } 1732 1733 session->revProcessedMsk |= (1<<effect->procId); 1734 1735 // ALOGV("PreProcessingFx_ProcessReverse In %d frames revEnabledMsk %08x revProcessedMsk %08x", 1736 // inBuffer->frameCount, session->revEnabledMsk, session->revProcessedMsk); 1737 1738 1739 if ((session->revProcessedMsk & session->revEnabledMsk) == session->revEnabledMsk) { 1740 effect->session->revProcessedMsk = 0; 1741 if (session->revResampler != NULL) { 1742 size_t fr = session->frameCount - session->framesRev; 1743 if (inBuffer->frameCount < fr) { 1744 fr = inBuffer->frameCount; 1745 } 1746 if (session->revBufSize < session->framesRev + fr) { 1747 session->revBufSize = session->framesRev + fr; 1748 session->revBuf = (int16_t *)realloc(session->revBuf, 1749 session->revBufSize * session->inChannelCount * sizeof(int16_t)); 1750 } 1751 memcpy(session->revBuf + session->framesRev * session->inChannelCount, 1752 inBuffer->s16, 1753 fr * session->inChannelCount * sizeof(int16_t)); 1754 1755 session->framesRev += fr; 1756 inBuffer->frameCount = fr; 1757 if (session->framesRev < session->frameCount) { 1758 return 0; 1759 } 1760 spx_uint32_t frIn = session->framesRev; 1761 spx_uint32_t frOut = session->apmFrameCount; 1762 if (session->inChannelCount == 1) { 1763 speex_resampler_process_int(session->revResampler, 1764 0, 1765 session->revBuf, 1766 &frIn, 1767 session->revFrame->_payloadData, 1768 &frOut); 1769 } else { 1770 speex_resampler_process_interleaved_int(session->revResampler, 1771 session->revBuf, 1772 &frIn, 1773 session->revFrame->_payloadData, 1774 &frOut); 1775 } 1776 memcpy(session->revBuf, 1777 session->revBuf + frIn * session->inChannelCount, 1778 (session->framesRev - frIn) * session->inChannelCount * sizeof(int16_t)); 1779 session->framesRev -= frIn; 1780 } else { 1781 size_t fr = session->frameCount - session->framesRev; 1782 if (inBuffer->frameCount < fr) { 1783 fr = inBuffer->frameCount; 1784 } 1785 memcpy(session->revFrame->_payloadData + session->framesRev * session->inChannelCount, 1786 inBuffer->s16, 1787 fr * session->inChannelCount * sizeof(int16_t)); 1788 session->framesRev += fr; 1789 inBuffer->frameCount = fr; 1790 if (session->framesRev < session->frameCount) { 1791 return 0; 1792 } 1793 session->framesRev = 0; 1794 } 1795 session->revFrame->_payloadDataLengthInSamples = 1796 session->apmFrameCount * session->inChannelCount; 1797 effect->session->apm->AnalyzeReverseStream(session->revFrame); 1798 return 0; 1799 } else { 1800 return -ENODATA; 1801 } 1802 } 1803 1804 1805 // effect_handle_t interface implementation for effect 1806 const struct effect_interface_s sEffectInterface = { 1807 PreProcessingFx_Process, 1808 PreProcessingFx_Command, 1809 PreProcessingFx_GetDescriptor, 1810 NULL 1811 }; 1812 1813 const struct effect_interface_s sEffectInterfaceReverse = { 1814 PreProcessingFx_Process, 1815 PreProcessingFx_Command, 1816 PreProcessingFx_GetDescriptor, 1817 PreProcessingFx_ProcessReverse 1818 }; 1819 1820 //------------------------------------------------------------------------------ 1821 // Effect Library Interface Implementation 1822 //------------------------------------------------------------------------------ 1823 1824 int PreProcessingLib_Create(const effect_uuid_t *uuid, 1825 int32_t sessionId, 1826 int32_t ioId, 1827 effect_handle_t *pInterface) 1828 { 1829 ALOGV("EffectCreate: uuid: %08x session %d IO: %d", uuid->timeLow, sessionId, ioId); 1830 1831 int status; 1832 const effect_descriptor_t *desc; 1833 preproc_session_t *session; 1834 uint32_t procId; 1835 1836 if (PreProc_Init() != 0) { 1837 return sInitStatus; 1838 } 1839 desc = PreProc_GetDescriptor(uuid); 1840 if (desc == NULL) { 1841 ALOGW("EffectCreate: fx not found uuid: %08x", uuid->timeLow); 1842 return -EINVAL; 1843 } 1844 procId = UuidToProcId(&desc->type); 1845 1846 session = PreProc_GetSession(procId, sessionId, ioId); 1847 if (session == NULL) { 1848 ALOGW("EffectCreate: no more session available"); 1849 return -EINVAL; 1850 } 1851 1852 status = Session_CreateEffect(session, procId, pInterface); 1853 1854 if (status < 0 && session->createdMsk == 0) { 1855 session->io = 0; 1856 } 1857 return status; 1858 } 1859 1860 int PreProcessingLib_Release(effect_handle_t interface) 1861 { 1862 int status; 1863 ALOGV("EffectRelease start %p", interface); 1864 if (PreProc_Init() != 0) { 1865 return sInitStatus; 1866 } 1867 1868 preproc_effect_t *fx = (preproc_effect_t *)interface; 1869 1870 if (fx->session->io == 0) { 1871 return -EINVAL; 1872 } 1873 return Session_ReleaseEffect(fx->session, fx); 1874 } 1875 1876 int PreProcessingLib_GetDescriptor(const effect_uuid_t *uuid, 1877 effect_descriptor_t *pDescriptor) { 1878 1879 if (pDescriptor == NULL || uuid == NULL){ 1880 return -EINVAL; 1881 } 1882 1883 const effect_descriptor_t *desc = PreProc_GetDescriptor(uuid); 1884 if (desc == NULL) { 1885 ALOGV("PreProcessingLib_GetDescriptor() not found"); 1886 return -EINVAL; 1887 } 1888 1889 ALOGV("PreProcessingLib_GetDescriptor() got fx %s", desc->name); 1890 1891 *pDescriptor = *desc; 1892 return 0; 1893 } 1894 1895 // This is the only symbol that needs to be exported 1896 __attribute__ ((visibility ("default"))) 1897 audio_effect_library_t AUDIO_EFFECT_LIBRARY_INFO_SYM = { 1898 .tag = AUDIO_EFFECT_LIBRARY_TAG, 1899 .version = EFFECT_LIBRARY_API_VERSION, 1900 .name = "Audio Preprocessing Library", 1901 .implementor = "The Android Open Source Project", 1902 .create_effect = PreProcessingLib_Create, 1903 .release_effect = PreProcessingLib_Release, 1904 .get_descriptor = PreProcessingLib_GetDescriptor 1905 }; 1906 1907 }; // extern "C" 1908