PreProcessing.cpp revision 3856b090cd04ba5dd4a59a12430ed724d5995909
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 "modules/interface/module_common_types.h" 28#include "modules/audio_processing/main/interface/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 = 0; 224static const int kAgcDefaultCompGain = 90; 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 LOGW("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 LOGW("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 LOGW("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 LOGW("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 LOGW("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 LOGW("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 LOGW("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 LOGW("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 LOGE("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 LOGE("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 LOGE("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 LOGW("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 LOGW("Session_CreateEffect could not allocate audio frame"); 742 goto error; 743 } 744 session->revFrame = new webrtc::AudioFrame(); 745 if (session->revFrame == NULL) { 746 LOGW("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 LOGW_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 LOGW("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 LOGW("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 LOGW("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 943int Session_SetReverseConfig(preproc_session_t *session, effect_config_t *config) 944{ 945 if (config->inputCfg.samplingRate != config->outputCfg.samplingRate || 946 config->inputCfg.format != config->outputCfg.format || 947 config->inputCfg.format != AUDIO_FORMAT_PCM_16_BIT) { 948 return -EINVAL; 949 } 950 951 ALOGV("Session_SetReverseConfig sr %d cnl %08x", 952 config->inputCfg.samplingRate, config->inputCfg.channels); 953 954 if (session->state < PREPROC_SESSION_STATE_CONFIG) { 955 return -ENOSYS; 956 } 957 if (config->inputCfg.samplingRate != session->samplingRate || 958 config->inputCfg.format != AUDIO_FORMAT_PCM_16_BIT) { 959 return -EINVAL; 960 } 961 uint32_t inCnl = popcount(config->inputCfg.channels); 962 int status = session->apm->set_num_reverse_channels(inCnl); 963 if (status < 0) { 964 return -EINVAL; 965 } 966 session->revChannelCount = inCnl; 967 session->revFrame->_audioChannel = inCnl; 968 session->revFrame->_frequencyInHz = session->apmSamplingRate; 969 return 0; 970} 971 972void Session_SetProcEnabled(preproc_session_t *session, uint32_t procId, bool enabled) 973{ 974 if (enabled) { 975 if(session->enabledMsk == 0) { 976 session->framesIn = 0; 977 if (session->inResampler != NULL) { 978 speex_resampler_reset_mem(session->inResampler); 979 } 980 session->framesOut = 0; 981 if (session->outResampler != NULL) { 982 speex_resampler_reset_mem(session->outResampler); 983 } 984 } 985 session->enabledMsk |= (1 << procId); 986 if (HasReverseStream(procId)) { 987 session->framesRev = 0; 988 if (session->revResampler != NULL) { 989 speex_resampler_reset_mem(session->revResampler); 990 } 991 session->revEnabledMsk |= (1 << procId); 992 } 993 } else { 994 session->enabledMsk &= ~(1 << procId); 995 if (HasReverseStream(procId)) { 996 session->revEnabledMsk &= ~(1 << procId); 997 } 998 } 999 ALOGV("Session_SetProcEnabled proc %d, enabled %d enabledMsk %08x revEnabledMsk %08x", 1000 procId, enabled, session->enabledMsk, session->revEnabledMsk); 1001 session->processedMsk = 0; 1002 if (HasReverseStream(procId)) { 1003 session->revProcessedMsk = 0; 1004 } 1005} 1006 1007//------------------------------------------------------------------------------ 1008// Bundle functions 1009//------------------------------------------------------------------------------ 1010 1011static int sInitStatus = 1; 1012static preproc_session_t sSessions[PREPROC_NUM_SESSIONS]; 1013 1014preproc_session_t *PreProc_GetSession(int32_t procId, int32_t sessionId, int32_t ioId) 1015{ 1016 size_t i; 1017 int free = -1; 1018 for (i = 0; i < PREPROC_NUM_SESSIONS; i++) { 1019 if (sSessions[i].io == ioId) { 1020 if (sSessions[i].createdMsk & (1 << procId)) { 1021 return NULL; 1022 } 1023 return &sSessions[i]; 1024 } 1025 } 1026 for (i = 0; i < PREPROC_NUM_SESSIONS; i++) { 1027 if (sSessions[i].io == 0) { 1028 sSessions[i].id = sessionId; 1029 sSessions[i].io = ioId; 1030 return &sSessions[i]; 1031 } 1032 } 1033 return NULL; 1034} 1035 1036 1037int PreProc_Init() { 1038 size_t i; 1039 int status = 0; 1040 1041 if (sInitStatus <= 0) { 1042 return sInitStatus; 1043 } 1044 for (i = 0; i < PREPROC_NUM_SESSIONS && status == 0; i++) { 1045 status = Session_Init(&sSessions[i]); 1046 } 1047 sInitStatus = status; 1048 return sInitStatus; 1049} 1050 1051const effect_descriptor_t *PreProc_GetDescriptor(effect_uuid_t *uuid) 1052{ 1053 size_t i; 1054 for (i = 0; i < PREPROC_NUM_EFFECTS; i++) { 1055 if (memcmp(&sDescriptors[i]->uuid, uuid, sizeof(effect_uuid_t)) == 0) { 1056 return sDescriptors[i]; 1057 } 1058 } 1059 return NULL; 1060} 1061 1062 1063extern "C" { 1064 1065//------------------------------------------------------------------------------ 1066// Effect Control Interface Implementation 1067//------------------------------------------------------------------------------ 1068 1069int PreProcessingFx_Process(effect_handle_t self, 1070 audio_buffer_t *inBuffer, 1071 audio_buffer_t *outBuffer) 1072{ 1073 preproc_effect_t * effect = (preproc_effect_t *)self; 1074 int status = 0; 1075 1076 if (effect == NULL){ 1077 ALOGV("PreProcessingFx_Process() ERROR effect == NULL"); 1078 return -EINVAL; 1079 } 1080 preproc_session_t * session = (preproc_session_t *)effect->session; 1081 1082 if (inBuffer == NULL || inBuffer->raw == NULL || 1083 outBuffer == NULL || outBuffer->raw == NULL){ 1084 LOGW("PreProcessingFx_Process() ERROR bad pointer"); 1085 return -EINVAL; 1086 } 1087 1088 session->processedMsk |= (1<<effect->procId); 1089 1090// ALOGV("PreProcessingFx_Process In %d frames enabledMsk %08x processedMsk %08x", 1091// inBuffer->frameCount, session->enabledMsk, session->processedMsk); 1092 1093 if ((session->processedMsk & session->enabledMsk) == session->enabledMsk) { 1094 effect->session->processedMsk = 0; 1095 size_t framesRq = outBuffer->frameCount; 1096 size_t framesWr = 0; 1097 if (session->framesOut) { 1098 size_t fr = session->framesOut; 1099 if (outBuffer->frameCount < fr) { 1100 fr = outBuffer->frameCount; 1101 } 1102 memcpy(outBuffer->s16, 1103 session->outBuf, 1104 fr * session->outChannelCount * sizeof(int16_t)); 1105 memcpy(session->outBuf, 1106 session->outBuf + fr * session->outChannelCount, 1107 (session->framesOut - fr) * session->outChannelCount * sizeof(int16_t)); 1108 session->framesOut -= fr; 1109 framesWr += fr; 1110 } 1111 outBuffer->frameCount = framesWr; 1112 if (framesWr == framesRq) { 1113 inBuffer->frameCount = 0; 1114 return 0; 1115 } 1116 1117 if (session->inResampler != NULL) { 1118 size_t fr = session->frameCount - session->framesIn; 1119 if (inBuffer->frameCount < fr) { 1120 fr = inBuffer->frameCount; 1121 } 1122 if (session->inBufSize < session->framesIn + fr) { 1123 session->inBufSize = session->framesIn + fr; 1124 session->inBuf = (int16_t *)realloc(session->inBuf, 1125 session->inBufSize * session->inChannelCount * sizeof(int16_t)); 1126 } 1127 memcpy(session->inBuf + session->framesIn * session->inChannelCount, 1128 inBuffer->s16, 1129 fr * session->inChannelCount * sizeof(int16_t)); 1130 1131 session->framesIn += fr; 1132 inBuffer->frameCount = fr; 1133 if (session->framesIn < session->frameCount) { 1134 return 0; 1135 } 1136 size_t frIn = session->framesIn; 1137 size_t frOut = session->apmFrameCount; 1138 if (session->inChannelCount == 1) { 1139 speex_resampler_process_int(session->inResampler, 1140 0, 1141 session->inBuf, 1142 &frIn, 1143 session->procFrame->_payloadData, 1144 &frOut); 1145 } else { 1146 speex_resampler_process_interleaved_int(session->inResampler, 1147 session->inBuf, 1148 &frIn, 1149 session->procFrame->_payloadData, 1150 &frOut); 1151 } 1152 memcpy(session->inBuf, 1153 session->inBuf + frIn * session->inChannelCount, 1154 (session->framesIn - frIn) * session->inChannelCount * sizeof(int16_t)); 1155 session->framesIn -= frIn; 1156 } else { 1157 size_t fr = session->frameCount - session->framesIn; 1158 if (inBuffer->frameCount < fr) { 1159 fr = inBuffer->frameCount; 1160 } 1161 memcpy(session->procFrame->_payloadData + session->framesIn * session->inChannelCount, 1162 inBuffer->s16, 1163 fr * session->inChannelCount * sizeof(int16_t)); 1164 session->framesIn += fr; 1165 inBuffer->frameCount = fr; 1166 if (session->framesIn < session->frameCount) { 1167 return 0; 1168 } 1169 session->framesIn = 0; 1170 } 1171 session->procFrame->_payloadDataLengthInSamples = 1172 session->apmFrameCount * session->inChannelCount; 1173 1174 effect->session->apm->ProcessStream(session->procFrame); 1175 1176 if (session->outBufSize < session->framesOut + session->frameCount) { 1177 session->outBufSize = session->framesOut + session->frameCount; 1178 session->outBuf = (int16_t *)realloc(session->outBuf, 1179 session->outBufSize * session->outChannelCount * sizeof(int16_t)); 1180 } 1181 1182 if (session->outResampler != NULL) { 1183 size_t frIn = session->apmFrameCount; 1184 size_t frOut = session->frameCount; 1185 if (session->inChannelCount == 1) { 1186 speex_resampler_process_int(session->outResampler, 1187 0, 1188 session->procFrame->_payloadData, 1189 &frIn, 1190 session->outBuf + session->framesOut * session->outChannelCount, 1191 &frOut); 1192 } else { 1193 speex_resampler_process_interleaved_int(session->outResampler, 1194 session->procFrame->_payloadData, 1195 &frIn, 1196 session->outBuf + session->framesOut * session->outChannelCount, 1197 &frOut); 1198 } 1199 session->framesOut += frOut; 1200 } else { 1201 memcpy(session->outBuf + session->framesOut * session->outChannelCount, 1202 session->procFrame->_payloadData, 1203 session->frameCount * session->outChannelCount * sizeof(int16_t)); 1204 session->framesOut += session->frameCount; 1205 } 1206 size_t fr = session->framesOut; 1207 if (framesRq - framesWr < fr) { 1208 fr = framesRq - framesWr; 1209 } 1210 memcpy(outBuffer->s16 + framesWr * session->outChannelCount, 1211 session->outBuf, 1212 fr * session->outChannelCount * sizeof(int16_t)); 1213 memcpy(session->outBuf, 1214 session->outBuf + fr * session->outChannelCount, 1215 (session->framesOut - fr) * session->outChannelCount * sizeof(int16_t)); 1216 session->framesOut -= fr; 1217 outBuffer->frameCount += fr; 1218 1219 return 0; 1220 } else { 1221 return -ENODATA; 1222 } 1223} 1224 1225int PreProcessingFx_Command(effect_handle_t self, 1226 uint32_t cmdCode, 1227 uint32_t cmdSize, 1228 void *pCmdData, 1229 uint32_t *replySize, 1230 void *pReplyData) 1231{ 1232 preproc_effect_t * effect = (preproc_effect_t *) self; 1233 int retsize; 1234 int status; 1235 1236 if (effect == NULL){ 1237 return -EINVAL; 1238 } 1239 1240 //ALOGV("PreProcessingFx_Command: command %d cmdSize %d",cmdCode, cmdSize); 1241 1242 switch (cmdCode){ 1243 case EFFECT_CMD_INIT: 1244 if (pReplyData == NULL || *replySize != sizeof(int)){ 1245 return -EINVAL; 1246 } 1247 if (effect->ops->init) { 1248 effect->ops->init(effect); 1249 } 1250 *(int *)pReplyData = 0; 1251 break; 1252 1253 case EFFECT_CMD_CONFIGURE: 1254 if (pCmdData == NULL|| 1255 cmdSize != sizeof(effect_config_t)|| 1256 pReplyData == NULL|| 1257 *replySize != sizeof(int)){ 1258 ALOGV("PreProcessingFx_Command cmdCode Case: " 1259 "EFFECT_CMD_CONFIGURE: ERROR"); 1260 return -EINVAL; 1261 } 1262 *(int *)pReplyData = Session_SetConfig(effect->session, (effect_config_t *)pCmdData); 1263 if (*(int *)pReplyData != 0) { 1264 break; 1265 } 1266 *(int *)pReplyData = Effect_SetState(effect, PREPROC_EFFECT_STATE_CONFIG); 1267 break; 1268 1269 case EFFECT_CMD_CONFIGURE_REVERSE: 1270 if (pCmdData == NULL|| 1271 cmdSize != sizeof(effect_config_t)|| 1272 pReplyData == NULL|| 1273 *replySize != sizeof(int)){ 1274 ALOGV("PreProcessingFx_Command cmdCode Case: " 1275 "EFFECT_CMD_CONFIGURE_REVERSE: ERROR"); 1276 return -EINVAL; 1277 } 1278 *(int *)pReplyData = Session_SetReverseConfig(effect->session, 1279 (effect_config_t *)pCmdData); 1280 if (*(int *)pReplyData != 0) { 1281 break; 1282 } 1283 break; 1284 1285 case EFFECT_CMD_RESET: 1286 if (effect->ops->reset) { 1287 effect->ops->reset(effect); 1288 } 1289 break; 1290 1291 case EFFECT_CMD_GET_PARAM:{ 1292 if (pCmdData == NULL || 1293 cmdSize < (int)sizeof(effect_param_t) || 1294 pReplyData == NULL || 1295 *replySize < (int)sizeof(effect_param_t)){ 1296 ALOGV("PreProcessingFx_Command cmdCode Case: " 1297 "EFFECT_CMD_GET_PARAM: ERROR"); 1298 return -EINVAL; 1299 } 1300 effect_param_t *p = (effect_param_t *)pCmdData; 1301 1302 memcpy(pReplyData, pCmdData, sizeof(effect_param_t) + p->psize); 1303 1304 p = (effect_param_t *)pReplyData; 1305 1306 int voffset = ((p->psize - 1) / sizeof(int32_t) + 1) * sizeof(int32_t); 1307 1308 if (effect->ops->get_parameter) { 1309 p->status = effect->ops->get_parameter(effect, p->data, 1310 (size_t *)&p->vsize, 1311 p->data + voffset); 1312 *replySize = sizeof(effect_param_t) + voffset + p->vsize; 1313 } 1314 } break; 1315 1316 case EFFECT_CMD_SET_PARAM:{ 1317 if (pCmdData == NULL|| 1318 cmdSize < (int)sizeof(effect_param_t) || 1319 pReplyData == NULL || 1320 *replySize != sizeof(int32_t)){ 1321 ALOGV("PreProcessingFx_Command cmdCode Case: " 1322 "EFFECT_CMD_SET_PARAM: ERROR"); 1323 return -EINVAL; 1324 } 1325 effect_param_t *p = (effect_param_t *) pCmdData; 1326 1327 if (p->psize != sizeof(int32_t)){ 1328 ALOGV("PreProcessingFx_Command cmdCode Case: " 1329 "EFFECT_CMD_SET_PARAM: ERROR, psize is not sizeof(int32_t)"); 1330 return -EINVAL; 1331 } 1332 if (effect->ops->set_parameter) { 1333 *(int *)pReplyData = effect->ops->set_parameter(effect, 1334 (void *)p->data, 1335 p->data + p->psize); 1336 } 1337 } break; 1338 1339 case EFFECT_CMD_ENABLE: 1340 if (pReplyData == NULL || *replySize != sizeof(int)){ 1341 ALOGV("PreProcessingFx_Command cmdCode Case: EFFECT_CMD_ENABLE: ERROR"); 1342 return -EINVAL; 1343 } 1344 *(int *)pReplyData = Effect_SetState(effect, PREPROC_EFFECT_STATE_ACTIVE); 1345 break; 1346 1347 case EFFECT_CMD_DISABLE: 1348 if (pReplyData == NULL || *replySize != sizeof(int)){ 1349 ALOGV("PreProcessingFx_Command cmdCode Case: EFFECT_CMD_DISABLE: ERROR"); 1350 return -EINVAL; 1351 } 1352 *(int *)pReplyData = Effect_SetState(effect, PREPROC_EFFECT_STATE_CONFIG); 1353 break; 1354 1355 case EFFECT_CMD_SET_DEVICE: 1356 case EFFECT_CMD_SET_INPUT_DEVICE: 1357 if (pCmdData == NULL || 1358 cmdSize != sizeof(uint32_t)) { 1359 ALOGV("PreProcessingFx_Command cmdCode Case: EFFECT_CMD_SET_DEVICE: ERROR"); 1360 return -EINVAL; 1361 } 1362 1363 if (effect->ops->set_device) { 1364 effect->ops->set_device(effect, *(uint32_t *)pCmdData); 1365 } 1366 break; 1367 1368 case EFFECT_CMD_SET_VOLUME: 1369 case EFFECT_CMD_SET_AUDIO_MODE: 1370 break; 1371 1372 default: 1373 return -EINVAL; 1374 } 1375 return 0; 1376} 1377 1378 1379int PreProcessingFx_GetDescriptor(effect_handle_t self, 1380 effect_descriptor_t *pDescriptor) 1381{ 1382 preproc_effect_t * effect = (preproc_effect_t *) self; 1383 1384 if (effect == NULL || pDescriptor == NULL) { 1385 return -EINVAL; 1386 } 1387 1388 memcpy(pDescriptor, sDescriptors[effect->procId], sizeof(effect_descriptor_t)); 1389 1390 return 0; 1391} 1392 1393int PreProcessingFx_ProcessReverse(effect_handle_t self, 1394 audio_buffer_t *inBuffer, 1395 audio_buffer_t *outBuffer) 1396{ 1397 preproc_effect_t * effect = (preproc_effect_t *)self; 1398 int status = 0; 1399 1400 if (effect == NULL){ 1401 LOGW("PreProcessingFx_ProcessReverse() ERROR effect == NULL"); 1402 return -EINVAL; 1403 } 1404 preproc_session_t * session = (preproc_session_t *)effect->session; 1405 1406 if (inBuffer == NULL || inBuffer->raw == NULL){ 1407 LOGW("PreProcessingFx_ProcessReverse() ERROR bad pointer"); 1408 return -EINVAL; 1409 } 1410 1411 session->revProcessedMsk |= (1<<effect->procId); 1412 1413// ALOGV("PreProcessingFx_ProcessReverse In %d frames revEnabledMsk %08x revProcessedMsk %08x", 1414// inBuffer->frameCount, session->revEnabledMsk, session->revProcessedMsk); 1415 1416 1417 if ((session->revProcessedMsk & session->revEnabledMsk) == session->revEnabledMsk) { 1418 effect->session->revProcessedMsk = 0; 1419 if (session->revResampler != NULL) { 1420 size_t fr = session->frameCount - session->framesRev; 1421 if (inBuffer->frameCount < fr) { 1422 fr = inBuffer->frameCount; 1423 } 1424 if (session->revBufSize < session->framesRev + fr) { 1425 session->revBufSize = session->framesRev + fr; 1426 session->revBuf = (int16_t *)realloc(session->revBuf, 1427 session->revBufSize * session->inChannelCount * sizeof(int16_t)); 1428 } 1429 memcpy(session->revBuf + session->framesRev * session->inChannelCount, 1430 inBuffer->s16, 1431 fr * session->inChannelCount * sizeof(int16_t)); 1432 1433 session->framesRev += fr; 1434 inBuffer->frameCount = fr; 1435 if (session->framesRev < session->frameCount) { 1436 return 0; 1437 } 1438 size_t frIn = session->framesRev; 1439 size_t frOut = session->apmFrameCount; 1440 if (session->inChannelCount == 1) { 1441 speex_resampler_process_int(session->revResampler, 1442 0, 1443 session->revBuf, 1444 &frIn, 1445 session->revFrame->_payloadData, 1446 &frOut); 1447 } else { 1448 speex_resampler_process_interleaved_int(session->revResampler, 1449 session->revBuf, 1450 &frIn, 1451 session->revFrame->_payloadData, 1452 &frOut); 1453 } 1454 memcpy(session->revBuf, 1455 session->revBuf + frIn * session->inChannelCount, 1456 (session->framesRev - frIn) * session->inChannelCount * sizeof(int16_t)); 1457 session->framesRev -= frIn; 1458 } else { 1459 size_t fr = session->frameCount - session->framesRev; 1460 if (inBuffer->frameCount < fr) { 1461 fr = inBuffer->frameCount; 1462 } 1463 memcpy(session->revFrame->_payloadData + session->framesRev * session->inChannelCount, 1464 inBuffer->s16, 1465 fr * session->inChannelCount * sizeof(int16_t)); 1466 session->framesRev += fr; 1467 inBuffer->frameCount = fr; 1468 if (session->framesRev < session->frameCount) { 1469 return 0; 1470 } 1471 session->framesRev = 0; 1472 } 1473 session->revFrame->_payloadDataLengthInSamples = 1474 session->apmFrameCount * session->inChannelCount; 1475 effect->session->apm->AnalyzeReverseStream(session->revFrame); 1476 return 0; 1477 } else { 1478 return -ENODATA; 1479 } 1480} 1481 1482 1483// effect_handle_t interface implementation for effect 1484const struct effect_interface_s sEffectInterface = { 1485 PreProcessingFx_Process, 1486 PreProcessingFx_Command, 1487 PreProcessingFx_GetDescriptor, 1488 NULL 1489}; 1490 1491const struct effect_interface_s sEffectInterfaceReverse = { 1492 PreProcessingFx_Process, 1493 PreProcessingFx_Command, 1494 PreProcessingFx_GetDescriptor, 1495 PreProcessingFx_ProcessReverse 1496}; 1497 1498//------------------------------------------------------------------------------ 1499// Effect Library Interface Implementation 1500//------------------------------------------------------------------------------ 1501 1502int PreProcessingLib_QueryNumberEffects(uint32_t *pNumEffects) 1503{ 1504 if (PreProc_Init() != 0) { 1505 return sInitStatus; 1506 } 1507 if (pNumEffects == NULL) { 1508 return -EINVAL; 1509 } 1510 *pNumEffects = PREPROC_NUM_EFFECTS; 1511 return sInitStatus; 1512} 1513 1514int PreProcessingLib_QueryEffect(uint32_t index, effect_descriptor_t *pDescriptor) 1515{ 1516 if (PreProc_Init() != 0) { 1517 return sInitStatus; 1518 } 1519 if (index >= PREPROC_NUM_EFFECTS) { 1520 return -EINVAL; 1521 } 1522 memcpy(pDescriptor, sDescriptors[index], sizeof(effect_descriptor_t)); 1523 return 0; 1524} 1525 1526int PreProcessingLib_Create(effect_uuid_t *uuid, 1527 int32_t sessionId, 1528 int32_t ioId, 1529 effect_handle_t *pInterface) 1530{ 1531 ALOGV("EffectCreate: uuid: %08x session %d IO: %d", uuid->timeLow, sessionId, ioId); 1532 1533 int status; 1534 const effect_descriptor_t *desc; 1535 preproc_session_t *session; 1536 uint32_t procId; 1537 1538 if (PreProc_Init() != 0) { 1539 return sInitStatus; 1540 } 1541 desc = PreProc_GetDescriptor(uuid); 1542 if (desc == NULL) { 1543 LOGW("EffectCreate: fx not found uuid: %08x", uuid->timeLow); 1544 return -EINVAL; 1545 } 1546 procId = UuidToProcId(&desc->type); 1547 1548 session = PreProc_GetSession(procId, sessionId, ioId); 1549 if (session == NULL) { 1550 LOGW("EffectCreate: no more session available"); 1551 return -EINVAL; 1552 } 1553 1554 status = Session_CreateEffect(session, procId, pInterface); 1555 1556 if (status < 0 && session->createdMsk == 0) { 1557 session->io = 0; 1558 } 1559 return status; 1560} 1561 1562int PreProcessingLib_Release(effect_handle_t interface) 1563{ 1564 int status; 1565 ALOGV("EffectRelease start %p", interface); 1566 if (PreProc_Init() != 0) { 1567 return sInitStatus; 1568 } 1569 1570 preproc_effect_t *fx = (preproc_effect_t *)interface; 1571 1572 if (fx->session->io == 0) { 1573 return -EINVAL; 1574 } 1575 return Session_ReleaseEffect(fx->session, fx); 1576} 1577 1578int PreProcessingLib_GetDescriptor(effect_uuid_t *uuid, 1579 effect_descriptor_t *pDescriptor) { 1580 1581 if (pDescriptor == NULL || uuid == NULL){ 1582 return -EINVAL; 1583 } 1584 1585 const effect_descriptor_t *desc = PreProc_GetDescriptor(uuid); 1586 if (desc == NULL) { 1587 ALOGV("PreProcessingLib_GetDescriptor() not found"); 1588 return -EINVAL; 1589 } 1590 1591 ALOGV("PreProcessingLib_GetDescriptor() got fx %s", desc->name); 1592 1593 memcpy(pDescriptor, desc, sizeof(effect_descriptor_t)); 1594 return 0; 1595} 1596 1597audio_effect_library_t AUDIO_EFFECT_LIBRARY_INFO_SYM = { 1598 tag : AUDIO_EFFECT_LIBRARY_TAG, 1599 version : EFFECT_LIBRARY_API_VERSION, 1600 name : "Audio Preprocessing Library", 1601 implementor : "The Android Open Source Project", 1602 query_num_effects : PreProcessingLib_QueryNumberEffects, 1603 query_effect : PreProcessingLib_QueryEffect, 1604 create_effect : PreProcessingLib_Create, 1605 release_effect : PreProcessingLib_Release, 1606 get_descriptor : PreProcessingLib_GetDescriptor 1607}; 1608 1609}; // extern "C" 1610