blob: 19a8b2f9b960f3b0c971e75aabfcb52d4f13e009 [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
Eric Laurenta9390d42011-06-17 20:17:17 -070021#include <audio_effects/effect_aec.h>
22#include <audio_effects/effect_agc.h>
Harish Mahendrakarb6926c72020-11-27 15:22:44 -080023#include <hardware/audio_effect.h>
24#include <utils/Log.h>
25#include <utils/Timers.h>
Saketh Sathuvalli08337032020-09-22 21:13:45 +053026#include <audio_effects/effect_agc2.h>
Eric Laurenta9390d42011-06-17 20:17:17 -070027#include <audio_effects/effect_ns.h>
Eric Laurent53876962012-01-31 12:35:20 -080028#include <audio_processing.h>
Harish Mahendrakarb6926c72020-11-27 15:22:44 -080029#include <module_common_types.h>
Eric Laurenta9390d42011-06-17 20:17:17 -070030
Eric Laurent3f9c84c2012-04-03 15:36:53 -070031// undefine to perform multi channels API functional tests
32//#define DUAL_MIC_TEST
Eric Laurenta9390d42011-06-17 20:17:17 -070033
34//------------------------------------------------------------------------------
35// local definitions
36//------------------------------------------------------------------------------
37
38// maximum number of sessions
39#define PREPROC_NUM_SESSIONS 8
40
41// types of pre processing modules
Harish Mahendrakarb6926c72020-11-27 15:22:44 -080042enum preproc_id {
43 PREPROC_AGC, // Automatic Gain Control
Harish Mahendrakarb6926c72020-11-27 15:22:44 -080044 PREPROC_AGC2, // Automatic Gain Control 2
Harish Mahendrakarb6926c72020-11-27 15:22:44 -080045 PREPROC_AEC, // Acoustic Echo Canceler
46 PREPROC_NS, // Noise Suppressor
Eric Laurenta9390d42011-06-17 20:17:17 -070047 PREPROC_NUM_EFFECTS
48};
49
50// Session state
51enum preproc_session_state {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -080052 PREPROC_SESSION_STATE_INIT, // initialized
53 PREPROC_SESSION_STATE_CONFIG // configuration received
Eric Laurenta9390d42011-06-17 20:17:17 -070054};
55
56// Effect/Preprocessor state
57enum preproc_effect_state {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -080058 PREPROC_EFFECT_STATE_INIT, // initialized
59 PREPROC_EFFECT_STATE_CREATED, // webRTC engine created
60 PREPROC_EFFECT_STATE_CONFIG, // configuration received/disabled
61 PREPROC_EFFECT_STATE_ACTIVE // active/enabled
Eric Laurenta9390d42011-06-17 20:17:17 -070062};
63
64// handle on webRTC engine
65typedef void* preproc_fx_handle_t;
66
67typedef struct preproc_session_s preproc_session_t;
68typedef struct preproc_effect_s preproc_effect_t;
69typedef struct preproc_ops_s preproc_ops_t;
70
71// Effect operation table. Functions for all pre processors are declared in sPreProcOps[] table.
72// Function pointer can be null if no action required.
73struct preproc_ops_s {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -080074 int (*create)(preproc_effect_t* fx);
75 int (*init)(preproc_effect_t* fx);
76 int (*reset)(preproc_effect_t* fx);
77 void (*enable)(preproc_effect_t* fx);
78 void (*disable)(preproc_effect_t* fx);
79 int (*set_parameter)(preproc_effect_t* fx, void* param, void* value);
80 int (*get_parameter)(preproc_effect_t* fx, void* param, uint32_t* size, void* value);
81 int (*set_device)(preproc_effect_t* fx, uint32_t device);
Eric Laurenta9390d42011-06-17 20:17:17 -070082};
83
84// Effect context
85struct preproc_effect_s {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -080086 const struct effect_interface_s* itfe;
87 uint32_t procId; // type of pre processor (enum preproc_id)
88 uint32_t state; // current state (enum preproc_effect_state)
89 preproc_session_t* session; // session the effect is on
90 const preproc_ops_t* ops; // effect ops table
91 preproc_fx_handle_t engine; // handle on webRTC engine
92 uint32_t type; // subtype of effect
Eric Laurent3f9c84c2012-04-03 15:36:53 -070093#ifdef DUAL_MIC_TEST
Harish Mahendrakarb6926c72020-11-27 15:22:44 -080094 bool aux_channels_on; // support auxiliary channels
95 size_t cur_channel_config; // current auciliary channel configuration
Eric Laurent3f9c84c2012-04-03 15:36:53 -070096#endif
Eric Laurenta9390d42011-06-17 20:17:17 -070097};
98
99// Session context
100struct preproc_session_s {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800101 struct preproc_effect_s effects[PREPROC_NUM_EFFECTS]; // effects in this session
102 uint32_t state; // current state (enum preproc_session_state)
103 int id; // audio session ID
104 int io; // handle of input stream this session is on
105 webrtc::AudioProcessing* apm; // handle on webRTC audio processing module (APM)
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530106 // Audio Processing module builder
107 webrtc::AudioProcessingBuilder ap_builder;
Harish Mahendrakard510fdd2021-03-16 13:26:31 -0700108 // frameCount represents the size of the buffers used for processing, and must represent 10ms.
109 size_t frameCount;
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800110 uint32_t samplingRate; // sampling rate at effect process interface
111 uint32_t inChannelCount; // input channel count
112 uint32_t outChannelCount; // output channel count
113 uint32_t createdMsk; // bit field containing IDs of crested pre processors
114 uint32_t enabledMsk; // bit field containing IDs of enabled pre processors
115 uint32_t processedMsk; // bit field containing IDs of pre processors already
116 // processed in current round
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530117 // audio config strucutre
118 webrtc::AudioProcessing::Config config;
119 webrtc::StreamConfig inputConfig; // input stream configuration
120 webrtc::StreamConfig outputConfig; // output stream configuration
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800121 uint32_t revChannelCount; // number of channels on reverse stream
122 uint32_t revEnabledMsk; // bit field containing IDs of enabled pre processors
123 // with reverse channel
124 uint32_t revProcessedMsk; // bit field containing IDs of pre processors with reverse
125 // channel already processed in current round
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530126 webrtc::StreamConfig revConfig; // reverse stream configuration.
Eric Laurenta9390d42011-06-17 20:17:17 -0700127};
128
Eric Laurent3f9c84c2012-04-03 15:36:53 -0700129#ifdef DUAL_MIC_TEST
130enum {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800131 PREPROC_CMD_DUAL_MIC_ENABLE = EFFECT_CMD_FIRST_PROPRIETARY, // enable dual mic mode
132 PREPROC_CMD_DUAL_MIC_PCM_DUMP_START, // start pcm capture
133 PREPROC_CMD_DUAL_MIC_PCM_DUMP_STOP // stop pcm capture
Eric Laurent3f9c84c2012-04-03 15:36:53 -0700134};
135
136enum {
137 CHANNEL_CFG_MONO,
138 CHANNEL_CFG_STEREO,
139 CHANNEL_CFG_MONO_AUX,
140 CHANNEL_CFG_STEREO_AUX,
141 CHANNEL_CFG_CNT,
142 CHANNEL_CFG_FIRST_AUX = CHANNEL_CFG_MONO_AUX,
143};
144
145const channel_config_t sDualMicConfigs[CHANNEL_CFG_CNT] = {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800146 {AUDIO_CHANNEL_IN_MONO, 0},
147 {AUDIO_CHANNEL_IN_STEREO, 0},
148 {AUDIO_CHANNEL_IN_FRONT, AUDIO_CHANNEL_IN_BACK},
149 {AUDIO_CHANNEL_IN_STEREO, AUDIO_CHANNEL_IN_RIGHT}};
Eric Laurent3f9c84c2012-04-03 15:36:53 -0700150
151bool sHasAuxChannels[PREPROC_NUM_EFFECTS] = {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800152 false, // PREPROC_AGC
Eric Laurent3f9c84c2012-04-03 15:36:53 -0700153 true, // PREPROC_AEC
154 true, // PREPROC_NS
155};
156
157bool gDualMicEnabled;
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800158FILE* gPcmDumpFh;
Eric Laurent3f9c84c2012-04-03 15:36:53 -0700159static pthread_mutex_t gPcmDumpLock = PTHREAD_MUTEX_INITIALIZER;
160#endif
161
Eric Laurenta9390d42011-06-17 20:17:17 -0700162//------------------------------------------------------------------------------
163// Effect descriptors
164//------------------------------------------------------------------------------
165
166// UUIDs for effect types have been generated from http://www.itu.int/ITU-T/asn1/uuid.html
167// as the pre processing effects are not defined by OpenSL ES
168
169// Automatic Gain Control
170static const effect_descriptor_t sAgcDescriptor = {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800171 {0x0a8abfe0, 0x654c, 0x11e0, 0xba26, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, // type
172 {0xaa8130e0, 0x66fc, 0x11e0, 0xbad0, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, // uuid
Eric Laurenta9390d42011-06-17 20:17:17 -0700173 EFFECT_CONTROL_API_VERSION,
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800174 (EFFECT_FLAG_TYPE_PRE_PROC | EFFECT_FLAG_DEVICE_IND),
175 0, // FIXME indicate CPU load
176 0, // FIXME indicate memory usage
Eric Laurenta9390d42011-06-17 20:17:17 -0700177 "Automatic Gain Control",
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800178 "The Android Open Source Project"};
Eric Laurenta9390d42011-06-17 20:17:17 -0700179
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530180// Automatic Gain Control 2
181static const effect_descriptor_t sAgc2Descriptor = {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800182 {0xae3c653b, 0xbe18, 0x4ab8, 0x8938, {0x41, 0x8f, 0x0a, 0x7f, 0x06, 0xac}}, // type
183 {0x89f38e65, 0xd4d2, 0x4d64, 0xad0e, {0x2b, 0x3e, 0x79, 0x9e, 0xa8, 0x86}}, // uuid
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530184 EFFECT_CONTROL_API_VERSION,
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800185 (EFFECT_FLAG_TYPE_PRE_PROC | EFFECT_FLAG_DEVICE_IND),
186 0, // FIXME indicate CPU load
187 0, // FIXME indicate memory usage
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530188 "Automatic Gain Control 2",
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800189 "The Android Open Source Project"};
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530190
Eric Laurenta9390d42011-06-17 20:17:17 -0700191// Acoustic Echo Cancellation
192static const effect_descriptor_t sAecDescriptor = {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800193 {0x7b491460, 0x8d4d, 0x11e0, 0xbd61, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, // type
194 {0xbb392ec0, 0x8d4d, 0x11e0, 0xa896, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, // uuid
Eric Laurenta9390d42011-06-17 20:17:17 -0700195 EFFECT_CONTROL_API_VERSION,
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800196 (EFFECT_FLAG_TYPE_PRE_PROC | EFFECT_FLAG_DEVICE_IND),
197 0, // FIXME indicate CPU load
198 0, // FIXME indicate memory usage
Eric Laurenta9390d42011-06-17 20:17:17 -0700199 "Acoustic Echo Canceler",
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800200 "The Android Open Source Project"};
Eric Laurenta9390d42011-06-17 20:17:17 -0700201
202// Noise suppression
203static const effect_descriptor_t sNsDescriptor = {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800204 {0x58b4b260, 0x8e06, 0x11e0, 0xaa8e, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, // type
205 {0xc06c8400, 0x8e06, 0x11e0, 0x9cb6, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, // uuid
Eric Laurenta9390d42011-06-17 20:17:17 -0700206 EFFECT_CONTROL_API_VERSION,
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800207 (EFFECT_FLAG_TYPE_PRE_PROC | EFFECT_FLAG_DEVICE_IND),
208 0, // FIXME indicate CPU load
209 0, // FIXME indicate memory usage
Eric Laurenta9390d42011-06-17 20:17:17 -0700210 "Noise Suppression",
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800211 "The Android Open Source Project"};
Eric Laurenta9390d42011-06-17 20:17:17 -0700212
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800213static const effect_descriptor_t* sDescriptors[PREPROC_NUM_EFFECTS] = {&sAgcDescriptor,
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800214 &sAgc2Descriptor,
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800215 &sAecDescriptor,
216 &sNsDescriptor};
Eric Laurenta9390d42011-06-17 20:17:17 -0700217
218//------------------------------------------------------------------------------
219// Helper functions
220//------------------------------------------------------------------------------
221
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800222const effect_uuid_t* const sUuidToPreProcTable[PREPROC_NUM_EFFECTS] = {FX_IID_AGC,
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800223 FX_IID_AGC2,
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800224 FX_IID_AEC, FX_IID_NS};
Eric Laurenta9390d42011-06-17 20:17:17 -0700225
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800226const effect_uuid_t* ProcIdToUuid(int procId) {
Eric Laurenta9390d42011-06-17 20:17:17 -0700227 if (procId >= PREPROC_NUM_EFFECTS) {
228 return EFFECT_UUID_NULL;
229 }
230 return sUuidToPreProcTable[procId];
231}
232
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800233uint32_t UuidToProcId(const effect_uuid_t* uuid) {
Eric Laurenta9390d42011-06-17 20:17:17 -0700234 size_t i;
235 for (i = 0; i < PREPROC_NUM_EFFECTS; i++) {
236 if (memcmp(uuid, sUuidToPreProcTable[i], sizeof(*uuid)) == 0) {
237 break;
238 }
239 }
240 return i;
241}
242
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800243bool HasReverseStream(uint32_t procId) {
Eric Laurenta9390d42011-06-17 20:17:17 -0700244 if (procId == PREPROC_AEC) {
245 return true;
246 }
247 return false;
248}
249
Eric Laurenta9390d42011-06-17 20:17:17 -0700250//------------------------------------------------------------------------------
251// Automatic Gain Control (AGC)
252//------------------------------------------------------------------------------
253
Eric Laurent53876962012-01-31 12:35:20 -0800254static const int kAgcDefaultTargetLevel = 3;
255static const int kAgcDefaultCompGain = 9;
Eric Laurenta9390d42011-06-17 20:17:17 -0700256static const bool kAgcDefaultLimiter = true;
257
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800258int Agc2Init(preproc_effect_t* effect) {
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530259 ALOGV("Agc2Init");
260 effect->session->config = effect->session->apm->GetConfig();
261 effect->session->config.gain_controller2.fixed_digital.gain_db = 0.f;
262 effect->session->config.gain_controller2.adaptive_digital.level_estimator =
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800263 effect->session->config.gain_controller2.kRms;
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530264 effect->session->config.gain_controller2.adaptive_digital.extra_saturation_margin_db = 2.f;
265 effect->session->apm->ApplyConfig(effect->session->config);
266 return 0;
267}
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530268
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800269int AgcInit(preproc_effect_t* effect) {
Steve Block3856b092011-10-20 11:56:00 +0100270 ALOGV("AgcInit");
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530271 effect->session->config = effect->session->apm->GetConfig();
272 effect->session->config.gain_controller1.target_level_dbfs = kAgcDefaultTargetLevel;
273 effect->session->config.gain_controller1.compression_gain_db = kAgcDefaultCompGain;
274 effect->session->config.gain_controller1.enable_limiter = kAgcDefaultLimiter;
275 effect->session->apm->ApplyConfig(effect->session->config);
Eric Laurenta9390d42011-06-17 20:17:17 -0700276 return 0;
277}
278
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800279int Agc2Create(preproc_effect_t* effect) {
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530280 Agc2Init(effect);
281 return 0;
282}
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530283
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800284int AgcCreate(preproc_effect_t* effect) {
Eric Laurenta9390d42011-06-17 20:17:17 -0700285 AgcInit(effect);
286 return 0;
287}
288
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800289int Agc2GetParameter(preproc_effect_t* effect, void* pParam, uint32_t* pValueSize, void* pValue) {
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530290 int status = 0;
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800291 uint32_t param = *(uint32_t*)pParam;
292 agc2_settings_t* pProperties = (agc2_settings_t*)pValue;
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530293
294 switch (param) {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800295 case AGC2_PARAM_FIXED_DIGITAL_GAIN:
296 if (*pValueSize < sizeof(float)) {
297 *pValueSize = 0.f;
298 return -EINVAL;
299 }
300 break;
301 case AGC2_PARAM_ADAPT_DIGI_LEVEL_ESTIMATOR:
302 if (*pValueSize < sizeof(int32_t)) {
303 *pValueSize = 0;
304 return -EINVAL;
305 }
306 break;
307 case AGC2_PARAM_ADAPT_DIGI_EXTRA_SATURATION_MARGIN:
308 if (*pValueSize < sizeof(float)) {
309 *pValueSize = 0.f;
310 return -EINVAL;
311 }
312 break;
313 case AGC2_PARAM_PROPERTIES:
314 if (*pValueSize < sizeof(agc2_settings_t)) {
315 *pValueSize = 0;
316 return -EINVAL;
317 }
318 break;
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530319
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800320 default:
321 ALOGW("Agc2GetParameter() unknown param %08x", param);
322 status = -EINVAL;
323 break;
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530324 }
325
326 effect->session->config = effect->session->apm->GetConfig();
327 switch (param) {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800328 case AGC2_PARAM_FIXED_DIGITAL_GAIN:
329 *(float*)pValue =
330 (float)(effect->session->config.gain_controller2.fixed_digital.gain_db);
331 ALOGV("Agc2GetParameter() target level %f dB", *(float*)pValue);
332 break;
333 case AGC2_PARAM_ADAPT_DIGI_LEVEL_ESTIMATOR:
334 *(uint32_t*)pValue = (uint32_t)(
335 effect->session->config.gain_controller2.adaptive_digital.level_estimator);
336 ALOGV("Agc2GetParameter() level estimator %d",
337 *(webrtc::AudioProcessing::Config::GainController2::LevelEstimator*)pValue);
338 break;
339 case AGC2_PARAM_ADAPT_DIGI_EXTRA_SATURATION_MARGIN:
340 *(float*)pValue = (float)(effect->session->config.gain_controller2.adaptive_digital
341 .extra_saturation_margin_db);
342 ALOGV("Agc2GetParameter() extra saturation margin %f dB", *(float*)pValue);
343 break;
344 case AGC2_PARAM_PROPERTIES:
345 pProperties->fixedDigitalGain =
346 (float)(effect->session->config.gain_controller2.fixed_digital.gain_db);
347 pProperties->level_estimator = (uint32_t)(
348 effect->session->config.gain_controller2.adaptive_digital.level_estimator);
349 pProperties->extraSaturationMargin =
350 (float)(effect->session->config.gain_controller2.adaptive_digital
351 .extra_saturation_margin_db);
352 break;
353 default:
354 ALOGW("Agc2GetParameter() unknown param %d", param);
355 status = -EINVAL;
356 break;
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530357 }
358
359 return status;
360}
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530361
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800362int AgcGetParameter(preproc_effect_t* effect, void* pParam, uint32_t* pValueSize, void* pValue) {
Eric Laurenta9390d42011-06-17 20:17:17 -0700363 int status = 0;
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800364 uint32_t param = *(uint32_t*)pParam;
365 t_agc_settings* pProperties = (t_agc_settings*)pValue;
Eric Laurenta9390d42011-06-17 20:17:17 -0700366
367 switch (param) {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800368 case AGC_PARAM_TARGET_LEVEL:
369 case AGC_PARAM_COMP_GAIN:
370 if (*pValueSize < sizeof(int16_t)) {
371 *pValueSize = 0;
372 return -EINVAL;
373 }
374 break;
375 case AGC_PARAM_LIMITER_ENA:
376 if (*pValueSize < sizeof(bool)) {
377 *pValueSize = 0;
378 return -EINVAL;
379 }
380 break;
381 case AGC_PARAM_PROPERTIES:
382 if (*pValueSize < sizeof(t_agc_settings)) {
383 *pValueSize = 0;
384 return -EINVAL;
385 }
386 break;
Eric Laurenta9390d42011-06-17 20:17:17 -0700387
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800388 default:
389 ALOGW("AgcGetParameter() unknown param %08x", param);
390 status = -EINVAL;
391 break;
Eric Laurenta9390d42011-06-17 20:17:17 -0700392 }
393
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530394 effect->session->config = effect->session->apm->GetConfig();
395 switch (param) {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800396 case AGC_PARAM_TARGET_LEVEL:
397 *(int16_t*)pValue =
398 (int16_t)(effect->session->config.gain_controller1.target_level_dbfs * -100);
399 ALOGV("AgcGetParameter() target level %d milliBels", *(int16_t*)pValue);
400 break;
401 case AGC_PARAM_COMP_GAIN:
402 *(int16_t*)pValue =
403 (int16_t)(effect->session->config.gain_controller1.compression_gain_db * -100);
404 ALOGV("AgcGetParameter() comp gain %d milliBels", *(int16_t*)pValue);
405 break;
406 case AGC_PARAM_LIMITER_ENA:
407 *(bool*)pValue = (bool)(effect->session->config.gain_controller1.enable_limiter);
408 ALOGV("AgcGetParameter() limiter enabled %s",
409 (*(int16_t*)pValue != 0) ? "true" : "false");
410 break;
411 case AGC_PARAM_PROPERTIES:
412 pProperties->targetLevel =
413 (int16_t)(effect->session->config.gain_controller1.target_level_dbfs * -100);
414 pProperties->compGain =
415 (int16_t)(effect->session->config.gain_controller1.compression_gain_db * -100);
416 pProperties->limiterEnabled =
417 (bool)(effect->session->config.gain_controller1.enable_limiter);
418 break;
419 default:
420 ALOGW("AgcGetParameter() unknown param %d", param);
421 status = -EINVAL;
422 break;
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530423 }
Eric Laurenta9390d42011-06-17 20:17:17 -0700424 return status;
425}
426
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800427int Agc2SetParameter(preproc_effect_t* effect, void* pParam, void* pValue) {
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530428 int status = 0;
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800429 uint32_t param = *(uint32_t*)pParam;
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530430 float valueFloat = 0.f;
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800431 agc2_settings_t* pProperties = (agc2_settings_t*)pValue;
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530432 effect->session->config = effect->session->apm->GetConfig();
433 switch (param) {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800434 case AGC2_PARAM_FIXED_DIGITAL_GAIN:
435 valueFloat = (float)(*(int32_t*)pValue);
436 ALOGV("Agc2SetParameter() fixed digital gain %f dB", valueFloat);
437 effect->session->config.gain_controller2.fixed_digital.gain_db = valueFloat;
438 break;
439 case AGC2_PARAM_ADAPT_DIGI_LEVEL_ESTIMATOR:
440 ALOGV("Agc2SetParameter() level estimator %d",
441 *(webrtc::AudioProcessing::Config::GainController2::LevelEstimator*)pValue);
442 effect->session->config.gain_controller2.adaptive_digital.level_estimator =
443 (*(webrtc::AudioProcessing::Config::GainController2::LevelEstimator*)pValue);
444 break;
445 case AGC2_PARAM_ADAPT_DIGI_EXTRA_SATURATION_MARGIN:
446 valueFloat = (float)(*(int32_t*)pValue);
447 ALOGV("Agc2SetParameter() extra saturation margin %f dB", valueFloat);
448 effect->session->config.gain_controller2.adaptive_digital.extra_saturation_margin_db =
449 valueFloat;
450 break;
451 case AGC2_PARAM_PROPERTIES:
452 ALOGV("Agc2SetParameter() properties gain %f, level %d margin %f",
453 pProperties->fixedDigitalGain, pProperties->level_estimator,
454 pProperties->extraSaturationMargin);
455 effect->session->config.gain_controller2.fixed_digital.gain_db =
456 pProperties->fixedDigitalGain;
457 effect->session->config.gain_controller2.adaptive_digital.level_estimator =
458 (webrtc::AudioProcessing::Config::GainController2::LevelEstimator)
459 pProperties->level_estimator;
460 effect->session->config.gain_controller2.adaptive_digital.extra_saturation_margin_db =
461 pProperties->extraSaturationMargin;
462 break;
463 default:
464 ALOGW("Agc2SetParameter() unknown param %08x value %08x", param, *(uint32_t*)pValue);
465 status = -EINVAL;
466 break;
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530467 }
468 effect->session->apm->ApplyConfig(effect->session->config);
469
470 ALOGV("Agc2SetParameter() done status %d", status);
471
472 return status;
473}
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530474
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800475int AgcSetParameter(preproc_effect_t* effect, void* pParam, void* pValue) {
Eric Laurenta9390d42011-06-17 20:17:17 -0700476 int status = 0;
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800477 uint32_t param = *(uint32_t*)pParam;
478 t_agc_settings* pProperties = (t_agc_settings*)pValue;
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530479 effect->session->config = effect->session->apm->GetConfig();
480 switch (param) {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800481 case AGC_PARAM_TARGET_LEVEL:
482 ALOGV("AgcSetParameter() target level %d milliBels", *(int16_t*)pValue);
483 effect->session->config.gain_controller1.target_level_dbfs =
484 (-(*(int16_t*)pValue / 100));
485 break;
486 case AGC_PARAM_COMP_GAIN:
487 ALOGV("AgcSetParameter() comp gain %d milliBels", *(int16_t*)pValue);
488 effect->session->config.gain_controller1.compression_gain_db =
489 (*(int16_t*)pValue / 100);
490 break;
491 case AGC_PARAM_LIMITER_ENA:
492 ALOGV("AgcSetParameter() limiter enabled %s", *(bool*)pValue ? "true" : "false");
493 effect->session->config.gain_controller1.enable_limiter = (*(bool*)pValue);
494 break;
495 case AGC_PARAM_PROPERTIES:
496 ALOGV("AgcSetParameter() properties level %d, gain %d limiter %d",
497 pProperties->targetLevel, pProperties->compGain, pProperties->limiterEnabled);
498 effect->session->config.gain_controller1.target_level_dbfs =
499 -(pProperties->targetLevel / 100);
500 effect->session->config.gain_controller1.compression_gain_db =
501 pProperties->compGain / 100;
502 effect->session->config.gain_controller1.enable_limiter = pProperties->limiterEnabled;
503 break;
504 default:
505 ALOGW("AgcSetParameter() unknown param %08x value %08x", param, *(uint32_t*)pValue);
506 status = -EINVAL;
507 break;
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530508 }
509 effect->session->apm->ApplyConfig(effect->session->config);
Eric Laurenta9390d42011-06-17 20:17:17 -0700510
Steve Block3856b092011-10-20 11:56:00 +0100511 ALOGV("AgcSetParameter() done status %d", status);
Eric Laurenta9390d42011-06-17 20:17:17 -0700512
513 return status;
514}
515
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800516void Agc2Enable(preproc_effect_t* effect) {
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530517 effect->session->config = effect->session->apm->GetConfig();
518 effect->session->config.gain_controller2.enabled = true;
519 effect->session->apm->ApplyConfig(effect->session->config);
520}
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530521
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800522void AgcEnable(preproc_effect_t* effect) {
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530523 effect->session->config = effect->session->apm->GetConfig();
524 effect->session->config.gain_controller1.enabled = true;
525 effect->session->apm->ApplyConfig(effect->session->config);
Eric Laurenta9390d42011-06-17 20:17:17 -0700526}
527
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800528void Agc2Disable(preproc_effect_t* effect) {
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530529 effect->session->config = effect->session->apm->GetConfig();
530 effect->session->config.gain_controller2.enabled = false;
531 effect->session->apm->ApplyConfig(effect->session->config);
532}
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530533
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800534void AgcDisable(preproc_effect_t* effect) {
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530535 effect->session->config = effect->session->apm->GetConfig();
536 effect->session->config.gain_controller1.enabled = false;
537 effect->session->apm->ApplyConfig(effect->session->config);
Eric Laurenta9390d42011-06-17 20:17:17 -0700538}
539
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800540static const preproc_ops_t sAgcOps = {AgcCreate, AgcInit, NULL, AgcEnable, AgcDisable,
541 AgcSetParameter, AgcGetParameter, NULL};
Eric Laurenta9390d42011-06-17 20:17:17 -0700542
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800543static const preproc_ops_t sAgc2Ops = {Agc2Create, Agc2Init, NULL,
544 Agc2Enable, Agc2Disable, Agc2SetParameter,
545 Agc2GetParameter, NULL};
Eric Laurenta9390d42011-06-17 20:17:17 -0700546
547//------------------------------------------------------------------------------
548// Acoustic Echo Canceler (AEC)
549//------------------------------------------------------------------------------
550
Eric Laurenta9390d42011-06-17 20:17:17 -0700551
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800552int AecInit(preproc_effect_t* effect) {
Steve Block3856b092011-10-20 11:56:00 +0100553 ALOGV("AecInit");
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800554 effect->session->config = effect->session->apm->GetConfig();
Rivukanta Bhattacharyac4c54172020-11-25 23:55:44 +0530555 effect->session->config.echo_canceller.mobile_mode = true;
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530556 effect->session->apm->ApplyConfig(effect->session->config);
Eric Laurenta9390d42011-06-17 20:17:17 -0700557 return 0;
558}
559
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800560int AecCreate(preproc_effect_t* effect) {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800561 AecInit(effect);
Eric Laurenta9390d42011-06-17 20:17:17 -0700562 return 0;
563}
564
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800565int AecGetParameter(preproc_effect_t* effect, void* pParam, uint32_t* pValueSize, void* pValue) {
Eric Laurenta9390d42011-06-17 20:17:17 -0700566 int status = 0;
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800567 uint32_t param = *(uint32_t*)pParam;
Eric Laurenta9390d42011-06-17 20:17:17 -0700568
569 if (*pValueSize < sizeof(uint32_t)) {
570 return -EINVAL;
571 }
572 switch (param) {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800573 case AEC_PARAM_ECHO_DELAY:
574 case AEC_PARAM_PROPERTIES:
575 *(uint32_t*)pValue = 1000 * effect->session->apm->stream_delay_ms();
576 ALOGV("AecGetParameter() echo delay %d us", *(uint32_t*)pValue);
577 break;
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800578 case AEC_PARAM_MOBILE_MODE:
579 effect->session->config = effect->session->apm->GetConfig();
580 *(uint32_t*)pValue = effect->session->config.echo_canceller.mobile_mode;
581 ALOGV("AecGetParameter() mobile mode %d us", *(uint32_t*)pValue);
582 break;
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800583 default:
584 ALOGW("AecGetParameter() unknown param %08x value %08x", param, *(uint32_t*)pValue);
585 status = -EINVAL;
586 break;
Eric Laurenta9390d42011-06-17 20:17:17 -0700587 }
588 return status;
589}
590
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800591int AecSetParameter(preproc_effect_t* effect, void* pParam, void* pValue) {
Eric Laurenta9390d42011-06-17 20:17:17 -0700592 int status = 0;
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800593 uint32_t param = *(uint32_t*)pParam;
594 uint32_t value = *(uint32_t*)pValue;
Eric Laurenta9390d42011-06-17 20:17:17 -0700595
596 switch (param) {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800597 case AEC_PARAM_ECHO_DELAY:
598 case AEC_PARAM_PROPERTIES:
599 status = effect->session->apm->set_stream_delay_ms(value / 1000);
600 ALOGV("AecSetParameter() echo delay %d us, status %d", value, status);
601 break;
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800602 case AEC_PARAM_MOBILE_MODE:
603 effect->session->config = effect->session->apm->GetConfig();
604 effect->session->config.echo_canceller.mobile_mode = value;
605 ALOGV("AecSetParameter() mobile mode %d us", value);
606 effect->session->apm->ApplyConfig(effect->session->config);
607 break;
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800608 default:
609 ALOGW("AecSetParameter() unknown param %08x value %08x", param, *(uint32_t*)pValue);
610 status = -EINVAL;
611 break;
Eric Laurenta9390d42011-06-17 20:17:17 -0700612 }
613 return status;
614}
615
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800616void AecEnable(preproc_effect_t* effect) {
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530617 effect->session->config = effect->session->apm->GetConfig();
618 effect->session->config.echo_canceller.enabled = true;
619 effect->session->apm->ApplyConfig(effect->session->config);
Eric Laurenta9390d42011-06-17 20:17:17 -0700620}
621
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800622void AecDisable(preproc_effect_t* effect) {
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530623 effect->session->config = effect->session->apm->GetConfig();
624 effect->session->config.echo_canceller.enabled = false;
625 effect->session->apm->ApplyConfig(effect->session->config);
Eric Laurenta9390d42011-06-17 20:17:17 -0700626}
627
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800628int AecSetDevice(preproc_effect_t* effect, uint32_t device) {
Steve Block3856b092011-10-20 11:56:00 +0100629 ALOGV("AecSetDevice %08x", device);
Eric Laurenta9390d42011-06-17 20:17:17 -0700630
Eric Laurent88959252012-08-28 14:26:53 -0700631 if (audio_is_input_device(device)) {
632 return 0;
633 }
634
Eric Laurenta9390d42011-06-17 20:17:17 -0700635 return 0;
636}
637
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800638static const preproc_ops_t sAecOps = {AecCreate, AecInit, NULL,
639 AecEnable, AecDisable, AecSetParameter,
640 AecGetParameter, AecSetDevice};
Eric Laurenta9390d42011-06-17 20:17:17 -0700641
642//------------------------------------------------------------------------------
643// Noise Suppression (NS)
644//------------------------------------------------------------------------------
645
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530646static const webrtc::AudioProcessing::Config::NoiseSuppression::Level kNsDefaultLevel =
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800647 webrtc::AudioProcessing::Config::NoiseSuppression::kModerate;
Eric Laurenta9390d42011-06-17 20:17:17 -0700648
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800649int NsInit(preproc_effect_t* effect) {
Steve Block3856b092011-10-20 11:56:00 +0100650 ALOGV("NsInit");
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800651 effect->session->config = effect->session->apm->GetConfig();
652 effect->session->config.noise_suppression.level = kNsDefaultLevel;
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530653 effect->session->apm->ApplyConfig(effect->session->config);
Alex Luebs766bf732015-12-14 21:32:13 -0800654 effect->type = NS_TYPE_SINGLE_CHANNEL;
Eric Laurenta9390d42011-06-17 20:17:17 -0700655 return 0;
656}
657
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800658int NsCreate(preproc_effect_t* effect) {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800659 NsInit(effect);
Eric Laurenta9390d42011-06-17 20:17:17 -0700660 return 0;
661}
662
Rivukanta Bhattacharya013e02e2021-03-12 05:50:55 +0530663int NsGetParameter(preproc_effect_t* /*effect __unused*/, void* /*pParam __unused*/,
664 uint32_t* /*pValueSize __unused*/, void* /*pValue __unused*/) {
Eric Laurenta9390d42011-06-17 20:17:17 -0700665 int status = 0;
666 return status;
667}
668
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800669int NsSetParameter(preproc_effect_t* effect, void* pParam, void* pValue) {
Eric Laurenta9390d42011-06-17 20:17:17 -0700670 int status = 0;
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800671 uint32_t param = *(uint32_t*)pParam;
672 uint32_t value = *(uint32_t*)pValue;
673 effect->session->config = effect->session->apm->GetConfig();
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530674 switch (param) {
675 case NS_PARAM_LEVEL:
676 effect->session->config.noise_suppression.level =
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800677 (webrtc::AudioProcessing::Config::NoiseSuppression::Level)value;
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530678 ALOGV("NsSetParameter() level %d", value);
679 break;
680 default:
681 ALOGW("NsSetParameter() unknown param %08x value %08x", param, value);
682 status = -EINVAL;
683 }
684 effect->session->apm->ApplyConfig(effect->session->config);
Alex Luebs766bf732015-12-14 21:32:13 -0800685
Eric Laurenta9390d42011-06-17 20:17:17 -0700686 return status;
687}
688
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800689void NsEnable(preproc_effect_t* effect) {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800690 effect->session->config = effect->session->apm->GetConfig();
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530691 effect->session->config.noise_suppression.enabled = true;
692 effect->session->apm->ApplyConfig(effect->session->config);
Eric Laurenta9390d42011-06-17 20:17:17 -0700693}
694
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800695void NsDisable(preproc_effect_t* effect) {
Steve Block3856b092011-10-20 11:56:00 +0100696 ALOGV("NsDisable");
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800697 effect->session->config = effect->session->apm->GetConfig();
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530698 effect->session->config.noise_suppression.enabled = false;
699 effect->session->apm->ApplyConfig(effect->session->config);
Eric Laurenta9390d42011-06-17 20:17:17 -0700700}
701
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800702static const preproc_ops_t sNsOps = {NsCreate, NsInit, NULL, NsEnable,
703 NsDisable, NsSetParameter, NsGetParameter, NULL};
Eric Laurenta9390d42011-06-17 20:17:17 -0700704
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800705static const preproc_ops_t* sPreProcOps[PREPROC_NUM_EFFECTS] = {&sAgcOps,
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800706 &sAgc2Ops,
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800707 &sAecOps, &sNsOps};
Eric Laurenta9390d42011-06-17 20:17:17 -0700708
709//------------------------------------------------------------------------------
710// Effect functions
711//------------------------------------------------------------------------------
712
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800713void Session_SetProcEnabled(preproc_session_t* session, uint32_t procId, bool enabled);
Eric Laurenta9390d42011-06-17 20:17:17 -0700714
715extern "C" const struct effect_interface_s sEffectInterface;
716extern "C" const struct effect_interface_s sEffectInterfaceReverse;
717
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800718#define BAD_STATE_ABORT(from, to) LOG_ALWAYS_FATAL("Bad state transition from %d to %d", from, to);
Eric Laurenta9390d42011-06-17 20:17:17 -0700719
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800720int Effect_SetState(preproc_effect_t* effect, uint32_t state) {
Eric Laurenta9390d42011-06-17 20:17:17 -0700721 int status = 0;
Steve Block3856b092011-10-20 11:56:00 +0100722 ALOGV("Effect_SetState proc %d, new %d old %d", effect->procId, state, effect->state);
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800723 switch (state) {
724 case PREPROC_EFFECT_STATE_INIT:
725 switch (effect->state) {
726 case PREPROC_EFFECT_STATE_ACTIVE:
727 effect->ops->disable(effect);
728 Session_SetProcEnabled(effect->session, effect->procId, false);
729 break;
730 case PREPROC_EFFECT_STATE_CONFIG:
731 case PREPROC_EFFECT_STATE_CREATED:
732 case PREPROC_EFFECT_STATE_INIT:
733 break;
734 default:
735 BAD_STATE_ABORT(effect->state, state);
736 }
737 break;
738 case PREPROC_EFFECT_STATE_CREATED:
739 switch (effect->state) {
740 case PREPROC_EFFECT_STATE_INIT:
741 status = effect->ops->create(effect);
742 break;
743 case PREPROC_EFFECT_STATE_CREATED:
744 case PREPROC_EFFECT_STATE_ACTIVE:
745 case PREPROC_EFFECT_STATE_CONFIG:
746 ALOGE("Effect_SetState invalid transition");
747 status = -ENOSYS;
748 break;
749 default:
750 BAD_STATE_ABORT(effect->state, state);
751 }
Andy Hung320fd852018-10-09 14:06:37 -0700752 break;
Eric Laurenta9390d42011-06-17 20:17:17 -0700753 case PREPROC_EFFECT_STATE_CONFIG:
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800754 switch (effect->state) {
755 case PREPROC_EFFECT_STATE_INIT:
756 ALOGE("Effect_SetState invalid transition");
757 status = -ENOSYS;
758 break;
759 case PREPROC_EFFECT_STATE_ACTIVE:
760 effect->ops->disable(effect);
761 Session_SetProcEnabled(effect->session, effect->procId, false);
762 break;
763 case PREPROC_EFFECT_STATE_CREATED:
764 case PREPROC_EFFECT_STATE_CONFIG:
765 break;
766 default:
767 BAD_STATE_ABORT(effect->state, state);
768 }
769 break;
770 case PREPROC_EFFECT_STATE_ACTIVE:
771 switch (effect->state) {
772 case PREPROC_EFFECT_STATE_INIT:
773 case PREPROC_EFFECT_STATE_CREATED:
774 ALOGE("Effect_SetState invalid transition");
775 status = -ENOSYS;
776 break;
777 case PREPROC_EFFECT_STATE_ACTIVE:
778 // enabling an already enabled effect is just ignored
779 break;
780 case PREPROC_EFFECT_STATE_CONFIG:
781 effect->ops->enable(effect);
782 Session_SetProcEnabled(effect->session, effect->procId, true);
783 break;
784 default:
785 BAD_STATE_ABORT(effect->state, state);
786 }
Eric Laurenta9390d42011-06-17 20:17:17 -0700787 break;
788 default:
789 BAD_STATE_ABORT(effect->state, state);
Eric Laurenta9390d42011-06-17 20:17:17 -0700790 }
791 if (status == 0) {
792 effect->state = state;
793 }
794 return status;
795}
796
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800797int Effect_Init(preproc_effect_t* effect, uint32_t procId) {
Eric Laurenta9390d42011-06-17 20:17:17 -0700798 if (HasReverseStream(procId)) {
799 effect->itfe = &sEffectInterfaceReverse;
800 } else {
801 effect->itfe = &sEffectInterface;
802 }
803 effect->ops = sPreProcOps[procId];
804 effect->procId = procId;
805 effect->state = PREPROC_EFFECT_STATE_INIT;
806 return 0;
807}
808
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800809int Effect_Create(preproc_effect_t* effect, preproc_session_t* session,
810 effect_handle_t* interface) {
Eric Laurenta9390d42011-06-17 20:17:17 -0700811 effect->session = session;
812 *interface = (effect_handle_t)&effect->itfe;
813 return Effect_SetState(effect, PREPROC_EFFECT_STATE_CREATED);
814}
815
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800816int Effect_Release(preproc_effect_t* effect) {
Eric Laurenta9390d42011-06-17 20:17:17 -0700817 return Effect_SetState(effect, PREPROC_EFFECT_STATE_INIT);
818}
819
Eric Laurenta9390d42011-06-17 20:17:17 -0700820//------------------------------------------------------------------------------
821// Session functions
822//------------------------------------------------------------------------------
823
824#define RESAMPLER_QUALITY SPEEX_RESAMPLER_QUALITY_VOIP
825
826static const int kPreprocDefaultSr = 16000;
827static const int kPreProcDefaultCnl = 1;
828
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800829int Session_Init(preproc_session_t* session) {
Eric Laurenta9390d42011-06-17 20:17:17 -0700830 size_t i;
831 int status = 0;
832
833 session->state = PREPROC_SESSION_STATE_INIT;
834 session->id = 0;
835 session->io = 0;
836 session->createdMsk = 0;
Eric Laurenta9390d42011-06-17 20:17:17 -0700837 for (i = 0; i < PREPROC_NUM_EFFECTS && status == 0; i++) {
838 status = Effect_Init(&session->effects[i], i);
839 }
840 return status;
841}
842
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800843extern "C" int Session_CreateEffect(preproc_session_t* session, int32_t procId,
844 effect_handle_t* interface) {
Eric Laurenta9390d42011-06-17 20:17:17 -0700845 int status = -ENOMEM;
846
Steve Block3856b092011-10-20 11:56:00 +0100847 ALOGV("Session_CreateEffect procId %d, createdMsk %08x", procId, session->createdMsk);
Eric Laurenta9390d42011-06-17 20:17:17 -0700848
849 if (session->createdMsk == 0) {
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530850 session->apm = session->ap_builder.Create();
851 if (session->apm == NULL) {
852 ALOGW("Session_CreateEffect could not get apm engine");
853 goto error;
854 }
Harish Mahendrakard510fdd2021-03-16 13:26:31 -0700855 session->frameCount = kPreprocDefaultSr / 100;
Eric Laurenta9390d42011-06-17 20:17:17 -0700856 session->samplingRate = kPreprocDefaultSr;
857 session->inChannelCount = kPreProcDefaultCnl;
858 session->outChannelCount = kPreProcDefaultCnl;
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530859 session->inputConfig.set_sample_rate_hz(kPreprocDefaultSr);
860 session->inputConfig.set_num_channels(kPreProcDefaultCnl);
861 session->outputConfig.set_sample_rate_hz(kPreprocDefaultSr);
862 session->outputConfig.set_num_channels(kPreProcDefaultCnl);
Eric Laurenta9390d42011-06-17 20:17:17 -0700863 session->revChannelCount = kPreProcDefaultCnl;
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530864 session->revConfig.set_sample_rate_hz(kPreprocDefaultSr);
865 session->revConfig.set_num_channels(kPreProcDefaultCnl);
Eric Laurenta9390d42011-06-17 20:17:17 -0700866 session->enabledMsk = 0;
867 session->processedMsk = 0;
868 session->revEnabledMsk = 0;
869 session->revProcessedMsk = 0;
Eric Laurenta9390d42011-06-17 20:17:17 -0700870 }
871 status = Effect_Create(&session->effects[procId], session, interface);
872 if (status < 0) {
873 goto error;
874 }
Steve Block3856b092011-10-20 11:56:00 +0100875 ALOGV("Session_CreateEffect OK");
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800876 session->createdMsk |= (1 << procId);
Eric Laurenta9390d42011-06-17 20:17:17 -0700877 return status;
878
879error:
880 if (session->createdMsk == 0) {
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530881 delete session->apm;
882 session->apm = NULL;
Eric Laurenta9390d42011-06-17 20:17:17 -0700883 }
884 return status;
885}
886
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800887int Session_ReleaseEffect(preproc_session_t* session, preproc_effect_t* fx) {
Steve Block5ff1dd52012-01-05 23:22:43 +0000888 ALOGW_IF(Effect_Release(fx) != 0, " Effect_Release() failed for proc ID %d", fx->procId);
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800889 session->createdMsk &= ~(1 << fx->procId);
Eric Laurenta9390d42011-06-17 20:17:17 -0700890 if (session->createdMsk == 0) {
Alex Luebs9718b7d2015-11-24 14:33:14 -0800891 delete session->apm;
Eric Laurenta9390d42011-06-17 20:17:17 -0700892 session->apm = NULL;
Eric Laurentb20cf7d2019-04-05 19:37:34 -0700893 session->id = 0;
Eric Laurenta9390d42011-06-17 20:17:17 -0700894 }
895
896 return 0;
897}
898
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800899int Session_SetConfig(preproc_session_t* session, effect_config_t* config) {
Alex Luebs3f11ef02016-01-15 15:51:58 -0800900 uint32_t inCnl = audio_channel_count_from_in_mask(config->inputCfg.channels);
901 uint32_t outCnl = audio_channel_count_from_in_mask(config->outputCfg.channels);
Eric Laurenta9390d42011-06-17 20:17:17 -0700902
903 if (config->inputCfg.samplingRate != config->outputCfg.samplingRate ||
904 config->inputCfg.format != config->outputCfg.format ||
905 config->inputCfg.format != AUDIO_FORMAT_PCM_16_BIT) {
906 return -EINVAL;
907 }
908
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800909 ALOGV("Session_SetConfig sr %d cnl %08x", config->inputCfg.samplingRate,
910 config->inputCfg.channels);
Eric Laurenta9390d42011-06-17 20:17:17 -0700911
Eric Laurenta9390d42011-06-17 20:17:17 -0700912 session->samplingRate = config->inputCfg.samplingRate;
Harish Mahendrakard510fdd2021-03-16 13:26:31 -0700913 session->frameCount = session->samplingRate / 100;
Eric Laurenta9390d42011-06-17 20:17:17 -0700914 session->inChannelCount = inCnl;
915 session->outChannelCount = outCnl;
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530916 session->inputConfig.set_sample_rate_hz(session->samplingRate);
917 session->inputConfig.set_num_channels(inCnl);
918 session->outputConfig.set_sample_rate_hz(session->samplingRate);
919 session->outputConfig.set_num_channels(inCnl);
Eric Laurenta9390d42011-06-17 20:17:17 -0700920
921 session->revChannelCount = inCnl;
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530922 session->revConfig.set_sample_rate_hz(session->samplingRate);
923 session->revConfig.set_num_channels(inCnl);
Eric Laurenta9390d42011-06-17 20:17:17 -0700924
Eric Laurenta9390d42011-06-17 20:17:17 -0700925 session->state = PREPROC_SESSION_STATE_CONFIG;
926 return 0;
927}
928
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800929void Session_GetConfig(preproc_session_t* session, effect_config_t* config) {
Eric Laurent3d5188b2011-12-16 15:30:36 -0800930 memset(config, 0, sizeof(effect_config_t));
931 config->inputCfg.samplingRate = config->outputCfg.samplingRate = session->samplingRate;
932 config->inputCfg.format = config->outputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
Glenn Kastenab334fd2012-03-14 12:56:06 -0700933 config->inputCfg.channels = audio_channel_in_mask_from_count(session->inChannelCount);
934 // "out" doesn't mean output device, so this is the correct API to convert channel count to mask
935 config->outputCfg.channels = audio_channel_in_mask_from_count(session->outChannelCount);
Eric Laurent3d5188b2011-12-16 15:30:36 -0800936 config->inputCfg.mask = config->outputCfg.mask =
937 (EFFECT_CONFIG_SMP_RATE | EFFECT_CONFIG_CHANNELS | EFFECT_CONFIG_FORMAT);
938}
939
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800940int Session_SetReverseConfig(preproc_session_t* session, effect_config_t* config) {
Eric Laurenta9390d42011-06-17 20:17:17 -0700941 if (config->inputCfg.samplingRate != config->outputCfg.samplingRate ||
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800942 config->inputCfg.format != config->outputCfg.format ||
943 config->inputCfg.format != AUDIO_FORMAT_PCM_16_BIT) {
Eric Laurenta9390d42011-06-17 20:17:17 -0700944 return -EINVAL;
945 }
946
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800947 ALOGV("Session_SetReverseConfig sr %d cnl %08x", config->inputCfg.samplingRate,
948 config->inputCfg.channels);
Eric Laurenta9390d42011-06-17 20:17:17 -0700949
950 if (session->state < PREPROC_SESSION_STATE_CONFIG) {
951 return -ENOSYS;
952 }
953 if (config->inputCfg.samplingRate != session->samplingRate ||
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800954 config->inputCfg.format != AUDIO_FORMAT_PCM_16_BIT) {
Eric Laurenta9390d42011-06-17 20:17:17 -0700955 return -EINVAL;
956 }
Andy Hunge5412692014-05-16 11:25:07 -0700957 uint32_t inCnl = audio_channel_count_from_out_mask(config->inputCfg.channels);
Eric Laurenta9390d42011-06-17 20:17:17 -0700958 session->revChannelCount = inCnl;
Eric Laurent3f9c84c2012-04-03 15:36:53 -0700959
Eric Laurenta9390d42011-06-17 20:17:17 -0700960 return 0;
961}
962
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800963void Session_GetReverseConfig(preproc_session_t* session, effect_config_t* config) {
Eric Laurent3d5188b2011-12-16 15:30:36 -0800964 memset(config, 0, sizeof(effect_config_t));
965 config->inputCfg.samplingRate = config->outputCfg.samplingRate = session->samplingRate;
966 config->inputCfg.format = config->outputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
967 config->inputCfg.channels = config->outputCfg.channels =
Glenn Kastenab334fd2012-03-14 12:56:06 -0700968 audio_channel_in_mask_from_count(session->revChannelCount);
Eric Laurent3d5188b2011-12-16 15:30:36 -0800969 config->inputCfg.mask = config->outputCfg.mask =
970 (EFFECT_CONFIG_SMP_RATE | EFFECT_CONFIG_CHANNELS | EFFECT_CONFIG_FORMAT);
971}
972
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800973void Session_SetProcEnabled(preproc_session_t* session, uint32_t procId, bool enabled) {
Eric Laurenta9390d42011-06-17 20:17:17 -0700974 if (enabled) {
Eric Laurenta9390d42011-06-17 20:17:17 -0700975 session->enabledMsk |= (1 << procId);
976 if (HasReverseStream(procId)) {
Eric Laurenta9390d42011-06-17 20:17:17 -0700977 session->revEnabledMsk |= (1 << procId);
978 }
979 } else {
980 session->enabledMsk &= ~(1 << procId);
981 if (HasReverseStream(procId)) {
982 session->revEnabledMsk &= ~(1 << procId);
983 }
984 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800985 ALOGV("Session_SetProcEnabled proc %d, enabled %d enabledMsk %08x revEnabledMsk %08x", procId,
986 enabled, session->enabledMsk, session->revEnabledMsk);
Eric Laurenta9390d42011-06-17 20:17:17 -0700987 session->processedMsk = 0;
988 if (HasReverseStream(procId)) {
989 session->revProcessedMsk = 0;
990 }
991}
992
993//------------------------------------------------------------------------------
994// Bundle functions
995//------------------------------------------------------------------------------
996
997static int sInitStatus = 1;
998static preproc_session_t sSessions[PREPROC_NUM_SESSIONS];
999
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001000preproc_session_t* PreProc_GetSession(int32_t procId, int32_t sessionId, int32_t ioId) {
Eric Laurenta9390d42011-06-17 20:17:17 -07001001 size_t i;
Eric Laurenta9390d42011-06-17 20:17:17 -07001002 for (i = 0; i < PREPROC_NUM_SESSIONS; i++) {
Eric Laurentb20cf7d2019-04-05 19:37:34 -07001003 if (sSessions[i].id == sessionId) {
Eric Laurenta9390d42011-06-17 20:17:17 -07001004 if (sSessions[i].createdMsk & (1 << procId)) {
1005 return NULL;
1006 }
1007 return &sSessions[i];
1008 }
1009 }
1010 for (i = 0; i < PREPROC_NUM_SESSIONS; i++) {
Eric Laurentb20cf7d2019-04-05 19:37:34 -07001011 if (sSessions[i].id == 0) {
Eric Laurenta9390d42011-06-17 20:17:17 -07001012 sSessions[i].id = sessionId;
1013 sSessions[i].io = ioId;
1014 return &sSessions[i];
1015 }
1016 }
1017 return NULL;
1018}
1019
Eric Laurenta9390d42011-06-17 20:17:17 -07001020int PreProc_Init() {
1021 size_t i;
1022 int status = 0;
1023
1024 if (sInitStatus <= 0) {
1025 return sInitStatus;
1026 }
1027 for (i = 0; i < PREPROC_NUM_SESSIONS && status == 0; i++) {
1028 status = Session_Init(&sSessions[i]);
1029 }
1030 sInitStatus = status;
1031 return sInitStatus;
1032}
1033
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001034const effect_descriptor_t* PreProc_GetDescriptor(const effect_uuid_t* uuid) {
Eric Laurenta9390d42011-06-17 20:17:17 -07001035 size_t i;
1036 for (i = 0; i < PREPROC_NUM_EFFECTS; i++) {
1037 if (memcmp(&sDescriptors[i]->uuid, uuid, sizeof(effect_uuid_t)) == 0) {
1038 return sDescriptors[i];
1039 }
1040 }
1041 return NULL;
1042}
1043
Eric Laurenta9390d42011-06-17 20:17:17 -07001044extern "C" {
1045
1046//------------------------------------------------------------------------------
1047// Effect Control Interface Implementation
1048//------------------------------------------------------------------------------
1049
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001050int PreProcessingFx_Process(effect_handle_t self, audio_buffer_t* inBuffer,
1051 audio_buffer_t* outBuffer) {
1052 preproc_effect_t* effect = (preproc_effect_t*)self;
Eric Laurenta9390d42011-06-17 20:17:17 -07001053
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001054 if (effect == NULL) {
Steve Block3856b092011-10-20 11:56:00 +01001055 ALOGV("PreProcessingFx_Process() ERROR effect == NULL");
Eric Laurenta9390d42011-06-17 20:17:17 -07001056 return -EINVAL;
1057 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001058 preproc_session_t* session = (preproc_session_t*)effect->session;
Eric Laurenta9390d42011-06-17 20:17:17 -07001059
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001060 if (inBuffer == NULL || inBuffer->raw == NULL || outBuffer == NULL || outBuffer->raw == NULL) {
Steve Block5ff1dd52012-01-05 23:22:43 +00001061 ALOGW("PreProcessingFx_Process() ERROR bad pointer");
Eric Laurenta9390d42011-06-17 20:17:17 -07001062 return -EINVAL;
1063 }
1064
Harish Mahendrakard510fdd2021-03-16 13:26:31 -07001065 if (inBuffer->frameCount != outBuffer->frameCount) {
1066 ALOGW("inBuffer->frameCount %zu is not equal to outBuffer->frameCount %zu",
1067 inBuffer->frameCount, outBuffer->frameCount);
1068 return -EINVAL;
1069 }
1070
1071 if (inBuffer->frameCount != session->frameCount) {
1072 ALOGW("inBuffer->frameCount %zu != %zu representing 10ms at sampling rate %d",
1073 inBuffer->frameCount, session->frameCount, session->samplingRate);
1074 return -EINVAL;
1075 }
1076
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001077 session->processedMsk |= (1 << effect->procId);
Eric Laurenta9390d42011-06-17 20:17:17 -07001078
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001079 // ALOGV("PreProcessingFx_Process In %d frames enabledMsk %08x processedMsk %08x",
1080 // inBuffer->frameCount, session->enabledMsk, session->processedMsk);
Eric Laurenta9390d42011-06-17 20:17:17 -07001081 if ((session->processedMsk & session->enabledMsk) == session->enabledMsk) {
1082 effect->session->processedMsk = 0;
Saketh Sathuvalli08337032020-09-22 21:13:45 +05301083 if (int status = effect->session->apm->ProcessStream(
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001084 (const int16_t* const)inBuffer->s16,
1085 (const webrtc::StreamConfig)effect->session->inputConfig,
1086 (const webrtc::StreamConfig)effect->session->outputConfig,
1087 (int16_t* const)outBuffer->s16);
1088 status != 0) {
Saketh Sathuvalli08337032020-09-22 21:13:45 +05301089 ALOGE("Process Stream failed with error %d\n", status);
1090 return status;
1091 }
Eric Laurenta9390d42011-06-17 20:17:17 -07001092 return 0;
1093 } else {
1094 return -ENODATA;
1095 }
1096}
1097
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001098int PreProcessingFx_Command(effect_handle_t self, uint32_t cmdCode, uint32_t cmdSize,
1099 void* pCmdData, uint32_t* replySize, void* pReplyData) {
1100 preproc_effect_t* effect = (preproc_effect_t*)self;
Eric Laurenta9390d42011-06-17 20:17:17 -07001101
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001102 if (effect == NULL) {
Eric Laurenta9390d42011-06-17 20:17:17 -07001103 return -EINVAL;
1104 }
1105
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001106 // ALOGV("PreProcessingFx_Command: command %d cmdSize %d",cmdCode, cmdSize);
Eric Laurenta9390d42011-06-17 20:17:17 -07001107
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001108 switch (cmdCode) {
Eric Laurenta9390d42011-06-17 20:17:17 -07001109 case EFFECT_CMD_INIT:
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001110 if (pReplyData == NULL || *replySize != sizeof(int)) {
Eric Laurenta9390d42011-06-17 20:17:17 -07001111 return -EINVAL;
1112 }
1113 if (effect->ops->init) {
1114 effect->ops->init(effect);
1115 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001116 *(int*)pReplyData = 0;
Eric Laurenta9390d42011-06-17 20:17:17 -07001117 break;
1118
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001119 case EFFECT_CMD_SET_CONFIG: {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001120 if (pCmdData == NULL || cmdSize != sizeof(effect_config_t) || pReplyData == NULL ||
1121 *replySize != sizeof(int)) {
Steve Block3856b092011-10-20 11:56:00 +01001122 ALOGV("PreProcessingFx_Command cmdCode Case: "
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001123 "EFFECT_CMD_SET_CONFIG: ERROR");
Eric Laurenta9390d42011-06-17 20:17:17 -07001124 return -EINVAL;
1125 }
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001126#ifdef DUAL_MIC_TEST
1127 // make sure that the config command is accepted by making as if all effects were
1128 // disabled: this is OK for functional tests
1129 uint32_t enabledMsk = effect->session->enabledMsk;
1130 if (gDualMicEnabled) {
1131 effect->session->enabledMsk = 0;
1132 }
1133#endif
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001134 *(int*)pReplyData = Session_SetConfig(effect->session, (effect_config_t*)pCmdData);
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001135#ifdef DUAL_MIC_TEST
1136 if (gDualMicEnabled) {
1137 effect->session->enabledMsk = enabledMsk;
1138 }
1139#endif
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001140 if (*(int*)pReplyData != 0) {
Eric Laurenta9390d42011-06-17 20:17:17 -07001141 break;
1142 }
Eric Laurent76533e92012-02-17 17:52:04 -08001143 if (effect->state != PREPROC_EFFECT_STATE_ACTIVE) {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001144 *(int*)pReplyData = Effect_SetState(effect, PREPROC_EFFECT_STATE_CONFIG);
Eric Laurent76533e92012-02-17 17:52:04 -08001145 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001146 } break;
Eric Laurenta9390d42011-06-17 20:17:17 -07001147
Eric Laurent3d5188b2011-12-16 15:30:36 -08001148 case EFFECT_CMD_GET_CONFIG:
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001149 if (pReplyData == NULL || *replySize != sizeof(effect_config_t)) {
Eric Laurent3d5188b2011-12-16 15:30:36 -08001150 ALOGV("\tLVM_ERROR : PreProcessingFx_Command cmdCode Case: "
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001151 "EFFECT_CMD_GET_CONFIG: ERROR");
Eric Laurent3d5188b2011-12-16 15:30:36 -08001152 return -EINVAL;
1153 }
1154
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001155 Session_GetConfig(effect->session, (effect_config_t*)pReplyData);
Eric Laurent3d5188b2011-12-16 15:30:36 -08001156 break;
1157
1158 case EFFECT_CMD_SET_CONFIG_REVERSE:
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001159 if (pCmdData == NULL || cmdSize != sizeof(effect_config_t) || pReplyData == NULL ||
Eric Laurent3d5188b2011-12-16 15:30:36 -08001160 *replySize != sizeof(int)) {
Steve Block3856b092011-10-20 11:56:00 +01001161 ALOGV("PreProcessingFx_Command cmdCode Case: "
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001162 "EFFECT_CMD_SET_CONFIG_REVERSE: ERROR");
Eric Laurenta9390d42011-06-17 20:17:17 -07001163 return -EINVAL;
1164 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001165 *(int*)pReplyData =
1166 Session_SetReverseConfig(effect->session, (effect_config_t*)pCmdData);
1167 if (*(int*)pReplyData != 0) {
Eric Laurenta9390d42011-06-17 20:17:17 -07001168 break;
1169 }
1170 break;
1171
Eric Laurent3d5188b2011-12-16 15:30:36 -08001172 case EFFECT_CMD_GET_CONFIG_REVERSE:
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001173 if (pReplyData == NULL || *replySize != sizeof(effect_config_t)) {
Eric Laurent3d5188b2011-12-16 15:30:36 -08001174 ALOGV("PreProcessingFx_Command cmdCode Case: "
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001175 "EFFECT_CMD_GET_CONFIG_REVERSE: ERROR");
Eric Laurent3d5188b2011-12-16 15:30:36 -08001176 return -EINVAL;
1177 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001178 Session_GetReverseConfig(effect->session, (effect_config_t*)pCmdData);
Eric Laurent3d5188b2011-12-16 15:30:36 -08001179 break;
1180
Eric Laurenta9390d42011-06-17 20:17:17 -07001181 case EFFECT_CMD_RESET:
1182 if (effect->ops->reset) {
1183 effect->ops->reset(effect);
1184 }
1185 break;
1186
Eric Laurent0f714a42015-06-19 15:33:57 -07001187 case EFFECT_CMD_GET_PARAM: {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001188 effect_param_t* p = (effect_param_t*)pCmdData;
Eric Laurent0f714a42015-06-19 15:33:57 -07001189
1190 if (pCmdData == NULL || cmdSize < sizeof(effect_param_t) ||
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001191 cmdSize < (sizeof(effect_param_t) + p->psize) || pReplyData == NULL ||
1192 replySize == NULL || *replySize < (sizeof(effect_param_t) + p->psize)) {
Steve Block3856b092011-10-20 11:56:00 +01001193 ALOGV("PreProcessingFx_Command cmdCode Case: "
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001194 "EFFECT_CMD_GET_PARAM: ERROR");
Eric Laurenta9390d42011-06-17 20:17:17 -07001195 return -EINVAL;
1196 }
Eric Laurenta9390d42011-06-17 20:17:17 -07001197
1198 memcpy(pReplyData, pCmdData, sizeof(effect_param_t) + p->psize);
1199
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001200 p = (effect_param_t*)pReplyData;
Eric Laurenta9390d42011-06-17 20:17:17 -07001201
1202 int voffset = ((p->psize - 1) / sizeof(int32_t) + 1) * sizeof(int32_t);
1203
1204 if (effect->ops->get_parameter) {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001205 p->status =
1206 effect->ops->get_parameter(effect, p->data, &p->vsize, p->data + voffset);
Eric Laurenta9390d42011-06-17 20:17:17 -07001207 *replySize = sizeof(effect_param_t) + voffset + p->vsize;
1208 }
1209 } break;
1210
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001211 case EFFECT_CMD_SET_PARAM: {
1212 if (pCmdData == NULL || cmdSize < sizeof(effect_param_t) || pReplyData == NULL ||
1213 replySize == NULL || *replySize != sizeof(int32_t)) {
Steve Block3856b092011-10-20 11:56:00 +01001214 ALOGV("PreProcessingFx_Command cmdCode Case: "
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001215 "EFFECT_CMD_SET_PARAM: ERROR");
Eric Laurenta9390d42011-06-17 20:17:17 -07001216 return -EINVAL;
1217 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001218 effect_param_t* p = (effect_param_t*)pCmdData;
Eric Laurenta9390d42011-06-17 20:17:17 -07001219
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001220 if (p->psize != sizeof(int32_t)) {
Steve Block3856b092011-10-20 11:56:00 +01001221 ALOGV("PreProcessingFx_Command cmdCode Case: "
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001222 "EFFECT_CMD_SET_PARAM: ERROR, psize is not sizeof(int32_t)");
Eric Laurenta9390d42011-06-17 20:17:17 -07001223 return -EINVAL;
1224 }
1225 if (effect->ops->set_parameter) {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001226 *(int*)pReplyData =
1227 effect->ops->set_parameter(effect, (void*)p->data, p->data + p->psize);
Eric Laurenta9390d42011-06-17 20:17:17 -07001228 }
1229 } break;
1230
1231 case EFFECT_CMD_ENABLE:
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001232 if (pReplyData == NULL || replySize == NULL || *replySize != sizeof(int)) {
Steve Block3856b092011-10-20 11:56:00 +01001233 ALOGV("PreProcessingFx_Command cmdCode Case: EFFECT_CMD_ENABLE: ERROR");
Eric Laurenta9390d42011-06-17 20:17:17 -07001234 return -EINVAL;
1235 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001236 *(int*)pReplyData = Effect_SetState(effect, PREPROC_EFFECT_STATE_ACTIVE);
Eric Laurenta9390d42011-06-17 20:17:17 -07001237 break;
1238
1239 case EFFECT_CMD_DISABLE:
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001240 if (pReplyData == NULL || replySize == NULL || *replySize != sizeof(int)) {
Steve Block3856b092011-10-20 11:56:00 +01001241 ALOGV("PreProcessingFx_Command cmdCode Case: EFFECT_CMD_DISABLE: ERROR");
Eric Laurenta9390d42011-06-17 20:17:17 -07001242 return -EINVAL;
1243 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001244 *(int*)pReplyData = Effect_SetState(effect, PREPROC_EFFECT_STATE_CONFIG);
Eric Laurenta9390d42011-06-17 20:17:17 -07001245 break;
1246
1247 case EFFECT_CMD_SET_DEVICE:
1248 case EFFECT_CMD_SET_INPUT_DEVICE:
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001249 if (pCmdData == NULL || cmdSize != sizeof(uint32_t)) {
Steve Block3856b092011-10-20 11:56:00 +01001250 ALOGV("PreProcessingFx_Command cmdCode Case: EFFECT_CMD_SET_DEVICE: ERROR");
Eric Laurenta9390d42011-06-17 20:17:17 -07001251 return -EINVAL;
1252 }
1253
1254 if (effect->ops->set_device) {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001255 effect->ops->set_device(effect, *(uint32_t*)pCmdData);
Eric Laurenta9390d42011-06-17 20:17:17 -07001256 }
1257 break;
1258
1259 case EFFECT_CMD_SET_VOLUME:
1260 case EFFECT_CMD_SET_AUDIO_MODE:
1261 break;
1262
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001263#ifdef DUAL_MIC_TEST
1264 ///// test commands start
1265 case PREPROC_CMD_DUAL_MIC_ENABLE: {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001266 if (pCmdData == NULL || cmdSize != sizeof(uint32_t) || pReplyData == NULL ||
1267 replySize == NULL) {
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001268 ALOGE("PreProcessingFx_Command cmdCode Case: "
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001269 "PREPROC_CMD_DUAL_MIC_ENABLE: ERROR");
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001270 *replySize = 0;
1271 return -EINVAL;
1272 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001273 gDualMicEnabled = *(bool*)pCmdData;
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001274 if (gDualMicEnabled) {
1275 effect->aux_channels_on = sHasAuxChannels[effect->procId];
1276 } else {
1277 effect->aux_channels_on = false;
1278 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001279 effect->cur_channel_config =
1280 (effect->session->inChannelCount == 1) ? CHANNEL_CFG_MONO : CHANNEL_CFG_STEREO;
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001281
1282 ALOGV("PREPROC_CMD_DUAL_MIC_ENABLE: %s", gDualMicEnabled ? "enabled" : "disabled");
1283 *replySize = sizeof(int);
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001284 *(int*)pReplyData = 0;
1285 } break;
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001286 case PREPROC_CMD_DUAL_MIC_PCM_DUMP_START: {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001287 if (pCmdData == NULL || pReplyData == NULL || replySize == NULL) {
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001288 ALOGE("PreProcessingFx_Command cmdCode Case: "
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001289 "PREPROC_CMD_DUAL_MIC_PCM_DUMP_START: ERROR");
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001290 *replySize = 0;
1291 return -EINVAL;
1292 }
1293 pthread_mutex_lock(&gPcmDumpLock);
1294 if (gPcmDumpFh != NULL) {
1295 fclose(gPcmDumpFh);
1296 gPcmDumpFh = NULL;
1297 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001298 char* path = strndup((char*)pCmdData, cmdSize);
1299 gPcmDumpFh = fopen((char*)path, "wb");
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001300 pthread_mutex_unlock(&gPcmDumpLock);
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001301 ALOGV("PREPROC_CMD_DUAL_MIC_PCM_DUMP_START: path %s gPcmDumpFh %p", path, gPcmDumpFh);
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001302 ALOGE_IF(gPcmDumpFh <= 0, "gPcmDumpFh open error %d %s", errno, strerror(errno));
1303 free(path);
1304 *replySize = sizeof(int);
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001305 *(int*)pReplyData = 0;
1306 } break;
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001307 case PREPROC_CMD_DUAL_MIC_PCM_DUMP_STOP: {
1308 if (pReplyData == NULL || replySize == NULL) {
1309 ALOGE("PreProcessingFx_Command cmdCode Case: "
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001310 "PREPROC_CMD_DUAL_MIC_PCM_DUMP_STOP: ERROR");
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001311 *replySize = 0;
1312 return -EINVAL;
1313 }
1314 pthread_mutex_lock(&gPcmDumpLock);
1315 if (gPcmDumpFh != NULL) {
1316 fclose(gPcmDumpFh);
1317 gPcmDumpFh = NULL;
1318 }
1319 pthread_mutex_unlock(&gPcmDumpLock);
1320 ALOGV("PREPROC_CMD_DUAL_MIC_PCM_DUMP_STOP");
1321 *replySize = sizeof(int);
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001322 *(int*)pReplyData = 0;
1323 } break;
1324 ///// test commands end
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001325
1326 case EFFECT_CMD_GET_FEATURE_SUPPORTED_CONFIGS: {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001327 if (!gDualMicEnabled) {
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001328 return -EINVAL;
1329 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001330 if (pCmdData == NULL || cmdSize != 2 * sizeof(uint32_t) || pReplyData == NULL ||
1331 replySize == NULL) {
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001332 ALOGE("PreProcessingFx_Command cmdCode Case: "
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001333 "EFFECT_CMD_GET_FEATURE_SUPPORTED_CONFIGS: ERROR");
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001334 *replySize = 0;
1335 return -EINVAL;
1336 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001337 if (*(uint32_t*)pCmdData != EFFECT_FEATURE_AUX_CHANNELS || !effect->aux_channels_on) {
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001338 ALOGV("PreProcessingFx_Command feature EFFECT_FEATURE_AUX_CHANNELS not supported by"
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001339 " fx %d",
1340 effect->procId);
1341 *(uint32_t*)pReplyData = -ENOSYS;
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001342 *replySize = sizeof(uint32_t);
1343 break;
1344 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001345 size_t num_configs = *((uint32_t*)pCmdData + 1);
1346 if (*replySize < (2 * sizeof(uint32_t) + num_configs * sizeof(channel_config_t))) {
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001347 *replySize = 0;
1348 return -EINVAL;
1349 }
1350
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001351 *((uint32_t*)pReplyData + 1) = CHANNEL_CFG_CNT;
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001352 if (num_configs < CHANNEL_CFG_CNT ||
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001353 *replySize < (2 * sizeof(uint32_t) + CHANNEL_CFG_CNT * sizeof(channel_config_t))) {
1354 *(uint32_t*)pReplyData = -ENOMEM;
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001355 } else {
1356 num_configs = CHANNEL_CFG_CNT;
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001357 *(uint32_t*)pReplyData = 0;
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001358 }
1359 ALOGV("PreProcessingFx_Command EFFECT_CMD_GET_FEATURE_SUPPORTED_CONFIGS num config %d",
1360 num_configs);
1361
1362 *replySize = 2 * sizeof(uint32_t) + num_configs * sizeof(channel_config_t);
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001363 *((uint32_t*)pReplyData + 1) = num_configs;
1364 memcpy((uint32_t*)pReplyData + 2, &sDualMicConfigs,
1365 num_configs * sizeof(channel_config_t));
1366 } break;
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001367 case EFFECT_CMD_GET_FEATURE_CONFIG:
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001368 if (!gDualMicEnabled) {
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001369 return -EINVAL;
1370 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001371 if (pCmdData == NULL || cmdSize != sizeof(uint32_t) || pReplyData == NULL ||
1372 replySize == NULL || *replySize < sizeof(uint32_t) + sizeof(channel_config_t)) {
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001373 ALOGE("PreProcessingFx_Command cmdCode Case: "
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001374 "EFFECT_CMD_GET_FEATURE_CONFIG: ERROR");
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001375 return -EINVAL;
1376 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001377 if (*(uint32_t*)pCmdData != EFFECT_FEATURE_AUX_CHANNELS || !effect->aux_channels_on) {
1378 *(uint32_t*)pReplyData = -ENOSYS;
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001379 *replySize = sizeof(uint32_t);
1380 break;
1381 }
1382 ALOGV("PreProcessingFx_Command EFFECT_CMD_GET_FEATURE_CONFIG");
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001383 *(uint32_t*)pReplyData = 0;
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001384 *replySize = sizeof(uint32_t) + sizeof(channel_config_t);
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001385 memcpy((uint32_t*)pReplyData + 1, &sDualMicConfigs[effect->cur_channel_config],
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001386 sizeof(channel_config_t));
1387 break;
1388 case EFFECT_CMD_SET_FEATURE_CONFIG: {
1389 ALOGV("PreProcessingFx_Command EFFECT_CMD_SET_FEATURE_CONFIG: "
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001390 "gDualMicEnabled %d effect->aux_channels_on %d",
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001391 gDualMicEnabled, effect->aux_channels_on);
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001392 if (!gDualMicEnabled) {
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001393 return -EINVAL;
1394 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001395 if (pCmdData == NULL || cmdSize != (sizeof(uint32_t) + sizeof(channel_config_t)) ||
1396 pReplyData == NULL || replySize == NULL || *replySize < sizeof(uint32_t)) {
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001397 ALOGE("PreProcessingFx_Command cmdCode Case: "
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001398 "EFFECT_CMD_SET_FEATURE_CONFIG: ERROR\n"
1399 "pCmdData %p cmdSize %d pReplyData %p replySize %p *replySize %d",
1400 pCmdData, cmdSize, pReplyData, replySize, replySize ? *replySize : -1);
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001401 return -EINVAL;
1402 }
1403 *replySize = sizeof(uint32_t);
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001404 if (*(uint32_t*)pCmdData != EFFECT_FEATURE_AUX_CHANNELS || !effect->aux_channels_on) {
1405 *(uint32_t*)pReplyData = -ENOSYS;
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001406 ALOGV("PreProcessingFx_Command cmdCode Case: "
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001407 "EFFECT_CMD_SET_FEATURE_CONFIG: ERROR\n"
1408 "CmdData %d effect->aux_channels_on %d",
1409 *(uint32_t*)pCmdData, effect->aux_channels_on);
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001410 break;
1411 }
1412 size_t i;
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001413 for (i = 0; i < CHANNEL_CFG_CNT; i++) {
1414 if (memcmp((uint32_t*)pCmdData + 1, &sDualMicConfigs[i],
1415 sizeof(channel_config_t)) == 0) {
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001416 break;
1417 }
1418 }
1419 if (i == CHANNEL_CFG_CNT) {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001420 *(uint32_t*)pReplyData = -EINVAL;
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001421 ALOGW("PreProcessingFx_Command EFFECT_CMD_SET_FEATURE_CONFIG invalid config"
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001422 "[%08x].[%08x]",
1423 *((uint32_t*)pCmdData + 1), *((uint32_t*)pCmdData + 2));
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001424 } else {
1425 effect->cur_channel_config = i;
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001426 *(uint32_t*)pReplyData = 0;
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001427 ALOGV("PreProcessingFx_Command EFFECT_CMD_SET_FEATURE_CONFIG New config"
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001428 "[%08x].[%08x]",
1429 sDualMicConfigs[i].main_channels, sDualMicConfigs[i].aux_channels);
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001430 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001431 } break;
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001432#endif
Eric Laurenta9390d42011-06-17 20:17:17 -07001433 default:
1434 return -EINVAL;
1435 }
1436 return 0;
1437}
1438
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001439int PreProcessingFx_GetDescriptor(effect_handle_t self, effect_descriptor_t* pDescriptor) {
1440 preproc_effect_t* effect = (preproc_effect_t*)self;
Eric Laurenta9390d42011-06-17 20:17:17 -07001441
1442 if (effect == NULL || pDescriptor == NULL) {
1443 return -EINVAL;
1444 }
1445
Glenn Kastena189a682012-02-20 12:16:30 -08001446 *pDescriptor = *sDescriptors[effect->procId];
Eric Laurenta9390d42011-06-17 20:17:17 -07001447
1448 return 0;
1449}
1450
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001451int PreProcessingFx_ProcessReverse(effect_handle_t self, audio_buffer_t* inBuffer,
Rivukanta Bhattacharya013e02e2021-03-12 05:50:55 +05301452 audio_buffer_t* outBuffer) {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001453 preproc_effect_t* effect = (preproc_effect_t*)self;
Eric Laurenta9390d42011-06-17 20:17:17 -07001454
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001455 if (effect == NULL) {
Steve Block5ff1dd52012-01-05 23:22:43 +00001456 ALOGW("PreProcessingFx_ProcessReverse() ERROR effect == NULL");
Eric Laurenta9390d42011-06-17 20:17:17 -07001457 return -EINVAL;
1458 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001459 preproc_session_t* session = (preproc_session_t*)effect->session;
Eric Laurenta9390d42011-06-17 20:17:17 -07001460
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001461 if (inBuffer == NULL || inBuffer->raw == NULL) {
Steve Block5ff1dd52012-01-05 23:22:43 +00001462 ALOGW("PreProcessingFx_ProcessReverse() ERROR bad pointer");
Eric Laurenta9390d42011-06-17 20:17:17 -07001463 return -EINVAL;
1464 }
1465
Harish Mahendrakard510fdd2021-03-16 13:26:31 -07001466 if (inBuffer->frameCount != outBuffer->frameCount) {
1467 ALOGW("inBuffer->frameCount %zu is not equal to outBuffer->frameCount %zu",
1468 inBuffer->frameCount, outBuffer->frameCount);
1469 return -EINVAL;
1470 }
1471
1472 if (inBuffer->frameCount != session->frameCount) {
1473 ALOGW("inBuffer->frameCount %zu != %zu representing 10ms at sampling rate %d",
1474 inBuffer->frameCount, session->frameCount, session->samplingRate);
1475 return -EINVAL;
1476 }
1477
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001478 session->revProcessedMsk |= (1 << effect->procId);
Eric Laurenta9390d42011-06-17 20:17:17 -07001479
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001480 // ALOGV("PreProcessingFx_ProcessReverse In %d frames revEnabledMsk %08x revProcessedMsk
1481 // %08x",
1482 // inBuffer->frameCount, session->revEnabledMsk, session->revProcessedMsk);
Eric Laurenta9390d42011-06-17 20:17:17 -07001483
1484 if ((session->revProcessedMsk & session->revEnabledMsk) == session->revEnabledMsk) {
1485 effect->session->revProcessedMsk = 0;
Saketh Sathuvalli08337032020-09-22 21:13:45 +05301486 if (int status = effect->session->apm->ProcessReverseStream(
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001487 (const int16_t* const)inBuffer->s16,
1488 (const webrtc::StreamConfig)effect->session->revConfig,
1489 (const webrtc::StreamConfig)effect->session->revConfig,
1490 (int16_t* const)outBuffer->s16);
1491 status != 0) {
Saketh Sathuvalli08337032020-09-22 21:13:45 +05301492 ALOGE("Process Reverse Stream failed with error %d\n", status);
1493 return status;
1494 }
Eric Laurenta9390d42011-06-17 20:17:17 -07001495 return 0;
1496 } else {
1497 return -ENODATA;
1498 }
1499}
1500
Eric Laurenta9390d42011-06-17 20:17:17 -07001501// effect_handle_t interface implementation for effect
1502const struct effect_interface_s sEffectInterface = {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001503 PreProcessingFx_Process, PreProcessingFx_Command, PreProcessingFx_GetDescriptor, NULL};
Eric Laurenta9390d42011-06-17 20:17:17 -07001504
1505const struct effect_interface_s sEffectInterfaceReverse = {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001506 PreProcessingFx_Process, PreProcessingFx_Command, PreProcessingFx_GetDescriptor,
1507 PreProcessingFx_ProcessReverse};
Eric Laurenta9390d42011-06-17 20:17:17 -07001508
1509//------------------------------------------------------------------------------
1510// Effect Library Interface Implementation
1511//------------------------------------------------------------------------------
1512
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001513int PreProcessingLib_Create(const effect_uuid_t* uuid, int32_t sessionId, int32_t ioId,
1514 effect_handle_t* pInterface) {
Steve Block3856b092011-10-20 11:56:00 +01001515 ALOGV("EffectCreate: uuid: %08x session %d IO: %d", uuid->timeLow, sessionId, ioId);
Eric Laurenta9390d42011-06-17 20:17:17 -07001516
1517 int status;
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001518 const effect_descriptor_t* desc;
1519 preproc_session_t* session;
Eric Laurenta9390d42011-06-17 20:17:17 -07001520 uint32_t procId;
1521
1522 if (PreProc_Init() != 0) {
1523 return sInitStatus;
1524 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001525 desc = PreProc_GetDescriptor(uuid);
Eric Laurenta9390d42011-06-17 20:17:17 -07001526 if (desc == NULL) {
Steve Block5ff1dd52012-01-05 23:22:43 +00001527 ALOGW("EffectCreate: fx not found uuid: %08x", uuid->timeLow);
Eric Laurenta9390d42011-06-17 20:17:17 -07001528 return -EINVAL;
1529 }
1530 procId = UuidToProcId(&desc->type);
1531
1532 session = PreProc_GetSession(procId, sessionId, ioId);
1533 if (session == NULL) {
Steve Block5ff1dd52012-01-05 23:22:43 +00001534 ALOGW("EffectCreate: no more session available");
Eric Laurenta9390d42011-06-17 20:17:17 -07001535 return -EINVAL;
1536 }
1537
1538 status = Session_CreateEffect(session, procId, pInterface);
1539
1540 if (status < 0 && session->createdMsk == 0) {
Eric Laurentb20cf7d2019-04-05 19:37:34 -07001541 session->id = 0;
Eric Laurenta9390d42011-06-17 20:17:17 -07001542 }
1543 return status;
1544}
1545
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001546int PreProcessingLib_Release(effect_handle_t interface) {
Steve Block3856b092011-10-20 11:56:00 +01001547 ALOGV("EffectRelease start %p", interface);
Eric Laurenta9390d42011-06-17 20:17:17 -07001548 if (PreProc_Init() != 0) {
1549 return sInitStatus;
1550 }
1551
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001552 preproc_effect_t* fx = (preproc_effect_t*)interface;
Eric Laurenta9390d42011-06-17 20:17:17 -07001553
Eric Laurentb20cf7d2019-04-05 19:37:34 -07001554 if (fx->session->id == 0) {
Eric Laurenta9390d42011-06-17 20:17:17 -07001555 return -EINVAL;
1556 }
1557 return Session_ReleaseEffect(fx->session, fx);
1558}
1559
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001560int PreProcessingLib_GetDescriptor(const effect_uuid_t* uuid, effect_descriptor_t* pDescriptor) {
1561 if (pDescriptor == NULL || uuid == NULL) {
Eric Laurenta9390d42011-06-17 20:17:17 -07001562 return -EINVAL;
1563 }
1564
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001565 const effect_descriptor_t* desc = PreProc_GetDescriptor(uuid);
Eric Laurenta9390d42011-06-17 20:17:17 -07001566 if (desc == NULL) {
Steve Block3856b092011-10-20 11:56:00 +01001567 ALOGV("PreProcessingLib_GetDescriptor() not found");
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001568 return -EINVAL;
Eric Laurenta9390d42011-06-17 20:17:17 -07001569 }
1570
Steve Block3856b092011-10-20 11:56:00 +01001571 ALOGV("PreProcessingLib_GetDescriptor() got fx %s", desc->name);
Eric Laurenta9390d42011-06-17 20:17:17 -07001572
Glenn Kastena189a682012-02-20 12:16:30 -08001573 *pDescriptor = *desc;
Eric Laurenta9390d42011-06-17 20:17:17 -07001574 return 0;
1575}
1576
Marco Nelissen7f16b192012-10-25 16:05:57 -07001577// This is the only symbol that needs to be exported
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001578__attribute__((visibility("default"))) audio_effect_library_t AUDIO_EFFECT_LIBRARY_INFO_SYM = {
1579 .tag = AUDIO_EFFECT_LIBRARY_TAG,
1580 .version = EFFECT_LIBRARY_API_VERSION,
1581 .name = "Audio Preprocessing Library",
1582 .implementor = "The Android Open Source Project",
1583 .create_effect = PreProcessingLib_Create,
1584 .release_effect = PreProcessingLib_Release,
1585 .get_descriptor = PreProcessingLib_GetDescriptor};
Eric Laurenta9390d42011-06-17 20:17:17 -07001586
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001587}; // extern "C"