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