PreProcessing.cpp revision ab334fd351ae5a0e18903da123d63e565b536874
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 // if at least one process is enabled, do not accept configuration changes 849 if (session->enabledMsk) { 850 if (session->samplingRate != config->inputCfg.samplingRate || 851 session->inChannelCount != inCnl || 852 session->outChannelCount != outCnl) { 853 return -ENOSYS; 854 } else { 855 return 0; 856 } 857 } 858 859 // AEC implementation is limited to 16kHz 860 if (config->inputCfg.samplingRate >= 32000 && !(session->createdMsk & (1 << PREPROC_AEC))) { 861 session->apmSamplingRate = 32000; 862 } else 863 if (config->inputCfg.samplingRate >= 16000) { 864 session->apmSamplingRate = 16000; 865 } else if (config->inputCfg.samplingRate >= 8000) { 866 session->apmSamplingRate = 8000; 867 } 868 status = session->apm->set_sample_rate_hz(session->apmSamplingRate); 869 if (status < 0) { 870 return -EINVAL; 871 } 872 status = session->apm->set_num_channels(inCnl, outCnl); 873 if (status < 0) { 874 return -EINVAL; 875 } 876 status = session->apm->set_num_reverse_channels(inCnl); 877 if (status < 0) { 878 return -EINVAL; 879 } 880 881 session->samplingRate = config->inputCfg.samplingRate; 882 session->apmFrameCount = session->apmSamplingRate / 100; 883 if (session->samplingRate == session->apmSamplingRate) { 884 session->frameCount = session->apmFrameCount; 885 } else { 886 session->frameCount = (session->apmFrameCount * session->samplingRate) / 887 session->apmSamplingRate + 1; 888 } 889 session->inChannelCount = inCnl; 890 session->outChannelCount = outCnl; 891 session->procFrame->_audioChannel = inCnl; 892 session->procFrame->_frequencyInHz = session->apmSamplingRate; 893 894 session->revChannelCount = inCnl; 895 session->revFrame->_audioChannel = inCnl; 896 session->revFrame->_frequencyInHz = session->apmSamplingRate; 897 898 if (session->inResampler != NULL) { 899 speex_resampler_destroy(session->inResampler); 900 session->inResampler = NULL; 901 } 902 if (session->outResampler != NULL) { 903 speex_resampler_destroy(session->outResampler); 904 session->outResampler = NULL; 905 } 906 if (session->revResampler != NULL) { 907 speex_resampler_destroy(session->revResampler); 908 session->revResampler = NULL; 909 } 910 if (session->samplingRate != session->apmSamplingRate) { 911 int error; 912 session->inResampler = speex_resampler_init(session->inChannelCount, 913 session->samplingRate, 914 session->apmSamplingRate, 915 RESAMPLER_QUALITY, 916 &error); 917 if (session->inResampler == NULL) { 918 ALOGW("Session_SetConfig Cannot create speex resampler: %s", 919 speex_resampler_strerror(error)); 920 return -EINVAL; 921 } 922 session->outResampler = speex_resampler_init(session->outChannelCount, 923 session->apmSamplingRate, 924 session->samplingRate, 925 RESAMPLER_QUALITY, 926 &error); 927 if (session->outResampler == NULL) { 928 ALOGW("Session_SetConfig Cannot create speex resampler: %s", 929 speex_resampler_strerror(error)); 930 speex_resampler_destroy(session->inResampler); 931 session->inResampler = NULL; 932 return -EINVAL; 933 } 934 session->revResampler = speex_resampler_init(session->inChannelCount, 935 session->samplingRate, 936 session->apmSamplingRate, 937 RESAMPLER_QUALITY, 938 &error); 939 if (session->revResampler == NULL) { 940 ALOGW("Session_SetConfig Cannot create speex resampler: %s", 941 speex_resampler_strerror(error)); 942 speex_resampler_destroy(session->inResampler); 943 session->inResampler = NULL; 944 speex_resampler_destroy(session->outResampler); 945 session->outResampler = NULL; 946 return -EINVAL; 947 } 948 } 949 950 session->state = PREPROC_SESSION_STATE_CONFIG; 951 return 0; 952} 953 954void Session_GetConfig(preproc_session_t *session, effect_config_t *config) 955{ 956 memset(config, 0, sizeof(effect_config_t)); 957 config->inputCfg.samplingRate = config->outputCfg.samplingRate = session->samplingRate; 958 config->inputCfg.format = config->outputCfg.format = AUDIO_FORMAT_PCM_16_BIT; 959 config->inputCfg.channels = audio_channel_in_mask_from_count(session->inChannelCount); 960 // "out" doesn't mean output device, so this is the correct API to convert channel count to mask 961 config->outputCfg.channels = audio_channel_in_mask_from_count(session->outChannelCount); 962 config->inputCfg.mask = config->outputCfg.mask = 963 (EFFECT_CONFIG_SMP_RATE | EFFECT_CONFIG_CHANNELS | EFFECT_CONFIG_FORMAT); 964} 965 966int Session_SetReverseConfig(preproc_session_t *session, effect_config_t *config) 967{ 968 if (config->inputCfg.samplingRate != config->outputCfg.samplingRate || 969 config->inputCfg.format != config->outputCfg.format || 970 config->inputCfg.format != AUDIO_FORMAT_PCM_16_BIT) { 971 return -EINVAL; 972 } 973 974 ALOGV("Session_SetReverseConfig sr %d cnl %08x", 975 config->inputCfg.samplingRate, config->inputCfg.channels); 976 977 if (session->state < PREPROC_SESSION_STATE_CONFIG) { 978 return -ENOSYS; 979 } 980 if (config->inputCfg.samplingRate != session->samplingRate || 981 config->inputCfg.format != AUDIO_FORMAT_PCM_16_BIT) { 982 return -EINVAL; 983 } 984 uint32_t inCnl = popcount(config->inputCfg.channels); 985 int status = session->apm->set_num_reverse_channels(inCnl); 986 if (status < 0) { 987 return -EINVAL; 988 } 989 session->revChannelCount = inCnl; 990 session->revFrame->_audioChannel = inCnl; 991 session->revFrame->_frequencyInHz = session->apmSamplingRate; 992 return 0; 993} 994 995void Session_GetReverseConfig(preproc_session_t *session, effect_config_t *config) 996{ 997 memset(config, 0, sizeof(effect_config_t)); 998 config->inputCfg.samplingRate = config->outputCfg.samplingRate = session->samplingRate; 999 config->inputCfg.format = config->outputCfg.format = AUDIO_FORMAT_PCM_16_BIT; 1000 config->inputCfg.channels = config->outputCfg.channels = 1001 audio_channel_in_mask_from_count(session->revChannelCount); 1002 config->inputCfg.mask = config->outputCfg.mask = 1003 (EFFECT_CONFIG_SMP_RATE | EFFECT_CONFIG_CHANNELS | EFFECT_CONFIG_FORMAT); 1004} 1005 1006void Session_SetProcEnabled(preproc_session_t *session, uint32_t procId, bool enabled) 1007{ 1008 if (enabled) { 1009 if(session->enabledMsk == 0) { 1010 session->framesIn = 0; 1011 if (session->inResampler != NULL) { 1012 speex_resampler_reset_mem(session->inResampler); 1013 } 1014 session->framesOut = 0; 1015 if (session->outResampler != NULL) { 1016 speex_resampler_reset_mem(session->outResampler); 1017 } 1018 } 1019 session->enabledMsk |= (1 << procId); 1020 if (HasReverseStream(procId)) { 1021 session->framesRev = 0; 1022 if (session->revResampler != NULL) { 1023 speex_resampler_reset_mem(session->revResampler); 1024 } 1025 session->revEnabledMsk |= (1 << procId); 1026 } 1027 } else { 1028 session->enabledMsk &= ~(1 << procId); 1029 if (HasReverseStream(procId)) { 1030 session->revEnabledMsk &= ~(1 << procId); 1031 } 1032 } 1033 ALOGV("Session_SetProcEnabled proc %d, enabled %d enabledMsk %08x revEnabledMsk %08x", 1034 procId, enabled, session->enabledMsk, session->revEnabledMsk); 1035 session->processedMsk = 0; 1036 if (HasReverseStream(procId)) { 1037 session->revProcessedMsk = 0; 1038 } 1039} 1040 1041//------------------------------------------------------------------------------ 1042// Bundle functions 1043//------------------------------------------------------------------------------ 1044 1045static int sInitStatus = 1; 1046static preproc_session_t sSessions[PREPROC_NUM_SESSIONS]; 1047 1048preproc_session_t *PreProc_GetSession(int32_t procId, int32_t sessionId, int32_t ioId) 1049{ 1050 size_t i; 1051 int free = -1; 1052 for (i = 0; i < PREPROC_NUM_SESSIONS; i++) { 1053 if (sSessions[i].io == ioId) { 1054 if (sSessions[i].createdMsk & (1 << procId)) { 1055 return NULL; 1056 } 1057 return &sSessions[i]; 1058 } 1059 } 1060 for (i = 0; i < PREPROC_NUM_SESSIONS; i++) { 1061 if (sSessions[i].io == 0) { 1062 sSessions[i].id = sessionId; 1063 sSessions[i].io = ioId; 1064 return &sSessions[i]; 1065 } 1066 } 1067 return NULL; 1068} 1069 1070 1071int PreProc_Init() { 1072 size_t i; 1073 int status = 0; 1074 1075 if (sInitStatus <= 0) { 1076 return sInitStatus; 1077 } 1078 for (i = 0; i < PREPROC_NUM_SESSIONS && status == 0; i++) { 1079 status = Session_Init(&sSessions[i]); 1080 } 1081 sInitStatus = status; 1082 return sInitStatus; 1083} 1084 1085const effect_descriptor_t *PreProc_GetDescriptor(const effect_uuid_t *uuid) 1086{ 1087 size_t i; 1088 for (i = 0; i < PREPROC_NUM_EFFECTS; i++) { 1089 if (memcmp(&sDescriptors[i]->uuid, uuid, sizeof(effect_uuid_t)) == 0) { 1090 return sDescriptors[i]; 1091 } 1092 } 1093 return NULL; 1094} 1095 1096 1097extern "C" { 1098 1099//------------------------------------------------------------------------------ 1100// Effect Control Interface Implementation 1101//------------------------------------------------------------------------------ 1102 1103int PreProcessingFx_Process(effect_handle_t self, 1104 audio_buffer_t *inBuffer, 1105 audio_buffer_t *outBuffer) 1106{ 1107 preproc_effect_t * effect = (preproc_effect_t *)self; 1108 int status = 0; 1109 1110 if (effect == NULL){ 1111 ALOGV("PreProcessingFx_Process() ERROR effect == NULL"); 1112 return -EINVAL; 1113 } 1114 preproc_session_t * session = (preproc_session_t *)effect->session; 1115 1116 if (inBuffer == NULL || inBuffer->raw == NULL || 1117 outBuffer == NULL || outBuffer->raw == NULL){ 1118 ALOGW("PreProcessingFx_Process() ERROR bad pointer"); 1119 return -EINVAL; 1120 } 1121 1122 session->processedMsk |= (1<<effect->procId); 1123 1124// ALOGV("PreProcessingFx_Process In %d frames enabledMsk %08x processedMsk %08x", 1125// inBuffer->frameCount, session->enabledMsk, session->processedMsk); 1126 1127 if ((session->processedMsk & session->enabledMsk) == session->enabledMsk) { 1128 effect->session->processedMsk = 0; 1129 size_t framesRq = outBuffer->frameCount; 1130 size_t framesWr = 0; 1131 if (session->framesOut) { 1132 size_t fr = session->framesOut; 1133 if (outBuffer->frameCount < fr) { 1134 fr = outBuffer->frameCount; 1135 } 1136 memcpy(outBuffer->s16, 1137 session->outBuf, 1138 fr * session->outChannelCount * sizeof(int16_t)); 1139 memcpy(session->outBuf, 1140 session->outBuf + fr * session->outChannelCount, 1141 (session->framesOut - fr) * session->outChannelCount * sizeof(int16_t)); 1142 session->framesOut -= fr; 1143 framesWr += fr; 1144 } 1145 outBuffer->frameCount = framesWr; 1146 if (framesWr == framesRq) { 1147 inBuffer->frameCount = 0; 1148 return 0; 1149 } 1150 1151 if (session->inResampler != NULL) { 1152 size_t fr = session->frameCount - session->framesIn; 1153 if (inBuffer->frameCount < fr) { 1154 fr = inBuffer->frameCount; 1155 } 1156 if (session->inBufSize < session->framesIn + fr) { 1157 session->inBufSize = session->framesIn + fr; 1158 session->inBuf = (int16_t *)realloc(session->inBuf, 1159 session->inBufSize * session->inChannelCount * sizeof(int16_t)); 1160 } 1161 memcpy(session->inBuf + session->framesIn * session->inChannelCount, 1162 inBuffer->s16, 1163 fr * session->inChannelCount * sizeof(int16_t)); 1164 1165 session->framesIn += fr; 1166 inBuffer->frameCount = fr; 1167 if (session->framesIn < session->frameCount) { 1168 return 0; 1169 } 1170 size_t frIn = session->framesIn; 1171 size_t frOut = session->apmFrameCount; 1172 if (session->inChannelCount == 1) { 1173 speex_resampler_process_int(session->inResampler, 1174 0, 1175 session->inBuf, 1176 &frIn, 1177 session->procFrame->_payloadData, 1178 &frOut); 1179 } else { 1180 speex_resampler_process_interleaved_int(session->inResampler, 1181 session->inBuf, 1182 &frIn, 1183 session->procFrame->_payloadData, 1184 &frOut); 1185 } 1186 memcpy(session->inBuf, 1187 session->inBuf + frIn * session->inChannelCount, 1188 (session->framesIn - frIn) * session->inChannelCount * sizeof(int16_t)); 1189 session->framesIn -= frIn; 1190 } else { 1191 size_t fr = session->frameCount - session->framesIn; 1192 if (inBuffer->frameCount < fr) { 1193 fr = inBuffer->frameCount; 1194 } 1195 memcpy(session->procFrame->_payloadData + session->framesIn * session->inChannelCount, 1196 inBuffer->s16, 1197 fr * session->inChannelCount * sizeof(int16_t)); 1198 session->framesIn += fr; 1199 inBuffer->frameCount = fr; 1200 if (session->framesIn < session->frameCount) { 1201 return 0; 1202 } 1203 session->framesIn = 0; 1204 } 1205 session->procFrame->_payloadDataLengthInSamples = 1206 session->apmFrameCount * session->inChannelCount; 1207 1208 effect->session->apm->ProcessStream(session->procFrame); 1209 1210 if (session->outBufSize < session->framesOut + session->frameCount) { 1211 session->outBufSize = session->framesOut + session->frameCount; 1212 session->outBuf = (int16_t *)realloc(session->outBuf, 1213 session->outBufSize * session->outChannelCount * sizeof(int16_t)); 1214 } 1215 1216 if (session->outResampler != NULL) { 1217 size_t frIn = session->apmFrameCount; 1218 size_t frOut = session->frameCount; 1219 if (session->inChannelCount == 1) { 1220 speex_resampler_process_int(session->outResampler, 1221 0, 1222 session->procFrame->_payloadData, 1223 &frIn, 1224 session->outBuf + session->framesOut * session->outChannelCount, 1225 &frOut); 1226 } else { 1227 speex_resampler_process_interleaved_int(session->outResampler, 1228 session->procFrame->_payloadData, 1229 &frIn, 1230 session->outBuf + session->framesOut * session->outChannelCount, 1231 &frOut); 1232 } 1233 session->framesOut += frOut; 1234 } else { 1235 memcpy(session->outBuf + session->framesOut * session->outChannelCount, 1236 session->procFrame->_payloadData, 1237 session->frameCount * session->outChannelCount * sizeof(int16_t)); 1238 session->framesOut += session->frameCount; 1239 } 1240 size_t fr = session->framesOut; 1241 if (framesRq - framesWr < fr) { 1242 fr = framesRq - framesWr; 1243 } 1244 memcpy(outBuffer->s16 + framesWr * session->outChannelCount, 1245 session->outBuf, 1246 fr * session->outChannelCount * sizeof(int16_t)); 1247 memcpy(session->outBuf, 1248 session->outBuf + fr * session->outChannelCount, 1249 (session->framesOut - fr) * session->outChannelCount * sizeof(int16_t)); 1250 session->framesOut -= fr; 1251 outBuffer->frameCount += fr; 1252 1253 return 0; 1254 } else { 1255 return -ENODATA; 1256 } 1257} 1258 1259int PreProcessingFx_Command(effect_handle_t self, 1260 uint32_t cmdCode, 1261 uint32_t cmdSize, 1262 void *pCmdData, 1263 uint32_t *replySize, 1264 void *pReplyData) 1265{ 1266 preproc_effect_t * effect = (preproc_effect_t *) self; 1267 int retsize; 1268 int status; 1269 1270 if (effect == NULL){ 1271 return -EINVAL; 1272 } 1273 1274 //ALOGV("PreProcessingFx_Command: command %d cmdSize %d",cmdCode, cmdSize); 1275 1276 switch (cmdCode){ 1277 case EFFECT_CMD_INIT: 1278 if (pReplyData == NULL || *replySize != sizeof(int)){ 1279 return -EINVAL; 1280 } 1281 if (effect->ops->init) { 1282 effect->ops->init(effect); 1283 } 1284 *(int *)pReplyData = 0; 1285 break; 1286 1287 case EFFECT_CMD_SET_CONFIG: 1288 if (pCmdData == NULL|| 1289 cmdSize != sizeof(effect_config_t)|| 1290 pReplyData == NULL|| 1291 *replySize != sizeof(int)){ 1292 ALOGV("PreProcessingFx_Command cmdCode Case: " 1293 "EFFECT_CMD_SET_CONFIG: ERROR"); 1294 return -EINVAL; 1295 } 1296 *(int *)pReplyData = Session_SetConfig(effect->session, (effect_config_t *)pCmdData); 1297 if (*(int *)pReplyData != 0) { 1298 break; 1299 } 1300 if (effect->state != PREPROC_EFFECT_STATE_ACTIVE) { 1301 *(int *)pReplyData = Effect_SetState(effect, PREPROC_EFFECT_STATE_CONFIG); 1302 } 1303 break; 1304 1305 case EFFECT_CMD_GET_CONFIG: 1306 if (pReplyData == NULL || 1307 *replySize != sizeof(effect_config_t)) { 1308 ALOGV("\tLVM_ERROR : PreProcessingFx_Command cmdCode Case: " 1309 "EFFECT_CMD_GET_CONFIG: ERROR"); 1310 return -EINVAL; 1311 } 1312 1313 Session_GetConfig(effect->session, (effect_config_t *)pReplyData); 1314 break; 1315 1316 case EFFECT_CMD_SET_CONFIG_REVERSE: 1317 if (pCmdData == NULL || 1318 cmdSize != sizeof(effect_config_t) || 1319 pReplyData == NULL || 1320 *replySize != sizeof(int)) { 1321 ALOGV("PreProcessingFx_Command cmdCode Case: " 1322 "EFFECT_CMD_SET_CONFIG_REVERSE: ERROR"); 1323 return -EINVAL; 1324 } 1325 *(int *)pReplyData = Session_SetReverseConfig(effect->session, 1326 (effect_config_t *)pCmdData); 1327 if (*(int *)pReplyData != 0) { 1328 break; 1329 } 1330 break; 1331 1332 case EFFECT_CMD_GET_CONFIG_REVERSE: 1333 if (pReplyData == NULL || 1334 *replySize != sizeof(effect_config_t)){ 1335 ALOGV("PreProcessingFx_Command cmdCode Case: " 1336 "EFFECT_CMD_GET_CONFIG_REVERSE: ERROR"); 1337 return -EINVAL; 1338 } 1339 Session_GetReverseConfig(effect->session, (effect_config_t *)pCmdData); 1340 break; 1341 1342 case EFFECT_CMD_RESET: 1343 if (effect->ops->reset) { 1344 effect->ops->reset(effect); 1345 } 1346 break; 1347 1348 case EFFECT_CMD_GET_PARAM:{ 1349 if (pCmdData == NULL || 1350 cmdSize < (int)sizeof(effect_param_t) || 1351 pReplyData == NULL || 1352 *replySize < (int)sizeof(effect_param_t)){ 1353 ALOGV("PreProcessingFx_Command cmdCode Case: " 1354 "EFFECT_CMD_GET_PARAM: ERROR"); 1355 return -EINVAL; 1356 } 1357 effect_param_t *p = (effect_param_t *)pCmdData; 1358 1359 memcpy(pReplyData, pCmdData, sizeof(effect_param_t) + p->psize); 1360 1361 p = (effect_param_t *)pReplyData; 1362 1363 int voffset = ((p->psize - 1) / sizeof(int32_t) + 1) * sizeof(int32_t); 1364 1365 if (effect->ops->get_parameter) { 1366 p->status = effect->ops->get_parameter(effect, p->data, 1367 (size_t *)&p->vsize, 1368 p->data + voffset); 1369 *replySize = sizeof(effect_param_t) + voffset + p->vsize; 1370 } 1371 } break; 1372 1373 case EFFECT_CMD_SET_PARAM:{ 1374 if (pCmdData == NULL|| 1375 cmdSize < (int)sizeof(effect_param_t) || 1376 pReplyData == NULL || 1377 *replySize != sizeof(int32_t)){ 1378 ALOGV("PreProcessingFx_Command cmdCode Case: " 1379 "EFFECT_CMD_SET_PARAM: ERROR"); 1380 return -EINVAL; 1381 } 1382 effect_param_t *p = (effect_param_t *) pCmdData; 1383 1384 if (p->psize != sizeof(int32_t)){ 1385 ALOGV("PreProcessingFx_Command cmdCode Case: " 1386 "EFFECT_CMD_SET_PARAM: ERROR, psize is not sizeof(int32_t)"); 1387 return -EINVAL; 1388 } 1389 if (effect->ops->set_parameter) { 1390 *(int *)pReplyData = effect->ops->set_parameter(effect, 1391 (void *)p->data, 1392 p->data + p->psize); 1393 } 1394 } break; 1395 1396 case EFFECT_CMD_ENABLE: 1397 if (pReplyData == NULL || *replySize != sizeof(int)){ 1398 ALOGV("PreProcessingFx_Command cmdCode Case: EFFECT_CMD_ENABLE: ERROR"); 1399 return -EINVAL; 1400 } 1401 *(int *)pReplyData = Effect_SetState(effect, PREPROC_EFFECT_STATE_ACTIVE); 1402 break; 1403 1404 case EFFECT_CMD_DISABLE: 1405 if (pReplyData == NULL || *replySize != sizeof(int)){ 1406 ALOGV("PreProcessingFx_Command cmdCode Case: EFFECT_CMD_DISABLE: ERROR"); 1407 return -EINVAL; 1408 } 1409 *(int *)pReplyData = Effect_SetState(effect, PREPROC_EFFECT_STATE_CONFIG); 1410 break; 1411 1412 case EFFECT_CMD_SET_DEVICE: 1413 case EFFECT_CMD_SET_INPUT_DEVICE: 1414 if (pCmdData == NULL || 1415 cmdSize != sizeof(uint32_t)) { 1416 ALOGV("PreProcessingFx_Command cmdCode Case: EFFECT_CMD_SET_DEVICE: ERROR"); 1417 return -EINVAL; 1418 } 1419 1420 if (effect->ops->set_device) { 1421 effect->ops->set_device(effect, *(uint32_t *)pCmdData); 1422 } 1423 break; 1424 1425 case EFFECT_CMD_SET_VOLUME: 1426 case EFFECT_CMD_SET_AUDIO_MODE: 1427 break; 1428 1429 default: 1430 return -EINVAL; 1431 } 1432 return 0; 1433} 1434 1435 1436int PreProcessingFx_GetDescriptor(effect_handle_t self, 1437 effect_descriptor_t *pDescriptor) 1438{ 1439 preproc_effect_t * effect = (preproc_effect_t *) self; 1440 1441 if (effect == NULL || pDescriptor == NULL) { 1442 return -EINVAL; 1443 } 1444 1445 memcpy(pDescriptor, sDescriptors[effect->procId], sizeof(effect_descriptor_t)); 1446 1447 return 0; 1448} 1449 1450int PreProcessingFx_ProcessReverse(effect_handle_t self, 1451 audio_buffer_t *inBuffer, 1452 audio_buffer_t *outBuffer) 1453{ 1454 preproc_effect_t * effect = (preproc_effect_t *)self; 1455 int status = 0; 1456 1457 if (effect == NULL){ 1458 ALOGW("PreProcessingFx_ProcessReverse() ERROR effect == NULL"); 1459 return -EINVAL; 1460 } 1461 preproc_session_t * session = (preproc_session_t *)effect->session; 1462 1463 if (inBuffer == NULL || inBuffer->raw == NULL){ 1464 ALOGW("PreProcessingFx_ProcessReverse() ERROR bad pointer"); 1465 return -EINVAL; 1466 } 1467 1468 session->revProcessedMsk |= (1<<effect->procId); 1469 1470// ALOGV("PreProcessingFx_ProcessReverse In %d frames revEnabledMsk %08x revProcessedMsk %08x", 1471// inBuffer->frameCount, session->revEnabledMsk, session->revProcessedMsk); 1472 1473 1474 if ((session->revProcessedMsk & session->revEnabledMsk) == session->revEnabledMsk) { 1475 effect->session->revProcessedMsk = 0; 1476 if (session->revResampler != NULL) { 1477 size_t fr = session->frameCount - session->framesRev; 1478 if (inBuffer->frameCount < fr) { 1479 fr = inBuffer->frameCount; 1480 } 1481 if (session->revBufSize < session->framesRev + fr) { 1482 session->revBufSize = session->framesRev + fr; 1483 session->revBuf = (int16_t *)realloc(session->revBuf, 1484 session->revBufSize * session->inChannelCount * sizeof(int16_t)); 1485 } 1486 memcpy(session->revBuf + session->framesRev * session->inChannelCount, 1487 inBuffer->s16, 1488 fr * session->inChannelCount * sizeof(int16_t)); 1489 1490 session->framesRev += fr; 1491 inBuffer->frameCount = fr; 1492 if (session->framesRev < session->frameCount) { 1493 return 0; 1494 } 1495 size_t frIn = session->framesRev; 1496 size_t frOut = session->apmFrameCount; 1497 if (session->inChannelCount == 1) { 1498 speex_resampler_process_int(session->revResampler, 1499 0, 1500 session->revBuf, 1501 &frIn, 1502 session->revFrame->_payloadData, 1503 &frOut); 1504 } else { 1505 speex_resampler_process_interleaved_int(session->revResampler, 1506 session->revBuf, 1507 &frIn, 1508 session->revFrame->_payloadData, 1509 &frOut); 1510 } 1511 memcpy(session->revBuf, 1512 session->revBuf + frIn * session->inChannelCount, 1513 (session->framesRev - frIn) * session->inChannelCount * sizeof(int16_t)); 1514 session->framesRev -= frIn; 1515 } else { 1516 size_t fr = session->frameCount - session->framesRev; 1517 if (inBuffer->frameCount < fr) { 1518 fr = inBuffer->frameCount; 1519 } 1520 memcpy(session->revFrame->_payloadData + session->framesRev * session->inChannelCount, 1521 inBuffer->s16, 1522 fr * session->inChannelCount * sizeof(int16_t)); 1523 session->framesRev += fr; 1524 inBuffer->frameCount = fr; 1525 if (session->framesRev < session->frameCount) { 1526 return 0; 1527 } 1528 session->framesRev = 0; 1529 } 1530 session->revFrame->_payloadDataLengthInSamples = 1531 session->apmFrameCount * session->inChannelCount; 1532 effect->session->apm->AnalyzeReverseStream(session->revFrame); 1533 return 0; 1534 } else { 1535 return -ENODATA; 1536 } 1537} 1538 1539 1540// effect_handle_t interface implementation for effect 1541const struct effect_interface_s sEffectInterface = { 1542 PreProcessingFx_Process, 1543 PreProcessingFx_Command, 1544 PreProcessingFx_GetDescriptor, 1545 NULL 1546}; 1547 1548const struct effect_interface_s sEffectInterfaceReverse = { 1549 PreProcessingFx_Process, 1550 PreProcessingFx_Command, 1551 PreProcessingFx_GetDescriptor, 1552 PreProcessingFx_ProcessReverse 1553}; 1554 1555//------------------------------------------------------------------------------ 1556// Effect Library Interface Implementation 1557//------------------------------------------------------------------------------ 1558 1559int PreProcessingLib_QueryNumberEffects(uint32_t *pNumEffects) 1560{ 1561 if (PreProc_Init() != 0) { 1562 return sInitStatus; 1563 } 1564 if (pNumEffects == NULL) { 1565 return -EINVAL; 1566 } 1567 *pNumEffects = PREPROC_NUM_EFFECTS; 1568 return sInitStatus; 1569} 1570 1571int PreProcessingLib_QueryEffect(uint32_t index, effect_descriptor_t *pDescriptor) 1572{ 1573 if (PreProc_Init() != 0) { 1574 return sInitStatus; 1575 } 1576 if (index >= PREPROC_NUM_EFFECTS) { 1577 return -EINVAL; 1578 } 1579 memcpy(pDescriptor, sDescriptors[index], sizeof(effect_descriptor_t)); 1580 return 0; 1581} 1582 1583int PreProcessingLib_Create(const effect_uuid_t *uuid, 1584 int32_t sessionId, 1585 int32_t ioId, 1586 effect_handle_t *pInterface) 1587{ 1588 ALOGV("EffectCreate: uuid: %08x session %d IO: %d", uuid->timeLow, sessionId, ioId); 1589 1590 int status; 1591 const effect_descriptor_t *desc; 1592 preproc_session_t *session; 1593 uint32_t procId; 1594 1595 if (PreProc_Init() != 0) { 1596 return sInitStatus; 1597 } 1598 desc = PreProc_GetDescriptor(uuid); 1599 if (desc == NULL) { 1600 ALOGW("EffectCreate: fx not found uuid: %08x", uuid->timeLow); 1601 return -EINVAL; 1602 } 1603 procId = UuidToProcId(&desc->type); 1604 1605 session = PreProc_GetSession(procId, sessionId, ioId); 1606 if (session == NULL) { 1607 ALOGW("EffectCreate: no more session available"); 1608 return -EINVAL; 1609 } 1610 1611 status = Session_CreateEffect(session, procId, pInterface); 1612 1613 if (status < 0 && session->createdMsk == 0) { 1614 session->io = 0; 1615 } 1616 return status; 1617} 1618 1619int PreProcessingLib_Release(effect_handle_t interface) 1620{ 1621 int status; 1622 ALOGV("EffectRelease start %p", interface); 1623 if (PreProc_Init() != 0) { 1624 return sInitStatus; 1625 } 1626 1627 preproc_effect_t *fx = (preproc_effect_t *)interface; 1628 1629 if (fx->session->io == 0) { 1630 return -EINVAL; 1631 } 1632 return Session_ReleaseEffect(fx->session, fx); 1633} 1634 1635int PreProcessingLib_GetDescriptor(const effect_uuid_t *uuid, 1636 effect_descriptor_t *pDescriptor) { 1637 1638 if (pDescriptor == NULL || uuid == NULL){ 1639 return -EINVAL; 1640 } 1641 1642 const effect_descriptor_t *desc = PreProc_GetDescriptor(uuid); 1643 if (desc == NULL) { 1644 ALOGV("PreProcessingLib_GetDescriptor() not found"); 1645 return -EINVAL; 1646 } 1647 1648 ALOGV("PreProcessingLib_GetDescriptor() got fx %s", desc->name); 1649 1650 memcpy(pDescriptor, desc, sizeof(effect_descriptor_t)); 1651 return 0; 1652} 1653 1654audio_effect_library_t AUDIO_EFFECT_LIBRARY_INFO_SYM = { 1655 tag : AUDIO_EFFECT_LIBRARY_TAG, 1656 version : EFFECT_LIBRARY_API_VERSION, 1657 name : "Audio Preprocessing Library", 1658 implementor : "The Android Open Source Project", 1659 query_num_effects : PreProcessingLib_QueryNumberEffects, 1660 query_effect : PreProcessingLib_QueryEffect, 1661 create_effect : PreProcessingLib_Create, 1662 release_effect : PreProcessingLib_Release, 1663 get_descriptor : PreProcessingLib_GetDescriptor 1664}; 1665 1666}; // extern "C" 1667