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, size_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 size_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 size_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, 579 void *pParam, 580 size_t *pValueSize, 581 void *pValue) 582 { 583 int status = 0; 584 return status; 585 } 586 587 int NsSetParameter (preproc_effect_t *effect, void *pParam, void *pValue) 588 { 589 int status = 0; 590 return status; 591 } 592 593 void NsEnable(preproc_effect_t *effect) 594 { 595 webrtc::NoiseSuppression *ns = static_cast<webrtc::NoiseSuppression *>(effect->engine); 596 ALOGV("NsEnable ns %p", ns); 597 ns->Enable(true); 598 } 599 600 void NsDisable(preproc_effect_t *effect) 601 { 602 ALOGV("NsDisable"); 603 webrtc::NoiseSuppression *ns = static_cast<webrtc::NoiseSuppression *>(effect->engine); 604 ns->Enable(false); 605 } 606 607 static const preproc_ops_t sNsOps = { 608 NsCreate, 609 NsInit, 610 NULL, 611 NsEnable, 612 NsDisable, 613 NsSetParameter, 614 NsGetParameter, 615 NULL 616 }; 617 618 619 static const preproc_ops_t *sPreProcOps[PREPROC_NUM_EFFECTS] = { 620 &sAgcOps, 621 &sAecOps, 622 &sNsOps 623 }; 624 625 626 //------------------------------------------------------------------------------ 627 // Effect functions 628 //------------------------------------------------------------------------------ 629 630 void Session_SetProcEnabled(preproc_session_t *session, uint32_t procId, bool enabled); 631 632 extern "C" const struct effect_interface_s sEffectInterface; 633 extern "C" const struct effect_interface_s sEffectInterfaceReverse; 634 635 #define BAD_STATE_ABORT(from, to) \ 636 LOG_ALWAYS_FATAL("Bad state transition from %d to %d", from, to); 637 638 int Effect_SetState(preproc_effect_t *effect, uint32_t state) 639 { 640 int status = 0; 641 ALOGV("Effect_SetState proc %d, new %d old %d", effect->procId, state, effect->state); 642 switch(state) { 643 case PREPROC_EFFECT_STATE_INIT: 644 switch(effect->state) { 645 case PREPROC_EFFECT_STATE_ACTIVE: 646 effect->ops->disable(effect); 647 Session_SetProcEnabled(effect->session, effect->procId, false); 648 case PREPROC_EFFECT_STATE_CONFIG: 649 case PREPROC_EFFECT_STATE_CREATED: 650 case PREPROC_EFFECT_STATE_INIT: 651 break; 652 default: 653 BAD_STATE_ABORT(effect->state, state); 654 } 655 break; 656 case PREPROC_EFFECT_STATE_CREATED: 657 switch(effect->state) { 658 case PREPROC_EFFECT_STATE_INIT: 659 status = effect->ops->create(effect); 660 break; 661 case PREPROC_EFFECT_STATE_CREATED: 662 case PREPROC_EFFECT_STATE_ACTIVE: 663 case PREPROC_EFFECT_STATE_CONFIG: 664 ALOGE("Effect_SetState invalid transition"); 665 status = -ENOSYS; 666 break; 667 default: 668 BAD_STATE_ABORT(effect->state, state); 669 } 670 break; 671 case PREPROC_EFFECT_STATE_CONFIG: 672 switch(effect->state) { 673 case PREPROC_EFFECT_STATE_INIT: 674 ALOGE("Effect_SetState invalid transition"); 675 status = -ENOSYS; 676 break; 677 case PREPROC_EFFECT_STATE_ACTIVE: 678 effect->ops->disable(effect); 679 Session_SetProcEnabled(effect->session, effect->procId, false); 680 break; 681 case PREPROC_EFFECT_STATE_CREATED: 682 case PREPROC_EFFECT_STATE_CONFIG: 683 break; 684 default: 685 BAD_STATE_ABORT(effect->state, state); 686 } 687 break; 688 case PREPROC_EFFECT_STATE_ACTIVE: 689 switch(effect->state) { 690 case PREPROC_EFFECT_STATE_INIT: 691 case PREPROC_EFFECT_STATE_CREATED: 692 ALOGE("Effect_SetState invalid transition"); 693 status = -ENOSYS; 694 break; 695 case PREPROC_EFFECT_STATE_ACTIVE: 696 // enabling an already enabled effect is just ignored 697 break; 698 case PREPROC_EFFECT_STATE_CONFIG: 699 effect->ops->enable(effect); 700 Session_SetProcEnabled(effect->session, effect->procId, true); 701 break; 702 default: 703 BAD_STATE_ABORT(effect->state, state); 704 } 705 break; 706 default: 707 BAD_STATE_ABORT(effect->state, state); 708 } 709 if (status == 0) { 710 effect->state = state; 711 } 712 return status; 713 } 714 715 int Effect_Init(preproc_effect_t *effect, uint32_t procId) 716 { 717 if (HasReverseStream(procId)) { 718 effect->itfe = &sEffectInterfaceReverse; 719 } else { 720 effect->itfe = &sEffectInterface; 721 } 722 effect->ops = sPreProcOps[procId]; 723 effect->procId = procId; 724 effect->state = PREPROC_EFFECT_STATE_INIT; 725 return 0; 726 } 727 728 int Effect_Create(preproc_effect_t *effect, 729 preproc_session_t *session, 730 effect_handle_t *interface) 731 { 732 effect->session = session; 733 *interface = (effect_handle_t)&effect->itfe; 734 return Effect_SetState(effect, PREPROC_EFFECT_STATE_CREATED); 735 } 736 737 int Effect_Release(preproc_effect_t *effect) 738 { 739 return Effect_SetState(effect, PREPROC_EFFECT_STATE_INIT); 740 } 741 742 743 //------------------------------------------------------------------------------ 744 // Session functions 745 //------------------------------------------------------------------------------ 746 747 #define RESAMPLER_QUALITY SPEEX_RESAMPLER_QUALITY_VOIP 748 749 static const int kPreprocDefaultSr = 16000; 750 static const int kPreProcDefaultCnl = 1; 751 752 int Session_Init(preproc_session_t *session) 753 { 754 size_t i; 755 int status = 0; 756 757 session->state = PREPROC_SESSION_STATE_INIT; 758 session->id = 0; 759 session->io = 0; 760 session->createdMsk = 0; 761 session->apm = NULL; 762 for (i = 0; i < PREPROC_NUM_EFFECTS && status == 0; i++) { 763 status = Effect_Init(&session->effects[i], i); 764 } 765 return status; 766 } 767 768 769 extern "C" int Session_CreateEffect(preproc_session_t *session, 770 int32_t procId, 771 effect_handle_t *interface) 772 { 773 int status = -ENOMEM; 774 775 ALOGV("Session_CreateEffect procId %d, createdMsk %08x", procId, session->createdMsk); 776 777 if (session->createdMsk == 0) { 778 session->apm = webrtc::AudioProcessing::Create(session->io); 779 if (session->apm == NULL) { 780 ALOGW("Session_CreateEffect could not get apm engine"); 781 goto error; 782 } 783 session->apm->set_sample_rate_hz(kPreprocDefaultSr); 784 session->apm->set_num_channels(kPreProcDefaultCnl, kPreProcDefaultCnl); 785 session->apm->set_num_reverse_channels(kPreProcDefaultCnl); 786 session->procFrame = new webrtc::AudioFrame(); 787 if (session->procFrame == NULL) { 788 ALOGW("Session_CreateEffect could not allocate audio frame"); 789 goto error; 790 } 791 session->revFrame = new webrtc::AudioFrame(); 792 if (session->revFrame == NULL) { 793 ALOGW("Session_CreateEffect could not allocate reverse audio frame"); 794 goto error; 795 } 796 session->apmSamplingRate = kPreprocDefaultSr; 797 session->apmFrameCount = (kPreprocDefaultSr) / 100; 798 session->frameCount = session->apmFrameCount; 799 session->samplingRate = kPreprocDefaultSr; 800 session->inChannelCount = kPreProcDefaultCnl; 801 session->outChannelCount = kPreProcDefaultCnl; 802 session->procFrame->_frequencyInHz = kPreprocDefaultSr; 803 session->procFrame->_audioChannel = kPreProcDefaultCnl; 804 session->revChannelCount = kPreProcDefaultCnl; 805 session->revFrame->_frequencyInHz = kPreprocDefaultSr; 806 session->revFrame->_audioChannel = kPreProcDefaultCnl; 807 session->enabledMsk = 0; 808 session->processedMsk = 0; 809 session->revEnabledMsk = 0; 810 session->revProcessedMsk = 0; 811 session->inResampler = NULL; 812 session->inBuf = NULL; 813 session->inBufSize = 0; 814 session->outResampler = NULL; 815 session->outBuf = NULL; 816 session->outBufSize = 0; 817 session->revResampler = NULL; 818 session->revBuf = NULL; 819 session->revBufSize = 0; 820 } 821 status = Effect_Create(&session->effects[procId], session, interface); 822 if (status < 0) { 823 goto error; 824 } 825 ALOGV("Session_CreateEffect OK"); 826 session->createdMsk |= (1<<procId); 827 return status; 828 829 error: 830 if (session->createdMsk == 0) { 831 delete session->revFrame; 832 session->revFrame = NULL; 833 delete session->procFrame; 834 session->procFrame = NULL; 835 webrtc::AudioProcessing::Destroy(session->apm); 836 session->apm = NULL; 837 } 838 return status; 839 } 840 841 int Session_ReleaseEffect(preproc_session_t *session, 842 preproc_effect_t *fx) 843 { 844 ALOGW_IF(Effect_Release(fx) != 0, " Effect_Release() failed for proc ID %d", fx->procId); 845 session->createdMsk &= ~(1<<fx->procId); 846 if (session->createdMsk == 0) { 847 webrtc::AudioProcessing::Destroy(session->apm); 848 session->apm = NULL; 849 delete session->procFrame; 850 session->procFrame = NULL; 851 delete session->revFrame; 852 session->revFrame = NULL; 853 if (session->inResampler != NULL) { 854 speex_resampler_destroy(session->inResampler); 855 session->inResampler = NULL; 856 } 857 if (session->outResampler != NULL) { 858 speex_resampler_destroy(session->outResampler); 859 session->outResampler = NULL; 860 } 861 if (session->revResampler != NULL) { 862 speex_resampler_destroy(session->revResampler); 863 session->revResampler = NULL; 864 } 865 delete session->inBuf; 866 session->inBuf = NULL; 867 delete session->outBuf; 868 session->outBuf = NULL; 869 delete session->revBuf; 870 session->revBuf = NULL; 871 872 session->io = 0; 873 } 874 875 return 0; 876 } 877 878 879 int Session_SetConfig(preproc_session_t *session, effect_config_t *config) 880 { 881 uint32_t sr; 882 uint32_t inCnl = popcount(config->inputCfg.channels); 883 uint32_t outCnl = popcount(config->outputCfg.channels); 884 885 if (config->inputCfg.samplingRate != config->outputCfg.samplingRate || 886 config->inputCfg.format != config->outputCfg.format || 887 config->inputCfg.format != AUDIO_FORMAT_PCM_16_BIT) { 888 return -EINVAL; 889 } 890 891 ALOGV("Session_SetConfig sr %d cnl %08x", 892 config->inputCfg.samplingRate, config->inputCfg.channels); 893 int status; 894 895 // if at least one process is enabled, do not accept configuration changes 896 if (session->enabledMsk) { 897 if (session->samplingRate != config->inputCfg.samplingRate || 898 session->inChannelCount != inCnl || 899 session->outChannelCount != outCnl) { 900 return -ENOSYS; 901 } else { 902 return 0; 903 } 904 } 905 906 // AEC implementation is limited to 16kHz 907 if (config->inputCfg.samplingRate >= 32000 && !(session->createdMsk & (1 << PREPROC_AEC))) { 908 session->apmSamplingRate = 32000; 909 } else 910 if (config->inputCfg.samplingRate >= 16000) { 911 session->apmSamplingRate = 16000; 912 } else if (config->inputCfg.samplingRate >= 8000) { 913 session->apmSamplingRate = 8000; 914 } 915 status = session->apm->set_sample_rate_hz(session->apmSamplingRate); 916 if (status < 0) { 917 return -EINVAL; 918 } 919 status = session->apm->set_num_channels(inCnl, outCnl); 920 if (status < 0) { 921 return -EINVAL; 922 } 923 status = session->apm->set_num_reverse_channels(inCnl); 924 if (status < 0) { 925 return -EINVAL; 926 } 927 928 session->samplingRate = config->inputCfg.samplingRate; 929 session->apmFrameCount = session->apmSamplingRate / 100; 930 if (session->samplingRate == session->apmSamplingRate) { 931 session->frameCount = session->apmFrameCount; 932 } else { 933 session->frameCount = (session->apmFrameCount * session->samplingRate) / 934 session->apmSamplingRate + 1; 935 } 936 session->inChannelCount = inCnl; 937 session->outChannelCount = outCnl; 938 session->procFrame->_audioChannel = inCnl; 939 session->procFrame->_frequencyInHz = session->apmSamplingRate; 940 941 session->revChannelCount = inCnl; 942 session->revFrame->_audioChannel = inCnl; 943 session->revFrame->_frequencyInHz = session->apmSamplingRate; 944 945 // force process buffer reallocation 946 session->inBufSize = 0; 947 session->outBufSize = 0; 948 session->framesIn = 0; 949 session->framesOut = 0; 950 951 952 if (session->inResampler != NULL) { 953 speex_resampler_destroy(session->inResampler); 954 session->inResampler = NULL; 955 } 956 if (session->outResampler != NULL) { 957 speex_resampler_destroy(session->outResampler); 958 session->outResampler = NULL; 959 } 960 if (session->revResampler != NULL) { 961 speex_resampler_destroy(session->revResampler); 962 session->revResampler = NULL; 963 } 964 if (session->samplingRate != session->apmSamplingRate) { 965 int error; 966 session->inResampler = speex_resampler_init(session->inChannelCount, 967 session->samplingRate, 968 session->apmSamplingRate, 969 RESAMPLER_QUALITY, 970 &error); 971 if (session->inResampler == NULL) { 972 ALOGW("Session_SetConfig Cannot create speex resampler: %s", 973 speex_resampler_strerror(error)); 974 return -EINVAL; 975 } 976 session->outResampler = speex_resampler_init(session->outChannelCount, 977 session->apmSamplingRate, 978 session->samplingRate, 979 RESAMPLER_QUALITY, 980 &error); 981 if (session->outResampler == NULL) { 982 ALOGW("Session_SetConfig Cannot create speex resampler: %s", 983 speex_resampler_strerror(error)); 984 speex_resampler_destroy(session->inResampler); 985 session->inResampler = NULL; 986 return -EINVAL; 987 } 988 session->revResampler = speex_resampler_init(session->inChannelCount, 989 session->samplingRate, 990 session->apmSamplingRate, 991 RESAMPLER_QUALITY, 992 &error); 993 if (session->revResampler == NULL) { 994 ALOGW("Session_SetConfig Cannot create speex resampler: %s", 995 speex_resampler_strerror(error)); 996 speex_resampler_destroy(session->inResampler); 997 session->inResampler = NULL; 998 speex_resampler_destroy(session->outResampler); 999 session->outResampler = NULL; 1000 return -EINVAL; 1001 } 1002 } 1003 1004 session->state = PREPROC_SESSION_STATE_CONFIG; 1005 return 0; 1006 } 1007 1008 void Session_GetConfig(preproc_session_t *session, effect_config_t *config) 1009 { 1010 memset(config, 0, sizeof(effect_config_t)); 1011 config->inputCfg.samplingRate = config->outputCfg.samplingRate = session->samplingRate; 1012 config->inputCfg.format = config->outputCfg.format = AUDIO_FORMAT_PCM_16_BIT; 1013 config->inputCfg.channels = audio_channel_in_mask_from_count(session->inChannelCount); 1014 // "out" doesn't mean output device, so this is the correct API to convert channel count to mask 1015 config->outputCfg.channels = audio_channel_in_mask_from_count(session->outChannelCount); 1016 config->inputCfg.mask = config->outputCfg.mask = 1017 (EFFECT_CONFIG_SMP_RATE | EFFECT_CONFIG_CHANNELS | EFFECT_CONFIG_FORMAT); 1018 } 1019 1020 int Session_SetReverseConfig(preproc_session_t *session, effect_config_t *config) 1021 { 1022 if (config->inputCfg.samplingRate != config->outputCfg.samplingRate || 1023 config->inputCfg.format != config->outputCfg.format || 1024 config->inputCfg.format != AUDIO_FORMAT_PCM_16_BIT) { 1025 return -EINVAL; 1026 } 1027 1028 ALOGV("Session_SetReverseConfig sr %d cnl %08x", 1029 config->inputCfg.samplingRate, config->inputCfg.channels); 1030 1031 if (session->state < PREPROC_SESSION_STATE_CONFIG) { 1032 return -ENOSYS; 1033 } 1034 if (config->inputCfg.samplingRate != session->samplingRate || 1035 config->inputCfg.format != AUDIO_FORMAT_PCM_16_BIT) { 1036 return -EINVAL; 1037 } 1038 uint32_t inCnl = popcount(config->inputCfg.channels); 1039 int status = session->apm->set_num_reverse_channels(inCnl); 1040 if (status < 0) { 1041 return -EINVAL; 1042 } 1043 session->revChannelCount = inCnl; 1044 session->revFrame->_audioChannel = inCnl; 1045 session->revFrame->_frequencyInHz = session->apmSamplingRate; 1046 // force process buffer reallocation 1047 session->revBufSize = 0; 1048 session->framesRev = 0; 1049 1050 return 0; 1051 } 1052 1053 void Session_GetReverseConfig(preproc_session_t *session, effect_config_t *config) 1054 { 1055 memset(config, 0, sizeof(effect_config_t)); 1056 config->inputCfg.samplingRate = config->outputCfg.samplingRate = session->samplingRate; 1057 config->inputCfg.format = config->outputCfg.format = AUDIO_FORMAT_PCM_16_BIT; 1058 config->inputCfg.channels = config->outputCfg.channels = 1059 audio_channel_in_mask_from_count(session->revChannelCount); 1060 config->inputCfg.mask = config->outputCfg.mask = 1061 (EFFECT_CONFIG_SMP_RATE | EFFECT_CONFIG_CHANNELS | EFFECT_CONFIG_FORMAT); 1062 } 1063 1064 void Session_SetProcEnabled(preproc_session_t *session, uint32_t procId, bool enabled) 1065 { 1066 if (enabled) { 1067 if(session->enabledMsk == 0) { 1068 session->framesIn = 0; 1069 if (session->inResampler != NULL) { 1070 speex_resampler_reset_mem(session->inResampler); 1071 } 1072 session->framesOut = 0; 1073 if (session->outResampler != NULL) { 1074 speex_resampler_reset_mem(session->outResampler); 1075 } 1076 } 1077 session->enabledMsk |= (1 << procId); 1078 if (HasReverseStream(procId)) { 1079 session->framesRev = 0; 1080 if (session->revResampler != NULL) { 1081 speex_resampler_reset_mem(session->revResampler); 1082 } 1083 session->revEnabledMsk |= (1 << procId); 1084 } 1085 } else { 1086 session->enabledMsk &= ~(1 << procId); 1087 if (HasReverseStream(procId)) { 1088 session->revEnabledMsk &= ~(1 << procId); 1089 } 1090 } 1091 ALOGV("Session_SetProcEnabled proc %d, enabled %d enabledMsk %08x revEnabledMsk %08x", 1092 procId, enabled, session->enabledMsk, session->revEnabledMsk); 1093 session->processedMsk = 0; 1094 if (HasReverseStream(procId)) { 1095 session->revProcessedMsk = 0; 1096 } 1097 } 1098 1099 //------------------------------------------------------------------------------ 1100 // Bundle functions 1101 //------------------------------------------------------------------------------ 1102 1103 static int sInitStatus = 1; 1104 static preproc_session_t sSessions[PREPROC_NUM_SESSIONS]; 1105 1106 preproc_session_t *PreProc_GetSession(int32_t procId, int32_t sessionId, int32_t ioId) 1107 { 1108 size_t i; 1109 int free = -1; 1110 for (i = 0; i < PREPROC_NUM_SESSIONS; i++) { 1111 if (sSessions[i].io == ioId) { 1112 if (sSessions[i].createdMsk & (1 << procId)) { 1113 return NULL; 1114 } 1115 return &sSessions[i]; 1116 } 1117 } 1118 for (i = 0; i < PREPROC_NUM_SESSIONS; i++) { 1119 if (sSessions[i].io == 0) { 1120 sSessions[i].id = sessionId; 1121 sSessions[i].io = ioId; 1122 return &sSessions[i]; 1123 } 1124 } 1125 return NULL; 1126 } 1127 1128 1129 int PreProc_Init() { 1130 size_t i; 1131 int status = 0; 1132 1133 if (sInitStatus <= 0) { 1134 return sInitStatus; 1135 } 1136 for (i = 0; i < PREPROC_NUM_SESSIONS && status == 0; i++) { 1137 status = Session_Init(&sSessions[i]); 1138 } 1139 sInitStatus = status; 1140 return sInitStatus; 1141 } 1142 1143 const effect_descriptor_t *PreProc_GetDescriptor(const effect_uuid_t *uuid) 1144 { 1145 size_t i; 1146 for (i = 0; i < PREPROC_NUM_EFFECTS; i++) { 1147 if (memcmp(&sDescriptors[i]->uuid, uuid, sizeof(effect_uuid_t)) == 0) { 1148 return sDescriptors[i]; 1149 } 1150 } 1151 return NULL; 1152 } 1153 1154 1155 extern "C" { 1156 1157 //------------------------------------------------------------------------------ 1158 // Effect Control Interface Implementation 1159 //------------------------------------------------------------------------------ 1160 1161 int PreProcessingFx_Process(effect_handle_t self, 1162 audio_buffer_t *inBuffer, 1163 audio_buffer_t *outBuffer) 1164 { 1165 preproc_effect_t * effect = (preproc_effect_t *)self; 1166 int status = 0; 1167 1168 if (effect == NULL){ 1169 ALOGV("PreProcessingFx_Process() ERROR effect == NULL"); 1170 return -EINVAL; 1171 } 1172 preproc_session_t * session = (preproc_session_t *)effect->session; 1173 1174 if (inBuffer == NULL || inBuffer->raw == NULL || 1175 outBuffer == NULL || outBuffer->raw == NULL){ 1176 ALOGW("PreProcessingFx_Process() ERROR bad pointer"); 1177 return -EINVAL; 1178 } 1179 1180 session->processedMsk |= (1<<effect->procId); 1181 1182 // ALOGV("PreProcessingFx_Process In %d frames enabledMsk %08x processedMsk %08x", 1183 // inBuffer->frameCount, session->enabledMsk, session->processedMsk); 1184 1185 if ((session->processedMsk & session->enabledMsk) == session->enabledMsk) { 1186 effect->session->processedMsk = 0; 1187 size_t framesRq = outBuffer->frameCount; 1188 size_t framesWr = 0; 1189 if (session->framesOut) { 1190 size_t fr = session->framesOut; 1191 if (outBuffer->frameCount < fr) { 1192 fr = outBuffer->frameCount; 1193 } 1194 memcpy(outBuffer->s16, 1195 session->outBuf, 1196 fr * session->outChannelCount * sizeof(int16_t)); 1197 memcpy(session->outBuf, 1198 session->outBuf + fr * session->outChannelCount, 1199 (session->framesOut - fr) * session->outChannelCount * sizeof(int16_t)); 1200 session->framesOut -= fr; 1201 framesWr += fr; 1202 } 1203 outBuffer->frameCount = framesWr; 1204 if (framesWr == framesRq) { 1205 inBuffer->frameCount = 0; 1206 return 0; 1207 } 1208 1209 if (session->inResampler != NULL) { 1210 size_t fr = session->frameCount - session->framesIn; 1211 if (inBuffer->frameCount < fr) { 1212 fr = inBuffer->frameCount; 1213 } 1214 if (session->inBufSize < session->framesIn + fr) { 1215 session->inBufSize = session->framesIn + fr; 1216 session->inBuf = (int16_t *)realloc(session->inBuf, 1217 session->inBufSize * session->inChannelCount * sizeof(int16_t)); 1218 } 1219 memcpy(session->inBuf + session->framesIn * session->inChannelCount, 1220 inBuffer->s16, 1221 fr * session->inChannelCount * sizeof(int16_t)); 1222 #ifdef DUAL_MIC_TEST 1223 pthread_mutex_lock(&gPcmDumpLock); 1224 if (gPcmDumpFh != NULL) { 1225 fwrite(inBuffer->raw, 1226 fr * session->inChannelCount * sizeof(int16_t), 1, gPcmDumpFh); 1227 } 1228 pthread_mutex_unlock(&gPcmDumpLock); 1229 #endif 1230 1231 session->framesIn += fr; 1232 inBuffer->frameCount = fr; 1233 if (session->framesIn < session->frameCount) { 1234 return 0; 1235 } 1236 size_t frIn = session->framesIn; 1237 size_t frOut = session->apmFrameCount; 1238 if (session->inChannelCount == 1) { 1239 speex_resampler_process_int(session->inResampler, 1240 0, 1241 session->inBuf, 1242 &frIn, 1243 session->procFrame->_payloadData, 1244 &frOut); 1245 } else { 1246 speex_resampler_process_interleaved_int(session->inResampler, 1247 session->inBuf, 1248 &frIn, 1249 session->procFrame->_payloadData, 1250 &frOut); 1251 } 1252 memcpy(session->inBuf, 1253 session->inBuf + frIn * session->inChannelCount, 1254 (session->framesIn - frIn) * session->inChannelCount * sizeof(int16_t)); 1255 session->framesIn -= frIn; 1256 } else { 1257 size_t fr = session->frameCount - session->framesIn; 1258 if (inBuffer->frameCount < fr) { 1259 fr = inBuffer->frameCount; 1260 } 1261 memcpy(session->procFrame->_payloadData + session->framesIn * session->inChannelCount, 1262 inBuffer->s16, 1263 fr * session->inChannelCount * sizeof(int16_t)); 1264 1265 #ifdef DUAL_MIC_TEST 1266 pthread_mutex_lock(&gPcmDumpLock); 1267 if (gPcmDumpFh != NULL) { 1268 fwrite(inBuffer->raw, 1269 fr * session->inChannelCount * sizeof(int16_t), 1, gPcmDumpFh); 1270 } 1271 pthread_mutex_unlock(&gPcmDumpLock); 1272 #endif 1273 1274 session->framesIn += fr; 1275 inBuffer->frameCount = fr; 1276 if (session->framesIn < session->frameCount) { 1277 return 0; 1278 } 1279 session->framesIn = 0; 1280 } 1281 session->procFrame->_payloadDataLengthInSamples = 1282 session->apmFrameCount * session->inChannelCount; 1283 1284 effect->session->apm->ProcessStream(session->procFrame); 1285 1286 if (session->outBufSize < session->framesOut + session->frameCount) { 1287 session->outBufSize = session->framesOut + session->frameCount; 1288 session->outBuf = (int16_t *)realloc(session->outBuf, 1289 session->outBufSize * session->outChannelCount * sizeof(int16_t)); 1290 } 1291 1292 if (session->outResampler != NULL) { 1293 size_t frIn = session->apmFrameCount; 1294 size_t frOut = session->frameCount; 1295 if (session->inChannelCount == 1) { 1296 speex_resampler_process_int(session->outResampler, 1297 0, 1298 session->procFrame->_payloadData, 1299 &frIn, 1300 session->outBuf + session->framesOut * session->outChannelCount, 1301 &frOut); 1302 } else { 1303 speex_resampler_process_interleaved_int(session->outResampler, 1304 session->procFrame->_payloadData, 1305 &frIn, 1306 session->outBuf + session->framesOut * session->outChannelCount, 1307 &frOut); 1308 } 1309 session->framesOut += frOut; 1310 } else { 1311 memcpy(session->outBuf + session->framesOut * session->outChannelCount, 1312 session->procFrame->_payloadData, 1313 session->frameCount * session->outChannelCount * sizeof(int16_t)); 1314 session->framesOut += session->frameCount; 1315 } 1316 size_t fr = session->framesOut; 1317 if (framesRq - framesWr < fr) { 1318 fr = framesRq - framesWr; 1319 } 1320 memcpy(outBuffer->s16 + framesWr * session->outChannelCount, 1321 session->outBuf, 1322 fr * session->outChannelCount * sizeof(int16_t)); 1323 memcpy(session->outBuf, 1324 session->outBuf + fr * session->outChannelCount, 1325 (session->framesOut - fr) * session->outChannelCount * sizeof(int16_t)); 1326 session->framesOut -= fr; 1327 outBuffer->frameCount += fr; 1328 1329 return 0; 1330 } else { 1331 return -ENODATA; 1332 } 1333 } 1334 1335 int PreProcessingFx_Command(effect_handle_t self, 1336 uint32_t cmdCode, 1337 uint32_t cmdSize, 1338 void *pCmdData, 1339 uint32_t *replySize, 1340 void *pReplyData) 1341 { 1342 preproc_effect_t * effect = (preproc_effect_t *) self; 1343 int retsize; 1344 int status; 1345 1346 if (effect == NULL){ 1347 return -EINVAL; 1348 } 1349 1350 //ALOGV("PreProcessingFx_Command: command %d cmdSize %d",cmdCode, cmdSize); 1351 1352 switch (cmdCode){ 1353 case EFFECT_CMD_INIT: 1354 if (pReplyData == NULL || *replySize != sizeof(int)){ 1355 return -EINVAL; 1356 } 1357 if (effect->ops->init) { 1358 effect->ops->init(effect); 1359 } 1360 *(int *)pReplyData = 0; 1361 break; 1362 1363 case EFFECT_CMD_SET_CONFIG: { 1364 if (pCmdData == NULL|| 1365 cmdSize != sizeof(effect_config_t)|| 1366 pReplyData == NULL|| 1367 *replySize != sizeof(int)){ 1368 ALOGV("PreProcessingFx_Command cmdCode Case: " 1369 "EFFECT_CMD_SET_CONFIG: ERROR"); 1370 return -EINVAL; 1371 } 1372 #ifdef DUAL_MIC_TEST 1373 // make sure that the config command is accepted by making as if all effects were 1374 // disabled: this is OK for functional tests 1375 uint32_t enabledMsk = effect->session->enabledMsk; 1376 if (gDualMicEnabled) { 1377 effect->session->enabledMsk = 0; 1378 } 1379 #endif 1380 *(int *)pReplyData = Session_SetConfig(effect->session, (effect_config_t *)pCmdData); 1381 #ifdef DUAL_MIC_TEST 1382 if (gDualMicEnabled) { 1383 effect->session->enabledMsk = enabledMsk; 1384 } 1385 #endif 1386 if (*(int *)pReplyData != 0) { 1387 break; 1388 } 1389 if (effect->state != PREPROC_EFFECT_STATE_ACTIVE) { 1390 *(int *)pReplyData = Effect_SetState(effect, PREPROC_EFFECT_STATE_CONFIG); 1391 } 1392 } break; 1393 1394 case EFFECT_CMD_GET_CONFIG: 1395 if (pReplyData == NULL || 1396 *replySize != sizeof(effect_config_t)) { 1397 ALOGV("\tLVM_ERROR : PreProcessingFx_Command cmdCode Case: " 1398 "EFFECT_CMD_GET_CONFIG: ERROR"); 1399 return -EINVAL; 1400 } 1401 1402 Session_GetConfig(effect->session, (effect_config_t *)pReplyData); 1403 break; 1404 1405 case EFFECT_CMD_SET_CONFIG_REVERSE: 1406 if (pCmdData == NULL || 1407 cmdSize != sizeof(effect_config_t) || 1408 pReplyData == NULL || 1409 *replySize != sizeof(int)) { 1410 ALOGV("PreProcessingFx_Command cmdCode Case: " 1411 "EFFECT_CMD_SET_CONFIG_REVERSE: ERROR"); 1412 return -EINVAL; 1413 } 1414 *(int *)pReplyData = Session_SetReverseConfig(effect->session, 1415 (effect_config_t *)pCmdData); 1416 if (*(int *)pReplyData != 0) { 1417 break; 1418 } 1419 break; 1420 1421 case EFFECT_CMD_GET_CONFIG_REVERSE: 1422 if (pReplyData == NULL || 1423 *replySize != sizeof(effect_config_t)){ 1424 ALOGV("PreProcessingFx_Command cmdCode Case: " 1425 "EFFECT_CMD_GET_CONFIG_REVERSE: ERROR"); 1426 return -EINVAL; 1427 } 1428 Session_GetReverseConfig(effect->session, (effect_config_t *)pCmdData); 1429 break; 1430 1431 case EFFECT_CMD_RESET: 1432 if (effect->ops->reset) { 1433 effect->ops->reset(effect); 1434 } 1435 break; 1436 1437 case EFFECT_CMD_GET_PARAM:{ 1438 if (pCmdData == NULL || 1439 cmdSize < (int)sizeof(effect_param_t) || 1440 pReplyData == NULL || 1441 *replySize < (int)sizeof(effect_param_t)){ 1442 ALOGV("PreProcessingFx_Command cmdCode Case: " 1443 "EFFECT_CMD_GET_PARAM: ERROR"); 1444 return -EINVAL; 1445 } 1446 effect_param_t *p = (effect_param_t *)pCmdData; 1447 1448 memcpy(pReplyData, pCmdData, sizeof(effect_param_t) + p->psize); 1449 1450 p = (effect_param_t *)pReplyData; 1451 1452 int voffset = ((p->psize - 1) / sizeof(int32_t) + 1) * sizeof(int32_t); 1453 1454 if (effect->ops->get_parameter) { 1455 p->status = effect->ops->get_parameter(effect, p->data, 1456 (size_t *)&p->vsize, 1457 p->data + voffset); 1458 *replySize = sizeof(effect_param_t) + voffset + p->vsize; 1459 } 1460 } break; 1461 1462 case EFFECT_CMD_SET_PARAM:{ 1463 if (pCmdData == NULL|| 1464 cmdSize < (int)sizeof(effect_param_t) || 1465 pReplyData == NULL || 1466 *replySize != sizeof(int32_t)){ 1467 ALOGV("PreProcessingFx_Command cmdCode Case: " 1468 "EFFECT_CMD_SET_PARAM: ERROR"); 1469 return -EINVAL; 1470 } 1471 effect_param_t *p = (effect_param_t *) pCmdData; 1472 1473 if (p->psize != sizeof(int32_t)){ 1474 ALOGV("PreProcessingFx_Command cmdCode Case: " 1475 "EFFECT_CMD_SET_PARAM: ERROR, psize is not sizeof(int32_t)"); 1476 return -EINVAL; 1477 } 1478 if (effect->ops->set_parameter) { 1479 *(int *)pReplyData = effect->ops->set_parameter(effect, 1480 (void *)p->data, 1481 p->data + p->psize); 1482 } 1483 } break; 1484 1485 case EFFECT_CMD_ENABLE: 1486 if (pReplyData == NULL || *replySize != sizeof(int)){ 1487 ALOGV("PreProcessingFx_Command cmdCode Case: EFFECT_CMD_ENABLE: ERROR"); 1488 return -EINVAL; 1489 } 1490 *(int *)pReplyData = Effect_SetState(effect, PREPROC_EFFECT_STATE_ACTIVE); 1491 break; 1492 1493 case EFFECT_CMD_DISABLE: 1494 if (pReplyData == NULL || *replySize != sizeof(int)){ 1495 ALOGV("PreProcessingFx_Command cmdCode Case: EFFECT_CMD_DISABLE: ERROR"); 1496 return -EINVAL; 1497 } 1498 *(int *)pReplyData = Effect_SetState(effect, PREPROC_EFFECT_STATE_CONFIG); 1499 break; 1500 1501 case EFFECT_CMD_SET_DEVICE: 1502 case EFFECT_CMD_SET_INPUT_DEVICE: 1503 if (pCmdData == NULL || 1504 cmdSize != sizeof(uint32_t)) { 1505 ALOGV("PreProcessingFx_Command cmdCode Case: EFFECT_CMD_SET_DEVICE: ERROR"); 1506 return -EINVAL; 1507 } 1508 1509 if (effect->ops->set_device) { 1510 effect->ops->set_device(effect, *(uint32_t *)pCmdData); 1511 } 1512 break; 1513 1514 case EFFECT_CMD_SET_VOLUME: 1515 case EFFECT_CMD_SET_AUDIO_MODE: 1516 break; 1517 1518 #ifdef DUAL_MIC_TEST 1519 ///// test commands start 1520 case PREPROC_CMD_DUAL_MIC_ENABLE: { 1521 if (pCmdData == NULL|| cmdSize != sizeof(uint32_t) || 1522 pReplyData == NULL || replySize == NULL) { 1523 ALOGE("PreProcessingFx_Command cmdCode Case: " 1524 "PREPROC_CMD_DUAL_MIC_ENABLE: ERROR"); 1525 *replySize = 0; 1526 return -EINVAL; 1527 } 1528 gDualMicEnabled = *(bool *)pCmdData; 1529 if (gDualMicEnabled) { 1530 effect->aux_channels_on = sHasAuxChannels[effect->procId]; 1531 } else { 1532 effect->aux_channels_on = false; 1533 } 1534 effect->cur_channel_config = (effect->session->inChannelCount == 1) ? 1535 CHANNEL_CFG_MONO : CHANNEL_CFG_STEREO; 1536 1537 ALOGV("PREPROC_CMD_DUAL_MIC_ENABLE: %s", gDualMicEnabled ? "enabled" : "disabled"); 1538 *replySize = sizeof(int); 1539 *(int *)pReplyData = 0; 1540 } break; 1541 case PREPROC_CMD_DUAL_MIC_PCM_DUMP_START: { 1542 if (pCmdData == NULL|| pReplyData == NULL || replySize == NULL) { 1543 ALOGE("PreProcessingFx_Command cmdCode Case: " 1544 "PREPROC_CMD_DUAL_MIC_PCM_DUMP_START: ERROR"); 1545 *replySize = 0; 1546 return -EINVAL; 1547 } 1548 pthread_mutex_lock(&gPcmDumpLock); 1549 if (gPcmDumpFh != NULL) { 1550 fclose(gPcmDumpFh); 1551 gPcmDumpFh = NULL; 1552 } 1553 char *path = strndup((char *)pCmdData, cmdSize); 1554 gPcmDumpFh = fopen((char *)path, "wb"); 1555 pthread_mutex_unlock(&gPcmDumpLock); 1556 ALOGV("PREPROC_CMD_DUAL_MIC_PCM_DUMP_START: path %s gPcmDumpFh %p", 1557 path, gPcmDumpFh); 1558 ALOGE_IF(gPcmDumpFh <= 0, "gPcmDumpFh open error %d %s", errno, strerror(errno)); 1559 free(path); 1560 *replySize = sizeof(int); 1561 *(int *)pReplyData = 0; 1562 } break; 1563 case PREPROC_CMD_DUAL_MIC_PCM_DUMP_STOP: { 1564 if (pReplyData == NULL || replySize == NULL) { 1565 ALOGE("PreProcessingFx_Command cmdCode Case: " 1566 "PREPROC_CMD_DUAL_MIC_PCM_DUMP_STOP: ERROR"); 1567 *replySize = 0; 1568 return -EINVAL; 1569 } 1570 pthread_mutex_lock(&gPcmDumpLock); 1571 if (gPcmDumpFh != NULL) { 1572 fclose(gPcmDumpFh); 1573 gPcmDumpFh = NULL; 1574 } 1575 pthread_mutex_unlock(&gPcmDumpLock); 1576 ALOGV("PREPROC_CMD_DUAL_MIC_PCM_DUMP_STOP"); 1577 *replySize = sizeof(int); 1578 *(int *)pReplyData = 0; 1579 } break; 1580 ///// test commands end 1581 1582 case EFFECT_CMD_GET_FEATURE_SUPPORTED_CONFIGS: { 1583 if(!gDualMicEnabled) { 1584 return -EINVAL; 1585 } 1586 if (pCmdData == NULL|| cmdSize != 2 * sizeof(uint32_t) || 1587 pReplyData == NULL || replySize == NULL) { 1588 ALOGE("PreProcessingFx_Command cmdCode Case: " 1589 "EFFECT_CMD_GET_FEATURE_SUPPORTED_CONFIGS: ERROR"); 1590 *replySize = 0; 1591 return -EINVAL; 1592 } 1593 if (*(uint32_t *)pCmdData != EFFECT_FEATURE_AUX_CHANNELS || 1594 !effect->aux_channels_on) { 1595 ALOGV("PreProcessingFx_Command feature EFFECT_FEATURE_AUX_CHANNELS not supported by" 1596 " fx %d", effect->procId); 1597 *(uint32_t *)pReplyData = -ENOSYS; 1598 *replySize = sizeof(uint32_t); 1599 break; 1600 } 1601 size_t num_configs = *((uint32_t *)pCmdData + 1); 1602 if (*replySize < (2 * sizeof(uint32_t) + 1603 num_configs * sizeof(channel_config_t))) { 1604 *replySize = 0; 1605 return -EINVAL; 1606 } 1607 1608 *((uint32_t *)pReplyData + 1) = CHANNEL_CFG_CNT; 1609 if (num_configs < CHANNEL_CFG_CNT || 1610 *replySize < (2 * sizeof(uint32_t) + 1611 CHANNEL_CFG_CNT * sizeof(channel_config_t))) { 1612 *(uint32_t *)pReplyData = -ENOMEM; 1613 } else { 1614 num_configs = CHANNEL_CFG_CNT; 1615 *(uint32_t *)pReplyData = 0; 1616 } 1617 ALOGV("PreProcessingFx_Command EFFECT_CMD_GET_FEATURE_SUPPORTED_CONFIGS num config %d", 1618 num_configs); 1619 1620 *replySize = 2 * sizeof(uint32_t) + num_configs * sizeof(channel_config_t); 1621 *((uint32_t *)pReplyData + 1) = num_configs; 1622 memcpy((uint32_t *)pReplyData + 2, &sDualMicConfigs, num_configs * sizeof(channel_config_t)); 1623 } break; 1624 case EFFECT_CMD_GET_FEATURE_CONFIG: 1625 if(!gDualMicEnabled) { 1626 return -EINVAL; 1627 } 1628 if (pCmdData == NULL|| cmdSize != sizeof(uint32_t) || 1629 pReplyData == NULL || replySize == NULL || 1630 *replySize < sizeof(uint32_t) + sizeof(channel_config_t)) { 1631 ALOGE("PreProcessingFx_Command cmdCode Case: " 1632 "EFFECT_CMD_GET_FEATURE_CONFIG: ERROR"); 1633 return -EINVAL; 1634 } 1635 if (*(uint32_t *)pCmdData != EFFECT_FEATURE_AUX_CHANNELS || !effect->aux_channels_on) { 1636 *(uint32_t *)pReplyData = -ENOSYS; 1637 *replySize = sizeof(uint32_t); 1638 break; 1639 } 1640 ALOGV("PreProcessingFx_Command EFFECT_CMD_GET_FEATURE_CONFIG"); 1641 *(uint32_t *)pReplyData = 0; 1642 *replySize = sizeof(uint32_t) + sizeof(channel_config_t); 1643 memcpy((uint32_t *)pReplyData + 1, 1644 &sDualMicConfigs[effect->cur_channel_config], 1645 sizeof(channel_config_t)); 1646 break; 1647 case EFFECT_CMD_SET_FEATURE_CONFIG: { 1648 ALOGV("PreProcessingFx_Command EFFECT_CMD_SET_FEATURE_CONFIG: " 1649 "gDualMicEnabled %d effect->aux_channels_on %d", 1650 gDualMicEnabled, effect->aux_channels_on); 1651 if(!gDualMicEnabled) { 1652 return -EINVAL; 1653 } 1654 if (pCmdData == NULL|| cmdSize != (sizeof(uint32_t) + sizeof(channel_config_t)) || 1655 pReplyData == NULL || replySize == NULL || 1656 *replySize < sizeof(uint32_t)) { 1657 ALOGE("PreProcessingFx_Command cmdCode Case: " 1658 "EFFECT_CMD_SET_FEATURE_CONFIG: ERROR\n" 1659 "pCmdData %p cmdSize %d pReplyData %p replySize %p *replySize %d", 1660 pCmdData, cmdSize, pReplyData, replySize, replySize ? *replySize : -1); 1661 return -EINVAL; 1662 } 1663 *replySize = sizeof(uint32_t); 1664 if (*(uint32_t *)pCmdData != EFFECT_FEATURE_AUX_CHANNELS || !effect->aux_channels_on) { 1665 *(uint32_t *)pReplyData = -ENOSYS; 1666 ALOGV("PreProcessingFx_Command cmdCode Case: " 1667 "EFFECT_CMD_SET_FEATURE_CONFIG: ERROR\n" 1668 "CmdData %d effect->aux_channels_on %d", 1669 *(uint32_t *)pCmdData, effect->aux_channels_on); 1670 break; 1671 } 1672 size_t i; 1673 for (i = 0; i < CHANNEL_CFG_CNT;i++) { 1674 if (memcmp((uint32_t *)pCmdData + 1, 1675 &sDualMicConfigs[i], sizeof(channel_config_t)) == 0) { 1676 break; 1677 } 1678 } 1679 if (i == CHANNEL_CFG_CNT) { 1680 *(uint32_t *)pReplyData = -EINVAL; 1681 ALOGW("PreProcessingFx_Command EFFECT_CMD_SET_FEATURE_CONFIG invalid config" 1682 "[%08x].[%08x]", *((uint32_t *)pCmdData + 1), *((uint32_t *)pCmdData + 2)); 1683 } else { 1684 effect->cur_channel_config = i; 1685 *(uint32_t *)pReplyData = 0; 1686 ALOGV("PreProcessingFx_Command EFFECT_CMD_SET_FEATURE_CONFIG New config" 1687 "[%08x].[%08x]", sDualMicConfigs[i].main_channels, sDualMicConfigs[i].aux_channels); 1688 } 1689 } break; 1690 #endif 1691 default: 1692 return -EINVAL; 1693 } 1694 return 0; 1695 } 1696 1697 1698 int PreProcessingFx_GetDescriptor(effect_handle_t self, 1699 effect_descriptor_t *pDescriptor) 1700 { 1701 preproc_effect_t * effect = (preproc_effect_t *) self; 1702 1703 if (effect == NULL || pDescriptor == NULL) { 1704 return -EINVAL; 1705 } 1706 1707 *pDescriptor = *sDescriptors[effect->procId]; 1708 1709 return 0; 1710 } 1711 1712 int PreProcessingFx_ProcessReverse(effect_handle_t self, 1713 audio_buffer_t *inBuffer, 1714 audio_buffer_t *outBuffer) 1715 { 1716 preproc_effect_t * effect = (preproc_effect_t *)self; 1717 int status = 0; 1718 1719 if (effect == NULL){ 1720 ALOGW("PreProcessingFx_ProcessReverse() ERROR effect == NULL"); 1721 return -EINVAL; 1722 } 1723 preproc_session_t * session = (preproc_session_t *)effect->session; 1724 1725 if (inBuffer == NULL || inBuffer->raw == NULL){ 1726 ALOGW("PreProcessingFx_ProcessReverse() ERROR bad pointer"); 1727 return -EINVAL; 1728 } 1729 1730 session->revProcessedMsk |= (1<<effect->procId); 1731 1732 // ALOGV("PreProcessingFx_ProcessReverse In %d frames revEnabledMsk %08x revProcessedMsk %08x", 1733 // inBuffer->frameCount, session->revEnabledMsk, session->revProcessedMsk); 1734 1735 1736 if ((session->revProcessedMsk & session->revEnabledMsk) == session->revEnabledMsk) { 1737 effect->session->revProcessedMsk = 0; 1738 if (session->revResampler != NULL) { 1739 size_t fr = session->frameCount - session->framesRev; 1740 if (inBuffer->frameCount < fr) { 1741 fr = inBuffer->frameCount; 1742 } 1743 if (session->revBufSize < session->framesRev + fr) { 1744 session->revBufSize = session->framesRev + fr; 1745 session->revBuf = (int16_t *)realloc(session->revBuf, 1746 session->revBufSize * session->inChannelCount * sizeof(int16_t)); 1747 } 1748 memcpy(session->revBuf + session->framesRev * session->inChannelCount, 1749 inBuffer->s16, 1750 fr * session->inChannelCount * sizeof(int16_t)); 1751 1752 session->framesRev += fr; 1753 inBuffer->frameCount = fr; 1754 if (session->framesRev < session->frameCount) { 1755 return 0; 1756 } 1757 size_t frIn = session->framesRev; 1758 size_t frOut = session->apmFrameCount; 1759 if (session->inChannelCount == 1) { 1760 speex_resampler_process_int(session->revResampler, 1761 0, 1762 session->revBuf, 1763 &frIn, 1764 session->revFrame->_payloadData, 1765 &frOut); 1766 } else { 1767 speex_resampler_process_interleaved_int(session->revResampler, 1768 session->revBuf, 1769 &frIn, 1770 session->revFrame->_payloadData, 1771 &frOut); 1772 } 1773 memcpy(session->revBuf, 1774 session->revBuf + frIn * session->inChannelCount, 1775 (session->framesRev - frIn) * session->inChannelCount * sizeof(int16_t)); 1776 session->framesRev -= frIn; 1777 } else { 1778 size_t fr = session->frameCount - session->framesRev; 1779 if (inBuffer->frameCount < fr) { 1780 fr = inBuffer->frameCount; 1781 } 1782 memcpy(session->revFrame->_payloadData + session->framesRev * session->inChannelCount, 1783 inBuffer->s16, 1784 fr * session->inChannelCount * sizeof(int16_t)); 1785 session->framesRev += fr; 1786 inBuffer->frameCount = fr; 1787 if (session->framesRev < session->frameCount) { 1788 return 0; 1789 } 1790 session->framesRev = 0; 1791 } 1792 session->revFrame->_payloadDataLengthInSamples = 1793 session->apmFrameCount * session->inChannelCount; 1794 effect->session->apm->AnalyzeReverseStream(session->revFrame); 1795 return 0; 1796 } else { 1797 return -ENODATA; 1798 } 1799 } 1800 1801 1802 // effect_handle_t interface implementation for effect 1803 const struct effect_interface_s sEffectInterface = { 1804 PreProcessingFx_Process, 1805 PreProcessingFx_Command, 1806 PreProcessingFx_GetDescriptor, 1807 NULL 1808 }; 1809 1810 const struct effect_interface_s sEffectInterfaceReverse = { 1811 PreProcessingFx_Process, 1812 PreProcessingFx_Command, 1813 PreProcessingFx_GetDescriptor, 1814 PreProcessingFx_ProcessReverse 1815 }; 1816 1817 //------------------------------------------------------------------------------ 1818 // Effect Library Interface Implementation 1819 //------------------------------------------------------------------------------ 1820 1821 int PreProcessingLib_Create(const effect_uuid_t *uuid, 1822 int32_t sessionId, 1823 int32_t ioId, 1824 effect_handle_t *pInterface) 1825 { 1826 ALOGV("EffectCreate: uuid: %08x session %d IO: %d", uuid->timeLow, sessionId, ioId); 1827 1828 int status; 1829 const effect_descriptor_t *desc; 1830 preproc_session_t *session; 1831 uint32_t procId; 1832 1833 if (PreProc_Init() != 0) { 1834 return sInitStatus; 1835 } 1836 desc = PreProc_GetDescriptor(uuid); 1837 if (desc == NULL) { 1838 ALOGW("EffectCreate: fx not found uuid: %08x", uuid->timeLow); 1839 return -EINVAL; 1840 } 1841 procId = UuidToProcId(&desc->type); 1842 1843 session = PreProc_GetSession(procId, sessionId, ioId); 1844 if (session == NULL) { 1845 ALOGW("EffectCreate: no more session available"); 1846 return -EINVAL; 1847 } 1848 1849 status = Session_CreateEffect(session, procId, pInterface); 1850 1851 if (status < 0 && session->createdMsk == 0) { 1852 session->io = 0; 1853 } 1854 return status; 1855 } 1856 1857 int PreProcessingLib_Release(effect_handle_t interface) 1858 { 1859 int status; 1860 ALOGV("EffectRelease start %p", interface); 1861 if (PreProc_Init() != 0) { 1862 return sInitStatus; 1863 } 1864 1865 preproc_effect_t *fx = (preproc_effect_t *)interface; 1866 1867 if (fx->session->io == 0) { 1868 return -EINVAL; 1869 } 1870 return Session_ReleaseEffect(fx->session, fx); 1871 } 1872 1873 int PreProcessingLib_GetDescriptor(const effect_uuid_t *uuid, 1874 effect_descriptor_t *pDescriptor) { 1875 1876 if (pDescriptor == NULL || uuid == NULL){ 1877 return -EINVAL; 1878 } 1879 1880 const effect_descriptor_t *desc = PreProc_GetDescriptor(uuid); 1881 if (desc == NULL) { 1882 ALOGV("PreProcessingLib_GetDescriptor() not found"); 1883 return -EINVAL; 1884 } 1885 1886 ALOGV("PreProcessingLib_GetDescriptor() got fx %s", desc->name); 1887 1888 *pDescriptor = *desc; 1889 return 0; 1890 } 1891 1892 // This is the only symbol that needs to be exported 1893 __attribute__ ((visibility ("default"))) 1894 audio_effect_library_t AUDIO_EFFECT_LIBRARY_INFO_SYM = { 1895 tag : AUDIO_EFFECT_LIBRARY_TAG, 1896 version : EFFECT_LIBRARY_API_VERSION, 1897 name : "Audio Preprocessing Library", 1898 implementor : "The Android Open Source Project", 1899 create_effect : PreProcessingLib_Create, 1900 release_effect : PreProcessingLib_Release, 1901 get_descriptor : PreProcessingLib_GetDescriptor 1902 }; 1903 1904 }; // extern "C" 1905