blob: f2f74a58404f4956b4720f0e5383a9eb186996c0 [file] [log] [blame]
Eric Laurenta9390d42011-06-17 20:17:17 -07001/*
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>
Saketh Sathuvalli08337032020-09-22 21:13:45 +053026#ifndef WEBRTC_LEGACY
27#include <audio_effects/effect_agc2.h>
28#endif
Eric Laurenta9390d42011-06-17 20:17:17 -070029#include <audio_effects/effect_ns.h>
Eric Laurent53876962012-01-31 12:35:20 -080030#include <module_common_types.h>
31#include <audio_processing.h>
Saketh Sathuvalli08337032020-09-22 21:13:45 +053032#ifdef WEBRTC_LEGACY
Eric Laurenta9390d42011-06-17 20:17:17 -070033#include "speex/speex_resampler.h"
Saketh Sathuvalli08337032020-09-22 21:13:45 +053034#endif
Eric Laurenta9390d42011-06-17 20:17:17 -070035
Eric Laurent3f9c84c2012-04-03 15:36:53 -070036// undefine to perform multi channels API functional tests
37//#define DUAL_MIC_TEST
Eric Laurenta9390d42011-06-17 20:17:17 -070038
39//------------------------------------------------------------------------------
40// local definitions
41//------------------------------------------------------------------------------
42
43// maximum number of sessions
44#define PREPROC_NUM_SESSIONS 8
45
46// types of pre processing modules
47enum preproc_id
48{
49 PREPROC_AGC, // Automatic Gain Control
Saketh Sathuvalli08337032020-09-22 21:13:45 +053050#ifndef WEBRTC_LEGACY
51 PREPROC_AGC2, // Automatic Gain Control 2
52#endif
Eric Laurenta9390d42011-06-17 20:17:17 -070053 PREPROC_AEC, // Acoustic Echo Canceler
54 PREPROC_NS, // Noise Suppressor
55 PREPROC_NUM_EFFECTS
56};
57
58// Session state
59enum preproc_session_state {
60 PREPROC_SESSION_STATE_INIT, // initialized
61 PREPROC_SESSION_STATE_CONFIG // configuration received
62};
63
64// Effect/Preprocessor state
65enum preproc_effect_state {
66 PREPROC_EFFECT_STATE_INIT, // initialized
67 PREPROC_EFFECT_STATE_CREATED, // webRTC engine created
68 PREPROC_EFFECT_STATE_CONFIG, // configuration received/disabled
69 PREPROC_EFFECT_STATE_ACTIVE // active/enabled
70};
71
72// handle on webRTC engine
73typedef void* preproc_fx_handle_t;
74
75typedef struct preproc_session_s preproc_session_t;
76typedef struct preproc_effect_s preproc_effect_t;
77typedef struct preproc_ops_s preproc_ops_t;
78
79// Effect operation table. Functions for all pre processors are declared in sPreProcOps[] table.
80// Function pointer can be null if no action required.
81struct preproc_ops_s {
82 int (* create)(preproc_effect_t *fx);
83 int (* init)(preproc_effect_t *fx);
84 int (* reset)(preproc_effect_t *fx);
85 void (* enable)(preproc_effect_t *fx);
86 void (* disable)(preproc_effect_t *fx);
87 int (* set_parameter)(preproc_effect_t *fx, void *param, void *value);
Ashok Bhatb302bd52014-02-18 11:40:00 +000088 int (* get_parameter)(preproc_effect_t *fx, void *param, uint32_t *size, void *value);
Eric Laurenta9390d42011-06-17 20:17:17 -070089 int (* set_device)(preproc_effect_t *fx, uint32_t device);
90};
91
92// Effect context
93struct preproc_effect_s {
94 const struct effect_interface_s *itfe;
95 uint32_t procId; // type of pre processor (enum preproc_id)
96 uint32_t state; // current state (enum preproc_effect_state)
97 preproc_session_t *session; // session the effect is on
98 const preproc_ops_t *ops; // effect ops table
99 preproc_fx_handle_t engine; // handle on webRTC engine
Alex Luebs766bf732015-12-14 21:32:13 -0800100 uint32_t type; // subtype of effect
Eric Laurent3f9c84c2012-04-03 15:36:53 -0700101#ifdef DUAL_MIC_TEST
102 bool aux_channels_on; // support auxiliary channels
103 size_t cur_channel_config; // current auciliary channel configuration
104#endif
Eric Laurenta9390d42011-06-17 20:17:17 -0700105};
106
107// Session context
108struct preproc_session_s {
109 struct preproc_effect_s effects[PREPROC_NUM_EFFECTS]; // effects in this session
110 uint32_t state; // current state (enum preproc_session_state)
111 int id; // audio session ID
112 int io; // handle of input stream this session is on
113 webrtc::AudioProcessing* apm; // handle on webRTC audio processing module (APM)
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530114#ifndef WEBRTC_LEGACY
115 // Audio Processing module builder
116 webrtc::AudioProcessingBuilder ap_builder;
117#endif
Eric Laurenta9390d42011-06-17 20:17:17 -0700118 size_t apmFrameCount; // buffer size for webRTC process (10 ms)
119 uint32_t apmSamplingRate; // webRTC APM sampling rate (8/16 or 32 kHz)
120 size_t frameCount; // buffer size before input resampler ( <=> apmFrameCount)
121 uint32_t samplingRate; // sampling rate at effect process interface
122 uint32_t inChannelCount; // input channel count
123 uint32_t outChannelCount; // output channel count
124 uint32_t createdMsk; // bit field containing IDs of crested pre processors
125 uint32_t enabledMsk; // bit field containing IDs of enabled pre processors
126 uint32_t processedMsk; // bit field containing IDs of pre processors already
127 // processed in current round
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530128#ifdef WEBRTC_LEGACY
Eric Laurenta9390d42011-06-17 20:17:17 -0700129 webrtc::AudioFrame *procFrame; // audio frame passed to webRTC AMP ProcessStream()
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530130#else
131 // audio config strucutre
132 webrtc::AudioProcessing::Config config;
133 webrtc::StreamConfig inputConfig; // input stream configuration
134 webrtc::StreamConfig outputConfig; // output stream configuration
135#endif
Eric Laurenta9390d42011-06-17 20:17:17 -0700136 int16_t *inBuf; // input buffer used when resampling
137 size_t inBufSize; // input buffer size in frames
138 size_t framesIn; // number of frames in input buffer
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530139#ifdef WEBRTC_LEGACY
Eric Laurenta9390d42011-06-17 20:17:17 -0700140 SpeexResamplerState *inResampler; // handle on input speex resampler
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530141#endif
Eric Laurenta9390d42011-06-17 20:17:17 -0700142 int16_t *outBuf; // output buffer used when resampling
143 size_t outBufSize; // output buffer size in frames
144 size_t framesOut; // number of frames in output buffer
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530145#ifdef WEBRTC_LEGACY
Eric Laurenta9390d42011-06-17 20:17:17 -0700146 SpeexResamplerState *outResampler; // handle on output speex resampler
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530147#endif
Eric Laurenta9390d42011-06-17 20:17:17 -0700148 uint32_t revChannelCount; // number of channels on reverse stream
149 uint32_t revEnabledMsk; // bit field containing IDs of enabled pre processors
150 // with reverse channel
151 uint32_t revProcessedMsk; // bit field containing IDs of pre processors with reverse
152 // channel already processed in current round
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530153#ifdef WEBRTC_LEGACY
Eric Laurenta9390d42011-06-17 20:17:17 -0700154 webrtc::AudioFrame *revFrame; // audio frame passed to webRTC AMP AnalyzeReverseStream()
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530155#else
156 webrtc::StreamConfig revConfig; // reverse stream configuration.
157#endif
Eric Laurenta9390d42011-06-17 20:17:17 -0700158 int16_t *revBuf; // reverse channel input buffer
159 size_t revBufSize; // reverse channel input buffer size
160 size_t framesRev; // number of frames in reverse channel input buffer
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530161#ifdef WEBRTC_LEGACY
Eric Laurenta9390d42011-06-17 20:17:17 -0700162 SpeexResamplerState *revResampler; // handle on reverse channel input speex resampler
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530163#endif
Eric Laurenta9390d42011-06-17 20:17:17 -0700164};
165
Eric Laurent3f9c84c2012-04-03 15:36:53 -0700166#ifdef DUAL_MIC_TEST
167enum {
168 PREPROC_CMD_DUAL_MIC_ENABLE = EFFECT_CMD_FIRST_PROPRIETARY, // enable dual mic mode
169 PREPROC_CMD_DUAL_MIC_PCM_DUMP_START, // start pcm capture
170 PREPROC_CMD_DUAL_MIC_PCM_DUMP_STOP // stop pcm capture
171};
172
173enum {
174 CHANNEL_CFG_MONO,
175 CHANNEL_CFG_STEREO,
176 CHANNEL_CFG_MONO_AUX,
177 CHANNEL_CFG_STEREO_AUX,
178 CHANNEL_CFG_CNT,
179 CHANNEL_CFG_FIRST_AUX = CHANNEL_CFG_MONO_AUX,
180};
181
182const channel_config_t sDualMicConfigs[CHANNEL_CFG_CNT] = {
183 {AUDIO_CHANNEL_IN_MONO , 0},
184 {AUDIO_CHANNEL_IN_STEREO , 0},
185 {AUDIO_CHANNEL_IN_FRONT , AUDIO_CHANNEL_IN_BACK},
186 {AUDIO_CHANNEL_IN_STEREO , AUDIO_CHANNEL_IN_RIGHT}
187};
188
189bool sHasAuxChannels[PREPROC_NUM_EFFECTS] = {
190 false, // PREPROC_AGC
191 true, // PREPROC_AEC
192 true, // PREPROC_NS
193};
194
195bool gDualMicEnabled;
196FILE *gPcmDumpFh;
197static pthread_mutex_t gPcmDumpLock = PTHREAD_MUTEX_INITIALIZER;
198#endif
199
200
Eric Laurenta9390d42011-06-17 20:17:17 -0700201//------------------------------------------------------------------------------
202// Effect descriptors
203//------------------------------------------------------------------------------
204
205// UUIDs for effect types have been generated from http://www.itu.int/ITU-T/asn1/uuid.html
206// as the pre processing effects are not defined by OpenSL ES
207
208// Automatic Gain Control
209static const effect_descriptor_t sAgcDescriptor = {
210 { 0x0a8abfe0, 0x654c, 0x11e0, 0xba26, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } }, // type
211 { 0xaa8130e0, 0x66fc, 0x11e0, 0xbad0, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } }, // uuid
212 EFFECT_CONTROL_API_VERSION,
213 (EFFECT_FLAG_TYPE_PRE_PROC|EFFECT_FLAG_DEVICE_IND),
214 0, //FIXME indicate CPU load
215 0, //FIXME indicate memory usage
216 "Automatic Gain Control",
217 "The Android Open Source Project"
218};
219
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530220#ifndef WEBRTC_LEGACY
221// Automatic Gain Control 2
222static const effect_descriptor_t sAgc2Descriptor = {
223 { 0xae3c653b, 0xbe18, 0x4ab8, 0x8938, { 0x41, 0x8f, 0x0a, 0x7f, 0x06, 0xac } }, // type
224 { 0x89f38e65, 0xd4d2, 0x4d64, 0xad0e, { 0x2b, 0x3e, 0x79, 0x9e, 0xa8, 0x86 } }, // uuid
225 EFFECT_CONTROL_API_VERSION,
226 (EFFECT_FLAG_TYPE_PRE_PROC|EFFECT_FLAG_DEVICE_IND),
227 0, //FIXME indicate CPU load
228 0, //FIXME indicate memory usage
229 "Automatic Gain Control 2",
230 "The Android Open Source Project"
231};
232#endif
233
Eric Laurenta9390d42011-06-17 20:17:17 -0700234// Acoustic Echo Cancellation
235static const effect_descriptor_t sAecDescriptor = {
236 { 0x7b491460, 0x8d4d, 0x11e0, 0xbd61, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } }, // type
237 { 0xbb392ec0, 0x8d4d, 0x11e0, 0xa896, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } }, // uuid
238 EFFECT_CONTROL_API_VERSION,
239 (EFFECT_FLAG_TYPE_PRE_PROC|EFFECT_FLAG_DEVICE_IND),
240 0, //FIXME indicate CPU load
241 0, //FIXME indicate memory usage
242 "Acoustic Echo Canceler",
243 "The Android Open Source Project"
244};
245
246// Noise suppression
247static const effect_descriptor_t sNsDescriptor = {
248 { 0x58b4b260, 0x8e06, 0x11e0, 0xaa8e, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } }, // type
249 { 0xc06c8400, 0x8e06, 0x11e0, 0x9cb6, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } }, // uuid
250 EFFECT_CONTROL_API_VERSION,
251 (EFFECT_FLAG_TYPE_PRE_PROC|EFFECT_FLAG_DEVICE_IND),
252 0, //FIXME indicate CPU load
253 0, //FIXME indicate memory usage
254 "Noise Suppression",
255 "The Android Open Source Project"
256};
257
258
259static const effect_descriptor_t *sDescriptors[PREPROC_NUM_EFFECTS] = {
260 &sAgcDescriptor,
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530261#ifndef WEBRTC_LEGACY
262 &sAgc2Descriptor,
263#endif
Eric Laurenta9390d42011-06-17 20:17:17 -0700264 &sAecDescriptor,
265 &sNsDescriptor
266};
267
268//------------------------------------------------------------------------------
269// Helper functions
270//------------------------------------------------------------------------------
271
272const effect_uuid_t * const sUuidToPreProcTable[PREPROC_NUM_EFFECTS] = {
273 FX_IID_AGC,
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530274#ifndef WEBRTC_LEGACY
275 FX_IID_AGC2,
276#endif
Eric Laurenta9390d42011-06-17 20:17:17 -0700277 FX_IID_AEC,
278 FX_IID_NS
279};
280
281
282const effect_uuid_t * ProcIdToUuid(int procId)
283{
284 if (procId >= PREPROC_NUM_EFFECTS) {
285 return EFFECT_UUID_NULL;
286 }
287 return sUuidToPreProcTable[procId];
288}
289
290uint32_t UuidToProcId(const effect_uuid_t * uuid)
291{
292 size_t i;
293 for (i = 0; i < PREPROC_NUM_EFFECTS; i++) {
294 if (memcmp(uuid, sUuidToPreProcTable[i], sizeof(*uuid)) == 0) {
295 break;
296 }
297 }
298 return i;
299}
300
301bool HasReverseStream(uint32_t procId)
302{
303 if (procId == PREPROC_AEC) {
304 return true;
305 }
306 return false;
307}
308
309
310//------------------------------------------------------------------------------
311// Automatic Gain Control (AGC)
312//------------------------------------------------------------------------------
313
Eric Laurent53876962012-01-31 12:35:20 -0800314static const int kAgcDefaultTargetLevel = 3;
315static const int kAgcDefaultCompGain = 9;
Eric Laurenta9390d42011-06-17 20:17:17 -0700316static const bool kAgcDefaultLimiter = true;
317
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530318#ifndef WEBRTC_LEGACY
319int Agc2Init (preproc_effect_t *effect)
320{
321 ALOGV("Agc2Init");
322 effect->session->config = effect->session->apm->GetConfig();
323 effect->session->config.gain_controller2.fixed_digital.gain_db = 0.f;
324 effect->session->config.gain_controller2.adaptive_digital.level_estimator =
325 effect->session->config.gain_controller2.kRms;
326 effect->session->config.gain_controller2.adaptive_digital.extra_saturation_margin_db = 2.f;
327 effect->session->apm->ApplyConfig(effect->session->config);
328 return 0;
329}
330#endif
331
Eric Laurenta9390d42011-06-17 20:17:17 -0700332int AgcInit (preproc_effect_t *effect)
333{
Steve Block3856b092011-10-20 11:56:00 +0100334 ALOGV("AgcInit");
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530335#ifdef WEBRTC_LEGACY
Eric Laurenta9390d42011-06-17 20:17:17 -0700336 webrtc::GainControl *agc = static_cast<webrtc::GainControl *>(effect->engine);
337 agc->set_mode(webrtc::GainControl::kFixedDigital);
338 agc->set_target_level_dbfs(kAgcDefaultTargetLevel);
339 agc->set_compression_gain_db(kAgcDefaultCompGain);
340 agc->enable_limiter(kAgcDefaultLimiter);
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530341#else
342 effect->session->config = effect->session->apm->GetConfig();
343 effect->session->config.gain_controller1.target_level_dbfs = kAgcDefaultTargetLevel;
344 effect->session->config.gain_controller1.compression_gain_db = kAgcDefaultCompGain;
345 effect->session->config.gain_controller1.enable_limiter = kAgcDefaultLimiter;
346 effect->session->apm->ApplyConfig(effect->session->config);
347#endif
Eric Laurenta9390d42011-06-17 20:17:17 -0700348 return 0;
349}
350
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530351#ifndef WEBRTC_LEGACY
352int Agc2Create(preproc_effect_t *effect)
353{
354 Agc2Init(effect);
355 return 0;
356}
357#endif
358
Eric Laurenta9390d42011-06-17 20:17:17 -0700359int AgcCreate(preproc_effect_t *effect)
360{
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530361#ifdef WEBRTC_LEGACY
Eric Laurenta9390d42011-06-17 20:17:17 -0700362 webrtc::GainControl *agc = effect->session->apm->gain_control();
Steve Block3856b092011-10-20 11:56:00 +0100363 ALOGV("AgcCreate got agc %p", agc);
Eric Laurenta9390d42011-06-17 20:17:17 -0700364 if (agc == NULL) {
Steve Block5ff1dd52012-01-05 23:22:43 +0000365 ALOGW("AgcCreate Error");
Eric Laurenta9390d42011-06-17 20:17:17 -0700366 return -ENOMEM;
367 }
368 effect->engine = static_cast<preproc_fx_handle_t>(agc);
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530369#endif
Eric Laurenta9390d42011-06-17 20:17:17 -0700370 AgcInit(effect);
371 return 0;
372}
373
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530374#ifndef WEBRTC_LEGACY
375int Agc2GetParameter(preproc_effect_t *effect,
376 void *pParam,
377 uint32_t *pValueSize,
378 void *pValue)
379{
380 int status = 0;
381 uint32_t param = *(uint32_t *)pParam;
382 agc2_settings_t *pProperties = (agc2_settings_t *)pValue;
383
384 switch (param) {
385 case AGC2_PARAM_FIXED_DIGITAL_GAIN:
386 if (*pValueSize < sizeof(float)) {
387 *pValueSize = 0.f;
388 return -EINVAL;
389 }
390 break;
391 case AGC2_PARAM_ADAPT_DIGI_LEVEL_ESTIMATOR:
392 if (*pValueSize < sizeof(int32_t)) {
393 *pValueSize = 0;
394 return -EINVAL;
395 }
396 break;
397 case AGC2_PARAM_ADAPT_DIGI_EXTRA_SATURATION_MARGIN:
398 if (*pValueSize < sizeof(float)) {
399 *pValueSize = 0.f;
400 return -EINVAL;
401 }
402 break;
403 case AGC2_PARAM_PROPERTIES:
404 if (*pValueSize < sizeof(agc2_settings_t)) {
405 *pValueSize = 0;
406 return -EINVAL;
407 }
408 break;
409
410 default:
411 ALOGW("Agc2GetParameter() unknown param %08x", param);
412 status = -EINVAL;
413 break;
414 }
415
416 effect->session->config = effect->session->apm->GetConfig();
417 switch (param) {
418 case AGC2_PARAM_FIXED_DIGITAL_GAIN:
419 *(float *) pValue =
420 (float)(effect->session->config.gain_controller2.fixed_digital.gain_db);
421 ALOGV("Agc2GetParameter() target level %f dB", *(float *) pValue);
422 break;
423 case AGC2_PARAM_ADAPT_DIGI_LEVEL_ESTIMATOR:
424 *(uint32_t *) pValue =
425 (uint32_t)(effect->session->config.gain_controller2.adaptive_digital.
426 level_estimator);
427 ALOGV("Agc2GetParameter() level estimator %d",
428 *(webrtc::AudioProcessing::Config::GainController2::LevelEstimator *) pValue);
429 break;
430 case AGC2_PARAM_ADAPT_DIGI_EXTRA_SATURATION_MARGIN:
431 *(float *) pValue =
432 (float)(effect->session->config.gain_controller2.adaptive_digital.
433 extra_saturation_margin_db);
434 ALOGV("Agc2GetParameter() extra saturation margin %f dB", *(float *) pValue);
435 break;
436 case AGC2_PARAM_PROPERTIES:
437 pProperties->fixedDigitalGain =
438 (float)(effect->session->config.gain_controller2.fixed_digital.gain_db);
439 pProperties->level_estimator =
440 (uint32_t)(effect->session->config.gain_controller2.adaptive_digital.
441 level_estimator);
442 pProperties->extraSaturationMargin =
443 (float)(effect->session->config.gain_controller2.adaptive_digital.
444 extra_saturation_margin_db);
445 break;
446 default:
447 ALOGW("Agc2GetParameter() unknown param %d", param);
448 status = -EINVAL;
449 break;
450 }
451
452 return status;
453}
454#endif
455
Eric Laurenta9390d42011-06-17 20:17:17 -0700456int AgcGetParameter(preproc_effect_t *effect,
457 void *pParam,
Ashok Bhatb302bd52014-02-18 11:40:00 +0000458 uint32_t *pValueSize,
Eric Laurenta9390d42011-06-17 20:17:17 -0700459 void *pValue)
460{
461 int status = 0;
462 uint32_t param = *(uint32_t *)pParam;
463 t_agc_settings *pProperties = (t_agc_settings *)pValue;
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530464#ifdef WEBRTC_LEGACY
Eric Laurenta9390d42011-06-17 20:17:17 -0700465 webrtc::GainControl *agc = static_cast<webrtc::GainControl *>(effect->engine);
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530466#endif
Eric Laurenta9390d42011-06-17 20:17:17 -0700467
468 switch (param) {
469 case AGC_PARAM_TARGET_LEVEL:
470 case AGC_PARAM_COMP_GAIN:
471 if (*pValueSize < sizeof(int16_t)) {
472 *pValueSize = 0;
473 return -EINVAL;
474 }
475 break;
476 case AGC_PARAM_LIMITER_ENA:
477 if (*pValueSize < sizeof(bool)) {
478 *pValueSize = 0;
479 return -EINVAL;
480 }
481 break;
482 case AGC_PARAM_PROPERTIES:
483 if (*pValueSize < sizeof(t_agc_settings)) {
484 *pValueSize = 0;
485 return -EINVAL;
486 }
487 break;
488
489 default:
Steve Block5ff1dd52012-01-05 23:22:43 +0000490 ALOGW("AgcGetParameter() unknown param %08x", param);
Eric Laurenta9390d42011-06-17 20:17:17 -0700491 status = -EINVAL;
492 break;
493 }
494
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530495#ifdef WEBRTC_LEGACY
Eric Laurenta9390d42011-06-17 20:17:17 -0700496 switch (param) {
497 case AGC_PARAM_TARGET_LEVEL:
498 *(int16_t *) pValue = (int16_t)(agc->target_level_dbfs() * -100);
Steve Block3856b092011-10-20 11:56:00 +0100499 ALOGV("AgcGetParameter() target level %d milliBels", *(int16_t *) pValue);
Eric Laurenta9390d42011-06-17 20:17:17 -0700500 break;
501 case AGC_PARAM_COMP_GAIN:
502 *(int16_t *) pValue = (int16_t)(agc->compression_gain_db() * 100);
Steve Block3856b092011-10-20 11:56:00 +0100503 ALOGV("AgcGetParameter() comp gain %d milliBels", *(int16_t *) pValue);
Eric Laurenta9390d42011-06-17 20:17:17 -0700504 break;
505 case AGC_PARAM_LIMITER_ENA:
506 *(bool *) pValue = (bool)agc->is_limiter_enabled();
Steve Block3856b092011-10-20 11:56:00 +0100507 ALOGV("AgcGetParameter() limiter enabled %s",
Eric Laurenta9390d42011-06-17 20:17:17 -0700508 (*(int16_t *) pValue != 0) ? "true" : "false");
509 break;
510 case AGC_PARAM_PROPERTIES:
511 pProperties->targetLevel = (int16_t)(agc->target_level_dbfs() * -100);
512 pProperties->compGain = (int16_t)(agc->compression_gain_db() * 100);
513 pProperties->limiterEnabled = (bool)agc->is_limiter_enabled();
514 break;
515 default:
Steve Block5ff1dd52012-01-05 23:22:43 +0000516 ALOGW("AgcGetParameter() unknown param %d", param);
Eric Laurenta9390d42011-06-17 20:17:17 -0700517 status = -EINVAL;
518 break;
519 }
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530520#else
521 effect->session->config = effect->session->apm->GetConfig();
522 switch (param) {
523 case AGC_PARAM_TARGET_LEVEL:
524 *(int16_t *) pValue =
525 (int16_t)(effect->session->config.gain_controller1.target_level_dbfs * -100);
526 ALOGV("AgcGetParameter() target level %d milliBels", *(int16_t *) pValue);
527 break;
528 case AGC_PARAM_COMP_GAIN:
529 *(int16_t *) pValue =
530 (int16_t)(effect->session->config.gain_controller1.compression_gain_db * -100);
531 ALOGV("AgcGetParameter() comp gain %d milliBels", *(int16_t *) pValue);
532 break;
533 case AGC_PARAM_LIMITER_ENA:
534 *(bool *) pValue =
535 (bool)(effect->session->config.gain_controller1.enable_limiter);
536 ALOGV("AgcGetParameter() limiter enabled %s",
537 (*(int16_t *) pValue != 0) ? "true" : "false");
538 break;
539 case AGC_PARAM_PROPERTIES:
540 pProperties->targetLevel =
541 (int16_t)(effect->session->config.gain_controller1.target_level_dbfs * -100);
542 pProperties->compGain =
543 (int16_t)(effect->session->config.gain_controller1.compression_gain_db * -100);
544 pProperties->limiterEnabled =
545 (bool)(effect->session->config.gain_controller1.enable_limiter);
546 break;
547 default:
548 ALOGW("AgcGetParameter() unknown param %d", param);
549 status = -EINVAL;
550 break;
551 }
552#endif
Eric Laurenta9390d42011-06-17 20:17:17 -0700553 return status;
554}
555
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530556#ifndef WEBRTC_LEGACY
557int Agc2SetParameter (preproc_effect_t *effect, void *pParam, void *pValue)
558{
559 int status = 0;
560 uint32_t param = *(uint32_t *)pParam;
561 float valueFloat = 0.f;
562 agc2_settings_t *pProperties = (agc2_settings_t *)pValue;
563 effect->session->config = effect->session->apm->GetConfig();
564 switch (param) {
565 case AGC2_PARAM_FIXED_DIGITAL_GAIN:
566 valueFloat = (float)(*(int32_t *) pValue);
567 ALOGV("Agc2SetParameter() fixed digital gain %f dB", valueFloat);
568 effect->session->config.gain_controller2.fixed_digital.gain_db = valueFloat;
569 break;
570 case AGC2_PARAM_ADAPT_DIGI_LEVEL_ESTIMATOR:
571 ALOGV("Agc2SetParameter() level estimator %d", *(webrtc::AudioProcessing::Config::
572 GainController2::LevelEstimator *) pValue);
573 effect->session->config.gain_controller2.adaptive_digital.level_estimator =
574 (*(webrtc::AudioProcessing::Config::GainController2::LevelEstimator *) pValue);
575 break;
576 case AGC2_PARAM_ADAPT_DIGI_EXTRA_SATURATION_MARGIN:
577 valueFloat = (float)(*(int32_t *) pValue);
578 ALOGV("Agc2SetParameter() extra saturation margin %f dB", valueFloat);
579 effect->session->config.gain_controller2.adaptive_digital.extra_saturation_margin_db =
580 valueFloat;
581 break;
582 case AGC2_PARAM_PROPERTIES:
583 ALOGV("Agc2SetParameter() properties gain %f, level %d margin %f",
584 pProperties->fixedDigitalGain,
585 pProperties->level_estimator,
586 pProperties->extraSaturationMargin);
587 effect->session->config.gain_controller2.fixed_digital.gain_db =
588 pProperties->fixedDigitalGain;
589 effect->session->config.gain_controller2.adaptive_digital.level_estimator =
590 (webrtc::AudioProcessing::Config::GainController2::LevelEstimator)pProperties->
591 level_estimator;
592 effect->session->config.gain_controller2.adaptive_digital.extra_saturation_margin_db =
593 pProperties->extraSaturationMargin;
594 break;
595 default:
596 ALOGW("Agc2SetParameter() unknown param %08x value %08x", param, *(uint32_t *)pValue);
597 status = -EINVAL;
598 break;
599 }
600 effect->session->apm->ApplyConfig(effect->session->config);
601
602 ALOGV("Agc2SetParameter() done status %d", status);
603
604 return status;
605}
606#endif
607
Eric Laurenta9390d42011-06-17 20:17:17 -0700608int AgcSetParameter (preproc_effect_t *effect, void *pParam, void *pValue)
609{
610 int status = 0;
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530611#ifdef WEBRTC_LEGACY
Eric Laurenta9390d42011-06-17 20:17:17 -0700612 uint32_t param = *(uint32_t *)pParam;
613 t_agc_settings *pProperties = (t_agc_settings *)pValue;
614 webrtc::GainControl *agc = static_cast<webrtc::GainControl *>(effect->engine);
615
616 switch (param) {
617 case AGC_PARAM_TARGET_LEVEL:
Steve Block3856b092011-10-20 11:56:00 +0100618 ALOGV("AgcSetParameter() target level %d milliBels", *(int16_t *)pValue);
Eric Laurenta9390d42011-06-17 20:17:17 -0700619 status = agc->set_target_level_dbfs(-(*(int16_t *)pValue / 100));
620 break;
621 case AGC_PARAM_COMP_GAIN:
Steve Block3856b092011-10-20 11:56:00 +0100622 ALOGV("AgcSetParameter() comp gain %d milliBels", *(int16_t *)pValue);
Eric Laurenta9390d42011-06-17 20:17:17 -0700623 status = agc->set_compression_gain_db(*(int16_t *)pValue / 100);
624 break;
625 case AGC_PARAM_LIMITER_ENA:
Steve Block3856b092011-10-20 11:56:00 +0100626 ALOGV("AgcSetParameter() limiter enabled %s", *(bool *)pValue ? "true" : "false");
Eric Laurenta9390d42011-06-17 20:17:17 -0700627 status = agc->enable_limiter(*(bool *)pValue);
628 break;
629 case AGC_PARAM_PROPERTIES:
Steve Block3856b092011-10-20 11:56:00 +0100630 ALOGV("AgcSetParameter() properties level %d, gain %d limiter %d",
Eric Laurenta9390d42011-06-17 20:17:17 -0700631 pProperties->targetLevel,
632 pProperties->compGain,
633 pProperties->limiterEnabled);
634 status = agc->set_target_level_dbfs(-(pProperties->targetLevel / 100));
635 if (status != 0) break;
636 status = agc->set_compression_gain_db(pProperties->compGain / 100);
637 if (status != 0) break;
638 status = agc->enable_limiter(pProperties->limiterEnabled);
639 break;
640 default:
Steve Block5ff1dd52012-01-05 23:22:43 +0000641 ALOGW("AgcSetParameter() unknown param %08x value %08x", param, *(uint32_t *)pValue);
Eric Laurenta9390d42011-06-17 20:17:17 -0700642 status = -EINVAL;
643 break;
644 }
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530645#else
646 uint32_t param = *(uint32_t *)pParam;
647 t_agc_settings *pProperties = (t_agc_settings *)pValue;
648 effect->session->config = effect->session->apm->GetConfig();
649 switch (param) {
650 case AGC_PARAM_TARGET_LEVEL:
651 ALOGV("AgcSetParameter() target level %d milliBels", *(int16_t *)pValue);
652 effect->session->config.gain_controller1.target_level_dbfs =
653 (-(*(int16_t *)pValue / 100));
654 break;
655 case AGC_PARAM_COMP_GAIN:
656 ALOGV("AgcSetParameter() comp gain %d milliBels", *(int16_t *)pValue);
657 effect->session->config.gain_controller1.compression_gain_db =
658 (*(int16_t *)pValue / 100);
659 break;
660 case AGC_PARAM_LIMITER_ENA:
661 ALOGV("AgcSetParameter() limiter enabled %s", *(bool *)pValue ? "true" : "false");
662 effect->session->config.gain_controller1.enable_limiter =
663 (*(bool *)pValue);
664 break;
665 case AGC_PARAM_PROPERTIES:
666 ALOGV("AgcSetParameter() properties level %d, gain %d limiter %d",
667 pProperties->targetLevel,
668 pProperties->compGain,
669 pProperties->limiterEnabled);
670 effect->session->config.gain_controller1.target_level_dbfs =
671 -(pProperties->targetLevel / 100);
672 effect->session->config.gain_controller1.compression_gain_db =
673 pProperties->compGain / 100;
674 effect->session->config.gain_controller1.enable_limiter =
675 pProperties->limiterEnabled;
676 break;
677 default:
678 ALOGW("AgcSetParameter() unknown param %08x value %08x", param, *(uint32_t *)pValue);
679 status = -EINVAL;
680 break;
681 }
682 effect->session->apm->ApplyConfig(effect->session->config);
683#endif
Eric Laurenta9390d42011-06-17 20:17:17 -0700684
Steve Block3856b092011-10-20 11:56:00 +0100685 ALOGV("AgcSetParameter() done status %d", status);
Eric Laurenta9390d42011-06-17 20:17:17 -0700686
687 return status;
688}
689
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530690#ifndef WEBRTC_LEGACY
691void Agc2Enable(preproc_effect_t *effect)
692{
693 effect->session->config = effect->session->apm->GetConfig();
694 effect->session->config.gain_controller2.enabled = true;
695 effect->session->apm->ApplyConfig(effect->session->config);
696}
697#endif
698
Eric Laurenta9390d42011-06-17 20:17:17 -0700699void AgcEnable(preproc_effect_t *effect)
700{
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530701#ifdef WEBRTC_LEGACY
Eric Laurenta9390d42011-06-17 20:17:17 -0700702 webrtc::GainControl *agc = static_cast<webrtc::GainControl *>(effect->engine);
Steve Block3856b092011-10-20 11:56:00 +0100703 ALOGV("AgcEnable agc %p", agc);
Eric Laurenta9390d42011-06-17 20:17:17 -0700704 agc->Enable(true);
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530705#else
706 effect->session->config = effect->session->apm->GetConfig();
707 effect->session->config.gain_controller1.enabled = true;
708 effect->session->apm->ApplyConfig(effect->session->config);
709#endif
Eric Laurenta9390d42011-06-17 20:17:17 -0700710}
711
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530712#ifndef WEBRTC_LEGACY
713void Agc2Disable(preproc_effect_t *effect)
714{
715 effect->session->config = effect->session->apm->GetConfig();
716 effect->session->config.gain_controller2.enabled = false;
717 effect->session->apm->ApplyConfig(effect->session->config);
718}
719#endif
720
Eric Laurenta9390d42011-06-17 20:17:17 -0700721void AgcDisable(preproc_effect_t *effect)
722{
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530723#ifdef WEBRTC_LEGACY
Steve Block3856b092011-10-20 11:56:00 +0100724 ALOGV("AgcDisable");
Eric Laurenta9390d42011-06-17 20:17:17 -0700725 webrtc::GainControl *agc = static_cast<webrtc::GainControl *>(effect->engine);
726 agc->Enable(false);
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530727#else
728 effect->session->config = effect->session->apm->GetConfig();
729 effect->session->config.gain_controller1.enabled = false;
730 effect->session->apm->ApplyConfig(effect->session->config);
731#endif
Eric Laurenta9390d42011-06-17 20:17:17 -0700732}
733
Eric Laurenta9390d42011-06-17 20:17:17 -0700734static const preproc_ops_t sAgcOps = {
735 AgcCreate,
736 AgcInit,
737 NULL,
738 AgcEnable,
739 AgcDisable,
740 AgcSetParameter,
741 AgcGetParameter,
742 NULL
743};
744
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530745#ifndef WEBRTC_LEGACY
746static const preproc_ops_t sAgc2Ops = {
747 Agc2Create,
748 Agc2Init,
749 NULL,
750 Agc2Enable,
751 Agc2Disable,
752 Agc2SetParameter,
753 Agc2GetParameter,
754 NULL
755};
756#endif
Eric Laurenta9390d42011-06-17 20:17:17 -0700757
758//------------------------------------------------------------------------------
759// Acoustic Echo Canceler (AEC)
760//------------------------------------------------------------------------------
761
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530762#ifdef WEBRTC_LEGACY
Eric Laurenta9390d42011-06-17 20:17:17 -0700763static const webrtc::EchoControlMobile::RoutingMode kAecDefaultMode =
764 webrtc::EchoControlMobile::kEarpiece;
765static const bool kAecDefaultComfortNoise = true;
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530766#endif
Eric Laurenta9390d42011-06-17 20:17:17 -0700767
768int AecInit (preproc_effect_t *effect)
769{
Steve Block3856b092011-10-20 11:56:00 +0100770 ALOGV("AecInit");
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530771#ifdef WEBRTC_LEGACY
Eric Laurenta9390d42011-06-17 20:17:17 -0700772 webrtc::EchoControlMobile *aec = static_cast<webrtc::EchoControlMobile *>(effect->engine);
773 aec->set_routing_mode(kAecDefaultMode);
774 aec->enable_comfort_noise(kAecDefaultComfortNoise);
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530775#else
776 effect->session->config =
777 effect->session->apm->GetConfig() ;
778 effect->session->config.echo_canceller.mobile_mode = false;
779 effect->session->apm->ApplyConfig(effect->session->config);
780#endif
Eric Laurenta9390d42011-06-17 20:17:17 -0700781 return 0;
782}
783
784int AecCreate(preproc_effect_t *effect)
785{
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530786#ifdef WEBRTC_LEGACY
Eric Laurenta9390d42011-06-17 20:17:17 -0700787 webrtc::EchoControlMobile *aec = effect->session->apm->echo_control_mobile();
Steve Block3856b092011-10-20 11:56:00 +0100788 ALOGV("AecCreate got aec %p", aec);
Eric Laurenta9390d42011-06-17 20:17:17 -0700789 if (aec == NULL) {
Steve Block5ff1dd52012-01-05 23:22:43 +0000790 ALOGW("AgcCreate Error");
Eric Laurenta9390d42011-06-17 20:17:17 -0700791 return -ENOMEM;
792 }
793 effect->engine = static_cast<preproc_fx_handle_t>(aec);
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530794#endif
Eric Laurenta9390d42011-06-17 20:17:17 -0700795 AecInit (effect);
796 return 0;
797}
798
Ashok Bhatb302bd52014-02-18 11:40:00 +0000799int AecGetParameter(preproc_effect_t *effect,
Eric Laurenta9390d42011-06-17 20:17:17 -0700800 void *pParam,
Ashok Bhatb302bd52014-02-18 11:40:00 +0000801 uint32_t *pValueSize,
Eric Laurenta9390d42011-06-17 20:17:17 -0700802 void *pValue)
803{
804 int status = 0;
805 uint32_t param = *(uint32_t *)pParam;
806
807 if (*pValueSize < sizeof(uint32_t)) {
808 return -EINVAL;
809 }
810 switch (param) {
811 case AEC_PARAM_ECHO_DELAY:
812 case AEC_PARAM_PROPERTIES:
813 *(uint32_t *)pValue = 1000 * effect->session->apm->stream_delay_ms();
Steve Block3856b092011-10-20 11:56:00 +0100814 ALOGV("AecGetParameter() echo delay %d us", *(uint32_t *)pValue);
Eric Laurenta9390d42011-06-17 20:17:17 -0700815 break;
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530816#ifndef WEBRTC_LEGACY
817 case AEC_PARAM_MOBILE_MODE:
818 effect->session->config =
819 effect->session->apm->GetConfig() ;
820 *(uint32_t *)pValue = effect->session->config.echo_canceller.mobile_mode;
821 ALOGV("AecGetParameter() mobile mode %d us", *(uint32_t *)pValue);
822 break;
823#endif
Eric Laurenta9390d42011-06-17 20:17:17 -0700824 default:
Steve Block5ff1dd52012-01-05 23:22:43 +0000825 ALOGW("AecGetParameter() unknown param %08x value %08x", param, *(uint32_t *)pValue);
Eric Laurenta9390d42011-06-17 20:17:17 -0700826 status = -EINVAL;
827 break;
828 }
829 return status;
830}
831
832int AecSetParameter (preproc_effect_t *effect, void *pParam, void *pValue)
833{
834 int status = 0;
835 uint32_t param = *(uint32_t *)pParam;
836 uint32_t value = *(uint32_t *)pValue;
837
838 switch (param) {
839 case AEC_PARAM_ECHO_DELAY:
840 case AEC_PARAM_PROPERTIES:
841 status = effect->session->apm->set_stream_delay_ms(value/1000);
Steve Block3856b092011-10-20 11:56:00 +0100842 ALOGV("AecSetParameter() echo delay %d us, status %d", value, status);
Eric Laurenta9390d42011-06-17 20:17:17 -0700843 break;
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530844#ifndef WEBRTC_LEGACY
845 case AEC_PARAM_MOBILE_MODE:
846 effect->session->config =
847 effect->session->apm->GetConfig() ;
848 effect->session->config.echo_canceller.mobile_mode = value;
849 ALOGV("AecSetParameter() mobile mode %d us", value);
850 effect->session->apm->ApplyConfig(effect->session->config);
851 break;
852#endif
Eric Laurenta9390d42011-06-17 20:17:17 -0700853 default:
Steve Block5ff1dd52012-01-05 23:22:43 +0000854 ALOGW("AecSetParameter() unknown param %08x value %08x", param, *(uint32_t *)pValue);
Eric Laurenta9390d42011-06-17 20:17:17 -0700855 status = -EINVAL;
856 break;
857 }
858 return status;
859}
860
861void AecEnable(preproc_effect_t *effect)
862{
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530863#ifdef WEBRTC_LEGACY
Eric Laurenta9390d42011-06-17 20:17:17 -0700864 webrtc::EchoControlMobile *aec = static_cast<webrtc::EchoControlMobile *>(effect->engine);
Steve Block3856b092011-10-20 11:56:00 +0100865 ALOGV("AecEnable aec %p", aec);
Eric Laurenta9390d42011-06-17 20:17:17 -0700866 aec->Enable(true);
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530867#else
868 effect->session->config = effect->session->apm->GetConfig();
869 effect->session->config.echo_canceller.enabled = true;
870 effect->session->apm->ApplyConfig(effect->session->config);
871#endif
Eric Laurenta9390d42011-06-17 20:17:17 -0700872}
873
874void AecDisable(preproc_effect_t *effect)
875{
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530876#ifdef WEBRTC_LEGACY
Steve Block3856b092011-10-20 11:56:00 +0100877 ALOGV("AecDisable");
Eric Laurenta9390d42011-06-17 20:17:17 -0700878 webrtc::EchoControlMobile *aec = static_cast<webrtc::EchoControlMobile *>(effect->engine);
879 aec->Enable(false);
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530880#else
881 effect->session->config = effect->session->apm->GetConfig();
882 effect->session->config.echo_canceller.enabled = false;
883 effect->session->apm->ApplyConfig(effect->session->config);
884#endif
Eric Laurenta9390d42011-06-17 20:17:17 -0700885}
886
887int AecSetDevice(preproc_effect_t *effect, uint32_t device)
888{
Steve Block3856b092011-10-20 11:56:00 +0100889 ALOGV("AecSetDevice %08x", device);
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530890#ifdef WEBRTC_LEGACY
Eric Laurenta9390d42011-06-17 20:17:17 -0700891 webrtc::EchoControlMobile *aec = static_cast<webrtc::EchoControlMobile *>(effect->engine);
892 webrtc::EchoControlMobile::RoutingMode mode = webrtc::EchoControlMobile::kQuietEarpieceOrHeadset;
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530893#endif
Eric Laurenta9390d42011-06-17 20:17:17 -0700894
Eric Laurent88959252012-08-28 14:26:53 -0700895 if (audio_is_input_device(device)) {
896 return 0;
897 }
898
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530899#ifdef WEBRTC_LEGACY
Eric Laurenta9390d42011-06-17 20:17:17 -0700900 switch(device) {
901 case AUDIO_DEVICE_OUT_EARPIECE:
902 mode = webrtc::EchoControlMobile::kEarpiece;
903 break;
904 case AUDIO_DEVICE_OUT_SPEAKER:
905 mode = webrtc::EchoControlMobile::kSpeakerphone;
906 break;
907 case AUDIO_DEVICE_OUT_WIRED_HEADSET:
908 case AUDIO_DEVICE_OUT_WIRED_HEADPHONE:
Eric Laurent904d6322017-03-17 17:20:47 -0700909 case AUDIO_DEVICE_OUT_USB_HEADSET:
Eric Laurenta9390d42011-06-17 20:17:17 -0700910 default:
911 break;
912 }
913 aec->set_routing_mode(mode);
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530914#endif
Eric Laurenta9390d42011-06-17 20:17:17 -0700915 return 0;
916}
917
918static const preproc_ops_t sAecOps = {
919 AecCreate,
920 AecInit,
921 NULL,
922 AecEnable,
923 AecDisable,
924 AecSetParameter,
925 AecGetParameter,
926 AecSetDevice
927};
928
929//------------------------------------------------------------------------------
930// Noise Suppression (NS)
931//------------------------------------------------------------------------------
932
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530933#ifdef WEBRTC_LEGACY
Eric Laurenta9390d42011-06-17 20:17:17 -0700934static const webrtc::NoiseSuppression::Level kNsDefaultLevel = webrtc::NoiseSuppression::kModerate;
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530935#else
936static const webrtc::AudioProcessing::Config::NoiseSuppression::Level kNsDefaultLevel =
937 webrtc::AudioProcessing::Config::NoiseSuppression::kModerate;
938#endif
Eric Laurenta9390d42011-06-17 20:17:17 -0700939
940int NsInit (preproc_effect_t *effect)
941{
Steve Block3856b092011-10-20 11:56:00 +0100942 ALOGV("NsInit");
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530943#ifdef WEBRTC_LEGACY
Eric Laurenta9390d42011-06-17 20:17:17 -0700944 webrtc::NoiseSuppression *ns = static_cast<webrtc::NoiseSuppression *>(effect->engine);
945 ns->set_level(kNsDefaultLevel);
Alex Luebs766bf732015-12-14 21:32:13 -0800946 webrtc::Config config;
947 std::vector<webrtc::Point> geometry;
948 // TODO(aluebs): Make the geometry settable.
949 geometry.push_back(webrtc::Point(-0.03f, 0.f, 0.f));
950 geometry.push_back(webrtc::Point(-0.01f, 0.f, 0.f));
951 geometry.push_back(webrtc::Point(0.01f, 0.f, 0.f));
952 geometry.push_back(webrtc::Point(0.03f, 0.f, 0.f));
953 // The geometry needs to be set with Beamforming enabled.
954 config.Set<webrtc::Beamforming>(
955 new webrtc::Beamforming(true, geometry));
956 effect->session->apm->SetExtraOptions(config);
957 config.Set<webrtc::Beamforming>(
958 new webrtc::Beamforming(false, geometry));
959 effect->session->apm->SetExtraOptions(config);
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530960#else
961 effect->session->config =
962 effect->session->apm->GetConfig() ;
963 effect->session->config.noise_suppression.level =
964 kNsDefaultLevel;
965 effect->session->apm->ApplyConfig(effect->session->config);
966#endif
Alex Luebs766bf732015-12-14 21:32:13 -0800967 effect->type = NS_TYPE_SINGLE_CHANNEL;
Eric Laurenta9390d42011-06-17 20:17:17 -0700968 return 0;
969}
970
971int NsCreate(preproc_effect_t *effect)
972{
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530973#ifdef WEBRTC_LEGACY
Eric Laurenta9390d42011-06-17 20:17:17 -0700974 webrtc::NoiseSuppression *ns = effect->session->apm->noise_suppression();
Steve Block3856b092011-10-20 11:56:00 +0100975 ALOGV("NsCreate got ns %p", ns);
Eric Laurenta9390d42011-06-17 20:17:17 -0700976 if (ns == NULL) {
Steve Block5ff1dd52012-01-05 23:22:43 +0000977 ALOGW("AgcCreate Error");
Eric Laurenta9390d42011-06-17 20:17:17 -0700978 return -ENOMEM;
979 }
980 effect->engine = static_cast<preproc_fx_handle_t>(ns);
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530981#endif
Eric Laurenta9390d42011-06-17 20:17:17 -0700982 NsInit (effect);
983 return 0;
984}
985
Eric Laurent0f714a42015-06-19 15:33:57 -0700986int NsGetParameter(preproc_effect_t *effect __unused,
987 void *pParam __unused,
988 uint32_t *pValueSize __unused,
989 void *pValue __unused)
Eric Laurenta9390d42011-06-17 20:17:17 -0700990{
991 int status = 0;
992 return status;
993}
994
Alex Luebs766bf732015-12-14 21:32:13 -0800995int NsSetParameter (preproc_effect_t *effect, void *pParam, void *pValue)
Eric Laurenta9390d42011-06-17 20:17:17 -0700996{
997 int status = 0;
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530998#ifdef WEBRTC_LEGACY
Alex Luebs766bf732015-12-14 21:32:13 -0800999 webrtc::NoiseSuppression *ns = static_cast<webrtc::NoiseSuppression *>(effect->engine);
1000 uint32_t param = *(uint32_t *)pParam;
1001 uint32_t value = *(uint32_t *)pValue;
1002 switch(param) {
1003 case NS_PARAM_LEVEL:
1004 ns->set_level((webrtc::NoiseSuppression::Level)value);
1005 ALOGV("NsSetParameter() level %d", value);
1006 break;
1007 case NS_PARAM_TYPE:
1008 {
1009 webrtc::Config config;
1010 std::vector<webrtc::Point> geometry;
1011 bool is_beamforming_enabled =
1012 value == NS_TYPE_MULTI_CHANNEL && ns->is_enabled();
1013 config.Set<webrtc::Beamforming>(
1014 new webrtc::Beamforming(is_beamforming_enabled, geometry));
1015 effect->session->apm->SetExtraOptions(config);
1016 effect->type = value;
1017 ALOGV("NsSetParameter() type %d", value);
1018 break;
1019 }
1020 default:
1021 ALOGW("NsSetParameter() unknown param %08x value %08x", param, value);
1022 status = -EINVAL;
1023 }
Saketh Sathuvalli08337032020-09-22 21:13:45 +05301024#else
1025 uint32_t param = *(uint32_t *)pParam;
1026 uint32_t value = *(uint32_t *)pValue;
1027 effect->session->config =
1028 effect->session->apm->GetConfig();
1029 switch (param) {
1030 case NS_PARAM_LEVEL:
1031 effect->session->config.noise_suppression.level =
1032 (webrtc::AudioProcessing::Config::NoiseSuppression::Level)value;
1033 ALOGV("NsSetParameter() level %d", value);
1034 break;
1035 default:
1036 ALOGW("NsSetParameter() unknown param %08x value %08x", param, value);
1037 status = -EINVAL;
1038 }
1039 effect->session->apm->ApplyConfig(effect->session->config);
1040#endif
Alex Luebs766bf732015-12-14 21:32:13 -08001041
Eric Laurenta9390d42011-06-17 20:17:17 -07001042 return status;
1043}
1044
1045void NsEnable(preproc_effect_t *effect)
1046{
Saketh Sathuvalli08337032020-09-22 21:13:45 +05301047#ifdef WEBRTC_LEGACY
Eric Laurenta9390d42011-06-17 20:17:17 -07001048 webrtc::NoiseSuppression *ns = static_cast<webrtc::NoiseSuppression *>(effect->engine);
Steve Block3856b092011-10-20 11:56:00 +01001049 ALOGV("NsEnable ns %p", ns);
Eric Laurenta9390d42011-06-17 20:17:17 -07001050 ns->Enable(true);
Alex Luebs766bf732015-12-14 21:32:13 -08001051 if (effect->type == NS_TYPE_MULTI_CHANNEL) {
1052 webrtc::Config config;
1053 std::vector<webrtc::Point> geometry;
1054 config.Set<webrtc::Beamforming>(new webrtc::Beamforming(true, geometry));
1055 effect->session->apm->SetExtraOptions(config);
1056 }
Saketh Sathuvalli08337032020-09-22 21:13:45 +05301057#else
1058 effect->session->config =
1059 effect->session->apm->GetConfig();
1060 effect->session->config.noise_suppression.enabled = true;
1061 effect->session->apm->ApplyConfig(effect->session->config);
1062#endif
Eric Laurenta9390d42011-06-17 20:17:17 -07001063}
1064
1065void NsDisable(preproc_effect_t *effect)
1066{
Steve Block3856b092011-10-20 11:56:00 +01001067 ALOGV("NsDisable");
Saketh Sathuvalli08337032020-09-22 21:13:45 +05301068#ifdef WEBRTC_LEGACY
Eric Laurenta9390d42011-06-17 20:17:17 -07001069 webrtc::NoiseSuppression *ns = static_cast<webrtc::NoiseSuppression *>(effect->engine);
1070 ns->Enable(false);
Alex Luebs766bf732015-12-14 21:32:13 -08001071 webrtc::Config config;
1072 std::vector<webrtc::Point> geometry;
1073 config.Set<webrtc::Beamforming>(new webrtc::Beamforming(false, geometry));
1074 effect->session->apm->SetExtraOptions(config);
Saketh Sathuvalli08337032020-09-22 21:13:45 +05301075#else
1076 effect->session->config =
1077 effect->session->apm->GetConfig();
1078 effect->session->config.noise_suppression.enabled = false;
1079 effect->session->apm->ApplyConfig(effect->session->config);
1080#endif
Eric Laurenta9390d42011-06-17 20:17:17 -07001081}
1082
1083static const preproc_ops_t sNsOps = {
1084 NsCreate,
1085 NsInit,
1086 NULL,
1087 NsEnable,
1088 NsDisable,
1089 NsSetParameter,
1090 NsGetParameter,
1091 NULL
1092};
1093
1094
Saketh Sathuvalli08337032020-09-22 21:13:45 +05301095
Eric Laurenta9390d42011-06-17 20:17:17 -07001096static const preproc_ops_t *sPreProcOps[PREPROC_NUM_EFFECTS] = {
1097 &sAgcOps,
Saketh Sathuvalli08337032020-09-22 21:13:45 +05301098#ifndef WEBRTC_LEGACY
1099 &sAgc2Ops,
1100#endif
Eric Laurenta9390d42011-06-17 20:17:17 -07001101 &sAecOps,
1102 &sNsOps
1103};
1104
1105
1106//------------------------------------------------------------------------------
1107// Effect functions
1108//------------------------------------------------------------------------------
1109
1110void Session_SetProcEnabled(preproc_session_t *session, uint32_t procId, bool enabled);
1111
1112extern "C" const struct effect_interface_s sEffectInterface;
1113extern "C" const struct effect_interface_s sEffectInterfaceReverse;
1114
1115#define BAD_STATE_ABORT(from, to) \
1116 LOG_ALWAYS_FATAL("Bad state transition from %d to %d", from, to);
1117
1118int Effect_SetState(preproc_effect_t *effect, uint32_t state)
1119{
1120 int status = 0;
Steve Block3856b092011-10-20 11:56:00 +01001121 ALOGV("Effect_SetState proc %d, new %d old %d", effect->procId, state, effect->state);
Eric Laurenta9390d42011-06-17 20:17:17 -07001122 switch(state) {
1123 case PREPROC_EFFECT_STATE_INIT:
1124 switch(effect->state) {
1125 case PREPROC_EFFECT_STATE_ACTIVE:
1126 effect->ops->disable(effect);
1127 Session_SetProcEnabled(effect->session, effect->procId, false);
Andy Hung320fd852018-10-09 14:06:37 -07001128 break;
Eric Laurenta9390d42011-06-17 20:17:17 -07001129 case PREPROC_EFFECT_STATE_CONFIG:
1130 case PREPROC_EFFECT_STATE_CREATED:
1131 case PREPROC_EFFECT_STATE_INIT:
1132 break;
1133 default:
1134 BAD_STATE_ABORT(effect->state, state);
1135 }
1136 break;
1137 case PREPROC_EFFECT_STATE_CREATED:
1138 switch(effect->state) {
1139 case PREPROC_EFFECT_STATE_INIT:
1140 status = effect->ops->create(effect);
1141 break;
1142 case PREPROC_EFFECT_STATE_CREATED:
1143 case PREPROC_EFFECT_STATE_ACTIVE:
1144 case PREPROC_EFFECT_STATE_CONFIG:
Steve Block29357bc2012-01-06 19:20:56 +00001145 ALOGE("Effect_SetState invalid transition");
Eric Laurenta9390d42011-06-17 20:17:17 -07001146 status = -ENOSYS;
1147 break;
1148 default:
1149 BAD_STATE_ABORT(effect->state, state);
1150 }
1151 break;
1152 case PREPROC_EFFECT_STATE_CONFIG:
1153 switch(effect->state) {
1154 case PREPROC_EFFECT_STATE_INIT:
Steve Block29357bc2012-01-06 19:20:56 +00001155 ALOGE("Effect_SetState invalid transition");
Eric Laurenta9390d42011-06-17 20:17:17 -07001156 status = -ENOSYS;
1157 break;
1158 case PREPROC_EFFECT_STATE_ACTIVE:
1159 effect->ops->disable(effect);
1160 Session_SetProcEnabled(effect->session, effect->procId, false);
1161 break;
1162 case PREPROC_EFFECT_STATE_CREATED:
1163 case PREPROC_EFFECT_STATE_CONFIG:
1164 break;
1165 default:
1166 BAD_STATE_ABORT(effect->state, state);
1167 }
1168 break;
1169 case PREPROC_EFFECT_STATE_ACTIVE:
1170 switch(effect->state) {
1171 case PREPROC_EFFECT_STATE_INIT:
1172 case PREPROC_EFFECT_STATE_CREATED:
Steve Block29357bc2012-01-06 19:20:56 +00001173 ALOGE("Effect_SetState invalid transition");
Eric Laurenta9390d42011-06-17 20:17:17 -07001174 status = -ENOSYS;
1175 break;
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001176 case PREPROC_EFFECT_STATE_ACTIVE:
1177 // enabling an already enabled effect is just ignored
1178 break;
Eric Laurenta9390d42011-06-17 20:17:17 -07001179 case PREPROC_EFFECT_STATE_CONFIG:
1180 effect->ops->enable(effect);
1181 Session_SetProcEnabled(effect->session, effect->procId, true);
1182 break;
1183 default:
1184 BAD_STATE_ABORT(effect->state, state);
1185 }
1186 break;
1187 default:
1188 BAD_STATE_ABORT(effect->state, state);
1189 }
1190 if (status == 0) {
1191 effect->state = state;
1192 }
1193 return status;
1194}
1195
1196int Effect_Init(preproc_effect_t *effect, uint32_t procId)
1197{
1198 if (HasReverseStream(procId)) {
1199 effect->itfe = &sEffectInterfaceReverse;
1200 } else {
1201 effect->itfe = &sEffectInterface;
1202 }
1203 effect->ops = sPreProcOps[procId];
1204 effect->procId = procId;
1205 effect->state = PREPROC_EFFECT_STATE_INIT;
1206 return 0;
1207}
1208
1209int Effect_Create(preproc_effect_t *effect,
1210 preproc_session_t *session,
1211 effect_handle_t *interface)
1212{
1213 effect->session = session;
1214 *interface = (effect_handle_t)&effect->itfe;
1215 return Effect_SetState(effect, PREPROC_EFFECT_STATE_CREATED);
1216}
1217
1218int Effect_Release(preproc_effect_t *effect)
1219{
1220 return Effect_SetState(effect, PREPROC_EFFECT_STATE_INIT);
1221}
1222
1223
1224//------------------------------------------------------------------------------
1225// Session functions
1226//------------------------------------------------------------------------------
1227
1228#define RESAMPLER_QUALITY SPEEX_RESAMPLER_QUALITY_VOIP
1229
1230static const int kPreprocDefaultSr = 16000;
1231static const int kPreProcDefaultCnl = 1;
1232
1233int Session_Init(preproc_session_t *session)
1234{
1235 size_t i;
1236 int status = 0;
1237
1238 session->state = PREPROC_SESSION_STATE_INIT;
1239 session->id = 0;
1240 session->io = 0;
1241 session->createdMsk = 0;
Saketh Sathuvalli08337032020-09-22 21:13:45 +05301242#ifdef WEBRTC_LEGACY
Eric Laurenta9390d42011-06-17 20:17:17 -07001243 session->apm = NULL;
Saketh Sathuvalli08337032020-09-22 21:13:45 +05301244#endif
Eric Laurenta9390d42011-06-17 20:17:17 -07001245 for (i = 0; i < PREPROC_NUM_EFFECTS && status == 0; i++) {
1246 status = Effect_Init(&session->effects[i], i);
1247 }
1248 return status;
1249}
1250
1251
1252extern "C" int Session_CreateEffect(preproc_session_t *session,
1253 int32_t procId,
1254 effect_handle_t *interface)
1255{
1256 int status = -ENOMEM;
1257
Steve Block3856b092011-10-20 11:56:00 +01001258 ALOGV("Session_CreateEffect procId %d, createdMsk %08x", procId, session->createdMsk);
Eric Laurenta9390d42011-06-17 20:17:17 -07001259
1260 if (session->createdMsk == 0) {
Saketh Sathuvalli08337032020-09-22 21:13:45 +05301261#ifdef WEBRTC_LEGACY
Alex Luebs9718b7d2015-11-24 14:33:14 -08001262 session->apm = webrtc::AudioProcessing::Create();
Eric Laurenta9390d42011-06-17 20:17:17 -07001263 if (session->apm == NULL) {
Steve Block5ff1dd52012-01-05 23:22:43 +00001264 ALOGW("Session_CreateEffect could not get apm engine");
Eric Laurenta9390d42011-06-17 20:17:17 -07001265 goto error;
1266 }
Alex Luebs9718b7d2015-11-24 14:33:14 -08001267 const webrtc::ProcessingConfig processing_config = {
1268 {{kPreprocDefaultSr, kPreProcDefaultCnl},
1269 {kPreprocDefaultSr, kPreProcDefaultCnl},
1270 {kPreprocDefaultSr, kPreProcDefaultCnl},
1271 {kPreprocDefaultSr, kPreProcDefaultCnl}}};
1272 session->apm->Initialize(processing_config);
Eric Laurenta9390d42011-06-17 20:17:17 -07001273 session->procFrame = new webrtc::AudioFrame();
1274 if (session->procFrame == NULL) {
Steve Block5ff1dd52012-01-05 23:22:43 +00001275 ALOGW("Session_CreateEffect could not allocate audio frame");
Eric Laurenta9390d42011-06-17 20:17:17 -07001276 goto error;
1277 }
1278 session->revFrame = new webrtc::AudioFrame();
1279 if (session->revFrame == NULL) {
Steve Block5ff1dd52012-01-05 23:22:43 +00001280 ALOGW("Session_CreateEffect could not allocate reverse audio frame");
Eric Laurenta9390d42011-06-17 20:17:17 -07001281 goto error;
1282 }
Saketh Sathuvalli08337032020-09-22 21:13:45 +05301283#else
1284 session->apm = session->ap_builder.Create();
1285 if (session->apm == NULL) {
1286 ALOGW("Session_CreateEffect could not get apm engine");
1287 goto error;
1288 }
1289#endif
Eric Laurenta9390d42011-06-17 20:17:17 -07001290 session->apmSamplingRate = kPreprocDefaultSr;
1291 session->apmFrameCount = (kPreprocDefaultSr) / 100;
1292 session->frameCount = session->apmFrameCount;
1293 session->samplingRate = kPreprocDefaultSr;
1294 session->inChannelCount = kPreProcDefaultCnl;
1295 session->outChannelCount = kPreProcDefaultCnl;
Saketh Sathuvalli08337032020-09-22 21:13:45 +05301296#ifdef WEBRTC_LEGACY
Chih-Hung Hsiehde7fa312015-10-13 10:58:08 -07001297 session->procFrame->sample_rate_hz_ = kPreprocDefaultSr;
1298 session->procFrame->num_channels_ = kPreProcDefaultCnl;
Saketh Sathuvalli08337032020-09-22 21:13:45 +05301299#else
1300 session->inputConfig.set_sample_rate_hz(kPreprocDefaultSr);
1301 session->inputConfig.set_num_channels(kPreProcDefaultCnl);
1302 session->outputConfig.set_sample_rate_hz(kPreprocDefaultSr);
1303 session->outputConfig.set_num_channels(kPreProcDefaultCnl);
1304#endif
Eric Laurenta9390d42011-06-17 20:17:17 -07001305 session->revChannelCount = kPreProcDefaultCnl;
Saketh Sathuvalli08337032020-09-22 21:13:45 +05301306#ifdef WEBRTC_LEGACY
Chih-Hung Hsiehde7fa312015-10-13 10:58:08 -07001307 session->revFrame->sample_rate_hz_ = kPreprocDefaultSr;
1308 session->revFrame->num_channels_ = kPreProcDefaultCnl;
Saketh Sathuvalli08337032020-09-22 21:13:45 +05301309#else
1310 session->revConfig.set_sample_rate_hz(kPreprocDefaultSr);
1311 session->revConfig.set_num_channels(kPreProcDefaultCnl);
1312#endif
Eric Laurenta9390d42011-06-17 20:17:17 -07001313 session->enabledMsk = 0;
1314 session->processedMsk = 0;
1315 session->revEnabledMsk = 0;
1316 session->revProcessedMsk = 0;
Saketh Sathuvalli08337032020-09-22 21:13:45 +05301317#ifdef WEBRTC_LEGACY
Eric Laurenta9390d42011-06-17 20:17:17 -07001318 session->inResampler = NULL;
Saketh Sathuvalli08337032020-09-22 21:13:45 +05301319#endif
Eric Laurenta9390d42011-06-17 20:17:17 -07001320 session->inBuf = NULL;
1321 session->inBufSize = 0;
Saketh Sathuvalli08337032020-09-22 21:13:45 +05301322#ifdef WEBRTC_LEGACY
Eric Laurenta9390d42011-06-17 20:17:17 -07001323 session->outResampler = NULL;
Saketh Sathuvalli08337032020-09-22 21:13:45 +05301324#endif
Eric Laurenta9390d42011-06-17 20:17:17 -07001325 session->outBuf = NULL;
1326 session->outBufSize = 0;
Saketh Sathuvalli08337032020-09-22 21:13:45 +05301327#ifdef WEBRTC_LEGACY
Eric Laurenta9390d42011-06-17 20:17:17 -07001328 session->revResampler = NULL;
Saketh Sathuvalli08337032020-09-22 21:13:45 +05301329#endif
Eric Laurenta9390d42011-06-17 20:17:17 -07001330 session->revBuf = NULL;
1331 session->revBufSize = 0;
1332 }
1333 status = Effect_Create(&session->effects[procId], session, interface);
1334 if (status < 0) {
1335 goto error;
1336 }
Steve Block3856b092011-10-20 11:56:00 +01001337 ALOGV("Session_CreateEffect OK");
Eric Laurenta9390d42011-06-17 20:17:17 -07001338 session->createdMsk |= (1<<procId);
1339 return status;
1340
1341error:
1342 if (session->createdMsk == 0) {
Saketh Sathuvalli08337032020-09-22 21:13:45 +05301343#ifdef WEBRTC_LEGACY
Eric Laurenta9390d42011-06-17 20:17:17 -07001344 delete session->revFrame;
1345 session->revFrame = NULL;
1346 delete session->procFrame;
1347 session->procFrame = NULL;
Alex Luebs9718b7d2015-11-24 14:33:14 -08001348 delete session->apm;
Chih-Hung Hsiehf29dc042018-07-31 15:22:49 -07001349 session->apm = NULL; // NOLINT(clang-analyzer-cplusplus.NewDelete)
Saketh Sathuvalli08337032020-09-22 21:13:45 +05301350#else
1351 delete session->apm;
1352 session->apm = NULL;
1353#endif
Eric Laurenta9390d42011-06-17 20:17:17 -07001354 }
1355 return status;
1356}
1357
1358int Session_ReleaseEffect(preproc_session_t *session,
1359 preproc_effect_t *fx)
1360{
Steve Block5ff1dd52012-01-05 23:22:43 +00001361 ALOGW_IF(Effect_Release(fx) != 0, " Effect_Release() failed for proc ID %d", fx->procId);
Eric Laurenta9390d42011-06-17 20:17:17 -07001362 session->createdMsk &= ~(1<<fx->procId);
1363 if (session->createdMsk == 0) {
Saketh Sathuvalli08337032020-09-22 21:13:45 +05301364#ifdef WEBRTC_LEGACY
Alex Luebs9718b7d2015-11-24 14:33:14 -08001365 delete session->apm;
Eric Laurenta9390d42011-06-17 20:17:17 -07001366 session->apm = NULL;
1367 delete session->procFrame;
1368 session->procFrame = NULL;
1369 delete session->revFrame;
1370 session->revFrame = NULL;
1371 if (session->inResampler != NULL) {
1372 speex_resampler_destroy(session->inResampler);
1373 session->inResampler = NULL;
1374 }
1375 if (session->outResampler != NULL) {
1376 speex_resampler_destroy(session->outResampler);
1377 session->outResampler = NULL;
1378 }
1379 if (session->revResampler != NULL) {
1380 speex_resampler_destroy(session->revResampler);
1381 session->revResampler = NULL;
1382 }
Saketh Sathuvalli08337032020-09-22 21:13:45 +05301383#else
1384 delete session->apm;
1385 session->apm = NULL;
1386#endif
Eric Laurenta9390d42011-06-17 20:17:17 -07001387 delete session->inBuf;
1388 session->inBuf = NULL;
1389 delete session->outBuf;
1390 session->outBuf = NULL;
1391 delete session->revBuf;
1392 session->revBuf = NULL;
1393
Eric Laurentb20cf7d2019-04-05 19:37:34 -07001394 session->id = 0;
Eric Laurenta9390d42011-06-17 20:17:17 -07001395 }
1396
1397 return 0;
1398}
1399
1400
1401int Session_SetConfig(preproc_session_t *session, effect_config_t *config)
1402{
Alex Luebs3f11ef02016-01-15 15:51:58 -08001403 uint32_t inCnl = audio_channel_count_from_in_mask(config->inputCfg.channels);
1404 uint32_t outCnl = audio_channel_count_from_in_mask(config->outputCfg.channels);
Eric Laurenta9390d42011-06-17 20:17:17 -07001405
1406 if (config->inputCfg.samplingRate != config->outputCfg.samplingRate ||
1407 config->inputCfg.format != config->outputCfg.format ||
1408 config->inputCfg.format != AUDIO_FORMAT_PCM_16_BIT) {
1409 return -EINVAL;
1410 }
1411
Steve Block3856b092011-10-20 11:56:00 +01001412 ALOGV("Session_SetConfig sr %d cnl %08x",
Eric Laurenta9390d42011-06-17 20:17:17 -07001413 config->inputCfg.samplingRate, config->inputCfg.channels);
Saketh Sathuvalli08337032020-09-22 21:13:45 +05301414#ifdef WEBRTC_LEGACY
Eric Laurenta9390d42011-06-17 20:17:17 -07001415 int status;
Saketh Sathuvalli08337032020-09-22 21:13:45 +05301416#endif
Eric Laurenta9390d42011-06-17 20:17:17 -07001417
1418 // AEC implementation is limited to 16kHz
1419 if (config->inputCfg.samplingRate >= 32000 && !(session->createdMsk & (1 << PREPROC_AEC))) {
1420 session->apmSamplingRate = 32000;
1421 } else
1422 if (config->inputCfg.samplingRate >= 16000) {
1423 session->apmSamplingRate = 16000;
1424 } else if (config->inputCfg.samplingRate >= 8000) {
1425 session->apmSamplingRate = 8000;
1426 }
Alex Luebs9718b7d2015-11-24 14:33:14 -08001427
Saketh Sathuvalli08337032020-09-22 21:13:45 +05301428#ifdef WEBRTC_LEGACY
Alex Luebs9718b7d2015-11-24 14:33:14 -08001429 const webrtc::ProcessingConfig processing_config = {
Alex Luebs3f11ef02016-01-15 15:51:58 -08001430 {{static_cast<int>(session->apmSamplingRate), inCnl},
1431 {static_cast<int>(session->apmSamplingRate), outCnl},
1432 {static_cast<int>(session->apmSamplingRate), inCnl},
1433 {static_cast<int>(session->apmSamplingRate), inCnl}}};
Alex Luebs9718b7d2015-11-24 14:33:14 -08001434 status = session->apm->Initialize(processing_config);
Eric Laurenta9390d42011-06-17 20:17:17 -07001435 if (status < 0) {
1436 return -EINVAL;
1437 }
Saketh Sathuvalli08337032020-09-22 21:13:45 +05301438#endif
Eric Laurenta9390d42011-06-17 20:17:17 -07001439
1440 session->samplingRate = config->inputCfg.samplingRate;
1441 session->apmFrameCount = session->apmSamplingRate / 100;
1442 if (session->samplingRate == session->apmSamplingRate) {
1443 session->frameCount = session->apmFrameCount;
1444 } else {
Saketh Sathuvalli08337032020-09-22 21:13:45 +05301445#ifdef WEBRTC_LEGACY
Eric Laurenta9390d42011-06-17 20:17:17 -07001446 session->frameCount = (session->apmFrameCount * session->samplingRate) /
1447 session->apmSamplingRate + 1;
Saketh Sathuvalli08337032020-09-22 21:13:45 +05301448#else
1449 session->frameCount = (session->apmFrameCount * session->samplingRate) /
1450 session->apmSamplingRate;
1451#endif
Eric Laurenta9390d42011-06-17 20:17:17 -07001452 }
1453 session->inChannelCount = inCnl;
1454 session->outChannelCount = outCnl;
Saketh Sathuvalli08337032020-09-22 21:13:45 +05301455#ifdef WEBRTC_LEGACY
Chih-Hung Hsiehde7fa312015-10-13 10:58:08 -07001456 session->procFrame->num_channels_ = inCnl;
1457 session->procFrame->sample_rate_hz_ = session->apmSamplingRate;
Saketh Sathuvalli08337032020-09-22 21:13:45 +05301458#else
1459 session->inputConfig.set_sample_rate_hz(session->samplingRate);
1460 session->inputConfig.set_num_channels(inCnl);
1461 session->outputConfig.set_sample_rate_hz(session->samplingRate);
1462 session->outputConfig.set_num_channels(inCnl);
1463#endif
Eric Laurenta9390d42011-06-17 20:17:17 -07001464
1465 session->revChannelCount = inCnl;
Saketh Sathuvalli08337032020-09-22 21:13:45 +05301466#ifdef WEBRTC_LEGACY
Chih-Hung Hsiehde7fa312015-10-13 10:58:08 -07001467 session->revFrame->num_channels_ = inCnl;
1468 session->revFrame->sample_rate_hz_ = session->apmSamplingRate;
Saketh Sathuvalli08337032020-09-22 21:13:45 +05301469#else
1470 session->revConfig.set_sample_rate_hz(session->samplingRate);
1471 session->revConfig.set_num_channels(inCnl);
1472#endif
Eric Laurenta9390d42011-06-17 20:17:17 -07001473
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001474 // force process buffer reallocation
1475 session->inBufSize = 0;
1476 session->outBufSize = 0;
1477 session->framesIn = 0;
1478 session->framesOut = 0;
1479
1480
Saketh Sathuvalli08337032020-09-22 21:13:45 +05301481#ifdef WEBRTC_LEGACY
Eric Laurenta9390d42011-06-17 20:17:17 -07001482 if (session->inResampler != NULL) {
1483 speex_resampler_destroy(session->inResampler);
1484 session->inResampler = NULL;
1485 }
1486 if (session->outResampler != NULL) {
1487 speex_resampler_destroy(session->outResampler);
1488 session->outResampler = NULL;
1489 }
1490 if (session->revResampler != NULL) {
1491 speex_resampler_destroy(session->revResampler);
1492 session->revResampler = NULL;
1493 }
1494 if (session->samplingRate != session->apmSamplingRate) {
1495 int error;
1496 session->inResampler = speex_resampler_init(session->inChannelCount,
1497 session->samplingRate,
1498 session->apmSamplingRate,
1499 RESAMPLER_QUALITY,
1500 &error);
1501 if (session->inResampler == NULL) {
Steve Block5ff1dd52012-01-05 23:22:43 +00001502 ALOGW("Session_SetConfig Cannot create speex resampler: %s",
Eric Laurenta9390d42011-06-17 20:17:17 -07001503 speex_resampler_strerror(error));
1504 return -EINVAL;
1505 }
1506 session->outResampler = speex_resampler_init(session->outChannelCount,
1507 session->apmSamplingRate,
1508 session->samplingRate,
1509 RESAMPLER_QUALITY,
1510 &error);
1511 if (session->outResampler == NULL) {
Steve Block5ff1dd52012-01-05 23:22:43 +00001512 ALOGW("Session_SetConfig Cannot create speex resampler: %s",
Eric Laurenta9390d42011-06-17 20:17:17 -07001513 speex_resampler_strerror(error));
1514 speex_resampler_destroy(session->inResampler);
1515 session->inResampler = NULL;
1516 return -EINVAL;
1517 }
1518 session->revResampler = speex_resampler_init(session->inChannelCount,
1519 session->samplingRate,
1520 session->apmSamplingRate,
1521 RESAMPLER_QUALITY,
1522 &error);
1523 if (session->revResampler == NULL) {
Steve Block5ff1dd52012-01-05 23:22:43 +00001524 ALOGW("Session_SetConfig Cannot create speex resampler: %s",
Eric Laurenta9390d42011-06-17 20:17:17 -07001525 speex_resampler_strerror(error));
1526 speex_resampler_destroy(session->inResampler);
1527 session->inResampler = NULL;
1528 speex_resampler_destroy(session->outResampler);
1529 session->outResampler = NULL;
1530 return -EINVAL;
1531 }
1532 }
Saketh Sathuvalli08337032020-09-22 21:13:45 +05301533#endif
Eric Laurenta9390d42011-06-17 20:17:17 -07001534
1535 session->state = PREPROC_SESSION_STATE_CONFIG;
1536 return 0;
1537}
1538
Eric Laurent3d5188b2011-12-16 15:30:36 -08001539void Session_GetConfig(preproc_session_t *session, effect_config_t *config)
1540{
1541 memset(config, 0, sizeof(effect_config_t));
1542 config->inputCfg.samplingRate = config->outputCfg.samplingRate = session->samplingRate;
1543 config->inputCfg.format = config->outputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
Glenn Kastenab334fd2012-03-14 12:56:06 -07001544 config->inputCfg.channels = audio_channel_in_mask_from_count(session->inChannelCount);
1545 // "out" doesn't mean output device, so this is the correct API to convert channel count to mask
1546 config->outputCfg.channels = audio_channel_in_mask_from_count(session->outChannelCount);
Eric Laurent3d5188b2011-12-16 15:30:36 -08001547 config->inputCfg.mask = config->outputCfg.mask =
1548 (EFFECT_CONFIG_SMP_RATE | EFFECT_CONFIG_CHANNELS | EFFECT_CONFIG_FORMAT);
1549}
1550
Eric Laurenta9390d42011-06-17 20:17:17 -07001551int Session_SetReverseConfig(preproc_session_t *session, effect_config_t *config)
1552{
1553 if (config->inputCfg.samplingRate != config->outputCfg.samplingRate ||
1554 config->inputCfg.format != config->outputCfg.format ||
1555 config->inputCfg.format != AUDIO_FORMAT_PCM_16_BIT) {
1556 return -EINVAL;
1557 }
1558
Steve Block3856b092011-10-20 11:56:00 +01001559 ALOGV("Session_SetReverseConfig sr %d cnl %08x",
Eric Laurenta9390d42011-06-17 20:17:17 -07001560 config->inputCfg.samplingRate, config->inputCfg.channels);
1561
1562 if (session->state < PREPROC_SESSION_STATE_CONFIG) {
1563 return -ENOSYS;
1564 }
1565 if (config->inputCfg.samplingRate != session->samplingRate ||
1566 config->inputCfg.format != AUDIO_FORMAT_PCM_16_BIT) {
1567 return -EINVAL;
1568 }
Andy Hunge5412692014-05-16 11:25:07 -07001569 uint32_t inCnl = audio_channel_count_from_out_mask(config->inputCfg.channels);
Saketh Sathuvalli08337032020-09-22 21:13:45 +05301570#ifdef WEBRTC_LEGACY
Alex Luebs9718b7d2015-11-24 14:33:14 -08001571 const webrtc::ProcessingConfig processing_config = {
Alex Luebs3f11ef02016-01-15 15:51:58 -08001572 {{static_cast<int>(session->apmSamplingRate), session->inChannelCount},
1573 {static_cast<int>(session->apmSamplingRate), session->outChannelCount},
1574 {static_cast<int>(session->apmSamplingRate), inCnl},
1575 {static_cast<int>(session->apmSamplingRate), inCnl}}};
Alex Luebs9718b7d2015-11-24 14:33:14 -08001576 int status = session->apm->Initialize(processing_config);
Eric Laurenta9390d42011-06-17 20:17:17 -07001577 if (status < 0) {
1578 return -EINVAL;
1579 }
Saketh Sathuvalli08337032020-09-22 21:13:45 +05301580#endif
Eric Laurenta9390d42011-06-17 20:17:17 -07001581 session->revChannelCount = inCnl;
Saketh Sathuvalli08337032020-09-22 21:13:45 +05301582#ifdef WEBRTC_LEGACY
Chih-Hung Hsiehde7fa312015-10-13 10:58:08 -07001583 session->revFrame->num_channels_ = inCnl;
1584 session->revFrame->sample_rate_hz_ = session->apmSamplingRate;
Saketh Sathuvalli08337032020-09-22 21:13:45 +05301585#endif
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001586 // force process buffer reallocation
1587 session->revBufSize = 0;
1588 session->framesRev = 0;
1589
Eric Laurenta9390d42011-06-17 20:17:17 -07001590 return 0;
1591}
1592
Eric Laurent3d5188b2011-12-16 15:30:36 -08001593void Session_GetReverseConfig(preproc_session_t *session, effect_config_t *config)
1594{
1595 memset(config, 0, sizeof(effect_config_t));
1596 config->inputCfg.samplingRate = config->outputCfg.samplingRate = session->samplingRate;
1597 config->inputCfg.format = config->outputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
1598 config->inputCfg.channels = config->outputCfg.channels =
Glenn Kastenab334fd2012-03-14 12:56:06 -07001599 audio_channel_in_mask_from_count(session->revChannelCount);
Eric Laurent3d5188b2011-12-16 15:30:36 -08001600 config->inputCfg.mask = config->outputCfg.mask =
1601 (EFFECT_CONFIG_SMP_RATE | EFFECT_CONFIG_CHANNELS | EFFECT_CONFIG_FORMAT);
1602}
1603
Eric Laurenta9390d42011-06-17 20:17:17 -07001604void Session_SetProcEnabled(preproc_session_t *session, uint32_t procId, bool enabled)
1605{
1606 if (enabled) {
1607 if(session->enabledMsk == 0) {
1608 session->framesIn = 0;
Saketh Sathuvalli08337032020-09-22 21:13:45 +05301609#ifdef WEBRTC_LEGACY
Eric Laurenta9390d42011-06-17 20:17:17 -07001610 if (session->inResampler != NULL) {
1611 speex_resampler_reset_mem(session->inResampler);
1612 }
1613 session->framesOut = 0;
1614 if (session->outResampler != NULL) {
1615 speex_resampler_reset_mem(session->outResampler);
1616 }
Saketh Sathuvalli08337032020-09-22 21:13:45 +05301617#endif
Eric Laurenta9390d42011-06-17 20:17:17 -07001618 }
1619 session->enabledMsk |= (1 << procId);
1620 if (HasReverseStream(procId)) {
1621 session->framesRev = 0;
Saketh Sathuvalli08337032020-09-22 21:13:45 +05301622#ifdef WEBRTC_LEGACY
Eric Laurenta9390d42011-06-17 20:17:17 -07001623 if (session->revResampler != NULL) {
1624 speex_resampler_reset_mem(session->revResampler);
1625 }
Saketh Sathuvalli08337032020-09-22 21:13:45 +05301626#endif
Eric Laurenta9390d42011-06-17 20:17:17 -07001627 session->revEnabledMsk |= (1 << procId);
1628 }
1629 } else {
1630 session->enabledMsk &= ~(1 << procId);
1631 if (HasReverseStream(procId)) {
1632 session->revEnabledMsk &= ~(1 << procId);
1633 }
1634 }
Steve Block3856b092011-10-20 11:56:00 +01001635 ALOGV("Session_SetProcEnabled proc %d, enabled %d enabledMsk %08x revEnabledMsk %08x",
Eric Laurenta9390d42011-06-17 20:17:17 -07001636 procId, enabled, session->enabledMsk, session->revEnabledMsk);
1637 session->processedMsk = 0;
1638 if (HasReverseStream(procId)) {
1639 session->revProcessedMsk = 0;
1640 }
1641}
1642
1643//------------------------------------------------------------------------------
1644// Bundle functions
1645//------------------------------------------------------------------------------
1646
1647static int sInitStatus = 1;
1648static preproc_session_t sSessions[PREPROC_NUM_SESSIONS];
1649
1650preproc_session_t *PreProc_GetSession(int32_t procId, int32_t sessionId, int32_t ioId)
1651{
1652 size_t i;
Eric Laurenta9390d42011-06-17 20:17:17 -07001653 for (i = 0; i < PREPROC_NUM_SESSIONS; i++) {
Eric Laurentb20cf7d2019-04-05 19:37:34 -07001654 if (sSessions[i].id == sessionId) {
Eric Laurenta9390d42011-06-17 20:17:17 -07001655 if (sSessions[i].createdMsk & (1 << procId)) {
1656 return NULL;
1657 }
1658 return &sSessions[i];
1659 }
1660 }
1661 for (i = 0; i < PREPROC_NUM_SESSIONS; i++) {
Eric Laurentb20cf7d2019-04-05 19:37:34 -07001662 if (sSessions[i].id == 0) {
Eric Laurenta9390d42011-06-17 20:17:17 -07001663 sSessions[i].id = sessionId;
1664 sSessions[i].io = ioId;
1665 return &sSessions[i];
1666 }
1667 }
1668 return NULL;
1669}
1670
1671
1672int PreProc_Init() {
1673 size_t i;
1674 int status = 0;
1675
1676 if (sInitStatus <= 0) {
1677 return sInitStatus;
1678 }
1679 for (i = 0; i < PREPROC_NUM_SESSIONS && status == 0; i++) {
1680 status = Session_Init(&sSessions[i]);
1681 }
1682 sInitStatus = status;
1683 return sInitStatus;
1684}
1685
Glenn Kasten5e92a782012-01-30 07:40:52 -08001686const effect_descriptor_t *PreProc_GetDescriptor(const effect_uuid_t *uuid)
Eric Laurenta9390d42011-06-17 20:17:17 -07001687{
1688 size_t i;
1689 for (i = 0; i < PREPROC_NUM_EFFECTS; i++) {
1690 if (memcmp(&sDescriptors[i]->uuid, uuid, sizeof(effect_uuid_t)) == 0) {
1691 return sDescriptors[i];
1692 }
1693 }
1694 return NULL;
1695}
1696
1697
1698extern "C" {
1699
1700//------------------------------------------------------------------------------
1701// Effect Control Interface Implementation
1702//------------------------------------------------------------------------------
1703
1704int PreProcessingFx_Process(effect_handle_t self,
1705 audio_buffer_t *inBuffer,
1706 audio_buffer_t *outBuffer)
1707{
1708 preproc_effect_t * effect = (preproc_effect_t *)self;
Eric Laurenta9390d42011-06-17 20:17:17 -07001709
1710 if (effect == NULL){
Steve Block3856b092011-10-20 11:56:00 +01001711 ALOGV("PreProcessingFx_Process() ERROR effect == NULL");
Eric Laurenta9390d42011-06-17 20:17:17 -07001712 return -EINVAL;
1713 }
1714 preproc_session_t * session = (preproc_session_t *)effect->session;
1715
1716 if (inBuffer == NULL || inBuffer->raw == NULL ||
1717 outBuffer == NULL || outBuffer->raw == NULL){
Steve Block5ff1dd52012-01-05 23:22:43 +00001718 ALOGW("PreProcessingFx_Process() ERROR bad pointer");
Eric Laurenta9390d42011-06-17 20:17:17 -07001719 return -EINVAL;
1720 }
1721
1722 session->processedMsk |= (1<<effect->procId);
1723
Steve Block3856b092011-10-20 11:56:00 +01001724// ALOGV("PreProcessingFx_Process In %d frames enabledMsk %08x processedMsk %08x",
Eric Laurenta9390d42011-06-17 20:17:17 -07001725// inBuffer->frameCount, session->enabledMsk, session->processedMsk);
1726
1727 if ((session->processedMsk & session->enabledMsk) == session->enabledMsk) {
1728 effect->session->processedMsk = 0;
1729 size_t framesRq = outBuffer->frameCount;
1730 size_t framesWr = 0;
1731 if (session->framesOut) {
1732 size_t fr = session->framesOut;
1733 if (outBuffer->frameCount < fr) {
1734 fr = outBuffer->frameCount;
1735 }
1736 memcpy(outBuffer->s16,
1737 session->outBuf,
1738 fr * session->outChannelCount * sizeof(int16_t));
Jiabin Huang0c9544a2020-06-04 00:46:19 +00001739 memmove(session->outBuf,
1740 session->outBuf + fr * session->outChannelCount,
1741 (session->framesOut - fr) * session->outChannelCount * sizeof(int16_t));
Eric Laurenta9390d42011-06-17 20:17:17 -07001742 session->framesOut -= fr;
1743 framesWr += fr;
1744 }
1745 outBuffer->frameCount = framesWr;
1746 if (framesWr == framesRq) {
1747 inBuffer->frameCount = 0;
1748 return 0;
1749 }
1750
Saketh Sathuvalli08337032020-09-22 21:13:45 +05301751#ifdef WEBRTC_LEGACY
Eric Laurenta9390d42011-06-17 20:17:17 -07001752 if (session->inResampler != NULL) {
1753 size_t fr = session->frameCount - session->framesIn;
1754 if (inBuffer->frameCount < fr) {
1755 fr = inBuffer->frameCount;
1756 }
1757 if (session->inBufSize < session->framesIn + fr) {
Eric Laurent679650f2015-08-21 14:01:50 -07001758 int16_t *buf;
Eric Laurenta9390d42011-06-17 20:17:17 -07001759 session->inBufSize = session->framesIn + fr;
Eric Laurent679650f2015-08-21 14:01:50 -07001760 buf = (int16_t *)realloc(session->inBuf,
Eric Laurenta9390d42011-06-17 20:17:17 -07001761 session->inBufSize * session->inChannelCount * sizeof(int16_t));
Eric Laurent679650f2015-08-21 14:01:50 -07001762 if (buf == NULL) {
1763 session->framesIn = 0;
1764 free(session->inBuf);
1765 session->inBuf = NULL;
1766 return -ENOMEM;
1767 }
1768 session->inBuf = buf;
Eric Laurenta9390d42011-06-17 20:17:17 -07001769 }
1770 memcpy(session->inBuf + session->framesIn * session->inChannelCount,
1771 inBuffer->s16,
1772 fr * session->inChannelCount * sizeof(int16_t));
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001773#ifdef DUAL_MIC_TEST
1774 pthread_mutex_lock(&gPcmDumpLock);
1775 if (gPcmDumpFh != NULL) {
1776 fwrite(inBuffer->raw,
1777 fr * session->inChannelCount * sizeof(int16_t), 1, gPcmDumpFh);
1778 }
1779 pthread_mutex_unlock(&gPcmDumpLock);
1780#endif
Eric Laurenta9390d42011-06-17 20:17:17 -07001781
1782 session->framesIn += fr;
1783 inBuffer->frameCount = fr;
1784 if (session->framesIn < session->frameCount) {
1785 return 0;
1786 }
Kévin PETIT377b2ec2014-02-03 12:35:36 +00001787 spx_uint32_t frIn = session->framesIn;
1788 spx_uint32_t frOut = session->apmFrameCount;
Eric Laurenta9390d42011-06-17 20:17:17 -07001789 if (session->inChannelCount == 1) {
1790 speex_resampler_process_int(session->inResampler,
1791 0,
1792 session->inBuf,
1793 &frIn,
Chih-Hung Hsiehde7fa312015-10-13 10:58:08 -07001794 session->procFrame->data_,
Eric Laurenta9390d42011-06-17 20:17:17 -07001795 &frOut);
1796 } else {
1797 speex_resampler_process_interleaved_int(session->inResampler,
1798 session->inBuf,
1799 &frIn,
Chih-Hung Hsiehde7fa312015-10-13 10:58:08 -07001800 session->procFrame->data_,
Eric Laurenta9390d42011-06-17 20:17:17 -07001801 &frOut);
1802 }
Jiabin Huang0c9544a2020-06-04 00:46:19 +00001803 memmove(session->inBuf,
1804 session->inBuf + frIn * session->inChannelCount,
1805 (session->framesIn - frIn) * session->inChannelCount * sizeof(int16_t));
Eric Laurenta9390d42011-06-17 20:17:17 -07001806 session->framesIn -= frIn;
1807 } else {
1808 size_t fr = session->frameCount - session->framesIn;
1809 if (inBuffer->frameCount < fr) {
1810 fr = inBuffer->frameCount;
1811 }
Chih-Hung Hsiehde7fa312015-10-13 10:58:08 -07001812 memcpy(session->procFrame->data_ + session->framesIn * session->inChannelCount,
Eric Laurenta9390d42011-06-17 20:17:17 -07001813 inBuffer->s16,
1814 fr * session->inChannelCount * sizeof(int16_t));
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001815
1816#ifdef DUAL_MIC_TEST
1817 pthread_mutex_lock(&gPcmDumpLock);
1818 if (gPcmDumpFh != NULL) {
1819 fwrite(inBuffer->raw,
1820 fr * session->inChannelCount * sizeof(int16_t), 1, gPcmDumpFh);
1821 }
1822 pthread_mutex_unlock(&gPcmDumpLock);
1823#endif
1824
Eric Laurenta9390d42011-06-17 20:17:17 -07001825 session->framesIn += fr;
1826 inBuffer->frameCount = fr;
1827 if (session->framesIn < session->frameCount) {
1828 return 0;
1829 }
1830 session->framesIn = 0;
1831 }
Alex Luebs766bf732015-12-14 21:32:13 -08001832 session->procFrame->samples_per_channel_ = session->apmFrameCount;
Eric Laurenta9390d42011-06-17 20:17:17 -07001833
1834 effect->session->apm->ProcessStream(session->procFrame);
Saketh Sathuvalli08337032020-09-22 21:13:45 +05301835#else
1836 size_t fr = session->frameCount - session->framesIn;
1837 if (inBuffer->frameCount < fr) {
1838 fr = inBuffer->frameCount;
1839 }
1840 session->framesIn += fr;
1841 inBuffer->frameCount = fr;
1842 if (session->framesIn < session->frameCount) {
1843 return 0;
1844 }
1845 session->framesIn = 0;
1846 if (int status = effect->session->apm->ProcessStream(
1847 (const int16_t* const)inBuffer->s16,
1848 (const webrtc::StreamConfig)effect->session->inputConfig,
1849 (const webrtc::StreamConfig)effect->session->outputConfig,
1850 (int16_t* const)outBuffer->s16);
1851 status != 0) {
1852 ALOGE("Process Stream failed with error %d\n", status);
1853 return status;
1854 }
1855 outBuffer->frameCount = inBuffer->frameCount;
1856#endif
Eric Laurenta9390d42011-06-17 20:17:17 -07001857
1858 if (session->outBufSize < session->framesOut + session->frameCount) {
Eric Laurent679650f2015-08-21 14:01:50 -07001859 int16_t *buf;
Eric Laurenta9390d42011-06-17 20:17:17 -07001860 session->outBufSize = session->framesOut + session->frameCount;
Eric Laurent679650f2015-08-21 14:01:50 -07001861 buf = (int16_t *)realloc(session->outBuf,
1862 session->outBufSize * session->outChannelCount * sizeof(int16_t));
1863 if (buf == NULL) {
1864 session->framesOut = 0;
1865 free(session->outBuf);
1866 session->outBuf = NULL;
1867 return -ENOMEM;
1868 }
1869 session->outBuf = buf;
Eric Laurenta9390d42011-06-17 20:17:17 -07001870 }
1871
Saketh Sathuvalli08337032020-09-22 21:13:45 +05301872#ifdef WEBRTC_LEGACY
Eric Laurenta9390d42011-06-17 20:17:17 -07001873 if (session->outResampler != NULL) {
Kévin PETIT377b2ec2014-02-03 12:35:36 +00001874 spx_uint32_t frIn = session->apmFrameCount;
1875 spx_uint32_t frOut = session->frameCount;
Eric Laurenta9390d42011-06-17 20:17:17 -07001876 if (session->inChannelCount == 1) {
1877 speex_resampler_process_int(session->outResampler,
1878 0,
Chih-Hung Hsiehde7fa312015-10-13 10:58:08 -07001879 session->procFrame->data_,
Eric Laurenta9390d42011-06-17 20:17:17 -07001880 &frIn,
1881 session->outBuf + session->framesOut * session->outChannelCount,
1882 &frOut);
1883 } else {
1884 speex_resampler_process_interleaved_int(session->outResampler,
Chih-Hung Hsiehde7fa312015-10-13 10:58:08 -07001885 session->procFrame->data_,
Eric Laurenta9390d42011-06-17 20:17:17 -07001886 &frIn,
1887 session->outBuf + session->framesOut * session->outChannelCount,
1888 &frOut);
1889 }
1890 session->framesOut += frOut;
1891 } else {
1892 memcpy(session->outBuf + session->framesOut * session->outChannelCount,
Chih-Hung Hsiehde7fa312015-10-13 10:58:08 -07001893 session->procFrame->data_,
Eric Laurenta9390d42011-06-17 20:17:17 -07001894 session->frameCount * session->outChannelCount * sizeof(int16_t));
1895 session->framesOut += session->frameCount;
1896 }
1897 size_t fr = session->framesOut;
Saketh Sathuvalli08337032020-09-22 21:13:45 +05301898#else
1899 fr = session->framesOut;
1900#endif
Eric Laurenta9390d42011-06-17 20:17:17 -07001901 if (framesRq - framesWr < fr) {
1902 fr = framesRq - framesWr;
1903 }
1904 memcpy(outBuffer->s16 + framesWr * session->outChannelCount,
1905 session->outBuf,
1906 fr * session->outChannelCount * sizeof(int16_t));
Jiabin Huang0c9544a2020-06-04 00:46:19 +00001907 memmove(session->outBuf,
1908 session->outBuf + fr * session->outChannelCount,
1909 (session->framesOut - fr) * session->outChannelCount * sizeof(int16_t));
Eric Laurenta9390d42011-06-17 20:17:17 -07001910 session->framesOut -= fr;
1911 outBuffer->frameCount += fr;
1912
1913 return 0;
1914 } else {
1915 return -ENODATA;
1916 }
1917}
1918
1919int PreProcessingFx_Command(effect_handle_t self,
1920 uint32_t cmdCode,
1921 uint32_t cmdSize,
1922 void *pCmdData,
1923 uint32_t *replySize,
1924 void *pReplyData)
1925{
1926 preproc_effect_t * effect = (preproc_effect_t *) self;
Eric Laurenta9390d42011-06-17 20:17:17 -07001927
1928 if (effect == NULL){
1929 return -EINVAL;
1930 }
1931
Steve Block3856b092011-10-20 11:56:00 +01001932 //ALOGV("PreProcessingFx_Command: command %d cmdSize %d",cmdCode, cmdSize);
Eric Laurenta9390d42011-06-17 20:17:17 -07001933
1934 switch (cmdCode){
1935 case EFFECT_CMD_INIT:
1936 if (pReplyData == NULL || *replySize != sizeof(int)){
1937 return -EINVAL;
1938 }
1939 if (effect->ops->init) {
1940 effect->ops->init(effect);
1941 }
1942 *(int *)pReplyData = 0;
1943 break;
1944
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001945 case EFFECT_CMD_SET_CONFIG: {
Eric Laurenta9390d42011-06-17 20:17:17 -07001946 if (pCmdData == NULL||
1947 cmdSize != sizeof(effect_config_t)||
1948 pReplyData == NULL||
1949 *replySize != sizeof(int)){
Steve Block3856b092011-10-20 11:56:00 +01001950 ALOGV("PreProcessingFx_Command cmdCode Case: "
Eric Laurent3d5188b2011-12-16 15:30:36 -08001951 "EFFECT_CMD_SET_CONFIG: ERROR");
Eric Laurenta9390d42011-06-17 20:17:17 -07001952 return -EINVAL;
1953 }
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001954#ifdef DUAL_MIC_TEST
1955 // make sure that the config command is accepted by making as if all effects were
1956 // disabled: this is OK for functional tests
1957 uint32_t enabledMsk = effect->session->enabledMsk;
1958 if (gDualMicEnabled) {
1959 effect->session->enabledMsk = 0;
1960 }
1961#endif
Eric Laurenta9390d42011-06-17 20:17:17 -07001962 *(int *)pReplyData = Session_SetConfig(effect->session, (effect_config_t *)pCmdData);
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001963#ifdef DUAL_MIC_TEST
1964 if (gDualMicEnabled) {
1965 effect->session->enabledMsk = enabledMsk;
1966 }
1967#endif
Eric Laurenta9390d42011-06-17 20:17:17 -07001968 if (*(int *)pReplyData != 0) {
1969 break;
1970 }
Eric Laurent76533e92012-02-17 17:52:04 -08001971 if (effect->state != PREPROC_EFFECT_STATE_ACTIVE) {
1972 *(int *)pReplyData = Effect_SetState(effect, PREPROC_EFFECT_STATE_CONFIG);
1973 }
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001974 } break;
Eric Laurenta9390d42011-06-17 20:17:17 -07001975
Eric Laurent3d5188b2011-12-16 15:30:36 -08001976 case EFFECT_CMD_GET_CONFIG:
1977 if (pReplyData == NULL ||
1978 *replySize != sizeof(effect_config_t)) {
1979 ALOGV("\tLVM_ERROR : PreProcessingFx_Command cmdCode Case: "
1980 "EFFECT_CMD_GET_CONFIG: ERROR");
1981 return -EINVAL;
1982 }
1983
Eric Laurent94fef382012-02-06 14:28:54 -08001984 Session_GetConfig(effect->session, (effect_config_t *)pReplyData);
Eric Laurent3d5188b2011-12-16 15:30:36 -08001985 break;
1986
1987 case EFFECT_CMD_SET_CONFIG_REVERSE:
1988 if (pCmdData == NULL ||
1989 cmdSize != sizeof(effect_config_t) ||
1990 pReplyData == NULL ||
1991 *replySize != sizeof(int)) {
Steve Block3856b092011-10-20 11:56:00 +01001992 ALOGV("PreProcessingFx_Command cmdCode Case: "
Eric Laurent3d5188b2011-12-16 15:30:36 -08001993 "EFFECT_CMD_SET_CONFIG_REVERSE: ERROR");
Eric Laurenta9390d42011-06-17 20:17:17 -07001994 return -EINVAL;
1995 }
1996 *(int *)pReplyData = Session_SetReverseConfig(effect->session,
1997 (effect_config_t *)pCmdData);
1998 if (*(int *)pReplyData != 0) {
1999 break;
2000 }
2001 break;
2002
Eric Laurent3d5188b2011-12-16 15:30:36 -08002003 case EFFECT_CMD_GET_CONFIG_REVERSE:
2004 if (pReplyData == NULL ||
2005 *replySize != sizeof(effect_config_t)){
2006 ALOGV("PreProcessingFx_Command cmdCode Case: "
2007 "EFFECT_CMD_GET_CONFIG_REVERSE: ERROR");
2008 return -EINVAL;
2009 }
2010 Session_GetReverseConfig(effect->session, (effect_config_t *)pCmdData);
2011 break;
2012
Eric Laurenta9390d42011-06-17 20:17:17 -07002013 case EFFECT_CMD_RESET:
2014 if (effect->ops->reset) {
2015 effect->ops->reset(effect);
2016 }
2017 break;
2018
Eric Laurent0f714a42015-06-19 15:33:57 -07002019 case EFFECT_CMD_GET_PARAM: {
2020 effect_param_t *p = (effect_param_t *)pCmdData;
2021
2022 if (pCmdData == NULL || cmdSize < sizeof(effect_param_t) ||
2023 cmdSize < (sizeof(effect_param_t) + p->psize) ||
2024 pReplyData == NULL || replySize == NULL ||
2025 *replySize < (sizeof(effect_param_t) + p->psize)){
Steve Block3856b092011-10-20 11:56:00 +01002026 ALOGV("PreProcessingFx_Command cmdCode Case: "
Eric Laurenta9390d42011-06-17 20:17:17 -07002027 "EFFECT_CMD_GET_PARAM: ERROR");
2028 return -EINVAL;
2029 }
Eric Laurenta9390d42011-06-17 20:17:17 -07002030
2031 memcpy(pReplyData, pCmdData, sizeof(effect_param_t) + p->psize);
2032
2033 p = (effect_param_t *)pReplyData;
2034
2035 int voffset = ((p->psize - 1) / sizeof(int32_t) + 1) * sizeof(int32_t);
2036
2037 if (effect->ops->get_parameter) {
2038 p->status = effect->ops->get_parameter(effect, p->data,
Ashok Bhatb302bd52014-02-18 11:40:00 +00002039 &p->vsize,
Eric Laurenta9390d42011-06-17 20:17:17 -07002040 p->data + voffset);
2041 *replySize = sizeof(effect_param_t) + voffset + p->vsize;
2042 }
2043 } break;
2044
2045 case EFFECT_CMD_SET_PARAM:{
2046 if (pCmdData == NULL||
Eric Laurent0f714a42015-06-19 15:33:57 -07002047 cmdSize < sizeof(effect_param_t) ||
2048 pReplyData == NULL || replySize == NULL ||
Eric Laurenta9390d42011-06-17 20:17:17 -07002049 *replySize != sizeof(int32_t)){
Steve Block3856b092011-10-20 11:56:00 +01002050 ALOGV("PreProcessingFx_Command cmdCode Case: "
Eric Laurenta9390d42011-06-17 20:17:17 -07002051 "EFFECT_CMD_SET_PARAM: ERROR");
2052 return -EINVAL;
2053 }
2054 effect_param_t *p = (effect_param_t *) pCmdData;
2055
2056 if (p->psize != sizeof(int32_t)){
Steve Block3856b092011-10-20 11:56:00 +01002057 ALOGV("PreProcessingFx_Command cmdCode Case: "
Eric Laurenta9390d42011-06-17 20:17:17 -07002058 "EFFECT_CMD_SET_PARAM: ERROR, psize is not sizeof(int32_t)");
2059 return -EINVAL;
2060 }
2061 if (effect->ops->set_parameter) {
2062 *(int *)pReplyData = effect->ops->set_parameter(effect,
2063 (void *)p->data,
2064 p->data + p->psize);
2065 }
2066 } break;
2067
2068 case EFFECT_CMD_ENABLE:
Eric Laurent0f714a42015-06-19 15:33:57 -07002069 if (pReplyData == NULL || replySize == NULL || *replySize != sizeof(int)){
Steve Block3856b092011-10-20 11:56:00 +01002070 ALOGV("PreProcessingFx_Command cmdCode Case: EFFECT_CMD_ENABLE: ERROR");
Eric Laurenta9390d42011-06-17 20:17:17 -07002071 return -EINVAL;
2072 }
2073 *(int *)pReplyData = Effect_SetState(effect, PREPROC_EFFECT_STATE_ACTIVE);
2074 break;
2075
2076 case EFFECT_CMD_DISABLE:
Eric Laurent0f714a42015-06-19 15:33:57 -07002077 if (pReplyData == NULL || replySize == NULL || *replySize != sizeof(int)){
Steve Block3856b092011-10-20 11:56:00 +01002078 ALOGV("PreProcessingFx_Command cmdCode Case: EFFECT_CMD_DISABLE: ERROR");
Eric Laurenta9390d42011-06-17 20:17:17 -07002079 return -EINVAL;
2080 }
2081 *(int *)pReplyData = Effect_SetState(effect, PREPROC_EFFECT_STATE_CONFIG);
2082 break;
2083
2084 case EFFECT_CMD_SET_DEVICE:
2085 case EFFECT_CMD_SET_INPUT_DEVICE:
2086 if (pCmdData == NULL ||
2087 cmdSize != sizeof(uint32_t)) {
Steve Block3856b092011-10-20 11:56:00 +01002088 ALOGV("PreProcessingFx_Command cmdCode Case: EFFECT_CMD_SET_DEVICE: ERROR");
Eric Laurenta9390d42011-06-17 20:17:17 -07002089 return -EINVAL;
2090 }
2091
2092 if (effect->ops->set_device) {
2093 effect->ops->set_device(effect, *(uint32_t *)pCmdData);
2094 }
2095 break;
2096
2097 case EFFECT_CMD_SET_VOLUME:
2098 case EFFECT_CMD_SET_AUDIO_MODE:
2099 break;
2100
Eric Laurent3f9c84c2012-04-03 15:36:53 -07002101#ifdef DUAL_MIC_TEST
2102 ///// test commands start
2103 case PREPROC_CMD_DUAL_MIC_ENABLE: {
2104 if (pCmdData == NULL|| cmdSize != sizeof(uint32_t) ||
2105 pReplyData == NULL || replySize == NULL) {
2106 ALOGE("PreProcessingFx_Command cmdCode Case: "
2107 "PREPROC_CMD_DUAL_MIC_ENABLE: ERROR");
2108 *replySize = 0;
2109 return -EINVAL;
2110 }
2111 gDualMicEnabled = *(bool *)pCmdData;
2112 if (gDualMicEnabled) {
2113 effect->aux_channels_on = sHasAuxChannels[effect->procId];
2114 } else {
2115 effect->aux_channels_on = false;
2116 }
2117 effect->cur_channel_config = (effect->session->inChannelCount == 1) ?
2118 CHANNEL_CFG_MONO : CHANNEL_CFG_STEREO;
2119
2120 ALOGV("PREPROC_CMD_DUAL_MIC_ENABLE: %s", gDualMicEnabled ? "enabled" : "disabled");
2121 *replySize = sizeof(int);
2122 *(int *)pReplyData = 0;
2123 } break;
2124 case PREPROC_CMD_DUAL_MIC_PCM_DUMP_START: {
2125 if (pCmdData == NULL|| pReplyData == NULL || replySize == NULL) {
2126 ALOGE("PreProcessingFx_Command cmdCode Case: "
2127 "PREPROC_CMD_DUAL_MIC_PCM_DUMP_START: ERROR");
2128 *replySize = 0;
2129 return -EINVAL;
2130 }
2131 pthread_mutex_lock(&gPcmDumpLock);
2132 if (gPcmDumpFh != NULL) {
2133 fclose(gPcmDumpFh);
2134 gPcmDumpFh = NULL;
2135 }
2136 char *path = strndup((char *)pCmdData, cmdSize);
2137 gPcmDumpFh = fopen((char *)path, "wb");
2138 pthread_mutex_unlock(&gPcmDumpLock);
2139 ALOGV("PREPROC_CMD_DUAL_MIC_PCM_DUMP_START: path %s gPcmDumpFh %p",
2140 path, gPcmDumpFh);
2141 ALOGE_IF(gPcmDumpFh <= 0, "gPcmDumpFh open error %d %s", errno, strerror(errno));
2142 free(path);
2143 *replySize = sizeof(int);
2144 *(int *)pReplyData = 0;
2145 } break;
2146 case PREPROC_CMD_DUAL_MIC_PCM_DUMP_STOP: {
2147 if (pReplyData == NULL || replySize == NULL) {
2148 ALOGE("PreProcessingFx_Command cmdCode Case: "
2149 "PREPROC_CMD_DUAL_MIC_PCM_DUMP_STOP: ERROR");
2150 *replySize = 0;
2151 return -EINVAL;
2152 }
2153 pthread_mutex_lock(&gPcmDumpLock);
2154 if (gPcmDumpFh != NULL) {
2155 fclose(gPcmDumpFh);
2156 gPcmDumpFh = NULL;
2157 }
2158 pthread_mutex_unlock(&gPcmDumpLock);
2159 ALOGV("PREPROC_CMD_DUAL_MIC_PCM_DUMP_STOP");
2160 *replySize = sizeof(int);
2161 *(int *)pReplyData = 0;
2162 } break;
2163 ///// test commands end
2164
2165 case EFFECT_CMD_GET_FEATURE_SUPPORTED_CONFIGS: {
2166 if(!gDualMicEnabled) {
2167 return -EINVAL;
2168 }
2169 if (pCmdData == NULL|| cmdSize != 2 * sizeof(uint32_t) ||
2170 pReplyData == NULL || replySize == NULL) {
2171 ALOGE("PreProcessingFx_Command cmdCode Case: "
2172 "EFFECT_CMD_GET_FEATURE_SUPPORTED_CONFIGS: ERROR");
2173 *replySize = 0;
2174 return -EINVAL;
2175 }
2176 if (*(uint32_t *)pCmdData != EFFECT_FEATURE_AUX_CHANNELS ||
2177 !effect->aux_channels_on) {
2178 ALOGV("PreProcessingFx_Command feature EFFECT_FEATURE_AUX_CHANNELS not supported by"
2179 " fx %d", effect->procId);
2180 *(uint32_t *)pReplyData = -ENOSYS;
2181 *replySize = sizeof(uint32_t);
2182 break;
2183 }
2184 size_t num_configs = *((uint32_t *)pCmdData + 1);
2185 if (*replySize < (2 * sizeof(uint32_t) +
2186 num_configs * sizeof(channel_config_t))) {
2187 *replySize = 0;
2188 return -EINVAL;
2189 }
2190
2191 *((uint32_t *)pReplyData + 1) = CHANNEL_CFG_CNT;
2192 if (num_configs < CHANNEL_CFG_CNT ||
2193 *replySize < (2 * sizeof(uint32_t) +
2194 CHANNEL_CFG_CNT * sizeof(channel_config_t))) {
2195 *(uint32_t *)pReplyData = -ENOMEM;
2196 } else {
2197 num_configs = CHANNEL_CFG_CNT;
2198 *(uint32_t *)pReplyData = 0;
2199 }
2200 ALOGV("PreProcessingFx_Command EFFECT_CMD_GET_FEATURE_SUPPORTED_CONFIGS num config %d",
2201 num_configs);
2202
2203 *replySize = 2 * sizeof(uint32_t) + num_configs * sizeof(channel_config_t);
2204 *((uint32_t *)pReplyData + 1) = num_configs;
2205 memcpy((uint32_t *)pReplyData + 2, &sDualMicConfigs, num_configs * sizeof(channel_config_t));
2206 } break;
2207 case EFFECT_CMD_GET_FEATURE_CONFIG:
2208 if(!gDualMicEnabled) {
2209 return -EINVAL;
2210 }
2211 if (pCmdData == NULL|| cmdSize != sizeof(uint32_t) ||
2212 pReplyData == NULL || replySize == NULL ||
2213 *replySize < sizeof(uint32_t) + sizeof(channel_config_t)) {
2214 ALOGE("PreProcessingFx_Command cmdCode Case: "
2215 "EFFECT_CMD_GET_FEATURE_CONFIG: ERROR");
2216 return -EINVAL;
2217 }
2218 if (*(uint32_t *)pCmdData != EFFECT_FEATURE_AUX_CHANNELS || !effect->aux_channels_on) {
2219 *(uint32_t *)pReplyData = -ENOSYS;
2220 *replySize = sizeof(uint32_t);
2221 break;
2222 }
2223 ALOGV("PreProcessingFx_Command EFFECT_CMD_GET_FEATURE_CONFIG");
2224 *(uint32_t *)pReplyData = 0;
2225 *replySize = sizeof(uint32_t) + sizeof(channel_config_t);
2226 memcpy((uint32_t *)pReplyData + 1,
2227 &sDualMicConfigs[effect->cur_channel_config],
2228 sizeof(channel_config_t));
2229 break;
2230 case EFFECT_CMD_SET_FEATURE_CONFIG: {
2231 ALOGV("PreProcessingFx_Command EFFECT_CMD_SET_FEATURE_CONFIG: "
2232 "gDualMicEnabled %d effect->aux_channels_on %d",
2233 gDualMicEnabled, effect->aux_channels_on);
2234 if(!gDualMicEnabled) {
2235 return -EINVAL;
2236 }
2237 if (pCmdData == NULL|| cmdSize != (sizeof(uint32_t) + sizeof(channel_config_t)) ||
2238 pReplyData == NULL || replySize == NULL ||
2239 *replySize < sizeof(uint32_t)) {
2240 ALOGE("PreProcessingFx_Command cmdCode Case: "
2241 "EFFECT_CMD_SET_FEATURE_CONFIG: ERROR\n"
2242 "pCmdData %p cmdSize %d pReplyData %p replySize %p *replySize %d",
2243 pCmdData, cmdSize, pReplyData, replySize, replySize ? *replySize : -1);
2244 return -EINVAL;
2245 }
2246 *replySize = sizeof(uint32_t);
2247 if (*(uint32_t *)pCmdData != EFFECT_FEATURE_AUX_CHANNELS || !effect->aux_channels_on) {
2248 *(uint32_t *)pReplyData = -ENOSYS;
2249 ALOGV("PreProcessingFx_Command cmdCode Case: "
2250 "EFFECT_CMD_SET_FEATURE_CONFIG: ERROR\n"
2251 "CmdData %d effect->aux_channels_on %d",
2252 *(uint32_t *)pCmdData, effect->aux_channels_on);
2253 break;
2254 }
2255 size_t i;
2256 for (i = 0; i < CHANNEL_CFG_CNT;i++) {
2257 if (memcmp((uint32_t *)pCmdData + 1,
2258 &sDualMicConfigs[i], sizeof(channel_config_t)) == 0) {
2259 break;
2260 }
2261 }
2262 if (i == CHANNEL_CFG_CNT) {
2263 *(uint32_t *)pReplyData = -EINVAL;
2264 ALOGW("PreProcessingFx_Command EFFECT_CMD_SET_FEATURE_CONFIG invalid config"
2265 "[%08x].[%08x]", *((uint32_t *)pCmdData + 1), *((uint32_t *)pCmdData + 2));
2266 } else {
2267 effect->cur_channel_config = i;
2268 *(uint32_t *)pReplyData = 0;
2269 ALOGV("PreProcessingFx_Command EFFECT_CMD_SET_FEATURE_CONFIG New config"
2270 "[%08x].[%08x]", sDualMicConfigs[i].main_channels, sDualMicConfigs[i].aux_channels);
2271 }
2272 } break;
2273#endif
Eric Laurenta9390d42011-06-17 20:17:17 -07002274 default:
2275 return -EINVAL;
2276 }
2277 return 0;
2278}
2279
2280
2281int PreProcessingFx_GetDescriptor(effect_handle_t self,
2282 effect_descriptor_t *pDescriptor)
2283{
2284 preproc_effect_t * effect = (preproc_effect_t *) self;
2285
2286 if (effect == NULL || pDescriptor == NULL) {
2287 return -EINVAL;
2288 }
2289
Glenn Kastena189a682012-02-20 12:16:30 -08002290 *pDescriptor = *sDescriptors[effect->procId];
Eric Laurenta9390d42011-06-17 20:17:17 -07002291
2292 return 0;
2293}
2294
2295int PreProcessingFx_ProcessReverse(effect_handle_t self,
2296 audio_buffer_t *inBuffer,
Eric Laurent0f714a42015-06-19 15:33:57 -07002297 audio_buffer_t *outBuffer __unused)
Eric Laurenta9390d42011-06-17 20:17:17 -07002298{
2299 preproc_effect_t * effect = (preproc_effect_t *)self;
Eric Laurenta9390d42011-06-17 20:17:17 -07002300
2301 if (effect == NULL){
Steve Block5ff1dd52012-01-05 23:22:43 +00002302 ALOGW("PreProcessingFx_ProcessReverse() ERROR effect == NULL");
Eric Laurenta9390d42011-06-17 20:17:17 -07002303 return -EINVAL;
2304 }
2305 preproc_session_t * session = (preproc_session_t *)effect->session;
2306
2307 if (inBuffer == NULL || inBuffer->raw == NULL){
Steve Block5ff1dd52012-01-05 23:22:43 +00002308 ALOGW("PreProcessingFx_ProcessReverse() ERROR bad pointer");
Eric Laurenta9390d42011-06-17 20:17:17 -07002309 return -EINVAL;
2310 }
2311
2312 session->revProcessedMsk |= (1<<effect->procId);
2313
Steve Block3856b092011-10-20 11:56:00 +01002314// ALOGV("PreProcessingFx_ProcessReverse In %d frames revEnabledMsk %08x revProcessedMsk %08x",
Eric Laurenta9390d42011-06-17 20:17:17 -07002315// inBuffer->frameCount, session->revEnabledMsk, session->revProcessedMsk);
2316
2317
2318 if ((session->revProcessedMsk & session->revEnabledMsk) == session->revEnabledMsk) {
2319 effect->session->revProcessedMsk = 0;
Saketh Sathuvalli08337032020-09-22 21:13:45 +05302320#ifdef WEBRTC_LEGACY
Eric Laurenta9390d42011-06-17 20:17:17 -07002321 if (session->revResampler != NULL) {
2322 size_t fr = session->frameCount - session->framesRev;
2323 if (inBuffer->frameCount < fr) {
2324 fr = inBuffer->frameCount;
2325 }
2326 if (session->revBufSize < session->framesRev + fr) {
Eric Laurent679650f2015-08-21 14:01:50 -07002327 int16_t *buf;
Eric Laurenta9390d42011-06-17 20:17:17 -07002328 session->revBufSize = session->framesRev + fr;
Eric Laurent679650f2015-08-21 14:01:50 -07002329 buf = (int16_t *)realloc(session->revBuf,
2330 session->revBufSize * session->inChannelCount * sizeof(int16_t));
2331 if (buf == NULL) {
2332 session->framesRev = 0;
2333 free(session->revBuf);
2334 session->revBuf = NULL;
2335 return -ENOMEM;
2336 }
2337 session->revBuf = buf;
Eric Laurenta9390d42011-06-17 20:17:17 -07002338 }
2339 memcpy(session->revBuf + session->framesRev * session->inChannelCount,
2340 inBuffer->s16,
2341 fr * session->inChannelCount * sizeof(int16_t));
2342
2343 session->framesRev += fr;
2344 inBuffer->frameCount = fr;
2345 if (session->framesRev < session->frameCount) {
2346 return 0;
2347 }
Kévin PETIT377b2ec2014-02-03 12:35:36 +00002348 spx_uint32_t frIn = session->framesRev;
2349 spx_uint32_t frOut = session->apmFrameCount;
Eric Laurenta9390d42011-06-17 20:17:17 -07002350 if (session->inChannelCount == 1) {
2351 speex_resampler_process_int(session->revResampler,
2352 0,
2353 session->revBuf,
2354 &frIn,
Chih-Hung Hsiehde7fa312015-10-13 10:58:08 -07002355 session->revFrame->data_,
Eric Laurenta9390d42011-06-17 20:17:17 -07002356 &frOut);
2357 } else {
2358 speex_resampler_process_interleaved_int(session->revResampler,
2359 session->revBuf,
2360 &frIn,
Chih-Hung Hsiehde7fa312015-10-13 10:58:08 -07002361 session->revFrame->data_,
Eric Laurenta9390d42011-06-17 20:17:17 -07002362 &frOut);
2363 }
Jiabin Huang0c9544a2020-06-04 00:46:19 +00002364 memmove(session->revBuf,
2365 session->revBuf + frIn * session->inChannelCount,
2366 (session->framesRev - frIn) * session->inChannelCount * sizeof(int16_t));
Eric Laurenta9390d42011-06-17 20:17:17 -07002367 session->framesRev -= frIn;
2368 } else {
2369 size_t fr = session->frameCount - session->framesRev;
2370 if (inBuffer->frameCount < fr) {
2371 fr = inBuffer->frameCount;
2372 }
Chih-Hung Hsiehde7fa312015-10-13 10:58:08 -07002373 memcpy(session->revFrame->data_ + session->framesRev * session->inChannelCount,
Eric Laurenta9390d42011-06-17 20:17:17 -07002374 inBuffer->s16,
2375 fr * session->inChannelCount * sizeof(int16_t));
2376 session->framesRev += fr;
2377 inBuffer->frameCount = fr;
2378 if (session->framesRev < session->frameCount) {
2379 return 0;
2380 }
2381 session->framesRev = 0;
2382 }
Alex Luebs766bf732015-12-14 21:32:13 -08002383 session->revFrame->samples_per_channel_ = session->apmFrameCount;
Eric Laurenta9390d42011-06-17 20:17:17 -07002384 effect->session->apm->AnalyzeReverseStream(session->revFrame);
Saketh Sathuvalli08337032020-09-22 21:13:45 +05302385#else
2386 size_t fr = session->frameCount - session->framesRev;
2387 if (inBuffer->frameCount < fr) {
2388 fr = inBuffer->frameCount;
2389 }
2390 session->framesRev += fr;
2391 inBuffer->frameCount = fr;
2392 if (session->framesRev < session->frameCount) {
2393 return 0;
2394 }
2395 session->framesRev = 0;
2396 if (int status = effect->session->apm->ProcessReverseStream(
2397 (const int16_t* const)inBuffer->s16,
2398 (const webrtc::StreamConfig)effect->session->revConfig,
2399 (const webrtc::StreamConfig)effect->session->revConfig,
2400 (int16_t* const)outBuffer->s16);
2401 status != 0) {
2402 ALOGE("Process Reverse Stream failed with error %d\n", status);
2403 return status;
2404 }
2405#endif
Eric Laurenta9390d42011-06-17 20:17:17 -07002406 return 0;
2407 } else {
2408 return -ENODATA;
2409 }
2410}
2411
2412
2413// effect_handle_t interface implementation for effect
2414const struct effect_interface_s sEffectInterface = {
2415 PreProcessingFx_Process,
2416 PreProcessingFx_Command,
2417 PreProcessingFx_GetDescriptor,
2418 NULL
2419};
2420
2421const struct effect_interface_s sEffectInterfaceReverse = {
2422 PreProcessingFx_Process,
2423 PreProcessingFx_Command,
2424 PreProcessingFx_GetDescriptor,
2425 PreProcessingFx_ProcessReverse
2426};
2427
2428//------------------------------------------------------------------------------
2429// Effect Library Interface Implementation
2430//------------------------------------------------------------------------------
2431
Glenn Kasten5e92a782012-01-30 07:40:52 -08002432int PreProcessingLib_Create(const effect_uuid_t *uuid,
Eric Laurenta9390d42011-06-17 20:17:17 -07002433 int32_t sessionId,
2434 int32_t ioId,
2435 effect_handle_t *pInterface)
2436{
Steve Block3856b092011-10-20 11:56:00 +01002437 ALOGV("EffectCreate: uuid: %08x session %d IO: %d", uuid->timeLow, sessionId, ioId);
Eric Laurenta9390d42011-06-17 20:17:17 -07002438
2439 int status;
2440 const effect_descriptor_t *desc;
2441 preproc_session_t *session;
2442 uint32_t procId;
2443
2444 if (PreProc_Init() != 0) {
2445 return sInitStatus;
2446 }
2447 desc = PreProc_GetDescriptor(uuid);
2448 if (desc == NULL) {
Steve Block5ff1dd52012-01-05 23:22:43 +00002449 ALOGW("EffectCreate: fx not found uuid: %08x", uuid->timeLow);
Eric Laurenta9390d42011-06-17 20:17:17 -07002450 return -EINVAL;
2451 }
2452 procId = UuidToProcId(&desc->type);
2453
2454 session = PreProc_GetSession(procId, sessionId, ioId);
2455 if (session == NULL) {
Steve Block5ff1dd52012-01-05 23:22:43 +00002456 ALOGW("EffectCreate: no more session available");
Eric Laurenta9390d42011-06-17 20:17:17 -07002457 return -EINVAL;
2458 }
2459
2460 status = Session_CreateEffect(session, procId, pInterface);
2461
2462 if (status < 0 && session->createdMsk == 0) {
Eric Laurentb20cf7d2019-04-05 19:37:34 -07002463 session->id = 0;
Eric Laurenta9390d42011-06-17 20:17:17 -07002464 }
2465 return status;
2466}
2467
2468int PreProcessingLib_Release(effect_handle_t interface)
2469{
Steve Block3856b092011-10-20 11:56:00 +01002470 ALOGV("EffectRelease start %p", interface);
Eric Laurenta9390d42011-06-17 20:17:17 -07002471 if (PreProc_Init() != 0) {
2472 return sInitStatus;
2473 }
2474
2475 preproc_effect_t *fx = (preproc_effect_t *)interface;
2476
Eric Laurentb20cf7d2019-04-05 19:37:34 -07002477 if (fx->session->id == 0) {
Eric Laurenta9390d42011-06-17 20:17:17 -07002478 return -EINVAL;
2479 }
2480 return Session_ReleaseEffect(fx->session, fx);
2481}
2482
Glenn Kasten5e92a782012-01-30 07:40:52 -08002483int PreProcessingLib_GetDescriptor(const effect_uuid_t *uuid,
Eric Laurenta9390d42011-06-17 20:17:17 -07002484 effect_descriptor_t *pDescriptor) {
2485
2486 if (pDescriptor == NULL || uuid == NULL){
2487 return -EINVAL;
2488 }
2489
2490 const effect_descriptor_t *desc = PreProc_GetDescriptor(uuid);
2491 if (desc == NULL) {
Steve Block3856b092011-10-20 11:56:00 +01002492 ALOGV("PreProcessingLib_GetDescriptor() not found");
Eric Laurenta9390d42011-06-17 20:17:17 -07002493 return -EINVAL;
2494 }
2495
Steve Block3856b092011-10-20 11:56:00 +01002496 ALOGV("PreProcessingLib_GetDescriptor() got fx %s", desc->name);
Eric Laurenta9390d42011-06-17 20:17:17 -07002497
Glenn Kastena189a682012-02-20 12:16:30 -08002498 *pDescriptor = *desc;
Eric Laurenta9390d42011-06-17 20:17:17 -07002499 return 0;
2500}
2501
Marco Nelissen7f16b192012-10-25 16:05:57 -07002502// This is the only symbol that needs to be exported
2503__attribute__ ((visibility ("default")))
Eric Laurenta9390d42011-06-17 20:17:17 -07002504audio_effect_library_t AUDIO_EFFECT_LIBRARY_INFO_SYM = {
synergydevc9d8ea72013-10-19 22:51:33 -07002505 .tag = AUDIO_EFFECT_LIBRARY_TAG,
2506 .version = EFFECT_LIBRARY_API_VERSION,
2507 .name = "Audio Preprocessing Library",
2508 .implementor = "The Android Open Source Project",
2509 .create_effect = PreProcessingLib_Create,
2510 .release_effect = PreProcessingLib_Release,
2511 .get_descriptor = PreProcessingLib_GetDescriptor
Eric Laurenta9390d42011-06-17 20:17:17 -07002512};
2513
2514}; // extern "C"