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