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