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 42 enum 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 51 enum preproc_session_state { 52 PREPROC_SESSION_STATE_INIT, // initialized 53 PREPROC_SESSION_STATE_CONFIG // configuration received 54 }; 55 56 // Effect/Preprocessor state 57 enum 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 65 typedef void* preproc_fx_handle_t; 66 67 typedef struct preproc_session_s preproc_session_t; 68 typedef struct preproc_effect_s preproc_effect_t; 69 typedef 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. 73 struct 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 85 struct 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 100 struct 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 138 enum { 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 144 enum { 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 153 const 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 160 bool sHasAuxChannels[PREPROC_NUM_EFFECTS] = { 161 false, // PREPROC_AGC 162 true, // PREPROC_AEC 163 true, // PREPROC_NS 164 }; 165 166 bool gDualMicEnabled; 167 FILE *gPcmDumpFh; 168 static 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 180 static 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 192 static 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 204 static 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 216 static const effect_descriptor_t *sDescriptors[PREPROC_NUM_EFFECTS] = { 217 &sAgcDescriptor, 218 &sAecDescriptor, 219 &sNsDescriptor 220 }; 221 222 //------------------------------------------------------------------------------ 223 // Helper functions 224 //------------------------------------------------------------------------------ 225 226 const effect_uuid_t * const sUuidToPreProcTable[PREPROC_NUM_EFFECTS] = { 227 FX_IID_AGC, 228 FX_IID_AEC, 229 FX_IID_NS 230 }; 231 232 233 const 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 241 uint32_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 252 bool 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 265 static const int kAgcDefaultTargetLevel = 3; 266 static const int kAgcDefaultCompGain = 9; 267 static const bool kAgcDefaultLimiter = true; 268 269 int 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 280 int 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 293 int 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 357 int 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 399 void 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 406 void 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 414 static 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 430 static const webrtc::EchoControlMobile::RoutingMode kAecDefaultMode = 431 webrtc::EchoControlMobile::kEarpiece; 432 static const bool kAecDefaultComfortNoise = true; 433 434 int 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 443 int 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 456 int 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 481 int 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 501 void 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 508 void 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 515 int 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 default: 535 break; 536 } 537 aec->set_routing_mode(mode); 538 return 0; 539 } 540 541 static const preproc_ops_t sAecOps = { 542 AecCreate, 543 AecInit, 544 NULL, 545 AecEnable, 546 AecDisable, 547 AecSetParameter, 548 AecGetParameter, 549 AecSetDevice 550 }; 551 552 //------------------------------------------------------------------------------ 553 // Noise Suppression (NS) 554 //------------------------------------------------------------------------------ 555 556 static const webrtc::NoiseSuppression::Level kNsDefaultLevel = webrtc::NoiseSuppression::kModerate; 557 558 int NsInit (preproc_effect_t *effect) 559 { 560 ALOGV("NsInit"); 561 webrtc::NoiseSuppression *ns = static_cast<webrtc::NoiseSuppression *>(effect->engine); 562 ns->set_level(kNsDefaultLevel); 563 webrtc::Config config; 564 std::vector<webrtc::Point> geometry; 565 // TODO(aluebs): Make the geometry settable. 566 geometry.push_back(webrtc::Point(-0.03f, 0.f, 0.f)); 567 geometry.push_back(webrtc::Point(-0.01f, 0.f, 0.f)); 568 geometry.push_back(webrtc::Point(0.01f, 0.f, 0.f)); 569 geometry.push_back(webrtc::Point(0.03f, 0.f, 0.f)); 570 // The geometry needs to be set with Beamforming enabled. 571 config.Set<webrtc::Beamforming>( 572 new webrtc::Beamforming(true, geometry)); 573 effect->session->apm->SetExtraOptions(config); 574 config.Set<webrtc::Beamforming>( 575 new webrtc::Beamforming(false, geometry)); 576 effect->session->apm->SetExtraOptions(config); 577 effect->type = NS_TYPE_SINGLE_CHANNEL; 578 return 0; 579 } 580 581 int NsCreate(preproc_effect_t *effect) 582 { 583 webrtc::NoiseSuppression *ns = effect->session->apm->noise_suppression(); 584 ALOGV("NsCreate got ns %p", ns); 585 if (ns == NULL) { 586 ALOGW("AgcCreate Error"); 587 return -ENOMEM; 588 } 589 effect->engine = static_cast<preproc_fx_handle_t>(ns); 590 NsInit (effect); 591 return 0; 592 } 593 594 int NsGetParameter(preproc_effect_t *effect __unused, 595 void *pParam __unused, 596 uint32_t *pValueSize __unused, 597 void *pValue __unused) 598 { 599 int status = 0; 600 return status; 601 } 602 603 int NsSetParameter (preproc_effect_t *effect, void *pParam, void *pValue) 604 { 605 int status = 0; 606 webrtc::NoiseSuppression *ns = static_cast<webrtc::NoiseSuppression *>(effect->engine); 607 uint32_t param = *(uint32_t *)pParam; 608 uint32_t value = *(uint32_t *)pValue; 609 switch(param) { 610 case NS_PARAM_LEVEL: 611 ns->set_level((webrtc::NoiseSuppression::Level)value); 612 ALOGV("NsSetParameter() level %d", value); 613 break; 614 case NS_PARAM_TYPE: 615 { 616 webrtc::Config config; 617 std::vector<webrtc::Point> geometry; 618 bool is_beamforming_enabled = 619 value == NS_TYPE_MULTI_CHANNEL && ns->is_enabled(); 620 config.Set<webrtc::Beamforming>( 621 new webrtc::Beamforming(is_beamforming_enabled, geometry)); 622 effect->session->apm->SetExtraOptions(config); 623 effect->type = value; 624 ALOGV("NsSetParameter() type %d", value); 625 break; 626 } 627 default: 628 ALOGW("NsSetParameter() unknown param %08x value %08x", param, value); 629 status = -EINVAL; 630 } 631 632 return status; 633 } 634 635 void NsEnable(preproc_effect_t *effect) 636 { 637 webrtc::NoiseSuppression *ns = static_cast<webrtc::NoiseSuppression *>(effect->engine); 638 ALOGV("NsEnable ns %p", ns); 639 ns->Enable(true); 640 if (effect->type == NS_TYPE_MULTI_CHANNEL) { 641 webrtc::Config config; 642 std::vector<webrtc::Point> geometry; 643 config.Set<webrtc::Beamforming>(new webrtc::Beamforming(true, geometry)); 644 effect->session->apm->SetExtraOptions(config); 645 } 646 } 647 648 void NsDisable(preproc_effect_t *effect) 649 { 650 ALOGV("NsDisable"); 651 webrtc::NoiseSuppression *ns = static_cast<webrtc::NoiseSuppression *>(effect->engine); 652 ns->Enable(false); 653 webrtc::Config config; 654 std::vector<webrtc::Point> geometry; 655 config.Set<webrtc::Beamforming>(new webrtc::Beamforming(false, geometry)); 656 effect->session->apm->SetExtraOptions(config); 657 } 658 659 static const preproc_ops_t sNsOps = { 660 NsCreate, 661 NsInit, 662 NULL, 663 NsEnable, 664 NsDisable, 665 NsSetParameter, 666 NsGetParameter, 667 NULL 668 }; 669 670 671 static const preproc_ops_t *sPreProcOps[PREPROC_NUM_EFFECTS] = { 672 &sAgcOps, 673 &sAecOps, 674 &sNsOps 675 }; 676 677 678 //------------------------------------------------------------------------------ 679 // Effect functions 680 //------------------------------------------------------------------------------ 681 682 void Session_SetProcEnabled(preproc_session_t *session, uint32_t procId, bool enabled); 683 684 extern "C" const struct effect_interface_s sEffectInterface; 685 extern "C" const struct effect_interface_s sEffectInterfaceReverse; 686 687 #define BAD_STATE_ABORT(from, to) \ 688 LOG_ALWAYS_FATAL("Bad state transition from %d to %d", from, to); 689 690 int Effect_SetState(preproc_effect_t *effect, uint32_t state) 691 { 692 int status = 0; 693 ALOGV("Effect_SetState proc %d, new %d old %d", effect->procId, state, effect->state); 694 switch(state) { 695 case PREPROC_EFFECT_STATE_INIT: 696 switch(effect->state) { 697 case PREPROC_EFFECT_STATE_ACTIVE: 698 effect->ops->disable(effect); 699 Session_SetProcEnabled(effect->session, effect->procId, false); 700 case PREPROC_EFFECT_STATE_CONFIG: 701 case PREPROC_EFFECT_STATE_CREATED: 702 case PREPROC_EFFECT_STATE_INIT: 703 break; 704 default: 705 BAD_STATE_ABORT(effect->state, state); 706 } 707 break; 708 case PREPROC_EFFECT_STATE_CREATED: 709 switch(effect->state) { 710 case PREPROC_EFFECT_STATE_INIT: 711 status = effect->ops->create(effect); 712 break; 713 case PREPROC_EFFECT_STATE_CREATED: 714 case PREPROC_EFFECT_STATE_ACTIVE: 715 case PREPROC_EFFECT_STATE_CONFIG: 716 ALOGE("Effect_SetState invalid transition"); 717 status = -ENOSYS; 718 break; 719 default: 720 BAD_STATE_ABORT(effect->state, state); 721 } 722 break; 723 case PREPROC_EFFECT_STATE_CONFIG: 724 switch(effect->state) { 725 case PREPROC_EFFECT_STATE_INIT: 726 ALOGE("Effect_SetState invalid transition"); 727 status = -ENOSYS; 728 break; 729 case PREPROC_EFFECT_STATE_ACTIVE: 730 effect->ops->disable(effect); 731 Session_SetProcEnabled(effect->session, effect->procId, false); 732 break; 733 case PREPROC_EFFECT_STATE_CREATED: 734 case PREPROC_EFFECT_STATE_CONFIG: 735 break; 736 default: 737 BAD_STATE_ABORT(effect->state, state); 738 } 739 break; 740 case PREPROC_EFFECT_STATE_ACTIVE: 741 switch(effect->state) { 742 case PREPROC_EFFECT_STATE_INIT: 743 case PREPROC_EFFECT_STATE_CREATED: 744 ALOGE("Effect_SetState invalid transition"); 745 status = -ENOSYS; 746 break; 747 case PREPROC_EFFECT_STATE_ACTIVE: 748 // enabling an already enabled effect is just ignored 749 break; 750 case PREPROC_EFFECT_STATE_CONFIG: 751 effect->ops->enable(effect); 752 Session_SetProcEnabled(effect->session, effect->procId, true); 753 break; 754 default: 755 BAD_STATE_ABORT(effect->state, state); 756 } 757 break; 758 default: 759 BAD_STATE_ABORT(effect->state, state); 760 } 761 if (status == 0) { 762 effect->state = state; 763 } 764 return status; 765 } 766 767 int Effect_Init(preproc_effect_t *effect, uint32_t procId) 768 { 769 if (HasReverseStream(procId)) { 770 effect->itfe = &sEffectInterfaceReverse; 771 } else { 772 effect->itfe = &sEffectInterface; 773 } 774 effect->ops = sPreProcOps[procId]; 775 effect->procId = procId; 776 effect->state = PREPROC_EFFECT_STATE_INIT; 777 return 0; 778 } 779 780 int Effect_Create(preproc_effect_t *effect, 781 preproc_session_t *session, 782 effect_handle_t *interface) 783 { 784 effect->session = session; 785 *interface = (effect_handle_t)&effect->itfe; 786 return Effect_SetState(effect, PREPROC_EFFECT_STATE_CREATED); 787 } 788 789 int Effect_Release(preproc_effect_t *effect) 790 { 791 return Effect_SetState(effect, PREPROC_EFFECT_STATE_INIT); 792 } 793 794 795 //------------------------------------------------------------------------------ 796 // Session functions 797 //------------------------------------------------------------------------------ 798 799 #define RESAMPLER_QUALITY SPEEX_RESAMPLER_QUALITY_VOIP 800 801 static const int kPreprocDefaultSr = 16000; 802 static const int kPreProcDefaultCnl = 1; 803 804 int Session_Init(preproc_session_t *session) 805 { 806 size_t i; 807 int status = 0; 808 809 session->state = PREPROC_SESSION_STATE_INIT; 810 session->id = 0; 811 session->io = 0; 812 session->createdMsk = 0; 813 session->apm = NULL; 814 for (i = 0; i < PREPROC_NUM_EFFECTS && status == 0; i++) { 815 status = Effect_Init(&session->effects[i], i); 816 } 817 return status; 818 } 819 820 821 extern "C" int Session_CreateEffect(preproc_session_t *session, 822 int32_t procId, 823 effect_handle_t *interface) 824 { 825 int status = -ENOMEM; 826 827 ALOGV("Session_CreateEffect procId %d, createdMsk %08x", procId, session->createdMsk); 828 829 if (session->createdMsk == 0) { 830 session->apm = webrtc::AudioProcessing::Create(); 831 if (session->apm == NULL) { 832 ALOGW("Session_CreateEffect could not get apm engine"); 833 goto error; 834 } 835 const webrtc::ProcessingConfig processing_config = { 836 {{kPreprocDefaultSr, kPreProcDefaultCnl}, 837 {kPreprocDefaultSr, kPreProcDefaultCnl}, 838 {kPreprocDefaultSr, kPreProcDefaultCnl}, 839 {kPreprocDefaultSr, kPreProcDefaultCnl}}}; 840 session->apm->Initialize(processing_config); 841 session->procFrame = new webrtc::AudioFrame(); 842 if (session->procFrame == NULL) { 843 ALOGW("Session_CreateEffect could not allocate audio frame"); 844 goto error; 845 } 846 session->revFrame = new webrtc::AudioFrame(); 847 if (session->revFrame == NULL) { 848 ALOGW("Session_CreateEffect could not allocate reverse audio frame"); 849 goto error; 850 } 851 session->apmSamplingRate = kPreprocDefaultSr; 852 session->apmFrameCount = (kPreprocDefaultSr) / 100; 853 session->frameCount = session->apmFrameCount; 854 session->samplingRate = kPreprocDefaultSr; 855 session->inChannelCount = kPreProcDefaultCnl; 856 session->outChannelCount = kPreProcDefaultCnl; 857 session->procFrame->sample_rate_hz_ = kPreprocDefaultSr; 858 session->procFrame->num_channels_ = kPreProcDefaultCnl; 859 session->revChannelCount = kPreProcDefaultCnl; 860 session->revFrame->sample_rate_hz_ = kPreprocDefaultSr; 861 session->revFrame->num_channels_ = kPreProcDefaultCnl; 862 session->enabledMsk = 0; 863 session->processedMsk = 0; 864 session->revEnabledMsk = 0; 865 session->revProcessedMsk = 0; 866 session->inResampler = NULL; 867 session->inBuf = NULL; 868 session->inBufSize = 0; 869 session->outResampler = NULL; 870 session->outBuf = NULL; 871 session->outBufSize = 0; 872 session->revResampler = NULL; 873 session->revBuf = NULL; 874 session->revBufSize = 0; 875 } 876 status = Effect_Create(&session->effects[procId], session, interface); 877 if (status < 0) { 878 goto error; 879 } 880 ALOGV("Session_CreateEffect OK"); 881 session->createdMsk |= (1<<procId); 882 return status; 883 884 error: 885 if (session->createdMsk == 0) { 886 delete session->revFrame; 887 session->revFrame = NULL; 888 delete session->procFrame; 889 session->procFrame = NULL; 890 delete session->apm; 891 session->apm = NULL; 892 } 893 return status; 894 } 895 896 int Session_ReleaseEffect(preproc_session_t *session, 897 preproc_effect_t *fx) 898 { 899 ALOGW_IF(Effect_Release(fx) != 0, " Effect_Release() failed for proc ID %d", fx->procId); 900 session->createdMsk &= ~(1<<fx->procId); 901 if (session->createdMsk == 0) { 902 delete session->apm; 903 session->apm = NULL; 904 delete session->procFrame; 905 session->procFrame = NULL; 906 delete session->revFrame; 907 session->revFrame = NULL; 908 if (session->inResampler != NULL) { 909 speex_resampler_destroy(session->inResampler); 910 session->inResampler = NULL; 911 } 912 if (session->outResampler != NULL) { 913 speex_resampler_destroy(session->outResampler); 914 session->outResampler = NULL; 915 } 916 if (session->revResampler != NULL) { 917 speex_resampler_destroy(session->revResampler); 918 session->revResampler = NULL; 919 } 920 delete session->inBuf; 921 session->inBuf = NULL; 922 delete session->outBuf; 923 session->outBuf = NULL; 924 delete session->revBuf; 925 session->revBuf = NULL; 926 927 session->io = 0; 928 } 929 930 return 0; 931 } 932 933 934 int Session_SetConfig(preproc_session_t *session, effect_config_t *config) 935 { 936 uint32_t sr; 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 1050 void 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 1062 int 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 1100 void 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 1111 void 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 1150 static int sInitStatus = 1; 1151 static preproc_session_t sSessions[PREPROC_NUM_SESSIONS]; 1152 1153 preproc_session_t *PreProc_GetSession(int32_t procId, int32_t sessionId, int32_t ioId) 1154 { 1155 size_t i; 1156 int free = -1; 1157 for (i = 0; i < PREPROC_NUM_SESSIONS; i++) { 1158 if (sSessions[i].io == ioId) { 1159 if (sSessions[i].createdMsk & (1 << procId)) { 1160 return NULL; 1161 } 1162 return &sSessions[i]; 1163 } 1164 } 1165 for (i = 0; i < PREPROC_NUM_SESSIONS; i++) { 1166 if (sSessions[i].io == 0) { 1167 sSessions[i].id = sessionId; 1168 sSessions[i].io = ioId; 1169 return &sSessions[i]; 1170 } 1171 } 1172 return NULL; 1173 } 1174 1175 1176 int PreProc_Init() { 1177 size_t i; 1178 int status = 0; 1179 1180 if (sInitStatus <= 0) { 1181 return sInitStatus; 1182 } 1183 for (i = 0; i < PREPROC_NUM_SESSIONS && status == 0; i++) { 1184 status = Session_Init(&sSessions[i]); 1185 } 1186 sInitStatus = status; 1187 return sInitStatus; 1188 } 1189 1190 const effect_descriptor_t *PreProc_GetDescriptor(const effect_uuid_t *uuid) 1191 { 1192 size_t i; 1193 for (i = 0; i < PREPROC_NUM_EFFECTS; i++) { 1194 if (memcmp(&sDescriptors[i]->uuid, uuid, sizeof(effect_uuid_t)) == 0) { 1195 return sDescriptors[i]; 1196 } 1197 } 1198 return NULL; 1199 } 1200 1201 1202 extern "C" { 1203 1204 //------------------------------------------------------------------------------ 1205 // Effect Control Interface Implementation 1206 //------------------------------------------------------------------------------ 1207 1208 int PreProcessingFx_Process(effect_handle_t self, 1209 audio_buffer_t *inBuffer, 1210 audio_buffer_t *outBuffer) 1211 { 1212 preproc_effect_t * effect = (preproc_effect_t *)self; 1213 int status = 0; 1214 1215 if (effect == NULL){ 1216 ALOGV("PreProcessingFx_Process() ERROR effect == NULL"); 1217 return -EINVAL; 1218 } 1219 preproc_session_t * session = (preproc_session_t *)effect->session; 1220 1221 if (inBuffer == NULL || inBuffer->raw == NULL || 1222 outBuffer == NULL || outBuffer->raw == NULL){ 1223 ALOGW("PreProcessingFx_Process() ERROR bad pointer"); 1224 return -EINVAL; 1225 } 1226 1227 session->processedMsk |= (1<<effect->procId); 1228 1229 // ALOGV("PreProcessingFx_Process In %d frames enabledMsk %08x processedMsk %08x", 1230 // inBuffer->frameCount, session->enabledMsk, session->processedMsk); 1231 1232 if ((session->processedMsk & session->enabledMsk) == session->enabledMsk) { 1233 effect->session->processedMsk = 0; 1234 size_t framesRq = outBuffer->frameCount; 1235 size_t framesWr = 0; 1236 if (session->framesOut) { 1237 size_t fr = session->framesOut; 1238 if (outBuffer->frameCount < fr) { 1239 fr = outBuffer->frameCount; 1240 } 1241 memcpy(outBuffer->s16, 1242 session->outBuf, 1243 fr * session->outChannelCount * sizeof(int16_t)); 1244 memcpy(session->outBuf, 1245 session->outBuf + fr * session->outChannelCount, 1246 (session->framesOut - fr) * session->outChannelCount * sizeof(int16_t)); 1247 session->framesOut -= fr; 1248 framesWr += fr; 1249 } 1250 outBuffer->frameCount = framesWr; 1251 if (framesWr == framesRq) { 1252 inBuffer->frameCount = 0; 1253 return 0; 1254 } 1255 1256 if (session->inResampler != NULL) { 1257 size_t fr = session->frameCount - session->framesIn; 1258 if (inBuffer->frameCount < fr) { 1259 fr = inBuffer->frameCount; 1260 } 1261 if (session->inBufSize < session->framesIn + fr) { 1262 int16_t *buf; 1263 session->inBufSize = session->framesIn + fr; 1264 buf = (int16_t *)realloc(session->inBuf, 1265 session->inBufSize * session->inChannelCount * sizeof(int16_t)); 1266 if (buf == NULL) { 1267 session->framesIn = 0; 1268 free(session->inBuf); 1269 session->inBuf = NULL; 1270 return -ENOMEM; 1271 } 1272 session->inBuf = buf; 1273 } 1274 memcpy(session->inBuf + session->framesIn * session->inChannelCount, 1275 inBuffer->s16, 1276 fr * session->inChannelCount * sizeof(int16_t)); 1277 #ifdef DUAL_MIC_TEST 1278 pthread_mutex_lock(&gPcmDumpLock); 1279 if (gPcmDumpFh != NULL) { 1280 fwrite(inBuffer->raw, 1281 fr * session->inChannelCount * sizeof(int16_t), 1, gPcmDumpFh); 1282 } 1283 pthread_mutex_unlock(&gPcmDumpLock); 1284 #endif 1285 1286 session->framesIn += fr; 1287 inBuffer->frameCount = fr; 1288 if (session->framesIn < session->frameCount) { 1289 return 0; 1290 } 1291 spx_uint32_t frIn = session->framesIn; 1292 spx_uint32_t frOut = session->apmFrameCount; 1293 if (session->inChannelCount == 1) { 1294 speex_resampler_process_int(session->inResampler, 1295 0, 1296 session->inBuf, 1297 &frIn, 1298 session->procFrame->data_, 1299 &frOut); 1300 } else { 1301 speex_resampler_process_interleaved_int(session->inResampler, 1302 session->inBuf, 1303 &frIn, 1304 session->procFrame->data_, 1305 &frOut); 1306 } 1307 memcpy(session->inBuf, 1308 session->inBuf + frIn * session->inChannelCount, 1309 (session->framesIn - frIn) * session->inChannelCount * sizeof(int16_t)); 1310 session->framesIn -= frIn; 1311 } else { 1312 size_t fr = session->frameCount - session->framesIn; 1313 if (inBuffer->frameCount < fr) { 1314 fr = inBuffer->frameCount; 1315 } 1316 memcpy(session->procFrame->data_ + session->framesIn * session->inChannelCount, 1317 inBuffer->s16, 1318 fr * session->inChannelCount * sizeof(int16_t)); 1319 1320 #ifdef DUAL_MIC_TEST 1321 pthread_mutex_lock(&gPcmDumpLock); 1322 if (gPcmDumpFh != NULL) { 1323 fwrite(inBuffer->raw, 1324 fr * session->inChannelCount * sizeof(int16_t), 1, gPcmDumpFh); 1325 } 1326 pthread_mutex_unlock(&gPcmDumpLock); 1327 #endif 1328 1329 session->framesIn += fr; 1330 inBuffer->frameCount = fr; 1331 if (session->framesIn < session->frameCount) { 1332 return 0; 1333 } 1334 session->framesIn = 0; 1335 } 1336 session->procFrame->samples_per_channel_ = session->apmFrameCount; 1337 1338 effect->session->apm->ProcessStream(session->procFrame); 1339 1340 if (session->outBufSize < session->framesOut + session->frameCount) { 1341 int16_t *buf; 1342 session->outBufSize = session->framesOut + session->frameCount; 1343 buf = (int16_t *)realloc(session->outBuf, 1344 session->outBufSize * session->outChannelCount * sizeof(int16_t)); 1345 if (buf == NULL) { 1346 session->framesOut = 0; 1347 free(session->outBuf); 1348 session->outBuf = NULL; 1349 return -ENOMEM; 1350 } 1351 session->outBuf = buf; 1352 } 1353 1354 if (session->outResampler != NULL) { 1355 spx_uint32_t frIn = session->apmFrameCount; 1356 spx_uint32_t frOut = session->frameCount; 1357 if (session->inChannelCount == 1) { 1358 speex_resampler_process_int(session->outResampler, 1359 0, 1360 session->procFrame->data_, 1361 &frIn, 1362 session->outBuf + session->framesOut * session->outChannelCount, 1363 &frOut); 1364 } else { 1365 speex_resampler_process_interleaved_int(session->outResampler, 1366 session->procFrame->data_, 1367 &frIn, 1368 session->outBuf + session->framesOut * session->outChannelCount, 1369 &frOut); 1370 } 1371 session->framesOut += frOut; 1372 } else { 1373 memcpy(session->outBuf + session->framesOut * session->outChannelCount, 1374 session->procFrame->data_, 1375 session->frameCount * session->outChannelCount * sizeof(int16_t)); 1376 session->framesOut += session->frameCount; 1377 } 1378 size_t fr = session->framesOut; 1379 if (framesRq - framesWr < fr) { 1380 fr = framesRq - framesWr; 1381 } 1382 memcpy(outBuffer->s16 + framesWr * session->outChannelCount, 1383 session->outBuf, 1384 fr * session->outChannelCount * sizeof(int16_t)); 1385 memcpy(session->outBuf, 1386 session->outBuf + fr * session->outChannelCount, 1387 (session->framesOut - fr) * session->outChannelCount * sizeof(int16_t)); 1388 session->framesOut -= fr; 1389 outBuffer->frameCount += fr; 1390 1391 return 0; 1392 } else { 1393 return -ENODATA; 1394 } 1395 } 1396 1397 int PreProcessingFx_Command(effect_handle_t self, 1398 uint32_t cmdCode, 1399 uint32_t cmdSize, 1400 void *pCmdData, 1401 uint32_t *replySize, 1402 void *pReplyData) 1403 { 1404 preproc_effect_t * effect = (preproc_effect_t *) self; 1405 int retsize; 1406 int status; 1407 1408 if (effect == NULL){ 1409 return -EINVAL; 1410 } 1411 1412 //ALOGV("PreProcessingFx_Command: command %d cmdSize %d",cmdCode, cmdSize); 1413 1414 switch (cmdCode){ 1415 case EFFECT_CMD_INIT: 1416 if (pReplyData == NULL || *replySize != sizeof(int)){ 1417 return -EINVAL; 1418 } 1419 if (effect->ops->init) { 1420 effect->ops->init(effect); 1421 } 1422 *(int *)pReplyData = 0; 1423 break; 1424 1425 case EFFECT_CMD_SET_CONFIG: { 1426 if (pCmdData == NULL|| 1427 cmdSize != sizeof(effect_config_t)|| 1428 pReplyData == NULL|| 1429 *replySize != sizeof(int)){ 1430 ALOGV("PreProcessingFx_Command cmdCode Case: " 1431 "EFFECT_CMD_SET_CONFIG: ERROR"); 1432 return -EINVAL; 1433 } 1434 #ifdef DUAL_MIC_TEST 1435 // make sure that the config command is accepted by making as if all effects were 1436 // disabled: this is OK for functional tests 1437 uint32_t enabledMsk = effect->session->enabledMsk; 1438 if (gDualMicEnabled) { 1439 effect->session->enabledMsk = 0; 1440 } 1441 #endif 1442 *(int *)pReplyData = Session_SetConfig(effect->session, (effect_config_t *)pCmdData); 1443 #ifdef DUAL_MIC_TEST 1444 if (gDualMicEnabled) { 1445 effect->session->enabledMsk = enabledMsk; 1446 } 1447 #endif 1448 if (*(int *)pReplyData != 0) { 1449 break; 1450 } 1451 if (effect->state != PREPROC_EFFECT_STATE_ACTIVE) { 1452 *(int *)pReplyData = Effect_SetState(effect, PREPROC_EFFECT_STATE_CONFIG); 1453 } 1454 } break; 1455 1456 case EFFECT_CMD_GET_CONFIG: 1457 if (pReplyData == NULL || 1458 *replySize != sizeof(effect_config_t)) { 1459 ALOGV("\tLVM_ERROR : PreProcessingFx_Command cmdCode Case: " 1460 "EFFECT_CMD_GET_CONFIG: ERROR"); 1461 return -EINVAL; 1462 } 1463 1464 Session_GetConfig(effect->session, (effect_config_t *)pReplyData); 1465 break; 1466 1467 case EFFECT_CMD_SET_CONFIG_REVERSE: 1468 if (pCmdData == NULL || 1469 cmdSize != sizeof(effect_config_t) || 1470 pReplyData == NULL || 1471 *replySize != sizeof(int)) { 1472 ALOGV("PreProcessingFx_Command cmdCode Case: " 1473 "EFFECT_CMD_SET_CONFIG_REVERSE: ERROR"); 1474 return -EINVAL; 1475 } 1476 *(int *)pReplyData = Session_SetReverseConfig(effect->session, 1477 (effect_config_t *)pCmdData); 1478 if (*(int *)pReplyData != 0) { 1479 break; 1480 } 1481 break; 1482 1483 case EFFECT_CMD_GET_CONFIG_REVERSE: 1484 if (pReplyData == NULL || 1485 *replySize != sizeof(effect_config_t)){ 1486 ALOGV("PreProcessingFx_Command cmdCode Case: " 1487 "EFFECT_CMD_GET_CONFIG_REVERSE: ERROR"); 1488 return -EINVAL; 1489 } 1490 Session_GetReverseConfig(effect->session, (effect_config_t *)pCmdData); 1491 break; 1492 1493 case EFFECT_CMD_RESET: 1494 if (effect->ops->reset) { 1495 effect->ops->reset(effect); 1496 } 1497 break; 1498 1499 case EFFECT_CMD_GET_PARAM: { 1500 effect_param_t *p = (effect_param_t *)pCmdData; 1501 1502 if (pCmdData == NULL || cmdSize < sizeof(effect_param_t) || 1503 cmdSize < (sizeof(effect_param_t) + p->psize) || 1504 pReplyData == NULL || replySize == NULL || 1505 *replySize < (sizeof(effect_param_t) + p->psize)){ 1506 ALOGV("PreProcessingFx_Command cmdCode Case: " 1507 "EFFECT_CMD_GET_PARAM: ERROR"); 1508 return -EINVAL; 1509 } 1510 1511 memcpy(pReplyData, pCmdData, sizeof(effect_param_t) + p->psize); 1512 1513 p = (effect_param_t *)pReplyData; 1514 1515 int voffset = ((p->psize - 1) / sizeof(int32_t) + 1) * sizeof(int32_t); 1516 1517 if (effect->ops->get_parameter) { 1518 p->status = effect->ops->get_parameter(effect, p->data, 1519 &p->vsize, 1520 p->data + voffset); 1521 *replySize = sizeof(effect_param_t) + voffset + p->vsize; 1522 } 1523 } break; 1524 1525 case EFFECT_CMD_SET_PARAM:{ 1526 if (pCmdData == NULL|| 1527 cmdSize < sizeof(effect_param_t) || 1528 pReplyData == NULL || replySize == NULL || 1529 *replySize != sizeof(int32_t)){ 1530 ALOGV("PreProcessingFx_Command cmdCode Case: " 1531 "EFFECT_CMD_SET_PARAM: ERROR"); 1532 return -EINVAL; 1533 } 1534 effect_param_t *p = (effect_param_t *) pCmdData; 1535 1536 if (p->psize != sizeof(int32_t)){ 1537 ALOGV("PreProcessingFx_Command cmdCode Case: " 1538 "EFFECT_CMD_SET_PARAM: ERROR, psize is not sizeof(int32_t)"); 1539 return -EINVAL; 1540 } 1541 if (effect->ops->set_parameter) { 1542 *(int *)pReplyData = effect->ops->set_parameter(effect, 1543 (void *)p->data, 1544 p->data + p->psize); 1545 } 1546 } break; 1547 1548 case EFFECT_CMD_ENABLE: 1549 if (pReplyData == NULL || replySize == NULL || *replySize != sizeof(int)){ 1550 ALOGV("PreProcessingFx_Command cmdCode Case: EFFECT_CMD_ENABLE: ERROR"); 1551 return -EINVAL; 1552 } 1553 *(int *)pReplyData = Effect_SetState(effect, PREPROC_EFFECT_STATE_ACTIVE); 1554 break; 1555 1556 case EFFECT_CMD_DISABLE: 1557 if (pReplyData == NULL || replySize == NULL || *replySize != sizeof(int)){ 1558 ALOGV("PreProcessingFx_Command cmdCode Case: EFFECT_CMD_DISABLE: ERROR"); 1559 return -EINVAL; 1560 } 1561 *(int *)pReplyData = Effect_SetState(effect, PREPROC_EFFECT_STATE_CONFIG); 1562 break; 1563 1564 case EFFECT_CMD_SET_DEVICE: 1565 case EFFECT_CMD_SET_INPUT_DEVICE: 1566 if (pCmdData == NULL || 1567 cmdSize != sizeof(uint32_t)) { 1568 ALOGV("PreProcessingFx_Command cmdCode Case: EFFECT_CMD_SET_DEVICE: ERROR"); 1569 return -EINVAL; 1570 } 1571 1572 if (effect->ops->set_device) { 1573 effect->ops->set_device(effect, *(uint32_t *)pCmdData); 1574 } 1575 break; 1576 1577 case EFFECT_CMD_SET_VOLUME: 1578 case EFFECT_CMD_SET_AUDIO_MODE: 1579 break; 1580 1581 #ifdef DUAL_MIC_TEST 1582 ///// test commands start 1583 case PREPROC_CMD_DUAL_MIC_ENABLE: { 1584 if (pCmdData == NULL|| cmdSize != sizeof(uint32_t) || 1585 pReplyData == NULL || replySize == NULL) { 1586 ALOGE("PreProcessingFx_Command cmdCode Case: " 1587 "PREPROC_CMD_DUAL_MIC_ENABLE: ERROR"); 1588 *replySize = 0; 1589 return -EINVAL; 1590 } 1591 gDualMicEnabled = *(bool *)pCmdData; 1592 if (gDualMicEnabled) { 1593 effect->aux_channels_on = sHasAuxChannels[effect->procId]; 1594 } else { 1595 effect->aux_channels_on = false; 1596 } 1597 effect->cur_channel_config = (effect->session->inChannelCount == 1) ? 1598 CHANNEL_CFG_MONO : CHANNEL_CFG_STEREO; 1599 1600 ALOGV("PREPROC_CMD_DUAL_MIC_ENABLE: %s", gDualMicEnabled ? "enabled" : "disabled"); 1601 *replySize = sizeof(int); 1602 *(int *)pReplyData = 0; 1603 } break; 1604 case PREPROC_CMD_DUAL_MIC_PCM_DUMP_START: { 1605 if (pCmdData == NULL|| pReplyData == NULL || replySize == NULL) { 1606 ALOGE("PreProcessingFx_Command cmdCode Case: " 1607 "PREPROC_CMD_DUAL_MIC_PCM_DUMP_START: ERROR"); 1608 *replySize = 0; 1609 return -EINVAL; 1610 } 1611 pthread_mutex_lock(&gPcmDumpLock); 1612 if (gPcmDumpFh != NULL) { 1613 fclose(gPcmDumpFh); 1614 gPcmDumpFh = NULL; 1615 } 1616 char *path = strndup((char *)pCmdData, cmdSize); 1617 gPcmDumpFh = fopen((char *)path, "wb"); 1618 pthread_mutex_unlock(&gPcmDumpLock); 1619 ALOGV("PREPROC_CMD_DUAL_MIC_PCM_DUMP_START: path %s gPcmDumpFh %p", 1620 path, gPcmDumpFh); 1621 ALOGE_IF(gPcmDumpFh <= 0, "gPcmDumpFh open error %d %s", errno, strerror(errno)); 1622 free(path); 1623 *replySize = sizeof(int); 1624 *(int *)pReplyData = 0; 1625 } break; 1626 case PREPROC_CMD_DUAL_MIC_PCM_DUMP_STOP: { 1627 if (pReplyData == NULL || replySize == NULL) { 1628 ALOGE("PreProcessingFx_Command cmdCode Case: " 1629 "PREPROC_CMD_DUAL_MIC_PCM_DUMP_STOP: ERROR"); 1630 *replySize = 0; 1631 return -EINVAL; 1632 } 1633 pthread_mutex_lock(&gPcmDumpLock); 1634 if (gPcmDumpFh != NULL) { 1635 fclose(gPcmDumpFh); 1636 gPcmDumpFh = NULL; 1637 } 1638 pthread_mutex_unlock(&gPcmDumpLock); 1639 ALOGV("PREPROC_CMD_DUAL_MIC_PCM_DUMP_STOP"); 1640 *replySize = sizeof(int); 1641 *(int *)pReplyData = 0; 1642 } break; 1643 ///// test commands end 1644 1645 case EFFECT_CMD_GET_FEATURE_SUPPORTED_CONFIGS: { 1646 if(!gDualMicEnabled) { 1647 return -EINVAL; 1648 } 1649 if (pCmdData == NULL|| cmdSize != 2 * sizeof(uint32_t) || 1650 pReplyData == NULL || replySize == NULL) { 1651 ALOGE("PreProcessingFx_Command cmdCode Case: " 1652 "EFFECT_CMD_GET_FEATURE_SUPPORTED_CONFIGS: ERROR"); 1653 *replySize = 0; 1654 return -EINVAL; 1655 } 1656 if (*(uint32_t *)pCmdData != EFFECT_FEATURE_AUX_CHANNELS || 1657 !effect->aux_channels_on) { 1658 ALOGV("PreProcessingFx_Command feature EFFECT_FEATURE_AUX_CHANNELS not supported by" 1659 " fx %d", effect->procId); 1660 *(uint32_t *)pReplyData = -ENOSYS; 1661 *replySize = sizeof(uint32_t); 1662 break; 1663 } 1664 size_t num_configs = *((uint32_t *)pCmdData + 1); 1665 if (*replySize < (2 * sizeof(uint32_t) + 1666 num_configs * sizeof(channel_config_t))) { 1667 *replySize = 0; 1668 return -EINVAL; 1669 } 1670 1671 *((uint32_t *)pReplyData + 1) = CHANNEL_CFG_CNT; 1672 if (num_configs < CHANNEL_CFG_CNT || 1673 *replySize < (2 * sizeof(uint32_t) + 1674 CHANNEL_CFG_CNT * sizeof(channel_config_t))) { 1675 *(uint32_t *)pReplyData = -ENOMEM; 1676 } else { 1677 num_configs = CHANNEL_CFG_CNT; 1678 *(uint32_t *)pReplyData = 0; 1679 } 1680 ALOGV("PreProcessingFx_Command EFFECT_CMD_GET_FEATURE_SUPPORTED_CONFIGS num config %d", 1681 num_configs); 1682 1683 *replySize = 2 * sizeof(uint32_t) + num_configs * sizeof(channel_config_t); 1684 *((uint32_t *)pReplyData + 1) = num_configs; 1685 memcpy((uint32_t *)pReplyData + 2, &sDualMicConfigs, num_configs * sizeof(channel_config_t)); 1686 } break; 1687 case EFFECT_CMD_GET_FEATURE_CONFIG: 1688 if(!gDualMicEnabled) { 1689 return -EINVAL; 1690 } 1691 if (pCmdData == NULL|| cmdSize != sizeof(uint32_t) || 1692 pReplyData == NULL || replySize == NULL || 1693 *replySize < sizeof(uint32_t) + sizeof(channel_config_t)) { 1694 ALOGE("PreProcessingFx_Command cmdCode Case: " 1695 "EFFECT_CMD_GET_FEATURE_CONFIG: ERROR"); 1696 return -EINVAL; 1697 } 1698 if (*(uint32_t *)pCmdData != EFFECT_FEATURE_AUX_CHANNELS || !effect->aux_channels_on) { 1699 *(uint32_t *)pReplyData = -ENOSYS; 1700 *replySize = sizeof(uint32_t); 1701 break; 1702 } 1703 ALOGV("PreProcessingFx_Command EFFECT_CMD_GET_FEATURE_CONFIG"); 1704 *(uint32_t *)pReplyData = 0; 1705 *replySize = sizeof(uint32_t) + sizeof(channel_config_t); 1706 memcpy((uint32_t *)pReplyData + 1, 1707 &sDualMicConfigs[effect->cur_channel_config], 1708 sizeof(channel_config_t)); 1709 break; 1710 case EFFECT_CMD_SET_FEATURE_CONFIG: { 1711 ALOGV("PreProcessingFx_Command EFFECT_CMD_SET_FEATURE_CONFIG: " 1712 "gDualMicEnabled %d effect->aux_channels_on %d", 1713 gDualMicEnabled, effect->aux_channels_on); 1714 if(!gDualMicEnabled) { 1715 return -EINVAL; 1716 } 1717 if (pCmdData == NULL|| cmdSize != (sizeof(uint32_t) + sizeof(channel_config_t)) || 1718 pReplyData == NULL || replySize == NULL || 1719 *replySize < sizeof(uint32_t)) { 1720 ALOGE("PreProcessingFx_Command cmdCode Case: " 1721 "EFFECT_CMD_SET_FEATURE_CONFIG: ERROR\n" 1722 "pCmdData %p cmdSize %d pReplyData %p replySize %p *replySize %d", 1723 pCmdData, cmdSize, pReplyData, replySize, replySize ? *replySize : -1); 1724 return -EINVAL; 1725 } 1726 *replySize = sizeof(uint32_t); 1727 if (*(uint32_t *)pCmdData != EFFECT_FEATURE_AUX_CHANNELS || !effect->aux_channels_on) { 1728 *(uint32_t *)pReplyData = -ENOSYS; 1729 ALOGV("PreProcessingFx_Command cmdCode Case: " 1730 "EFFECT_CMD_SET_FEATURE_CONFIG: ERROR\n" 1731 "CmdData %d effect->aux_channels_on %d", 1732 *(uint32_t *)pCmdData, effect->aux_channels_on); 1733 break; 1734 } 1735 size_t i; 1736 for (i = 0; i < CHANNEL_CFG_CNT;i++) { 1737 if (memcmp((uint32_t *)pCmdData + 1, 1738 &sDualMicConfigs[i], sizeof(channel_config_t)) == 0) { 1739 break; 1740 } 1741 } 1742 if (i == CHANNEL_CFG_CNT) { 1743 *(uint32_t *)pReplyData = -EINVAL; 1744 ALOGW("PreProcessingFx_Command EFFECT_CMD_SET_FEATURE_CONFIG invalid config" 1745 "[%08x].[%08x]", *((uint32_t *)pCmdData + 1), *((uint32_t *)pCmdData + 2)); 1746 } else { 1747 effect->cur_channel_config = i; 1748 *(uint32_t *)pReplyData = 0; 1749 ALOGV("PreProcessingFx_Command EFFECT_CMD_SET_FEATURE_CONFIG New config" 1750 "[%08x].[%08x]", sDualMicConfigs[i].main_channels, sDualMicConfigs[i].aux_channels); 1751 } 1752 } break; 1753 #endif 1754 default: 1755 return -EINVAL; 1756 } 1757 return 0; 1758 } 1759 1760 1761 int PreProcessingFx_GetDescriptor(effect_handle_t self, 1762 effect_descriptor_t *pDescriptor) 1763 { 1764 preproc_effect_t * effect = (preproc_effect_t *) self; 1765 1766 if (effect == NULL || pDescriptor == NULL) { 1767 return -EINVAL; 1768 } 1769 1770 *pDescriptor = *sDescriptors[effect->procId]; 1771 1772 return 0; 1773 } 1774 1775 int PreProcessingFx_ProcessReverse(effect_handle_t self, 1776 audio_buffer_t *inBuffer, 1777 audio_buffer_t *outBuffer __unused) 1778 { 1779 preproc_effect_t * effect = (preproc_effect_t *)self; 1780 int status = 0; 1781 1782 if (effect == NULL){ 1783 ALOGW("PreProcessingFx_ProcessReverse() ERROR effect == NULL"); 1784 return -EINVAL; 1785 } 1786 preproc_session_t * session = (preproc_session_t *)effect->session; 1787 1788 if (inBuffer == NULL || inBuffer->raw == NULL){ 1789 ALOGW("PreProcessingFx_ProcessReverse() ERROR bad pointer"); 1790 return -EINVAL; 1791 } 1792 1793 session->revProcessedMsk |= (1<<effect->procId); 1794 1795 // ALOGV("PreProcessingFx_ProcessReverse In %d frames revEnabledMsk %08x revProcessedMsk %08x", 1796 // inBuffer->frameCount, session->revEnabledMsk, session->revProcessedMsk); 1797 1798 1799 if ((session->revProcessedMsk & session->revEnabledMsk) == session->revEnabledMsk) { 1800 effect->session->revProcessedMsk = 0; 1801 if (session->revResampler != NULL) { 1802 size_t fr = session->frameCount - session->framesRev; 1803 if (inBuffer->frameCount < fr) { 1804 fr = inBuffer->frameCount; 1805 } 1806 if (session->revBufSize < session->framesRev + fr) { 1807 int16_t *buf; 1808 session->revBufSize = session->framesRev + fr; 1809 buf = (int16_t *)realloc(session->revBuf, 1810 session->revBufSize * session->inChannelCount * sizeof(int16_t)); 1811 if (buf == NULL) { 1812 session->framesRev = 0; 1813 free(session->revBuf); 1814 session->revBuf = NULL; 1815 return -ENOMEM; 1816 } 1817 session->revBuf = buf; 1818 } 1819 memcpy(session->revBuf + session->framesRev * session->inChannelCount, 1820 inBuffer->s16, 1821 fr * session->inChannelCount * sizeof(int16_t)); 1822 1823 session->framesRev += fr; 1824 inBuffer->frameCount = fr; 1825 if (session->framesRev < session->frameCount) { 1826 return 0; 1827 } 1828 spx_uint32_t frIn = session->framesRev; 1829 spx_uint32_t frOut = session->apmFrameCount; 1830 if (session->inChannelCount == 1) { 1831 speex_resampler_process_int(session->revResampler, 1832 0, 1833 session->revBuf, 1834 &frIn, 1835 session->revFrame->data_, 1836 &frOut); 1837 } else { 1838 speex_resampler_process_interleaved_int(session->revResampler, 1839 session->revBuf, 1840 &frIn, 1841 session->revFrame->data_, 1842 &frOut); 1843 } 1844 memcpy(session->revBuf, 1845 session->revBuf + frIn * session->inChannelCount, 1846 (session->framesRev - frIn) * session->inChannelCount * sizeof(int16_t)); 1847 session->framesRev -= frIn; 1848 } else { 1849 size_t fr = session->frameCount - session->framesRev; 1850 if (inBuffer->frameCount < fr) { 1851 fr = inBuffer->frameCount; 1852 } 1853 memcpy(session->revFrame->data_ + session->framesRev * session->inChannelCount, 1854 inBuffer->s16, 1855 fr * session->inChannelCount * sizeof(int16_t)); 1856 session->framesRev += fr; 1857 inBuffer->frameCount = fr; 1858 if (session->framesRev < session->frameCount) { 1859 return 0; 1860 } 1861 session->framesRev = 0; 1862 } 1863 session->revFrame->samples_per_channel_ = session->apmFrameCount; 1864 effect->session->apm->AnalyzeReverseStream(session->revFrame); 1865 return 0; 1866 } else { 1867 return -ENODATA; 1868 } 1869 } 1870 1871 1872 // effect_handle_t interface implementation for effect 1873 const struct effect_interface_s sEffectInterface = { 1874 PreProcessingFx_Process, 1875 PreProcessingFx_Command, 1876 PreProcessingFx_GetDescriptor, 1877 NULL 1878 }; 1879 1880 const struct effect_interface_s sEffectInterfaceReverse = { 1881 PreProcessingFx_Process, 1882 PreProcessingFx_Command, 1883 PreProcessingFx_GetDescriptor, 1884 PreProcessingFx_ProcessReverse 1885 }; 1886 1887 //------------------------------------------------------------------------------ 1888 // Effect Library Interface Implementation 1889 //------------------------------------------------------------------------------ 1890 1891 int PreProcessingLib_Create(const effect_uuid_t *uuid, 1892 int32_t sessionId, 1893 int32_t ioId, 1894 effect_handle_t *pInterface) 1895 { 1896 ALOGV("EffectCreate: uuid: %08x session %d IO: %d", uuid->timeLow, sessionId, ioId); 1897 1898 int status; 1899 const effect_descriptor_t *desc; 1900 preproc_session_t *session; 1901 uint32_t procId; 1902 1903 if (PreProc_Init() != 0) { 1904 return sInitStatus; 1905 } 1906 desc = PreProc_GetDescriptor(uuid); 1907 if (desc == NULL) { 1908 ALOGW("EffectCreate: fx not found uuid: %08x", uuid->timeLow); 1909 return -EINVAL; 1910 } 1911 procId = UuidToProcId(&desc->type); 1912 1913 session = PreProc_GetSession(procId, sessionId, ioId); 1914 if (session == NULL) { 1915 ALOGW("EffectCreate: no more session available"); 1916 return -EINVAL; 1917 } 1918 1919 status = Session_CreateEffect(session, procId, pInterface); 1920 1921 if (status < 0 && session->createdMsk == 0) { 1922 session->io = 0; 1923 } 1924 return status; 1925 } 1926 1927 int PreProcessingLib_Release(effect_handle_t interface) 1928 { 1929 int status; 1930 ALOGV("EffectRelease start %p", interface); 1931 if (PreProc_Init() != 0) { 1932 return sInitStatus; 1933 } 1934 1935 preproc_effect_t *fx = (preproc_effect_t *)interface; 1936 1937 if (fx->session->io == 0) { 1938 return -EINVAL; 1939 } 1940 return Session_ReleaseEffect(fx->session, fx); 1941 } 1942 1943 int PreProcessingLib_GetDescriptor(const effect_uuid_t *uuid, 1944 effect_descriptor_t *pDescriptor) { 1945 1946 if (pDescriptor == NULL || uuid == NULL){ 1947 return -EINVAL; 1948 } 1949 1950 const effect_descriptor_t *desc = PreProc_GetDescriptor(uuid); 1951 if (desc == NULL) { 1952 ALOGV("PreProcessingLib_GetDescriptor() not found"); 1953 return -EINVAL; 1954 } 1955 1956 ALOGV("PreProcessingLib_GetDescriptor() got fx %s", desc->name); 1957 1958 *pDescriptor = *desc; 1959 return 0; 1960 } 1961 1962 // This is the only symbol that needs to be exported 1963 __attribute__ ((visibility ("default"))) 1964 audio_effect_library_t AUDIO_EFFECT_LIBRARY_INFO_SYM = { 1965 .tag = AUDIO_EFFECT_LIBRARY_TAG, 1966 .version = EFFECT_LIBRARY_API_VERSION, 1967 .name = "Audio Preprocessing Library", 1968 .implementor = "The Android Open Source Project", 1969 .create_effect = PreProcessingLib_Create, 1970 .release_effect = PreProcessingLib_Release, 1971 .get_descriptor = PreProcessingLib_GetDescriptor 1972 }; 1973 1974 }; // extern "C" 1975