1/* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include <stdlib.h> 18#include <string.h> 19#define LOG_TAG "PreProcessing" 20//#define LOG_NDEBUG 0 21#include <utils/Log.h> 22#include <utils/Timers.h> 23#include <hardware/audio_effect.h> 24#include <audio_effects/effect_aec.h> 25#include <audio_effects/effect_agc.h> 26#include <audio_effects/effect_ns.h> 27#include <module_common_types.h> 28#include <audio_processing.h> 29#include "speex/speex_resampler.h" 30 31// undefine to perform multi channels API functional tests 32//#define DUAL_MIC_TEST 33 34//------------------------------------------------------------------------------ 35// local definitions 36//------------------------------------------------------------------------------ 37 38// maximum number of sessions 39#define PREPROC_NUM_SESSIONS 8 40 41// types of pre processing modules 42enum preproc_id 43{ 44 PREPROC_AGC, // Automatic Gain Control 45 PREPROC_AEC, // Acoustic Echo Canceler 46 PREPROC_NS, // Noise Suppressor 47 PREPROC_NUM_EFFECTS 48}; 49 50// Session state 51enum preproc_session_state { 52 PREPROC_SESSION_STATE_INIT, // initialized 53 PREPROC_SESSION_STATE_CONFIG // configuration received 54}; 55 56// Effect/Preprocessor state 57enum preproc_effect_state { 58 PREPROC_EFFECT_STATE_INIT, // initialized 59 PREPROC_EFFECT_STATE_CREATED, // webRTC engine created 60 PREPROC_EFFECT_STATE_CONFIG, // configuration received/disabled 61 PREPROC_EFFECT_STATE_ACTIVE // active/enabled 62}; 63 64// handle on webRTC engine 65typedef void* preproc_fx_handle_t; 66 67typedef struct preproc_session_s preproc_session_t; 68typedef struct preproc_effect_s preproc_effect_t; 69typedef struct preproc_ops_s preproc_ops_t; 70 71// Effect operation table. Functions for all pre processors are declared in sPreProcOps[] table. 72// Function pointer can be null if no action required. 73struct preproc_ops_s { 74 int (* create)(preproc_effect_t *fx); 75 int (* init)(preproc_effect_t *fx); 76 int (* reset)(preproc_effect_t *fx); 77 void (* enable)(preproc_effect_t *fx); 78 void (* disable)(preproc_effect_t *fx); 79 int (* set_parameter)(preproc_effect_t *fx, void *param, void *value); 80 int (* get_parameter)(preproc_effect_t *fx, void *param, uint32_t *size, void *value); 81 int (* set_device)(preproc_effect_t *fx, uint32_t device); 82}; 83 84// Effect context 85struct preproc_effect_s { 86 const struct effect_interface_s *itfe; 87 uint32_t procId; // type of pre processor (enum preproc_id) 88 uint32_t state; // current state (enum preproc_effect_state) 89 preproc_session_t *session; // session the effect is on 90 const preproc_ops_t *ops; // effect ops table 91 preproc_fx_handle_t engine; // handle on webRTC engine 92 uint32_t type; // subtype of effect 93#ifdef DUAL_MIC_TEST 94 bool aux_channels_on; // support auxiliary channels 95 size_t cur_channel_config; // current auciliary channel configuration 96#endif 97}; 98 99// Session context 100struct preproc_session_s { 101 struct preproc_effect_s effects[PREPROC_NUM_EFFECTS]; // effects in this session 102 uint32_t state; // current state (enum preproc_session_state) 103 int id; // audio session ID 104 int io; // handle of input stream this session is on 105 webrtc::AudioProcessing* apm; // handle on webRTC audio processing module (APM) 106 size_t apmFrameCount; // buffer size for webRTC process (10 ms) 107 uint32_t apmSamplingRate; // webRTC APM sampling rate (8/16 or 32 kHz) 108 size_t frameCount; // buffer size before input resampler ( <=> apmFrameCount) 109 uint32_t samplingRate; // sampling rate at effect process interface 110 uint32_t inChannelCount; // input channel count 111 uint32_t outChannelCount; // output channel count 112 uint32_t createdMsk; // bit field containing IDs of crested pre processors 113 uint32_t enabledMsk; // bit field containing IDs of enabled pre processors 114 uint32_t processedMsk; // bit field containing IDs of pre processors already 115 // processed in current round 116 webrtc::AudioFrame *procFrame; // audio frame passed to webRTC AMP ProcessStream() 117 int16_t *inBuf; // input buffer used when resampling 118 size_t inBufSize; // input buffer size in frames 119 size_t framesIn; // number of frames in input buffer 120 SpeexResamplerState *inResampler; // handle on input speex resampler 121 int16_t *outBuf; // output buffer used when resampling 122 size_t outBufSize; // output buffer size in frames 123 size_t framesOut; // number of frames in output buffer 124 SpeexResamplerState *outResampler; // handle on output speex resampler 125 uint32_t revChannelCount; // number of channels on reverse stream 126 uint32_t revEnabledMsk; // bit field containing IDs of enabled pre processors 127 // with reverse channel 128 uint32_t revProcessedMsk; // bit field containing IDs of pre processors with reverse 129 // channel already processed in current round 130 webrtc::AudioFrame *revFrame; // audio frame passed to webRTC AMP AnalyzeReverseStream() 131 int16_t *revBuf; // reverse channel input buffer 132 size_t revBufSize; // reverse channel input buffer size 133 size_t framesRev; // number of frames in reverse channel input buffer 134 SpeexResamplerState *revResampler; // handle on reverse channel input speex resampler 135}; 136 137#ifdef DUAL_MIC_TEST 138enum { 139 PREPROC_CMD_DUAL_MIC_ENABLE = EFFECT_CMD_FIRST_PROPRIETARY, // enable dual mic mode 140 PREPROC_CMD_DUAL_MIC_PCM_DUMP_START, // start pcm capture 141 PREPROC_CMD_DUAL_MIC_PCM_DUMP_STOP // stop pcm capture 142}; 143 144enum { 145 CHANNEL_CFG_MONO, 146 CHANNEL_CFG_STEREO, 147 CHANNEL_CFG_MONO_AUX, 148 CHANNEL_CFG_STEREO_AUX, 149 CHANNEL_CFG_CNT, 150 CHANNEL_CFG_FIRST_AUX = CHANNEL_CFG_MONO_AUX, 151}; 152 153const channel_config_t sDualMicConfigs[CHANNEL_CFG_CNT] = { 154 {AUDIO_CHANNEL_IN_MONO , 0}, 155 {AUDIO_CHANNEL_IN_STEREO , 0}, 156 {AUDIO_CHANNEL_IN_FRONT , AUDIO_CHANNEL_IN_BACK}, 157 {AUDIO_CHANNEL_IN_STEREO , AUDIO_CHANNEL_IN_RIGHT} 158}; 159 160bool sHasAuxChannels[PREPROC_NUM_EFFECTS] = { 161 false, // PREPROC_AGC 162 true, // PREPROC_AEC 163 true, // PREPROC_NS 164}; 165 166bool gDualMicEnabled; 167FILE *gPcmDumpFh; 168static pthread_mutex_t gPcmDumpLock = PTHREAD_MUTEX_INITIALIZER; 169#endif 170 171 172//------------------------------------------------------------------------------ 173// Effect descriptors 174//------------------------------------------------------------------------------ 175 176// UUIDs for effect types have been generated from http://www.itu.int/ITU-T/asn1/uuid.html 177// as the pre processing effects are not defined by OpenSL ES 178 179// Automatic Gain Control 180static const effect_descriptor_t sAgcDescriptor = { 181 { 0x0a8abfe0, 0x654c, 0x11e0, 0xba26, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } }, // type 182 { 0xaa8130e0, 0x66fc, 0x11e0, 0xbad0, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } }, // uuid 183 EFFECT_CONTROL_API_VERSION, 184 (EFFECT_FLAG_TYPE_PRE_PROC|EFFECT_FLAG_DEVICE_IND), 185 0, //FIXME indicate CPU load 186 0, //FIXME indicate memory usage 187 "Automatic Gain Control", 188 "The Android Open Source Project" 189}; 190 191// Acoustic Echo Cancellation 192static const effect_descriptor_t sAecDescriptor = { 193 { 0x7b491460, 0x8d4d, 0x11e0, 0xbd61, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } }, // type 194 { 0xbb392ec0, 0x8d4d, 0x11e0, 0xa896, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } }, // uuid 195 EFFECT_CONTROL_API_VERSION, 196 (EFFECT_FLAG_TYPE_PRE_PROC|EFFECT_FLAG_DEVICE_IND), 197 0, //FIXME indicate CPU load 198 0, //FIXME indicate memory usage 199 "Acoustic Echo Canceler", 200 "The Android Open Source Project" 201}; 202 203// Noise suppression 204static const effect_descriptor_t sNsDescriptor = { 205 { 0x58b4b260, 0x8e06, 0x11e0, 0xaa8e, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } }, // type 206 { 0xc06c8400, 0x8e06, 0x11e0, 0x9cb6, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } }, // uuid 207 EFFECT_CONTROL_API_VERSION, 208 (EFFECT_FLAG_TYPE_PRE_PROC|EFFECT_FLAG_DEVICE_IND), 209 0, //FIXME indicate CPU load 210 0, //FIXME indicate memory usage 211 "Noise Suppression", 212 "The Android Open Source Project" 213}; 214 215 216static const effect_descriptor_t *sDescriptors[PREPROC_NUM_EFFECTS] = { 217 &sAgcDescriptor, 218 &sAecDescriptor, 219 &sNsDescriptor 220}; 221 222//------------------------------------------------------------------------------ 223// Helper functions 224//------------------------------------------------------------------------------ 225 226const effect_uuid_t * const sUuidToPreProcTable[PREPROC_NUM_EFFECTS] = { 227 FX_IID_AGC, 228 FX_IID_AEC, 229 FX_IID_NS 230}; 231 232 233const effect_uuid_t * ProcIdToUuid(int procId) 234{ 235 if (procId >= PREPROC_NUM_EFFECTS) { 236 return EFFECT_UUID_NULL; 237 } 238 return sUuidToPreProcTable[procId]; 239} 240 241uint32_t UuidToProcId(const effect_uuid_t * uuid) 242{ 243 size_t i; 244 for (i = 0; i < PREPROC_NUM_EFFECTS; i++) { 245 if (memcmp(uuid, sUuidToPreProcTable[i], sizeof(*uuid)) == 0) { 246 break; 247 } 248 } 249 return i; 250} 251 252bool HasReverseStream(uint32_t procId) 253{ 254 if (procId == PREPROC_AEC) { 255 return true; 256 } 257 return false; 258} 259 260 261//------------------------------------------------------------------------------ 262// Automatic Gain Control (AGC) 263//------------------------------------------------------------------------------ 264 265static const int kAgcDefaultTargetLevel = 3; 266static const int kAgcDefaultCompGain = 9; 267static const bool kAgcDefaultLimiter = true; 268 269int AgcInit (preproc_effect_t *effect) 270{ 271 ALOGV("AgcInit"); 272 webrtc::GainControl *agc = static_cast<webrtc::GainControl *>(effect->engine); 273 agc->set_mode(webrtc::GainControl::kFixedDigital); 274 agc->set_target_level_dbfs(kAgcDefaultTargetLevel); 275 agc->set_compression_gain_db(kAgcDefaultCompGain); 276 agc->enable_limiter(kAgcDefaultLimiter); 277 return 0; 278} 279 280int AgcCreate(preproc_effect_t *effect) 281{ 282 webrtc::GainControl *agc = effect->session->apm->gain_control(); 283 ALOGV("AgcCreate got agc %p", agc); 284 if (agc == NULL) { 285 ALOGW("AgcCreate Error"); 286 return -ENOMEM; 287 } 288 effect->engine = static_cast<preproc_fx_handle_t>(agc); 289 AgcInit(effect); 290 return 0; 291} 292 293int AgcGetParameter(preproc_effect_t *effect, 294 void *pParam, 295 uint32_t *pValueSize, 296 void *pValue) 297{ 298 int status = 0; 299 uint32_t param = *(uint32_t *)pParam; 300 t_agc_settings *pProperties = (t_agc_settings *)pValue; 301 webrtc::GainControl *agc = static_cast<webrtc::GainControl *>(effect->engine); 302 303 switch (param) { 304 case AGC_PARAM_TARGET_LEVEL: 305 case AGC_PARAM_COMP_GAIN: 306 if (*pValueSize < sizeof(int16_t)) { 307 *pValueSize = 0; 308 return -EINVAL; 309 } 310 break; 311 case AGC_PARAM_LIMITER_ENA: 312 if (*pValueSize < sizeof(bool)) { 313 *pValueSize = 0; 314 return -EINVAL; 315 } 316 break; 317 case AGC_PARAM_PROPERTIES: 318 if (*pValueSize < sizeof(t_agc_settings)) { 319 *pValueSize = 0; 320 return -EINVAL; 321 } 322 break; 323 324 default: 325 ALOGW("AgcGetParameter() unknown param %08x", param); 326 status = -EINVAL; 327 break; 328 } 329 330 switch (param) { 331 case AGC_PARAM_TARGET_LEVEL: 332 *(int16_t *) pValue = (int16_t)(agc->target_level_dbfs() * -100); 333 ALOGV("AgcGetParameter() target level %d milliBels", *(int16_t *) pValue); 334 break; 335 case AGC_PARAM_COMP_GAIN: 336 *(int16_t *) pValue = (int16_t)(agc->compression_gain_db() * 100); 337 ALOGV("AgcGetParameter() comp gain %d milliBels", *(int16_t *) pValue); 338 break; 339 case AGC_PARAM_LIMITER_ENA: 340 *(bool *) pValue = (bool)agc->is_limiter_enabled(); 341 ALOGV("AgcGetParameter() limiter enabled %s", 342 (*(int16_t *) pValue != 0) ? "true" : "false"); 343 break; 344 case AGC_PARAM_PROPERTIES: 345 pProperties->targetLevel = (int16_t)(agc->target_level_dbfs() * -100); 346 pProperties->compGain = (int16_t)(agc->compression_gain_db() * 100); 347 pProperties->limiterEnabled = (bool)agc->is_limiter_enabled(); 348 break; 349 default: 350 ALOGW("AgcGetParameter() unknown param %d", param); 351 status = -EINVAL; 352 break; 353 } 354 return status; 355} 356 357int AgcSetParameter (preproc_effect_t *effect, void *pParam, void *pValue) 358{ 359 int status = 0; 360 uint32_t param = *(uint32_t *)pParam; 361 t_agc_settings *pProperties = (t_agc_settings *)pValue; 362 webrtc::GainControl *agc = static_cast<webrtc::GainControl *>(effect->engine); 363 364 switch (param) { 365 case AGC_PARAM_TARGET_LEVEL: 366 ALOGV("AgcSetParameter() target level %d milliBels", *(int16_t *)pValue); 367 status = agc->set_target_level_dbfs(-(*(int16_t *)pValue / 100)); 368 break; 369 case AGC_PARAM_COMP_GAIN: 370 ALOGV("AgcSetParameter() comp gain %d milliBels", *(int16_t *)pValue); 371 status = agc->set_compression_gain_db(*(int16_t *)pValue / 100); 372 break; 373 case AGC_PARAM_LIMITER_ENA: 374 ALOGV("AgcSetParameter() limiter enabled %s", *(bool *)pValue ? "true" : "false"); 375 status = agc->enable_limiter(*(bool *)pValue); 376 break; 377 case AGC_PARAM_PROPERTIES: 378 ALOGV("AgcSetParameter() properties level %d, gain %d limiter %d", 379 pProperties->targetLevel, 380 pProperties->compGain, 381 pProperties->limiterEnabled); 382 status = agc->set_target_level_dbfs(-(pProperties->targetLevel / 100)); 383 if (status != 0) break; 384 status = agc->set_compression_gain_db(pProperties->compGain / 100); 385 if (status != 0) break; 386 status = agc->enable_limiter(pProperties->limiterEnabled); 387 break; 388 default: 389 ALOGW("AgcSetParameter() unknown param %08x value %08x", param, *(uint32_t *)pValue); 390 status = -EINVAL; 391 break; 392 } 393 394 ALOGV("AgcSetParameter() done status %d", status); 395 396 return status; 397} 398 399void AgcEnable(preproc_effect_t *effect) 400{ 401 webrtc::GainControl *agc = static_cast<webrtc::GainControl *>(effect->engine); 402 ALOGV("AgcEnable agc %p", agc); 403 agc->Enable(true); 404} 405 406void AgcDisable(preproc_effect_t *effect) 407{ 408 ALOGV("AgcDisable"); 409 webrtc::GainControl *agc = static_cast<webrtc::GainControl *>(effect->engine); 410 agc->Enable(false); 411} 412 413 414static const preproc_ops_t sAgcOps = { 415 AgcCreate, 416 AgcInit, 417 NULL, 418 AgcEnable, 419 AgcDisable, 420 AgcSetParameter, 421 AgcGetParameter, 422 NULL 423}; 424 425 426//------------------------------------------------------------------------------ 427// Acoustic Echo Canceler (AEC) 428//------------------------------------------------------------------------------ 429 430static const webrtc::EchoControlMobile::RoutingMode kAecDefaultMode = 431 webrtc::EchoControlMobile::kEarpiece; 432static const bool kAecDefaultComfortNoise = true; 433 434int AecInit (preproc_effect_t *effect) 435{ 436 ALOGV("AecInit"); 437 webrtc::EchoControlMobile *aec = static_cast<webrtc::EchoControlMobile *>(effect->engine); 438 aec->set_routing_mode(kAecDefaultMode); 439 aec->enable_comfort_noise(kAecDefaultComfortNoise); 440 return 0; 441} 442 443int AecCreate(preproc_effect_t *effect) 444{ 445 webrtc::EchoControlMobile *aec = effect->session->apm->echo_control_mobile(); 446 ALOGV("AecCreate got aec %p", aec); 447 if (aec == NULL) { 448 ALOGW("AgcCreate Error"); 449 return -ENOMEM; 450 } 451 effect->engine = static_cast<preproc_fx_handle_t>(aec); 452 AecInit (effect); 453 return 0; 454} 455 456int AecGetParameter(preproc_effect_t *effect, 457 void *pParam, 458 uint32_t *pValueSize, 459 void *pValue) 460{ 461 int status = 0; 462 uint32_t param = *(uint32_t *)pParam; 463 464 if (*pValueSize < sizeof(uint32_t)) { 465 return -EINVAL; 466 } 467 switch (param) { 468 case AEC_PARAM_ECHO_DELAY: 469 case AEC_PARAM_PROPERTIES: 470 *(uint32_t *)pValue = 1000 * effect->session->apm->stream_delay_ms(); 471 ALOGV("AecGetParameter() echo delay %d us", *(uint32_t *)pValue); 472 break; 473 default: 474 ALOGW("AecGetParameter() unknown param %08x value %08x", param, *(uint32_t *)pValue); 475 status = -EINVAL; 476 break; 477 } 478 return status; 479} 480 481int AecSetParameter (preproc_effect_t *effect, void *pParam, void *pValue) 482{ 483 int status = 0; 484 uint32_t param = *(uint32_t *)pParam; 485 uint32_t value = *(uint32_t *)pValue; 486 487 switch (param) { 488 case AEC_PARAM_ECHO_DELAY: 489 case AEC_PARAM_PROPERTIES: 490 status = effect->session->apm->set_stream_delay_ms(value/1000); 491 ALOGV("AecSetParameter() echo delay %d us, status %d", value, status); 492 break; 493 default: 494 ALOGW("AecSetParameter() unknown param %08x value %08x", param, *(uint32_t *)pValue); 495 status = -EINVAL; 496 break; 497 } 498 return status; 499} 500 501void AecEnable(preproc_effect_t *effect) 502{ 503 webrtc::EchoControlMobile *aec = static_cast<webrtc::EchoControlMobile *>(effect->engine); 504 ALOGV("AecEnable aec %p", aec); 505 aec->Enable(true); 506} 507 508void AecDisable(preproc_effect_t *effect) 509{ 510 ALOGV("AecDisable"); 511 webrtc::EchoControlMobile *aec = static_cast<webrtc::EchoControlMobile *>(effect->engine); 512 aec->Enable(false); 513} 514 515int AecSetDevice(preproc_effect_t *effect, uint32_t device) 516{ 517 ALOGV("AecSetDevice %08x", device); 518 webrtc::EchoControlMobile *aec = static_cast<webrtc::EchoControlMobile *>(effect->engine); 519 webrtc::EchoControlMobile::RoutingMode mode = webrtc::EchoControlMobile::kQuietEarpieceOrHeadset; 520 521 if (audio_is_input_device(device)) { 522 return 0; 523 } 524 525 switch(device) { 526 case AUDIO_DEVICE_OUT_EARPIECE: 527 mode = webrtc::EchoControlMobile::kEarpiece; 528 break; 529 case AUDIO_DEVICE_OUT_SPEAKER: 530 mode = webrtc::EchoControlMobile::kSpeakerphone; 531 break; 532 case AUDIO_DEVICE_OUT_WIRED_HEADSET: 533 case AUDIO_DEVICE_OUT_WIRED_HEADPHONE: 534 case AUDIO_DEVICE_OUT_USB_HEADSET: 535 default: 536 break; 537 } 538 aec->set_routing_mode(mode); 539 return 0; 540} 541 542static const preproc_ops_t sAecOps = { 543 AecCreate, 544 AecInit, 545 NULL, 546 AecEnable, 547 AecDisable, 548 AecSetParameter, 549 AecGetParameter, 550 AecSetDevice 551}; 552 553//------------------------------------------------------------------------------ 554// Noise Suppression (NS) 555//------------------------------------------------------------------------------ 556 557static const webrtc::NoiseSuppression::Level kNsDefaultLevel = webrtc::NoiseSuppression::kModerate; 558 559int NsInit (preproc_effect_t *effect) 560{ 561 ALOGV("NsInit"); 562 webrtc::NoiseSuppression *ns = static_cast<webrtc::NoiseSuppression *>(effect->engine); 563 ns->set_level(kNsDefaultLevel); 564 webrtc::Config config; 565 std::vector<webrtc::Point> geometry; 566 // TODO(aluebs): Make the geometry settable. 567 geometry.push_back(webrtc::Point(-0.03f, 0.f, 0.f)); 568 geometry.push_back(webrtc::Point(-0.01f, 0.f, 0.f)); 569 geometry.push_back(webrtc::Point(0.01f, 0.f, 0.f)); 570 geometry.push_back(webrtc::Point(0.03f, 0.f, 0.f)); 571 // The geometry needs to be set with Beamforming enabled. 572 config.Set<webrtc::Beamforming>( 573 new webrtc::Beamforming(true, geometry)); 574 effect->session->apm->SetExtraOptions(config); 575 config.Set<webrtc::Beamforming>( 576 new webrtc::Beamforming(false, geometry)); 577 effect->session->apm->SetExtraOptions(config); 578 effect->type = NS_TYPE_SINGLE_CHANNEL; 579 return 0; 580} 581 582int NsCreate(preproc_effect_t *effect) 583{ 584 webrtc::NoiseSuppression *ns = effect->session->apm->noise_suppression(); 585 ALOGV("NsCreate got ns %p", ns); 586 if (ns == NULL) { 587 ALOGW("AgcCreate Error"); 588 return -ENOMEM; 589 } 590 effect->engine = static_cast<preproc_fx_handle_t>(ns); 591 NsInit (effect); 592 return 0; 593} 594 595int NsGetParameter(preproc_effect_t *effect __unused, 596 void *pParam __unused, 597 uint32_t *pValueSize __unused, 598 void *pValue __unused) 599{ 600 int status = 0; 601 return status; 602} 603 604int NsSetParameter (preproc_effect_t *effect, void *pParam, void *pValue) 605{ 606 int status = 0; 607 webrtc::NoiseSuppression *ns = static_cast<webrtc::NoiseSuppression *>(effect->engine); 608 uint32_t param = *(uint32_t *)pParam; 609 uint32_t value = *(uint32_t *)pValue; 610 switch(param) { 611 case NS_PARAM_LEVEL: 612 ns->set_level((webrtc::NoiseSuppression::Level)value); 613 ALOGV("NsSetParameter() level %d", value); 614 break; 615 case NS_PARAM_TYPE: 616 { 617 webrtc::Config config; 618 std::vector<webrtc::Point> geometry; 619 bool is_beamforming_enabled = 620 value == NS_TYPE_MULTI_CHANNEL && ns->is_enabled(); 621 config.Set<webrtc::Beamforming>( 622 new webrtc::Beamforming(is_beamforming_enabled, geometry)); 623 effect->session->apm->SetExtraOptions(config); 624 effect->type = value; 625 ALOGV("NsSetParameter() type %d", value); 626 break; 627 } 628 default: 629 ALOGW("NsSetParameter() unknown param %08x value %08x", param, value); 630 status = -EINVAL; 631 } 632 633 return status; 634} 635 636void NsEnable(preproc_effect_t *effect) 637{ 638 webrtc::NoiseSuppression *ns = static_cast<webrtc::NoiseSuppression *>(effect->engine); 639 ALOGV("NsEnable ns %p", ns); 640 ns->Enable(true); 641 if (effect->type == NS_TYPE_MULTI_CHANNEL) { 642 webrtc::Config config; 643 std::vector<webrtc::Point> geometry; 644 config.Set<webrtc::Beamforming>(new webrtc::Beamforming(true, geometry)); 645 effect->session->apm->SetExtraOptions(config); 646 } 647} 648 649void NsDisable(preproc_effect_t *effect) 650{ 651 ALOGV("NsDisable"); 652 webrtc::NoiseSuppression *ns = static_cast<webrtc::NoiseSuppression *>(effect->engine); 653 ns->Enable(false); 654 webrtc::Config config; 655 std::vector<webrtc::Point> geometry; 656 config.Set<webrtc::Beamforming>(new webrtc::Beamforming(false, geometry)); 657 effect->session->apm->SetExtraOptions(config); 658} 659 660static const preproc_ops_t sNsOps = { 661 NsCreate, 662 NsInit, 663 NULL, 664 NsEnable, 665 NsDisable, 666 NsSetParameter, 667 NsGetParameter, 668 NULL 669}; 670 671 672static const preproc_ops_t *sPreProcOps[PREPROC_NUM_EFFECTS] = { 673 &sAgcOps, 674 &sAecOps, 675 &sNsOps 676}; 677 678 679//------------------------------------------------------------------------------ 680// Effect functions 681//------------------------------------------------------------------------------ 682 683void Session_SetProcEnabled(preproc_session_t *session, uint32_t procId, bool enabled); 684 685extern "C" const struct effect_interface_s sEffectInterface; 686extern "C" const struct effect_interface_s sEffectInterfaceReverse; 687 688#define BAD_STATE_ABORT(from, to) \ 689 LOG_ALWAYS_FATAL("Bad state transition from %d to %d", from, to); 690 691int Effect_SetState(preproc_effect_t *effect, uint32_t state) 692{ 693 int status = 0; 694 ALOGV("Effect_SetState proc %d, new %d old %d", effect->procId, state, effect->state); 695 switch(state) { 696 case PREPROC_EFFECT_STATE_INIT: 697 switch(effect->state) { 698 case PREPROC_EFFECT_STATE_ACTIVE: 699 effect->ops->disable(effect); 700 Session_SetProcEnabled(effect->session, effect->procId, false); 701 case PREPROC_EFFECT_STATE_CONFIG: 702 case PREPROC_EFFECT_STATE_CREATED: 703 case PREPROC_EFFECT_STATE_INIT: 704 break; 705 default: 706 BAD_STATE_ABORT(effect->state, state); 707 } 708 break; 709 case PREPROC_EFFECT_STATE_CREATED: 710 switch(effect->state) { 711 case PREPROC_EFFECT_STATE_INIT: 712 status = effect->ops->create(effect); 713 break; 714 case PREPROC_EFFECT_STATE_CREATED: 715 case PREPROC_EFFECT_STATE_ACTIVE: 716 case PREPROC_EFFECT_STATE_CONFIG: 717 ALOGE("Effect_SetState invalid transition"); 718 status = -ENOSYS; 719 break; 720 default: 721 BAD_STATE_ABORT(effect->state, state); 722 } 723 break; 724 case PREPROC_EFFECT_STATE_CONFIG: 725 switch(effect->state) { 726 case PREPROC_EFFECT_STATE_INIT: 727 ALOGE("Effect_SetState invalid transition"); 728 status = -ENOSYS; 729 break; 730 case PREPROC_EFFECT_STATE_ACTIVE: 731 effect->ops->disable(effect); 732 Session_SetProcEnabled(effect->session, effect->procId, false); 733 break; 734 case PREPROC_EFFECT_STATE_CREATED: 735 case PREPROC_EFFECT_STATE_CONFIG: 736 break; 737 default: 738 BAD_STATE_ABORT(effect->state, state); 739 } 740 break; 741 case PREPROC_EFFECT_STATE_ACTIVE: 742 switch(effect->state) { 743 case PREPROC_EFFECT_STATE_INIT: 744 case PREPROC_EFFECT_STATE_CREATED: 745 ALOGE("Effect_SetState invalid transition"); 746 status = -ENOSYS; 747 break; 748 case PREPROC_EFFECT_STATE_ACTIVE: 749 // enabling an already enabled effect is just ignored 750 break; 751 case PREPROC_EFFECT_STATE_CONFIG: 752 effect->ops->enable(effect); 753 Session_SetProcEnabled(effect->session, effect->procId, true); 754 break; 755 default: 756 BAD_STATE_ABORT(effect->state, state); 757 } 758 break; 759 default: 760 BAD_STATE_ABORT(effect->state, state); 761 } 762 if (status == 0) { 763 effect->state = state; 764 } 765 return status; 766} 767 768int Effect_Init(preproc_effect_t *effect, uint32_t procId) 769{ 770 if (HasReverseStream(procId)) { 771 effect->itfe = &sEffectInterfaceReverse; 772 } else { 773 effect->itfe = &sEffectInterface; 774 } 775 effect->ops = sPreProcOps[procId]; 776 effect->procId = procId; 777 effect->state = PREPROC_EFFECT_STATE_INIT; 778 return 0; 779} 780 781int Effect_Create(preproc_effect_t *effect, 782 preproc_session_t *session, 783 effect_handle_t *interface) 784{ 785 effect->session = session; 786 *interface = (effect_handle_t)&effect->itfe; 787 return Effect_SetState(effect, PREPROC_EFFECT_STATE_CREATED); 788} 789 790int Effect_Release(preproc_effect_t *effect) 791{ 792 return Effect_SetState(effect, PREPROC_EFFECT_STATE_INIT); 793} 794 795 796//------------------------------------------------------------------------------ 797// Session functions 798//------------------------------------------------------------------------------ 799 800#define RESAMPLER_QUALITY SPEEX_RESAMPLER_QUALITY_VOIP 801 802static const int kPreprocDefaultSr = 16000; 803static const int kPreProcDefaultCnl = 1; 804 805int Session_Init(preproc_session_t *session) 806{ 807 size_t i; 808 int status = 0; 809 810 session->state = PREPROC_SESSION_STATE_INIT; 811 session->id = 0; 812 session->io = 0; 813 session->createdMsk = 0; 814 session->apm = NULL; 815 for (i = 0; i < PREPROC_NUM_EFFECTS && status == 0; i++) { 816 status = Effect_Init(&session->effects[i], i); 817 } 818 return status; 819} 820 821 822extern "C" int Session_CreateEffect(preproc_session_t *session, 823 int32_t procId, 824 effect_handle_t *interface) 825{ 826 int status = -ENOMEM; 827 828 ALOGV("Session_CreateEffect procId %d, createdMsk %08x", procId, session->createdMsk); 829 830 if (session->createdMsk == 0) { 831 session->apm = webrtc::AudioProcessing::Create(); 832 if (session->apm == NULL) { 833 ALOGW("Session_CreateEffect could not get apm engine"); 834 goto error; 835 } 836 const webrtc::ProcessingConfig processing_config = { 837 {{kPreprocDefaultSr, kPreProcDefaultCnl}, 838 {kPreprocDefaultSr, kPreProcDefaultCnl}, 839 {kPreprocDefaultSr, kPreProcDefaultCnl}, 840 {kPreprocDefaultSr, kPreProcDefaultCnl}}}; 841 session->apm->Initialize(processing_config); 842 session->procFrame = new webrtc::AudioFrame(); 843 if (session->procFrame == NULL) { 844 ALOGW("Session_CreateEffect could not allocate audio frame"); 845 goto error; 846 } 847 session->revFrame = new webrtc::AudioFrame(); 848 if (session->revFrame == NULL) { 849 ALOGW("Session_CreateEffect could not allocate reverse audio frame"); 850 goto error; 851 } 852 session->apmSamplingRate = kPreprocDefaultSr; 853 session->apmFrameCount = (kPreprocDefaultSr) / 100; 854 session->frameCount = session->apmFrameCount; 855 session->samplingRate = kPreprocDefaultSr; 856 session->inChannelCount = kPreProcDefaultCnl; 857 session->outChannelCount = kPreProcDefaultCnl; 858 session->procFrame->sample_rate_hz_ = kPreprocDefaultSr; 859 session->procFrame->num_channels_ = kPreProcDefaultCnl; 860 session->revChannelCount = kPreProcDefaultCnl; 861 session->revFrame->sample_rate_hz_ = kPreprocDefaultSr; 862 session->revFrame->num_channels_ = kPreProcDefaultCnl; 863 session->enabledMsk = 0; 864 session->processedMsk = 0; 865 session->revEnabledMsk = 0; 866 session->revProcessedMsk = 0; 867 session->inResampler = NULL; 868 session->inBuf = NULL; 869 session->inBufSize = 0; 870 session->outResampler = NULL; 871 session->outBuf = NULL; 872 session->outBufSize = 0; 873 session->revResampler = NULL; 874 session->revBuf = NULL; 875 session->revBufSize = 0; 876 } 877 status = Effect_Create(&session->effects[procId], session, interface); 878 if (status < 0) { 879 goto error; 880 } 881 ALOGV("Session_CreateEffect OK"); 882 session->createdMsk |= (1<<procId); 883 return status; 884 885error: 886 if (session->createdMsk == 0) { 887 delete session->revFrame; 888 session->revFrame = NULL; 889 delete session->procFrame; 890 session->procFrame = NULL; 891 delete session->apm; 892 session->apm = NULL; 893 } 894 return status; 895} 896 897int Session_ReleaseEffect(preproc_session_t *session, 898 preproc_effect_t *fx) 899{ 900 ALOGW_IF(Effect_Release(fx) != 0, " Effect_Release() failed for proc ID %d", fx->procId); 901 session->createdMsk &= ~(1<<fx->procId); 902 if (session->createdMsk == 0) { 903 delete session->apm; 904 session->apm = NULL; 905 delete session->procFrame; 906 session->procFrame = NULL; 907 delete session->revFrame; 908 session->revFrame = NULL; 909 if (session->inResampler != NULL) { 910 speex_resampler_destroy(session->inResampler); 911 session->inResampler = NULL; 912 } 913 if (session->outResampler != NULL) { 914 speex_resampler_destroy(session->outResampler); 915 session->outResampler = NULL; 916 } 917 if (session->revResampler != NULL) { 918 speex_resampler_destroy(session->revResampler); 919 session->revResampler = NULL; 920 } 921 delete session->inBuf; 922 session->inBuf = NULL; 923 delete session->outBuf; 924 session->outBuf = NULL; 925 delete session->revBuf; 926 session->revBuf = NULL; 927 928 session->io = 0; 929 } 930 931 return 0; 932} 933 934 935int Session_SetConfig(preproc_session_t *session, effect_config_t *config) 936{ 937 uint32_t inCnl = audio_channel_count_from_in_mask(config->inputCfg.channels); 938 uint32_t outCnl = audio_channel_count_from_in_mask(config->outputCfg.channels); 939 940 if (config->inputCfg.samplingRate != config->outputCfg.samplingRate || 941 config->inputCfg.format != config->outputCfg.format || 942 config->inputCfg.format != AUDIO_FORMAT_PCM_16_BIT) { 943 return -EINVAL; 944 } 945 946 ALOGV("Session_SetConfig sr %d cnl %08x", 947 config->inputCfg.samplingRate, config->inputCfg.channels); 948 int status; 949 950 // AEC implementation is limited to 16kHz 951 if (config->inputCfg.samplingRate >= 32000 && !(session->createdMsk & (1 << PREPROC_AEC))) { 952 session->apmSamplingRate = 32000; 953 } else 954 if (config->inputCfg.samplingRate >= 16000) { 955 session->apmSamplingRate = 16000; 956 } else if (config->inputCfg.samplingRate >= 8000) { 957 session->apmSamplingRate = 8000; 958 } 959 960 const webrtc::ProcessingConfig processing_config = { 961 {{static_cast<int>(session->apmSamplingRate), inCnl}, 962 {static_cast<int>(session->apmSamplingRate), outCnl}, 963 {static_cast<int>(session->apmSamplingRate), inCnl}, 964 {static_cast<int>(session->apmSamplingRate), inCnl}}}; 965 status = session->apm->Initialize(processing_config); 966 if (status < 0) { 967 return -EINVAL; 968 } 969 970 session->samplingRate = config->inputCfg.samplingRate; 971 session->apmFrameCount = session->apmSamplingRate / 100; 972 if (session->samplingRate == session->apmSamplingRate) { 973 session->frameCount = session->apmFrameCount; 974 } else { 975 session->frameCount = (session->apmFrameCount * session->samplingRate) / 976 session->apmSamplingRate + 1; 977 } 978 session->inChannelCount = inCnl; 979 session->outChannelCount = outCnl; 980 session->procFrame->num_channels_ = inCnl; 981 session->procFrame->sample_rate_hz_ = session->apmSamplingRate; 982 983 session->revChannelCount = inCnl; 984 session->revFrame->num_channels_ = inCnl; 985 session->revFrame->sample_rate_hz_ = session->apmSamplingRate; 986 987 // force process buffer reallocation 988 session->inBufSize = 0; 989 session->outBufSize = 0; 990 session->framesIn = 0; 991 session->framesOut = 0; 992 993 994 if (session->inResampler != NULL) { 995 speex_resampler_destroy(session->inResampler); 996 session->inResampler = NULL; 997 } 998 if (session->outResampler != NULL) { 999 speex_resampler_destroy(session->outResampler); 1000 session->outResampler = NULL; 1001 } 1002 if (session->revResampler != NULL) { 1003 speex_resampler_destroy(session->revResampler); 1004 session->revResampler = NULL; 1005 } 1006 if (session->samplingRate != session->apmSamplingRate) { 1007 int error; 1008 session->inResampler = speex_resampler_init(session->inChannelCount, 1009 session->samplingRate, 1010 session->apmSamplingRate, 1011 RESAMPLER_QUALITY, 1012 &error); 1013 if (session->inResampler == NULL) { 1014 ALOGW("Session_SetConfig Cannot create speex resampler: %s", 1015 speex_resampler_strerror(error)); 1016 return -EINVAL; 1017 } 1018 session->outResampler = speex_resampler_init(session->outChannelCount, 1019 session->apmSamplingRate, 1020 session->samplingRate, 1021 RESAMPLER_QUALITY, 1022 &error); 1023 if (session->outResampler == NULL) { 1024 ALOGW("Session_SetConfig Cannot create speex resampler: %s", 1025 speex_resampler_strerror(error)); 1026 speex_resampler_destroy(session->inResampler); 1027 session->inResampler = NULL; 1028 return -EINVAL; 1029 } 1030 session->revResampler = speex_resampler_init(session->inChannelCount, 1031 session->samplingRate, 1032 session->apmSamplingRate, 1033 RESAMPLER_QUALITY, 1034 &error); 1035 if (session->revResampler == NULL) { 1036 ALOGW("Session_SetConfig Cannot create speex resampler: %s", 1037 speex_resampler_strerror(error)); 1038 speex_resampler_destroy(session->inResampler); 1039 session->inResampler = NULL; 1040 speex_resampler_destroy(session->outResampler); 1041 session->outResampler = NULL; 1042 return -EINVAL; 1043 } 1044 } 1045 1046 session->state = PREPROC_SESSION_STATE_CONFIG; 1047 return 0; 1048} 1049 1050void Session_GetConfig(preproc_session_t *session, effect_config_t *config) 1051{ 1052 memset(config, 0, sizeof(effect_config_t)); 1053 config->inputCfg.samplingRate = config->outputCfg.samplingRate = session->samplingRate; 1054 config->inputCfg.format = config->outputCfg.format = AUDIO_FORMAT_PCM_16_BIT; 1055 config->inputCfg.channels = audio_channel_in_mask_from_count(session->inChannelCount); 1056 // "out" doesn't mean output device, so this is the correct API to convert channel count to mask 1057 config->outputCfg.channels = audio_channel_in_mask_from_count(session->outChannelCount); 1058 config->inputCfg.mask = config->outputCfg.mask = 1059 (EFFECT_CONFIG_SMP_RATE | EFFECT_CONFIG_CHANNELS | EFFECT_CONFIG_FORMAT); 1060} 1061 1062int Session_SetReverseConfig(preproc_session_t *session, effect_config_t *config) 1063{ 1064 if (config->inputCfg.samplingRate != config->outputCfg.samplingRate || 1065 config->inputCfg.format != config->outputCfg.format || 1066 config->inputCfg.format != AUDIO_FORMAT_PCM_16_BIT) { 1067 return -EINVAL; 1068 } 1069 1070 ALOGV("Session_SetReverseConfig sr %d cnl %08x", 1071 config->inputCfg.samplingRate, config->inputCfg.channels); 1072 1073 if (session->state < PREPROC_SESSION_STATE_CONFIG) { 1074 return -ENOSYS; 1075 } 1076 if (config->inputCfg.samplingRate != session->samplingRate || 1077 config->inputCfg.format != AUDIO_FORMAT_PCM_16_BIT) { 1078 return -EINVAL; 1079 } 1080 uint32_t inCnl = audio_channel_count_from_out_mask(config->inputCfg.channels); 1081 const webrtc::ProcessingConfig processing_config = { 1082 {{static_cast<int>(session->apmSamplingRate), session->inChannelCount}, 1083 {static_cast<int>(session->apmSamplingRate), session->outChannelCount}, 1084 {static_cast<int>(session->apmSamplingRate), inCnl}, 1085 {static_cast<int>(session->apmSamplingRate), inCnl}}}; 1086 int status = session->apm->Initialize(processing_config); 1087 if (status < 0) { 1088 return -EINVAL; 1089 } 1090 session->revChannelCount = inCnl; 1091 session->revFrame->num_channels_ = inCnl; 1092 session->revFrame->sample_rate_hz_ = session->apmSamplingRate; 1093 // force process buffer reallocation 1094 session->revBufSize = 0; 1095 session->framesRev = 0; 1096 1097 return 0; 1098} 1099 1100void Session_GetReverseConfig(preproc_session_t *session, effect_config_t *config) 1101{ 1102 memset(config, 0, sizeof(effect_config_t)); 1103 config->inputCfg.samplingRate = config->outputCfg.samplingRate = session->samplingRate; 1104 config->inputCfg.format = config->outputCfg.format = AUDIO_FORMAT_PCM_16_BIT; 1105 config->inputCfg.channels = config->outputCfg.channels = 1106 audio_channel_in_mask_from_count(session->revChannelCount); 1107 config->inputCfg.mask = config->outputCfg.mask = 1108 (EFFECT_CONFIG_SMP_RATE | EFFECT_CONFIG_CHANNELS | EFFECT_CONFIG_FORMAT); 1109} 1110 1111void Session_SetProcEnabled(preproc_session_t *session, uint32_t procId, bool enabled) 1112{ 1113 if (enabled) { 1114 if(session->enabledMsk == 0) { 1115 session->framesIn = 0; 1116 if (session->inResampler != NULL) { 1117 speex_resampler_reset_mem(session->inResampler); 1118 } 1119 session->framesOut = 0; 1120 if (session->outResampler != NULL) { 1121 speex_resampler_reset_mem(session->outResampler); 1122 } 1123 } 1124 session->enabledMsk |= (1 << procId); 1125 if (HasReverseStream(procId)) { 1126 session->framesRev = 0; 1127 if (session->revResampler != NULL) { 1128 speex_resampler_reset_mem(session->revResampler); 1129 } 1130 session->revEnabledMsk |= (1 << procId); 1131 } 1132 } else { 1133 session->enabledMsk &= ~(1 << procId); 1134 if (HasReverseStream(procId)) { 1135 session->revEnabledMsk &= ~(1 << procId); 1136 } 1137 } 1138 ALOGV("Session_SetProcEnabled proc %d, enabled %d enabledMsk %08x revEnabledMsk %08x", 1139 procId, enabled, session->enabledMsk, session->revEnabledMsk); 1140 session->processedMsk = 0; 1141 if (HasReverseStream(procId)) { 1142 session->revProcessedMsk = 0; 1143 } 1144} 1145 1146//------------------------------------------------------------------------------ 1147// Bundle functions 1148//------------------------------------------------------------------------------ 1149 1150static int sInitStatus = 1; 1151static preproc_session_t sSessions[PREPROC_NUM_SESSIONS]; 1152 1153preproc_session_t *PreProc_GetSession(int32_t procId, int32_t sessionId, int32_t ioId) 1154{ 1155 size_t i; 1156 for (i = 0; i < PREPROC_NUM_SESSIONS; i++) { 1157 if (sSessions[i].io == ioId) { 1158 if (sSessions[i].createdMsk & (1 << procId)) { 1159 return NULL; 1160 } 1161 return &sSessions[i]; 1162 } 1163 } 1164 for (i = 0; i < PREPROC_NUM_SESSIONS; i++) { 1165 if (sSessions[i].io == 0) { 1166 sSessions[i].id = sessionId; 1167 sSessions[i].io = ioId; 1168 return &sSessions[i]; 1169 } 1170 } 1171 return NULL; 1172} 1173 1174 1175int PreProc_Init() { 1176 size_t i; 1177 int status = 0; 1178 1179 if (sInitStatus <= 0) { 1180 return sInitStatus; 1181 } 1182 for (i = 0; i < PREPROC_NUM_SESSIONS && status == 0; i++) { 1183 status = Session_Init(&sSessions[i]); 1184 } 1185 sInitStatus = status; 1186 return sInitStatus; 1187} 1188 1189const effect_descriptor_t *PreProc_GetDescriptor(const effect_uuid_t *uuid) 1190{ 1191 size_t i; 1192 for (i = 0; i < PREPROC_NUM_EFFECTS; i++) { 1193 if (memcmp(&sDescriptors[i]->uuid, uuid, sizeof(effect_uuid_t)) == 0) { 1194 return sDescriptors[i]; 1195 } 1196 } 1197 return NULL; 1198} 1199 1200 1201extern "C" { 1202 1203//------------------------------------------------------------------------------ 1204// Effect Control Interface Implementation 1205//------------------------------------------------------------------------------ 1206 1207int PreProcessingFx_Process(effect_handle_t self, 1208 audio_buffer_t *inBuffer, 1209 audio_buffer_t *outBuffer) 1210{ 1211 preproc_effect_t * effect = (preproc_effect_t *)self; 1212 1213 if (effect == NULL){ 1214 ALOGV("PreProcessingFx_Process() ERROR effect == NULL"); 1215 return -EINVAL; 1216 } 1217 preproc_session_t * session = (preproc_session_t *)effect->session; 1218 1219 if (inBuffer == NULL || inBuffer->raw == NULL || 1220 outBuffer == NULL || outBuffer->raw == NULL){ 1221 ALOGW("PreProcessingFx_Process() ERROR bad pointer"); 1222 return -EINVAL; 1223 } 1224 1225 session->processedMsk |= (1<<effect->procId); 1226 1227// ALOGV("PreProcessingFx_Process In %d frames enabledMsk %08x processedMsk %08x", 1228// inBuffer->frameCount, session->enabledMsk, session->processedMsk); 1229 1230 if ((session->processedMsk & session->enabledMsk) == session->enabledMsk) { 1231 effect->session->processedMsk = 0; 1232 size_t framesRq = outBuffer->frameCount; 1233 size_t framesWr = 0; 1234 if (session->framesOut) { 1235 size_t fr = session->framesOut; 1236 if (outBuffer->frameCount < fr) { 1237 fr = outBuffer->frameCount; 1238 } 1239 memcpy(outBuffer->s16, 1240 session->outBuf, 1241 fr * session->outChannelCount * sizeof(int16_t)); 1242 memcpy(session->outBuf, 1243 session->outBuf + fr * session->outChannelCount, 1244 (session->framesOut - fr) * session->outChannelCount * sizeof(int16_t)); 1245 session->framesOut -= fr; 1246 framesWr += fr; 1247 } 1248 outBuffer->frameCount = framesWr; 1249 if (framesWr == framesRq) { 1250 inBuffer->frameCount = 0; 1251 return 0; 1252 } 1253 1254 if (session->inResampler != NULL) { 1255 size_t fr = session->frameCount - session->framesIn; 1256 if (inBuffer->frameCount < fr) { 1257 fr = inBuffer->frameCount; 1258 } 1259 if (session->inBufSize < session->framesIn + fr) { 1260 int16_t *buf; 1261 session->inBufSize = session->framesIn + fr; 1262 buf = (int16_t *)realloc(session->inBuf, 1263 session->inBufSize * session->inChannelCount * sizeof(int16_t)); 1264 if (buf == NULL) { 1265 session->framesIn = 0; 1266 free(session->inBuf); 1267 session->inBuf = NULL; 1268 return -ENOMEM; 1269 } 1270 session->inBuf = buf; 1271 } 1272 memcpy(session->inBuf + session->framesIn * session->inChannelCount, 1273 inBuffer->s16, 1274 fr * session->inChannelCount * sizeof(int16_t)); 1275#ifdef DUAL_MIC_TEST 1276 pthread_mutex_lock(&gPcmDumpLock); 1277 if (gPcmDumpFh != NULL) { 1278 fwrite(inBuffer->raw, 1279 fr * session->inChannelCount * sizeof(int16_t), 1, gPcmDumpFh); 1280 } 1281 pthread_mutex_unlock(&gPcmDumpLock); 1282#endif 1283 1284 session->framesIn += fr; 1285 inBuffer->frameCount = fr; 1286 if (session->framesIn < session->frameCount) { 1287 return 0; 1288 } 1289 spx_uint32_t frIn = session->framesIn; 1290 spx_uint32_t frOut = session->apmFrameCount; 1291 if (session->inChannelCount == 1) { 1292 speex_resampler_process_int(session->inResampler, 1293 0, 1294 session->inBuf, 1295 &frIn, 1296 session->procFrame->data_, 1297 &frOut); 1298 } else { 1299 speex_resampler_process_interleaved_int(session->inResampler, 1300 session->inBuf, 1301 &frIn, 1302 session->procFrame->data_, 1303 &frOut); 1304 } 1305 memcpy(session->inBuf, 1306 session->inBuf + frIn * session->inChannelCount, 1307 (session->framesIn - frIn) * session->inChannelCount * sizeof(int16_t)); 1308 session->framesIn -= frIn; 1309 } else { 1310 size_t fr = session->frameCount - session->framesIn; 1311 if (inBuffer->frameCount < fr) { 1312 fr = inBuffer->frameCount; 1313 } 1314 memcpy(session->procFrame->data_ + session->framesIn * session->inChannelCount, 1315 inBuffer->s16, 1316 fr * session->inChannelCount * sizeof(int16_t)); 1317 1318#ifdef DUAL_MIC_TEST 1319 pthread_mutex_lock(&gPcmDumpLock); 1320 if (gPcmDumpFh != NULL) { 1321 fwrite(inBuffer->raw, 1322 fr * session->inChannelCount * sizeof(int16_t), 1, gPcmDumpFh); 1323 } 1324 pthread_mutex_unlock(&gPcmDumpLock); 1325#endif 1326 1327 session->framesIn += fr; 1328 inBuffer->frameCount = fr; 1329 if (session->framesIn < session->frameCount) { 1330 return 0; 1331 } 1332 session->framesIn = 0; 1333 } 1334 session->procFrame->samples_per_channel_ = session->apmFrameCount; 1335 1336 effect->session->apm->ProcessStream(session->procFrame); 1337 1338 if (session->outBufSize < session->framesOut + session->frameCount) { 1339 int16_t *buf; 1340 session->outBufSize = session->framesOut + session->frameCount; 1341 buf = (int16_t *)realloc(session->outBuf, 1342 session->outBufSize * session->outChannelCount * sizeof(int16_t)); 1343 if (buf == NULL) { 1344 session->framesOut = 0; 1345 free(session->outBuf); 1346 session->outBuf = NULL; 1347 return -ENOMEM; 1348 } 1349 session->outBuf = buf; 1350 } 1351 1352 if (session->outResampler != NULL) { 1353 spx_uint32_t frIn = session->apmFrameCount; 1354 spx_uint32_t frOut = session->frameCount; 1355 if (session->inChannelCount == 1) { 1356 speex_resampler_process_int(session->outResampler, 1357 0, 1358 session->procFrame->data_, 1359 &frIn, 1360 session->outBuf + session->framesOut * session->outChannelCount, 1361 &frOut); 1362 } else { 1363 speex_resampler_process_interleaved_int(session->outResampler, 1364 session->procFrame->data_, 1365 &frIn, 1366 session->outBuf + session->framesOut * session->outChannelCount, 1367 &frOut); 1368 } 1369 session->framesOut += frOut; 1370 } else { 1371 memcpy(session->outBuf + session->framesOut * session->outChannelCount, 1372 session->procFrame->data_, 1373 session->frameCount * session->outChannelCount * sizeof(int16_t)); 1374 session->framesOut += session->frameCount; 1375 } 1376 size_t fr = session->framesOut; 1377 if (framesRq - framesWr < fr) { 1378 fr = framesRq - framesWr; 1379 } 1380 memcpy(outBuffer->s16 + framesWr * session->outChannelCount, 1381 session->outBuf, 1382 fr * session->outChannelCount * sizeof(int16_t)); 1383 memcpy(session->outBuf, 1384 session->outBuf + fr * session->outChannelCount, 1385 (session->framesOut - fr) * session->outChannelCount * sizeof(int16_t)); 1386 session->framesOut -= fr; 1387 outBuffer->frameCount += fr; 1388 1389 return 0; 1390 } else { 1391 return -ENODATA; 1392 } 1393} 1394 1395int PreProcessingFx_Command(effect_handle_t self, 1396 uint32_t cmdCode, 1397 uint32_t cmdSize, 1398 void *pCmdData, 1399 uint32_t *replySize, 1400 void *pReplyData) 1401{ 1402 preproc_effect_t * effect = (preproc_effect_t *) self; 1403 1404 if (effect == NULL){ 1405 return -EINVAL; 1406 } 1407 1408 //ALOGV("PreProcessingFx_Command: command %d cmdSize %d",cmdCode, cmdSize); 1409 1410 switch (cmdCode){ 1411 case EFFECT_CMD_INIT: 1412 if (pReplyData == NULL || *replySize != sizeof(int)){ 1413 return -EINVAL; 1414 } 1415 if (effect->ops->init) { 1416 effect->ops->init(effect); 1417 } 1418 *(int *)pReplyData = 0; 1419 break; 1420 1421 case EFFECT_CMD_SET_CONFIG: { 1422 if (pCmdData == NULL|| 1423 cmdSize != sizeof(effect_config_t)|| 1424 pReplyData == NULL|| 1425 *replySize != sizeof(int)){ 1426 ALOGV("PreProcessingFx_Command cmdCode Case: " 1427 "EFFECT_CMD_SET_CONFIG: ERROR"); 1428 return -EINVAL; 1429 } 1430#ifdef DUAL_MIC_TEST 1431 // make sure that the config command is accepted by making as if all effects were 1432 // disabled: this is OK for functional tests 1433 uint32_t enabledMsk = effect->session->enabledMsk; 1434 if (gDualMicEnabled) { 1435 effect->session->enabledMsk = 0; 1436 } 1437#endif 1438 *(int *)pReplyData = Session_SetConfig(effect->session, (effect_config_t *)pCmdData); 1439#ifdef DUAL_MIC_TEST 1440 if (gDualMicEnabled) { 1441 effect->session->enabledMsk = enabledMsk; 1442 } 1443#endif 1444 if (*(int *)pReplyData != 0) { 1445 break; 1446 } 1447 if (effect->state != PREPROC_EFFECT_STATE_ACTIVE) { 1448 *(int *)pReplyData = Effect_SetState(effect, PREPROC_EFFECT_STATE_CONFIG); 1449 } 1450 } break; 1451 1452 case EFFECT_CMD_GET_CONFIG: 1453 if (pReplyData == NULL || 1454 *replySize != sizeof(effect_config_t)) { 1455 ALOGV("\tLVM_ERROR : PreProcessingFx_Command cmdCode Case: " 1456 "EFFECT_CMD_GET_CONFIG: ERROR"); 1457 return -EINVAL; 1458 } 1459 1460 Session_GetConfig(effect->session, (effect_config_t *)pReplyData); 1461 break; 1462 1463 case EFFECT_CMD_SET_CONFIG_REVERSE: 1464 if (pCmdData == NULL || 1465 cmdSize != sizeof(effect_config_t) || 1466 pReplyData == NULL || 1467 *replySize != sizeof(int)) { 1468 ALOGV("PreProcessingFx_Command cmdCode Case: " 1469 "EFFECT_CMD_SET_CONFIG_REVERSE: ERROR"); 1470 return -EINVAL; 1471 } 1472 *(int *)pReplyData = Session_SetReverseConfig(effect->session, 1473 (effect_config_t *)pCmdData); 1474 if (*(int *)pReplyData != 0) { 1475 break; 1476 } 1477 break; 1478 1479 case EFFECT_CMD_GET_CONFIG_REVERSE: 1480 if (pReplyData == NULL || 1481 *replySize != sizeof(effect_config_t)){ 1482 ALOGV("PreProcessingFx_Command cmdCode Case: " 1483 "EFFECT_CMD_GET_CONFIG_REVERSE: ERROR"); 1484 return -EINVAL; 1485 } 1486 Session_GetReverseConfig(effect->session, (effect_config_t *)pCmdData); 1487 break; 1488 1489 case EFFECT_CMD_RESET: 1490 if (effect->ops->reset) { 1491 effect->ops->reset(effect); 1492 } 1493 break; 1494 1495 case EFFECT_CMD_GET_PARAM: { 1496 effect_param_t *p = (effect_param_t *)pCmdData; 1497 1498 if (pCmdData == NULL || cmdSize < sizeof(effect_param_t) || 1499 cmdSize < (sizeof(effect_param_t) + p->psize) || 1500 pReplyData == NULL || replySize == NULL || 1501 *replySize < (sizeof(effect_param_t) + p->psize)){ 1502 ALOGV("PreProcessingFx_Command cmdCode Case: " 1503 "EFFECT_CMD_GET_PARAM: ERROR"); 1504 return -EINVAL; 1505 } 1506 1507 memcpy(pReplyData, pCmdData, sizeof(effect_param_t) + p->psize); 1508 1509 p = (effect_param_t *)pReplyData; 1510 1511 int voffset = ((p->psize - 1) / sizeof(int32_t) + 1) * sizeof(int32_t); 1512 1513 if (effect->ops->get_parameter) { 1514 p->status = effect->ops->get_parameter(effect, p->data, 1515 &p->vsize, 1516 p->data + voffset); 1517 *replySize = sizeof(effect_param_t) + voffset + p->vsize; 1518 } 1519 } break; 1520 1521 case EFFECT_CMD_SET_PARAM:{ 1522 if (pCmdData == NULL|| 1523 cmdSize < sizeof(effect_param_t) || 1524 pReplyData == NULL || replySize == NULL || 1525 *replySize != sizeof(int32_t)){ 1526 ALOGV("PreProcessingFx_Command cmdCode Case: " 1527 "EFFECT_CMD_SET_PARAM: ERROR"); 1528 return -EINVAL; 1529 } 1530 effect_param_t *p = (effect_param_t *) pCmdData; 1531 1532 if (p->psize != sizeof(int32_t)){ 1533 ALOGV("PreProcessingFx_Command cmdCode Case: " 1534 "EFFECT_CMD_SET_PARAM: ERROR, psize is not sizeof(int32_t)"); 1535 return -EINVAL; 1536 } 1537 if (effect->ops->set_parameter) { 1538 *(int *)pReplyData = effect->ops->set_parameter(effect, 1539 (void *)p->data, 1540 p->data + p->psize); 1541 } 1542 } break; 1543 1544 case EFFECT_CMD_ENABLE: 1545 if (pReplyData == NULL || replySize == NULL || *replySize != sizeof(int)){ 1546 ALOGV("PreProcessingFx_Command cmdCode Case: EFFECT_CMD_ENABLE: ERROR"); 1547 return -EINVAL; 1548 } 1549 *(int *)pReplyData = Effect_SetState(effect, PREPROC_EFFECT_STATE_ACTIVE); 1550 break; 1551 1552 case EFFECT_CMD_DISABLE: 1553 if (pReplyData == NULL || replySize == NULL || *replySize != sizeof(int)){ 1554 ALOGV("PreProcessingFx_Command cmdCode Case: EFFECT_CMD_DISABLE: ERROR"); 1555 return -EINVAL; 1556 } 1557 *(int *)pReplyData = Effect_SetState(effect, PREPROC_EFFECT_STATE_CONFIG); 1558 break; 1559 1560 case EFFECT_CMD_SET_DEVICE: 1561 case EFFECT_CMD_SET_INPUT_DEVICE: 1562 if (pCmdData == NULL || 1563 cmdSize != sizeof(uint32_t)) { 1564 ALOGV("PreProcessingFx_Command cmdCode Case: EFFECT_CMD_SET_DEVICE: ERROR"); 1565 return -EINVAL; 1566 } 1567 1568 if (effect->ops->set_device) { 1569 effect->ops->set_device(effect, *(uint32_t *)pCmdData); 1570 } 1571 break; 1572 1573 case EFFECT_CMD_SET_VOLUME: 1574 case EFFECT_CMD_SET_AUDIO_MODE: 1575 break; 1576 1577#ifdef DUAL_MIC_TEST 1578 ///// test commands start 1579 case PREPROC_CMD_DUAL_MIC_ENABLE: { 1580 if (pCmdData == NULL|| cmdSize != sizeof(uint32_t) || 1581 pReplyData == NULL || replySize == NULL) { 1582 ALOGE("PreProcessingFx_Command cmdCode Case: " 1583 "PREPROC_CMD_DUAL_MIC_ENABLE: ERROR"); 1584 *replySize = 0; 1585 return -EINVAL; 1586 } 1587 gDualMicEnabled = *(bool *)pCmdData; 1588 if (gDualMicEnabled) { 1589 effect->aux_channels_on = sHasAuxChannels[effect->procId]; 1590 } else { 1591 effect->aux_channels_on = false; 1592 } 1593 effect->cur_channel_config = (effect->session->inChannelCount == 1) ? 1594 CHANNEL_CFG_MONO : CHANNEL_CFG_STEREO; 1595 1596 ALOGV("PREPROC_CMD_DUAL_MIC_ENABLE: %s", gDualMicEnabled ? "enabled" : "disabled"); 1597 *replySize = sizeof(int); 1598 *(int *)pReplyData = 0; 1599 } break; 1600 case PREPROC_CMD_DUAL_MIC_PCM_DUMP_START: { 1601 if (pCmdData == NULL|| pReplyData == NULL || replySize == NULL) { 1602 ALOGE("PreProcessingFx_Command cmdCode Case: " 1603 "PREPROC_CMD_DUAL_MIC_PCM_DUMP_START: ERROR"); 1604 *replySize = 0; 1605 return -EINVAL; 1606 } 1607 pthread_mutex_lock(&gPcmDumpLock); 1608 if (gPcmDumpFh != NULL) { 1609 fclose(gPcmDumpFh); 1610 gPcmDumpFh = NULL; 1611 } 1612 char *path = strndup((char *)pCmdData, cmdSize); 1613 gPcmDumpFh = fopen((char *)path, "wb"); 1614 pthread_mutex_unlock(&gPcmDumpLock); 1615 ALOGV("PREPROC_CMD_DUAL_MIC_PCM_DUMP_START: path %s gPcmDumpFh %p", 1616 path, gPcmDumpFh); 1617 ALOGE_IF(gPcmDumpFh <= 0, "gPcmDumpFh open error %d %s", errno, strerror(errno)); 1618 free(path); 1619 *replySize = sizeof(int); 1620 *(int *)pReplyData = 0; 1621 } break; 1622 case PREPROC_CMD_DUAL_MIC_PCM_DUMP_STOP: { 1623 if (pReplyData == NULL || replySize == NULL) { 1624 ALOGE("PreProcessingFx_Command cmdCode Case: " 1625 "PREPROC_CMD_DUAL_MIC_PCM_DUMP_STOP: ERROR"); 1626 *replySize = 0; 1627 return -EINVAL; 1628 } 1629 pthread_mutex_lock(&gPcmDumpLock); 1630 if (gPcmDumpFh != NULL) { 1631 fclose(gPcmDumpFh); 1632 gPcmDumpFh = NULL; 1633 } 1634 pthread_mutex_unlock(&gPcmDumpLock); 1635 ALOGV("PREPROC_CMD_DUAL_MIC_PCM_DUMP_STOP"); 1636 *replySize = sizeof(int); 1637 *(int *)pReplyData = 0; 1638 } break; 1639 ///// test commands end 1640 1641 case EFFECT_CMD_GET_FEATURE_SUPPORTED_CONFIGS: { 1642 if(!gDualMicEnabled) { 1643 return -EINVAL; 1644 } 1645 if (pCmdData == NULL|| cmdSize != 2 * sizeof(uint32_t) || 1646 pReplyData == NULL || replySize == NULL) { 1647 ALOGE("PreProcessingFx_Command cmdCode Case: " 1648 "EFFECT_CMD_GET_FEATURE_SUPPORTED_CONFIGS: ERROR"); 1649 *replySize = 0; 1650 return -EINVAL; 1651 } 1652 if (*(uint32_t *)pCmdData != EFFECT_FEATURE_AUX_CHANNELS || 1653 !effect->aux_channels_on) { 1654 ALOGV("PreProcessingFx_Command feature EFFECT_FEATURE_AUX_CHANNELS not supported by" 1655 " fx %d", effect->procId); 1656 *(uint32_t *)pReplyData = -ENOSYS; 1657 *replySize = sizeof(uint32_t); 1658 break; 1659 } 1660 size_t num_configs = *((uint32_t *)pCmdData + 1); 1661 if (*replySize < (2 * sizeof(uint32_t) + 1662 num_configs * sizeof(channel_config_t))) { 1663 *replySize = 0; 1664 return -EINVAL; 1665 } 1666 1667 *((uint32_t *)pReplyData + 1) = CHANNEL_CFG_CNT; 1668 if (num_configs < CHANNEL_CFG_CNT || 1669 *replySize < (2 * sizeof(uint32_t) + 1670 CHANNEL_CFG_CNT * sizeof(channel_config_t))) { 1671 *(uint32_t *)pReplyData = -ENOMEM; 1672 } else { 1673 num_configs = CHANNEL_CFG_CNT; 1674 *(uint32_t *)pReplyData = 0; 1675 } 1676 ALOGV("PreProcessingFx_Command EFFECT_CMD_GET_FEATURE_SUPPORTED_CONFIGS num config %d", 1677 num_configs); 1678 1679 *replySize = 2 * sizeof(uint32_t) + num_configs * sizeof(channel_config_t); 1680 *((uint32_t *)pReplyData + 1) = num_configs; 1681 memcpy((uint32_t *)pReplyData + 2, &sDualMicConfigs, num_configs * sizeof(channel_config_t)); 1682 } break; 1683 case EFFECT_CMD_GET_FEATURE_CONFIG: 1684 if(!gDualMicEnabled) { 1685 return -EINVAL; 1686 } 1687 if (pCmdData == NULL|| cmdSize != sizeof(uint32_t) || 1688 pReplyData == NULL || replySize == NULL || 1689 *replySize < sizeof(uint32_t) + sizeof(channel_config_t)) { 1690 ALOGE("PreProcessingFx_Command cmdCode Case: " 1691 "EFFECT_CMD_GET_FEATURE_CONFIG: ERROR"); 1692 return -EINVAL; 1693 } 1694 if (*(uint32_t *)pCmdData != EFFECT_FEATURE_AUX_CHANNELS || !effect->aux_channels_on) { 1695 *(uint32_t *)pReplyData = -ENOSYS; 1696 *replySize = sizeof(uint32_t); 1697 break; 1698 } 1699 ALOGV("PreProcessingFx_Command EFFECT_CMD_GET_FEATURE_CONFIG"); 1700 *(uint32_t *)pReplyData = 0; 1701 *replySize = sizeof(uint32_t) + sizeof(channel_config_t); 1702 memcpy((uint32_t *)pReplyData + 1, 1703 &sDualMicConfigs[effect->cur_channel_config], 1704 sizeof(channel_config_t)); 1705 break; 1706 case EFFECT_CMD_SET_FEATURE_CONFIG: { 1707 ALOGV("PreProcessingFx_Command EFFECT_CMD_SET_FEATURE_CONFIG: " 1708 "gDualMicEnabled %d effect->aux_channels_on %d", 1709 gDualMicEnabled, effect->aux_channels_on); 1710 if(!gDualMicEnabled) { 1711 return -EINVAL; 1712 } 1713 if (pCmdData == NULL|| cmdSize != (sizeof(uint32_t) + sizeof(channel_config_t)) || 1714 pReplyData == NULL || replySize == NULL || 1715 *replySize < sizeof(uint32_t)) { 1716 ALOGE("PreProcessingFx_Command cmdCode Case: " 1717 "EFFECT_CMD_SET_FEATURE_CONFIG: ERROR\n" 1718 "pCmdData %p cmdSize %d pReplyData %p replySize %p *replySize %d", 1719 pCmdData, cmdSize, pReplyData, replySize, replySize ? *replySize : -1); 1720 return -EINVAL; 1721 } 1722 *replySize = sizeof(uint32_t); 1723 if (*(uint32_t *)pCmdData != EFFECT_FEATURE_AUX_CHANNELS || !effect->aux_channels_on) { 1724 *(uint32_t *)pReplyData = -ENOSYS; 1725 ALOGV("PreProcessingFx_Command cmdCode Case: " 1726 "EFFECT_CMD_SET_FEATURE_CONFIG: ERROR\n" 1727 "CmdData %d effect->aux_channels_on %d", 1728 *(uint32_t *)pCmdData, effect->aux_channels_on); 1729 break; 1730 } 1731 size_t i; 1732 for (i = 0; i < CHANNEL_CFG_CNT;i++) { 1733 if (memcmp((uint32_t *)pCmdData + 1, 1734 &sDualMicConfigs[i], sizeof(channel_config_t)) == 0) { 1735 break; 1736 } 1737 } 1738 if (i == CHANNEL_CFG_CNT) { 1739 *(uint32_t *)pReplyData = -EINVAL; 1740 ALOGW("PreProcessingFx_Command EFFECT_CMD_SET_FEATURE_CONFIG invalid config" 1741 "[%08x].[%08x]", *((uint32_t *)pCmdData + 1), *((uint32_t *)pCmdData + 2)); 1742 } else { 1743 effect->cur_channel_config = i; 1744 *(uint32_t *)pReplyData = 0; 1745 ALOGV("PreProcessingFx_Command EFFECT_CMD_SET_FEATURE_CONFIG New config" 1746 "[%08x].[%08x]", sDualMicConfigs[i].main_channels, sDualMicConfigs[i].aux_channels); 1747 } 1748 } break; 1749#endif 1750 default: 1751 return -EINVAL; 1752 } 1753 return 0; 1754} 1755 1756 1757int PreProcessingFx_GetDescriptor(effect_handle_t self, 1758 effect_descriptor_t *pDescriptor) 1759{ 1760 preproc_effect_t * effect = (preproc_effect_t *) self; 1761 1762 if (effect == NULL || pDescriptor == NULL) { 1763 return -EINVAL; 1764 } 1765 1766 *pDescriptor = *sDescriptors[effect->procId]; 1767 1768 return 0; 1769} 1770 1771int PreProcessingFx_ProcessReverse(effect_handle_t self, 1772 audio_buffer_t *inBuffer, 1773 audio_buffer_t *outBuffer __unused) 1774{ 1775 preproc_effect_t * effect = (preproc_effect_t *)self; 1776 1777 if (effect == NULL){ 1778 ALOGW("PreProcessingFx_ProcessReverse() ERROR effect == NULL"); 1779 return -EINVAL; 1780 } 1781 preproc_session_t * session = (preproc_session_t *)effect->session; 1782 1783 if (inBuffer == NULL || inBuffer->raw == NULL){ 1784 ALOGW("PreProcessingFx_ProcessReverse() ERROR bad pointer"); 1785 return -EINVAL; 1786 } 1787 1788 session->revProcessedMsk |= (1<<effect->procId); 1789 1790// ALOGV("PreProcessingFx_ProcessReverse In %d frames revEnabledMsk %08x revProcessedMsk %08x", 1791// inBuffer->frameCount, session->revEnabledMsk, session->revProcessedMsk); 1792 1793 1794 if ((session->revProcessedMsk & session->revEnabledMsk) == session->revEnabledMsk) { 1795 effect->session->revProcessedMsk = 0; 1796 if (session->revResampler != NULL) { 1797 size_t fr = session->frameCount - session->framesRev; 1798 if (inBuffer->frameCount < fr) { 1799 fr = inBuffer->frameCount; 1800 } 1801 if (session->revBufSize < session->framesRev + fr) { 1802 int16_t *buf; 1803 session->revBufSize = session->framesRev + fr; 1804 buf = (int16_t *)realloc(session->revBuf, 1805 session->revBufSize * session->inChannelCount * sizeof(int16_t)); 1806 if (buf == NULL) { 1807 session->framesRev = 0; 1808 free(session->revBuf); 1809 session->revBuf = NULL; 1810 return -ENOMEM; 1811 } 1812 session->revBuf = buf; 1813 } 1814 memcpy(session->revBuf + session->framesRev * session->inChannelCount, 1815 inBuffer->s16, 1816 fr * session->inChannelCount * sizeof(int16_t)); 1817 1818 session->framesRev += fr; 1819 inBuffer->frameCount = fr; 1820 if (session->framesRev < session->frameCount) { 1821 return 0; 1822 } 1823 spx_uint32_t frIn = session->framesRev; 1824 spx_uint32_t frOut = session->apmFrameCount; 1825 if (session->inChannelCount == 1) { 1826 speex_resampler_process_int(session->revResampler, 1827 0, 1828 session->revBuf, 1829 &frIn, 1830 session->revFrame->data_, 1831 &frOut); 1832 } else { 1833 speex_resampler_process_interleaved_int(session->revResampler, 1834 session->revBuf, 1835 &frIn, 1836 session->revFrame->data_, 1837 &frOut); 1838 } 1839 memcpy(session->revBuf, 1840 session->revBuf + frIn * session->inChannelCount, 1841 (session->framesRev - frIn) * session->inChannelCount * sizeof(int16_t)); 1842 session->framesRev -= frIn; 1843 } else { 1844 size_t fr = session->frameCount - session->framesRev; 1845 if (inBuffer->frameCount < fr) { 1846 fr = inBuffer->frameCount; 1847 } 1848 memcpy(session->revFrame->data_ + session->framesRev * session->inChannelCount, 1849 inBuffer->s16, 1850 fr * session->inChannelCount * sizeof(int16_t)); 1851 session->framesRev += fr; 1852 inBuffer->frameCount = fr; 1853 if (session->framesRev < session->frameCount) { 1854 return 0; 1855 } 1856 session->framesRev = 0; 1857 } 1858 session->revFrame->samples_per_channel_ = session->apmFrameCount; 1859 effect->session->apm->AnalyzeReverseStream(session->revFrame); 1860 return 0; 1861 } else { 1862 return -ENODATA; 1863 } 1864} 1865 1866 1867// effect_handle_t interface implementation for effect 1868const struct effect_interface_s sEffectInterface = { 1869 PreProcessingFx_Process, 1870 PreProcessingFx_Command, 1871 PreProcessingFx_GetDescriptor, 1872 NULL 1873}; 1874 1875const struct effect_interface_s sEffectInterfaceReverse = { 1876 PreProcessingFx_Process, 1877 PreProcessingFx_Command, 1878 PreProcessingFx_GetDescriptor, 1879 PreProcessingFx_ProcessReverse 1880}; 1881 1882//------------------------------------------------------------------------------ 1883// Effect Library Interface Implementation 1884//------------------------------------------------------------------------------ 1885 1886int PreProcessingLib_Create(const effect_uuid_t *uuid, 1887 int32_t sessionId, 1888 int32_t ioId, 1889 effect_handle_t *pInterface) 1890{ 1891 ALOGV("EffectCreate: uuid: %08x session %d IO: %d", uuid->timeLow, sessionId, ioId); 1892 1893 int status; 1894 const effect_descriptor_t *desc; 1895 preproc_session_t *session; 1896 uint32_t procId; 1897 1898 if (PreProc_Init() != 0) { 1899 return sInitStatus; 1900 } 1901 desc = PreProc_GetDescriptor(uuid); 1902 if (desc == NULL) { 1903 ALOGW("EffectCreate: fx not found uuid: %08x", uuid->timeLow); 1904 return -EINVAL; 1905 } 1906 procId = UuidToProcId(&desc->type); 1907 1908 session = PreProc_GetSession(procId, sessionId, ioId); 1909 if (session == NULL) { 1910 ALOGW("EffectCreate: no more session available"); 1911 return -EINVAL; 1912 } 1913 1914 status = Session_CreateEffect(session, procId, pInterface); 1915 1916 if (status < 0 && session->createdMsk == 0) { 1917 session->io = 0; 1918 } 1919 return status; 1920} 1921 1922int PreProcessingLib_Release(effect_handle_t interface) 1923{ 1924 ALOGV("EffectRelease start %p", interface); 1925 if (PreProc_Init() != 0) { 1926 return sInitStatus; 1927 } 1928 1929 preproc_effect_t *fx = (preproc_effect_t *)interface; 1930 1931 if (fx->session->io == 0) { 1932 return -EINVAL; 1933 } 1934 return Session_ReleaseEffect(fx->session, fx); 1935} 1936 1937int PreProcessingLib_GetDescriptor(const effect_uuid_t *uuid, 1938 effect_descriptor_t *pDescriptor) { 1939 1940 if (pDescriptor == NULL || uuid == NULL){ 1941 return -EINVAL; 1942 } 1943 1944 const effect_descriptor_t *desc = PreProc_GetDescriptor(uuid); 1945 if (desc == NULL) { 1946 ALOGV("PreProcessingLib_GetDescriptor() not found"); 1947 return -EINVAL; 1948 } 1949 1950 ALOGV("PreProcessingLib_GetDescriptor() got fx %s", desc->name); 1951 1952 *pDescriptor = *desc; 1953 return 0; 1954} 1955 1956// This is the only symbol that needs to be exported 1957__attribute__ ((visibility ("default"))) 1958audio_effect_library_t AUDIO_EFFECT_LIBRARY_INFO_SYM = { 1959 .tag = AUDIO_EFFECT_LIBRARY_TAG, 1960 .version = EFFECT_LIBRARY_API_VERSION, 1961 .name = "Audio Preprocessing Library", 1962 .implementor = "The Android Open Source Project", 1963 .create_effect = PreProcessingLib_Create, 1964 .release_effect = PreProcessingLib_Release, 1965 .get_descriptor = PreProcessingLib_GetDescriptor 1966}; 1967 1968}; // extern "C" 1969