blob: 59f1fc3c0e1cc5634935f634c5925b783fe6cc44 [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
Jorge E. Moreira9e87e442022-12-22 11:30:27 -0800105 rtc::scoped_refptr<webrtc::AudioProcessing>
106 apm; // handle on webRTC audio processing module (APM)
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530107 // Audio Processing module builder
108 webrtc::AudioProcessingBuilder ap_builder;
Harish Mahendrakard510fdd2021-03-16 13:26:31 -0700109 // frameCount represents the size of the buffers used for processing, and must represent 10ms.
110 size_t frameCount;
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800111 uint32_t samplingRate; // sampling rate at effect process interface
112 uint32_t inChannelCount; // input channel count
113 uint32_t outChannelCount; // output channel count
114 uint32_t createdMsk; // bit field containing IDs of crested pre processors
115 uint32_t enabledMsk; // bit field containing IDs of enabled pre processors
116 uint32_t processedMsk; // bit field containing IDs of pre processors already
117 // processed in current round
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530118 // audio config strucutre
119 webrtc::AudioProcessing::Config config;
120 webrtc::StreamConfig inputConfig; // input stream configuration
121 webrtc::StreamConfig outputConfig; // output stream configuration
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800122 uint32_t revChannelCount; // number of channels on reverse stream
123 uint32_t revEnabledMsk; // bit field containing IDs of enabled pre processors
124 // with reverse channel
125 uint32_t revProcessedMsk; // bit field containing IDs of pre processors with reverse
126 // channel already processed in current round
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530127 webrtc::StreamConfig revConfig; // reverse stream configuration.
Eric Laurenta9390d42011-06-17 20:17:17 -0700128};
129
Eric Laurent3f9c84c2012-04-03 15:36:53 -0700130#ifdef DUAL_MIC_TEST
131enum {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800132 PREPROC_CMD_DUAL_MIC_ENABLE = EFFECT_CMD_FIRST_PROPRIETARY, // enable dual mic mode
133 PREPROC_CMD_DUAL_MIC_PCM_DUMP_START, // start pcm capture
134 PREPROC_CMD_DUAL_MIC_PCM_DUMP_STOP // stop pcm capture
Eric Laurent3f9c84c2012-04-03 15:36:53 -0700135};
136
137enum {
138 CHANNEL_CFG_MONO,
139 CHANNEL_CFG_STEREO,
140 CHANNEL_CFG_MONO_AUX,
141 CHANNEL_CFG_STEREO_AUX,
142 CHANNEL_CFG_CNT,
143 CHANNEL_CFG_FIRST_AUX = CHANNEL_CFG_MONO_AUX,
144};
145
146const channel_config_t sDualMicConfigs[CHANNEL_CFG_CNT] = {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800147 {AUDIO_CHANNEL_IN_MONO, 0},
148 {AUDIO_CHANNEL_IN_STEREO, 0},
149 {AUDIO_CHANNEL_IN_FRONT, AUDIO_CHANNEL_IN_BACK},
150 {AUDIO_CHANNEL_IN_STEREO, AUDIO_CHANNEL_IN_RIGHT}};
Eric Laurent3f9c84c2012-04-03 15:36:53 -0700151
152bool sHasAuxChannels[PREPROC_NUM_EFFECTS] = {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800153 false, // PREPROC_AGC
Atneya Nair2a77e832021-12-08 19:31:45 -0500154 false, // PREPROC_AGC2
Eric Laurent3f9c84c2012-04-03 15:36:53 -0700155 true, // PREPROC_AEC
156 true, // PREPROC_NS
157};
158
159bool gDualMicEnabled;
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800160FILE* gPcmDumpFh;
Eric Laurent3f9c84c2012-04-03 15:36:53 -0700161static pthread_mutex_t gPcmDumpLock = PTHREAD_MUTEX_INITIALIZER;
162#endif
163
Eric Laurenta9390d42011-06-17 20:17:17 -0700164//------------------------------------------------------------------------------
165// Effect descriptors
166//------------------------------------------------------------------------------
167
168// UUIDs for effect types have been generated from http://www.itu.int/ITU-T/asn1/uuid.html
169// as the pre processing effects are not defined by OpenSL ES
170
171// Automatic Gain Control
172static const effect_descriptor_t sAgcDescriptor = {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800173 {0x0a8abfe0, 0x654c, 0x11e0, 0xba26, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, // type
174 {0xaa8130e0, 0x66fc, 0x11e0, 0xbad0, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, // uuid
Eric Laurenta9390d42011-06-17 20:17:17 -0700175 EFFECT_CONTROL_API_VERSION,
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800176 (EFFECT_FLAG_TYPE_PRE_PROC | EFFECT_FLAG_DEVICE_IND),
177 0, // FIXME indicate CPU load
178 0, // FIXME indicate memory usage
Eric Laurenta9390d42011-06-17 20:17:17 -0700179 "Automatic Gain Control",
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800180 "The Android Open Source Project"};
Eric Laurenta9390d42011-06-17 20:17:17 -0700181
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530182// Automatic Gain Control 2
183static const effect_descriptor_t sAgc2Descriptor = {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800184 {0xae3c653b, 0xbe18, 0x4ab8, 0x8938, {0x41, 0x8f, 0x0a, 0x7f, 0x06, 0xac}}, // type
185 {0x89f38e65, 0xd4d2, 0x4d64, 0xad0e, {0x2b, 0x3e, 0x79, 0x9e, 0xa8, 0x86}}, // uuid
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530186 EFFECT_CONTROL_API_VERSION,
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800187 (EFFECT_FLAG_TYPE_PRE_PROC | EFFECT_FLAG_DEVICE_IND),
188 0, // FIXME indicate CPU load
189 0, // FIXME indicate memory usage
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530190 "Automatic Gain Control 2",
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800191 "The Android Open Source Project"};
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530192
Eric Laurenta9390d42011-06-17 20:17:17 -0700193// Acoustic Echo Cancellation
194static const effect_descriptor_t sAecDescriptor = {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800195 {0x7b491460, 0x8d4d, 0x11e0, 0xbd61, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, // type
196 {0xbb392ec0, 0x8d4d, 0x11e0, 0xa896, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, // uuid
Eric Laurenta9390d42011-06-17 20:17:17 -0700197 EFFECT_CONTROL_API_VERSION,
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800198 (EFFECT_FLAG_TYPE_PRE_PROC | EFFECT_FLAG_DEVICE_IND),
199 0, // FIXME indicate CPU load
200 0, // FIXME indicate memory usage
Eric Laurenta9390d42011-06-17 20:17:17 -0700201 "Acoustic Echo Canceler",
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800202 "The Android Open Source Project"};
Eric Laurenta9390d42011-06-17 20:17:17 -0700203
204// Noise suppression
205static const effect_descriptor_t sNsDescriptor = {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800206 {0x58b4b260, 0x8e06, 0x11e0, 0xaa8e, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, // type
207 {0xc06c8400, 0x8e06, 0x11e0, 0x9cb6, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, // uuid
Eric Laurenta9390d42011-06-17 20:17:17 -0700208 EFFECT_CONTROL_API_VERSION,
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800209 (EFFECT_FLAG_TYPE_PRE_PROC | EFFECT_FLAG_DEVICE_IND),
210 0, // FIXME indicate CPU load
211 0, // FIXME indicate memory usage
Eric Laurenta9390d42011-06-17 20:17:17 -0700212 "Noise Suppression",
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800213 "The Android Open Source Project"};
Eric Laurenta9390d42011-06-17 20:17:17 -0700214
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800215static const effect_descriptor_t* sDescriptors[PREPROC_NUM_EFFECTS] = {&sAgcDescriptor,
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800216 &sAgc2Descriptor,
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800217 &sAecDescriptor,
218 &sNsDescriptor};
Eric Laurenta9390d42011-06-17 20:17:17 -0700219
220//------------------------------------------------------------------------------
221// Helper functions
222//------------------------------------------------------------------------------
223
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800224const effect_uuid_t* const sUuidToPreProcTable[PREPROC_NUM_EFFECTS] = {FX_IID_AGC,
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800225 FX_IID_AGC2,
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800226 FX_IID_AEC, FX_IID_NS};
Eric Laurenta9390d42011-06-17 20:17:17 -0700227
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800228const effect_uuid_t* ProcIdToUuid(int procId) {
Eric Laurenta9390d42011-06-17 20:17:17 -0700229 if (procId >= PREPROC_NUM_EFFECTS) {
230 return EFFECT_UUID_NULL;
231 }
232 return sUuidToPreProcTable[procId];
233}
234
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800235uint32_t UuidToProcId(const effect_uuid_t* uuid) {
Eric Laurenta9390d42011-06-17 20:17:17 -0700236 size_t i;
237 for (i = 0; i < PREPROC_NUM_EFFECTS; i++) {
238 if (memcmp(uuid, sUuidToPreProcTable[i], sizeof(*uuid)) == 0) {
239 break;
240 }
241 }
242 return i;
243}
244
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800245bool HasReverseStream(uint32_t procId) {
Eric Laurenta9390d42011-06-17 20:17:17 -0700246 if (procId == PREPROC_AEC) {
247 return true;
248 }
249 return false;
250}
251
Eric Laurenta9390d42011-06-17 20:17:17 -0700252//------------------------------------------------------------------------------
253// Automatic Gain Control (AGC)
254//------------------------------------------------------------------------------
255
Eric Laurent53876962012-01-31 12:35:20 -0800256static const int kAgcDefaultTargetLevel = 3;
257static const int kAgcDefaultCompGain = 9;
Eric Laurenta9390d42011-06-17 20:17:17 -0700258static const bool kAgcDefaultLimiter = true;
259
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800260int Agc2Init(preproc_effect_t* effect) {
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530261 ALOGV("Agc2Init");
262 effect->session->config = effect->session->apm->GetConfig();
263 effect->session->config.gain_controller2.fixed_digital.gain_db = 0.f;
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530264 effect->session->apm->ApplyConfig(effect->session->config);
265 return 0;
266}
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530267
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800268int AgcInit(preproc_effect_t* effect) {
Steve Block3856b092011-10-20 11:56:00 +0100269 ALOGV("AgcInit");
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530270 effect->session->config = effect->session->apm->GetConfig();
271 effect->session->config.gain_controller1.target_level_dbfs = kAgcDefaultTargetLevel;
272 effect->session->config.gain_controller1.compression_gain_db = kAgcDefaultCompGain;
273 effect->session->config.gain_controller1.enable_limiter = kAgcDefaultLimiter;
274 effect->session->apm->ApplyConfig(effect->session->config);
Eric Laurenta9390d42011-06-17 20:17:17 -0700275 return 0;
276}
277
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800278int Agc2Create(preproc_effect_t* effect) {
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530279 Agc2Init(effect);
280 return 0;
281}
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530282
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800283int AgcCreate(preproc_effect_t* effect) {
Eric Laurenta9390d42011-06-17 20:17:17 -0700284 AgcInit(effect);
285 return 0;
286}
287
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800288int Agc2GetParameter(preproc_effect_t* effect, void* pParam, uint32_t* pValueSize, void* pValue) {
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530289 int status = 0;
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800290 uint32_t param = *(uint32_t*)pParam;
291 agc2_settings_t* pProperties = (agc2_settings_t*)pValue;
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530292
293 switch (param) {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800294 case AGC2_PARAM_FIXED_DIGITAL_GAIN:
295 if (*pValueSize < sizeof(float)) {
296 *pValueSize = 0.f;
297 return -EINVAL;
298 }
299 break;
300 case AGC2_PARAM_ADAPT_DIGI_LEVEL_ESTIMATOR:
301 if (*pValueSize < sizeof(int32_t)) {
302 *pValueSize = 0;
303 return -EINVAL;
304 }
305 break;
306 case AGC2_PARAM_ADAPT_DIGI_EXTRA_SATURATION_MARGIN:
307 if (*pValueSize < sizeof(float)) {
308 *pValueSize = 0.f;
309 return -EINVAL;
310 }
311 break;
312 case AGC2_PARAM_PROPERTIES:
313 if (*pValueSize < sizeof(agc2_settings_t)) {
314 *pValueSize = 0;
315 return -EINVAL;
316 }
317 break;
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530318
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800319 default:
320 ALOGW("Agc2GetParameter() unknown param %08x", param);
321 status = -EINVAL;
322 break;
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530323 }
324
325 effect->session->config = effect->session->apm->GetConfig();
326 switch (param) {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800327 case AGC2_PARAM_FIXED_DIGITAL_GAIN:
328 *(float*)pValue =
329 (float)(effect->session->config.gain_controller2.fixed_digital.gain_db);
330 ALOGV("Agc2GetParameter() target level %f dB", *(float*)pValue);
331 break;
332 case AGC2_PARAM_ADAPT_DIGI_LEVEL_ESTIMATOR:
Jorge E. Moreira9e87e442022-12-22 11:30:27 -0800333 // WebRTC only supports RMS level estimator now
334 *(uint32_t*)pValue = (uint32_t)(0);
335 ALOGV("Agc2GetParameter() level estimator RMS");
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800336 break;
337 case AGC2_PARAM_ADAPT_DIGI_EXTRA_SATURATION_MARGIN:
Jorge E. Moreira9e87e442022-12-22 11:30:27 -0800338 *(float*)pValue = (float)(2.0);
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800339 ALOGV("Agc2GetParameter() extra saturation margin %f dB", *(float*)pValue);
340 break;
341 case AGC2_PARAM_PROPERTIES:
342 pProperties->fixedDigitalGain =
343 (float)(effect->session->config.gain_controller2.fixed_digital.gain_db);
Jorge E. Moreira9e87e442022-12-22 11:30:27 -0800344 pProperties->level_estimator = 0;
345 pProperties->extraSaturationMargin = 2.0;
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800346 break;
347 default:
348 ALOGW("Agc2GetParameter() unknown param %d", param);
349 status = -EINVAL;
350 break;
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530351 }
352
353 return status;
354}
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530355
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800356int AgcGetParameter(preproc_effect_t* effect, void* pParam, uint32_t* pValueSize, void* pValue) {
Eric Laurenta9390d42011-06-17 20:17:17 -0700357 int status = 0;
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800358 uint32_t param = *(uint32_t*)pParam;
359 t_agc_settings* pProperties = (t_agc_settings*)pValue;
Eric Laurenta9390d42011-06-17 20:17:17 -0700360
361 switch (param) {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800362 case AGC_PARAM_TARGET_LEVEL:
363 case AGC_PARAM_COMP_GAIN:
364 if (*pValueSize < sizeof(int16_t)) {
365 *pValueSize = 0;
366 return -EINVAL;
367 }
368 break;
369 case AGC_PARAM_LIMITER_ENA:
370 if (*pValueSize < sizeof(bool)) {
371 *pValueSize = 0;
372 return -EINVAL;
373 }
374 break;
375 case AGC_PARAM_PROPERTIES:
376 if (*pValueSize < sizeof(t_agc_settings)) {
377 *pValueSize = 0;
378 return -EINVAL;
379 }
380 break;
Eric Laurenta9390d42011-06-17 20:17:17 -0700381
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800382 default:
383 ALOGW("AgcGetParameter() unknown param %08x", param);
384 status = -EINVAL;
385 break;
Eric Laurenta9390d42011-06-17 20:17:17 -0700386 }
387
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530388 effect->session->config = effect->session->apm->GetConfig();
389 switch (param) {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800390 case AGC_PARAM_TARGET_LEVEL:
391 *(int16_t*)pValue =
392 (int16_t)(effect->session->config.gain_controller1.target_level_dbfs * -100);
393 ALOGV("AgcGetParameter() target level %d milliBels", *(int16_t*)pValue);
394 break;
395 case AGC_PARAM_COMP_GAIN:
396 *(int16_t*)pValue =
397 (int16_t)(effect->session->config.gain_controller1.compression_gain_db * -100);
398 ALOGV("AgcGetParameter() comp gain %d milliBels", *(int16_t*)pValue);
399 break;
400 case AGC_PARAM_LIMITER_ENA:
401 *(bool*)pValue = (bool)(effect->session->config.gain_controller1.enable_limiter);
402 ALOGV("AgcGetParameter() limiter enabled %s",
403 (*(int16_t*)pValue != 0) ? "true" : "false");
404 break;
405 case AGC_PARAM_PROPERTIES:
406 pProperties->targetLevel =
407 (int16_t)(effect->session->config.gain_controller1.target_level_dbfs * -100);
408 pProperties->compGain =
409 (int16_t)(effect->session->config.gain_controller1.compression_gain_db * -100);
410 pProperties->limiterEnabled =
411 (bool)(effect->session->config.gain_controller1.enable_limiter);
412 break;
413 default:
414 ALOGW("AgcGetParameter() unknown param %d", param);
415 status = -EINVAL;
416 break;
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530417 }
Eric Laurenta9390d42011-06-17 20:17:17 -0700418 return status;
419}
420
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800421int Agc2SetParameter(preproc_effect_t* effect, void* pParam, void* pValue) {
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530422 int status = 0;
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800423 uint32_t param = *(uint32_t*)pParam;
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530424 float valueFloat = 0.f;
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800425 agc2_settings_t* pProperties = (agc2_settings_t*)pValue;
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530426 effect->session->config = effect->session->apm->GetConfig();
427 switch (param) {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800428 case AGC2_PARAM_FIXED_DIGITAL_GAIN:
429 valueFloat = (float)(*(int32_t*)pValue);
430 ALOGV("Agc2SetParameter() fixed digital gain %f dB", valueFloat);
431 effect->session->config.gain_controller2.fixed_digital.gain_db = valueFloat;
432 break;
433 case AGC2_PARAM_ADAPT_DIGI_LEVEL_ESTIMATOR:
Jorge E. Moreira9e87e442022-12-22 11:30:27 -0800434 ALOGV("Agc2SetParameter() level estimator %d", *(uint32_t*)pValue);
435 if (*(uint32_t*)pValue != 0) {
436 // only RMS is supported
437 status = -EINVAL;
438 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800439 break;
440 case AGC2_PARAM_ADAPT_DIGI_EXTRA_SATURATION_MARGIN:
441 valueFloat = (float)(*(int32_t*)pValue);
442 ALOGV("Agc2SetParameter() extra saturation margin %f dB", valueFloat);
Jorge E. Moreira9e87e442022-12-22 11:30:27 -0800443 if (valueFloat != 2.0) {
444 // extra_staturation_margin_db is no longer configurable in webrtc
445 status = -EINVAL;
446 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800447 break;
448 case AGC2_PARAM_PROPERTIES:
449 ALOGV("Agc2SetParameter() properties gain %f, level %d margin %f",
450 pProperties->fixedDigitalGain, pProperties->level_estimator,
451 pProperties->extraSaturationMargin);
452 effect->session->config.gain_controller2.fixed_digital.gain_db =
453 pProperties->fixedDigitalGain;
Jorge E. Moreira9e87e442022-12-22 11:30:27 -0800454 if (pProperties->level_estimator != 0 || pProperties->extraSaturationMargin != 2.0) {
455 status = -EINVAL;
456 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800457 break;
458 default:
459 ALOGW("Agc2SetParameter() unknown param %08x value %08x", param, *(uint32_t*)pValue);
460 status = -EINVAL;
461 break;
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530462 }
463 effect->session->apm->ApplyConfig(effect->session->config);
464
465 ALOGV("Agc2SetParameter() done status %d", status);
466
467 return status;
468}
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530469
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800470int AgcSetParameter(preproc_effect_t* effect, void* pParam, void* pValue) {
Eric Laurenta9390d42011-06-17 20:17:17 -0700471 int status = 0;
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800472 uint32_t param = *(uint32_t*)pParam;
473 t_agc_settings* pProperties = (t_agc_settings*)pValue;
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530474 effect->session->config = effect->session->apm->GetConfig();
475 switch (param) {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800476 case AGC_PARAM_TARGET_LEVEL:
477 ALOGV("AgcSetParameter() target level %d milliBels", *(int16_t*)pValue);
478 effect->session->config.gain_controller1.target_level_dbfs =
479 (-(*(int16_t*)pValue / 100));
480 break;
481 case AGC_PARAM_COMP_GAIN:
482 ALOGV("AgcSetParameter() comp gain %d milliBels", *(int16_t*)pValue);
483 effect->session->config.gain_controller1.compression_gain_db =
484 (*(int16_t*)pValue / 100);
485 break;
486 case AGC_PARAM_LIMITER_ENA:
487 ALOGV("AgcSetParameter() limiter enabled %s", *(bool*)pValue ? "true" : "false");
488 effect->session->config.gain_controller1.enable_limiter = (*(bool*)pValue);
489 break;
490 case AGC_PARAM_PROPERTIES:
491 ALOGV("AgcSetParameter() properties level %d, gain %d limiter %d",
492 pProperties->targetLevel, pProperties->compGain, pProperties->limiterEnabled);
493 effect->session->config.gain_controller1.target_level_dbfs =
494 -(pProperties->targetLevel / 100);
495 effect->session->config.gain_controller1.compression_gain_db =
496 pProperties->compGain / 100;
497 effect->session->config.gain_controller1.enable_limiter = pProperties->limiterEnabled;
498 break;
499 default:
500 ALOGW("AgcSetParameter() unknown param %08x value %08x", param, *(uint32_t*)pValue);
501 status = -EINVAL;
502 break;
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530503 }
504 effect->session->apm->ApplyConfig(effect->session->config);
Eric Laurenta9390d42011-06-17 20:17:17 -0700505
Steve Block3856b092011-10-20 11:56:00 +0100506 ALOGV("AgcSetParameter() done status %d", status);
Eric Laurenta9390d42011-06-17 20:17:17 -0700507
508 return status;
509}
510
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800511void Agc2Enable(preproc_effect_t* effect) {
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530512 effect->session->config = effect->session->apm->GetConfig();
513 effect->session->config.gain_controller2.enabled = true;
514 effect->session->apm->ApplyConfig(effect->session->config);
515}
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530516
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800517void AgcEnable(preproc_effect_t* effect) {
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530518 effect->session->config = effect->session->apm->GetConfig();
519 effect->session->config.gain_controller1.enabled = true;
520 effect->session->apm->ApplyConfig(effect->session->config);
Eric Laurenta9390d42011-06-17 20:17:17 -0700521}
522
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800523void Agc2Disable(preproc_effect_t* effect) {
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530524 effect->session->config = effect->session->apm->GetConfig();
525 effect->session->config.gain_controller2.enabled = false;
526 effect->session->apm->ApplyConfig(effect->session->config);
527}
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530528
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800529void AgcDisable(preproc_effect_t* effect) {
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530530 effect->session->config = effect->session->apm->GetConfig();
531 effect->session->config.gain_controller1.enabled = false;
532 effect->session->apm->ApplyConfig(effect->session->config);
Eric Laurenta9390d42011-06-17 20:17:17 -0700533}
534
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800535static const preproc_ops_t sAgcOps = {AgcCreate, AgcInit, NULL, AgcEnable, AgcDisable,
536 AgcSetParameter, AgcGetParameter, NULL};
Eric Laurenta9390d42011-06-17 20:17:17 -0700537
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800538static const preproc_ops_t sAgc2Ops = {Agc2Create, Agc2Init, NULL,
539 Agc2Enable, Agc2Disable, Agc2SetParameter,
540 Agc2GetParameter, NULL};
Eric Laurenta9390d42011-06-17 20:17:17 -0700541
542//------------------------------------------------------------------------------
543// Acoustic Echo Canceler (AEC)
544//------------------------------------------------------------------------------
545
Eric Laurenta9390d42011-06-17 20:17:17 -0700546
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800547int AecInit(preproc_effect_t* effect) {
Steve Block3856b092011-10-20 11:56:00 +0100548 ALOGV("AecInit");
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800549 effect->session->config = effect->session->apm->GetConfig();
Rivukanta Bhattacharyac4c54172020-11-25 23:55:44 +0530550 effect->session->config.echo_canceller.mobile_mode = true;
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530551 effect->session->apm->ApplyConfig(effect->session->config);
Eric Laurenta9390d42011-06-17 20:17:17 -0700552 return 0;
553}
554
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800555int AecCreate(preproc_effect_t* effect) {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800556 AecInit(effect);
Eric Laurenta9390d42011-06-17 20:17:17 -0700557 return 0;
558}
559
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800560int AecGetParameter(preproc_effect_t* effect, void* pParam, uint32_t* pValueSize, void* pValue) {
Eric Laurenta9390d42011-06-17 20:17:17 -0700561 int status = 0;
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800562 uint32_t param = *(uint32_t*)pParam;
Eric Laurenta9390d42011-06-17 20:17:17 -0700563
564 if (*pValueSize < sizeof(uint32_t)) {
565 return -EINVAL;
566 }
567 switch (param) {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800568 case AEC_PARAM_ECHO_DELAY:
569 case AEC_PARAM_PROPERTIES:
570 *(uint32_t*)pValue = 1000 * effect->session->apm->stream_delay_ms();
571 ALOGV("AecGetParameter() echo delay %d us", *(uint32_t*)pValue);
572 break;
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800573 case AEC_PARAM_MOBILE_MODE:
574 effect->session->config = effect->session->apm->GetConfig();
575 *(uint32_t*)pValue = effect->session->config.echo_canceller.mobile_mode;
576 ALOGV("AecGetParameter() mobile mode %d us", *(uint32_t*)pValue);
577 break;
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800578 default:
579 ALOGW("AecGetParameter() unknown param %08x value %08x", param, *(uint32_t*)pValue);
580 status = -EINVAL;
581 break;
Eric Laurenta9390d42011-06-17 20:17:17 -0700582 }
583 return status;
584}
585
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800586int AecSetParameter(preproc_effect_t* effect, void* pParam, void* pValue) {
Eric Laurenta9390d42011-06-17 20:17:17 -0700587 int status = 0;
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800588 uint32_t param = *(uint32_t*)pParam;
589 uint32_t value = *(uint32_t*)pValue;
Eric Laurenta9390d42011-06-17 20:17:17 -0700590
591 switch (param) {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800592 case AEC_PARAM_ECHO_DELAY:
593 case AEC_PARAM_PROPERTIES:
594 status = effect->session->apm->set_stream_delay_ms(value / 1000);
595 ALOGV("AecSetParameter() echo delay %d us, status %d", value, status);
596 break;
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800597 case AEC_PARAM_MOBILE_MODE:
598 effect->session->config = effect->session->apm->GetConfig();
599 effect->session->config.echo_canceller.mobile_mode = value;
600 ALOGV("AecSetParameter() mobile mode %d us", value);
601 effect->session->apm->ApplyConfig(effect->session->config);
602 break;
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800603 default:
604 ALOGW("AecSetParameter() unknown param %08x value %08x", param, *(uint32_t*)pValue);
605 status = -EINVAL;
606 break;
Eric Laurenta9390d42011-06-17 20:17:17 -0700607 }
608 return status;
609}
610
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800611void AecEnable(preproc_effect_t* effect) {
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530612 effect->session->config = effect->session->apm->GetConfig();
613 effect->session->config.echo_canceller.enabled = true;
614 effect->session->apm->ApplyConfig(effect->session->config);
Eric Laurenta9390d42011-06-17 20:17:17 -0700615}
616
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800617void AecDisable(preproc_effect_t* effect) {
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530618 effect->session->config = effect->session->apm->GetConfig();
619 effect->session->config.echo_canceller.enabled = false;
620 effect->session->apm->ApplyConfig(effect->session->config);
Eric Laurenta9390d42011-06-17 20:17:17 -0700621}
622
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800623int AecSetDevice(preproc_effect_t* effect, uint32_t device) {
Steve Block3856b092011-10-20 11:56:00 +0100624 ALOGV("AecSetDevice %08x", device);
Eric Laurenta9390d42011-06-17 20:17:17 -0700625
Eric Laurent88959252012-08-28 14:26:53 -0700626 if (audio_is_input_device(device)) {
627 return 0;
628 }
629
Eric Laurenta9390d42011-06-17 20:17:17 -0700630 return 0;
631}
632
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800633static const preproc_ops_t sAecOps = {AecCreate, AecInit, NULL,
634 AecEnable, AecDisable, AecSetParameter,
635 AecGetParameter, AecSetDevice};
Eric Laurenta9390d42011-06-17 20:17:17 -0700636
637//------------------------------------------------------------------------------
638// Noise Suppression (NS)
639//------------------------------------------------------------------------------
640
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530641static const webrtc::AudioProcessing::Config::NoiseSuppression::Level kNsDefaultLevel =
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800642 webrtc::AudioProcessing::Config::NoiseSuppression::kModerate;
Eric Laurenta9390d42011-06-17 20:17:17 -0700643
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800644int NsInit(preproc_effect_t* effect) {
Steve Block3856b092011-10-20 11:56:00 +0100645 ALOGV("NsInit");
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800646 effect->session->config = effect->session->apm->GetConfig();
647 effect->session->config.noise_suppression.level = kNsDefaultLevel;
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530648 effect->session->apm->ApplyConfig(effect->session->config);
Alex Luebs766bf732015-12-14 21:32:13 -0800649 effect->type = NS_TYPE_SINGLE_CHANNEL;
Eric Laurenta9390d42011-06-17 20:17:17 -0700650 return 0;
651}
652
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800653int NsCreate(preproc_effect_t* effect) {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800654 NsInit(effect);
Eric Laurenta9390d42011-06-17 20:17:17 -0700655 return 0;
656}
657
Rivukanta Bhattacharya013e02e2021-03-12 05:50:55 +0530658int NsGetParameter(preproc_effect_t* /*effect __unused*/, void* /*pParam __unused*/,
659 uint32_t* /*pValueSize __unused*/, void* /*pValue __unused*/) {
Eric Laurenta9390d42011-06-17 20:17:17 -0700660 int status = 0;
661 return status;
662}
663
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800664int NsSetParameter(preproc_effect_t* effect, void* pParam, void* pValue) {
Eric Laurenta9390d42011-06-17 20:17:17 -0700665 int status = 0;
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800666 uint32_t param = *(uint32_t*)pParam;
667 uint32_t value = *(uint32_t*)pValue;
668 effect->session->config = effect->session->apm->GetConfig();
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530669 switch (param) {
670 case NS_PARAM_LEVEL:
671 effect->session->config.noise_suppression.level =
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800672 (webrtc::AudioProcessing::Config::NoiseSuppression::Level)value;
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530673 ALOGV("NsSetParameter() level %d", value);
674 break;
675 default:
676 ALOGW("NsSetParameter() unknown param %08x value %08x", param, value);
677 status = -EINVAL;
678 }
679 effect->session->apm->ApplyConfig(effect->session->config);
Alex Luebs766bf732015-12-14 21:32:13 -0800680
Eric Laurenta9390d42011-06-17 20:17:17 -0700681 return status;
682}
683
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800684void NsEnable(preproc_effect_t* effect) {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800685 effect->session->config = effect->session->apm->GetConfig();
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530686 effect->session->config.noise_suppression.enabled = true;
687 effect->session->apm->ApplyConfig(effect->session->config);
Eric Laurenta9390d42011-06-17 20:17:17 -0700688}
689
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800690void NsDisable(preproc_effect_t* effect) {
Steve Block3856b092011-10-20 11:56:00 +0100691 ALOGV("NsDisable");
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800692 effect->session->config = effect->session->apm->GetConfig();
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530693 effect->session->config.noise_suppression.enabled = false;
694 effect->session->apm->ApplyConfig(effect->session->config);
Eric Laurenta9390d42011-06-17 20:17:17 -0700695}
696
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800697static const preproc_ops_t sNsOps = {NsCreate, NsInit, NULL, NsEnable,
698 NsDisable, NsSetParameter, NsGetParameter, NULL};
Eric Laurenta9390d42011-06-17 20:17:17 -0700699
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800700static const preproc_ops_t* sPreProcOps[PREPROC_NUM_EFFECTS] = {&sAgcOps,
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800701 &sAgc2Ops,
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800702 &sAecOps, &sNsOps};
Eric Laurenta9390d42011-06-17 20:17:17 -0700703
704//------------------------------------------------------------------------------
705// Effect functions
706//------------------------------------------------------------------------------
707
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800708void Session_SetProcEnabled(preproc_session_t* session, uint32_t procId, bool enabled);
Eric Laurenta9390d42011-06-17 20:17:17 -0700709
710extern "C" const struct effect_interface_s sEffectInterface;
711extern "C" const struct effect_interface_s sEffectInterfaceReverse;
712
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800713#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 -0700714
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800715int Effect_SetState(preproc_effect_t* effect, uint32_t state) {
Eric Laurenta9390d42011-06-17 20:17:17 -0700716 int status = 0;
Steve Block3856b092011-10-20 11:56:00 +0100717 ALOGV("Effect_SetState proc %d, new %d old %d", effect->procId, state, effect->state);
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800718 switch (state) {
719 case PREPROC_EFFECT_STATE_INIT:
720 switch (effect->state) {
721 case PREPROC_EFFECT_STATE_ACTIVE:
722 effect->ops->disable(effect);
723 Session_SetProcEnabled(effect->session, effect->procId, false);
724 break;
725 case PREPROC_EFFECT_STATE_CONFIG:
726 case PREPROC_EFFECT_STATE_CREATED:
727 case PREPROC_EFFECT_STATE_INIT:
728 break;
729 default:
730 BAD_STATE_ABORT(effect->state, state);
731 }
732 break;
733 case PREPROC_EFFECT_STATE_CREATED:
734 switch (effect->state) {
735 case PREPROC_EFFECT_STATE_INIT:
736 status = effect->ops->create(effect);
737 break;
738 case PREPROC_EFFECT_STATE_CREATED:
739 case PREPROC_EFFECT_STATE_ACTIVE:
740 case PREPROC_EFFECT_STATE_CONFIG:
741 ALOGE("Effect_SetState invalid transition");
742 status = -ENOSYS;
743 break;
744 default:
745 BAD_STATE_ABORT(effect->state, state);
746 }
Andy Hung320fd852018-10-09 14:06:37 -0700747 break;
Eric Laurenta9390d42011-06-17 20:17:17 -0700748 case PREPROC_EFFECT_STATE_CONFIG:
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800749 switch (effect->state) {
750 case PREPROC_EFFECT_STATE_INIT:
751 ALOGE("Effect_SetState invalid transition");
752 status = -ENOSYS;
753 break;
754 case PREPROC_EFFECT_STATE_ACTIVE:
755 effect->ops->disable(effect);
756 Session_SetProcEnabled(effect->session, effect->procId, false);
757 break;
758 case PREPROC_EFFECT_STATE_CREATED:
759 case PREPROC_EFFECT_STATE_CONFIG:
760 break;
761 default:
762 BAD_STATE_ABORT(effect->state, state);
763 }
764 break;
765 case PREPROC_EFFECT_STATE_ACTIVE:
766 switch (effect->state) {
767 case PREPROC_EFFECT_STATE_INIT:
768 case PREPROC_EFFECT_STATE_CREATED:
769 ALOGE("Effect_SetState invalid transition");
770 status = -ENOSYS;
771 break;
772 case PREPROC_EFFECT_STATE_ACTIVE:
773 // enabling an already enabled effect is just ignored
774 break;
775 case PREPROC_EFFECT_STATE_CONFIG:
776 effect->ops->enable(effect);
777 Session_SetProcEnabled(effect->session, effect->procId, true);
778 break;
779 default:
780 BAD_STATE_ABORT(effect->state, state);
781 }
Eric Laurenta9390d42011-06-17 20:17:17 -0700782 break;
783 default:
784 BAD_STATE_ABORT(effect->state, state);
Eric Laurenta9390d42011-06-17 20:17:17 -0700785 }
786 if (status == 0) {
787 effect->state = state;
788 }
789 return status;
790}
791
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800792int Effect_Init(preproc_effect_t* effect, uint32_t procId) {
Eric Laurenta9390d42011-06-17 20:17:17 -0700793 if (HasReverseStream(procId)) {
794 effect->itfe = &sEffectInterfaceReverse;
795 } else {
796 effect->itfe = &sEffectInterface;
797 }
798 effect->ops = sPreProcOps[procId];
799 effect->procId = procId;
800 effect->state = PREPROC_EFFECT_STATE_INIT;
801 return 0;
802}
803
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800804int Effect_Create(preproc_effect_t* effect, preproc_session_t* session,
805 effect_handle_t* interface) {
Eric Laurenta9390d42011-06-17 20:17:17 -0700806 effect->session = session;
807 *interface = (effect_handle_t)&effect->itfe;
808 return Effect_SetState(effect, PREPROC_EFFECT_STATE_CREATED);
809}
810
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800811int Effect_Release(preproc_effect_t* effect) {
Eric Laurenta9390d42011-06-17 20:17:17 -0700812 return Effect_SetState(effect, PREPROC_EFFECT_STATE_INIT);
813}
814
Eric Laurenta9390d42011-06-17 20:17:17 -0700815//------------------------------------------------------------------------------
816// Session functions
817//------------------------------------------------------------------------------
818
819#define RESAMPLER_QUALITY SPEEX_RESAMPLER_QUALITY_VOIP
820
821static const int kPreprocDefaultSr = 16000;
822static const int kPreProcDefaultCnl = 1;
823
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800824int Session_Init(preproc_session_t* session) {
Eric Laurenta9390d42011-06-17 20:17:17 -0700825 size_t i;
826 int status = 0;
827
828 session->state = PREPROC_SESSION_STATE_INIT;
829 session->id = 0;
830 session->io = 0;
831 session->createdMsk = 0;
Eric Laurenta9390d42011-06-17 20:17:17 -0700832 for (i = 0; i < PREPROC_NUM_EFFECTS && status == 0; i++) {
833 status = Effect_Init(&session->effects[i], i);
834 }
835 return status;
836}
837
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800838extern "C" int Session_CreateEffect(preproc_session_t* session, int32_t procId,
839 effect_handle_t* interface) {
Eric Laurenta9390d42011-06-17 20:17:17 -0700840 int status = -ENOMEM;
841
Steve Block3856b092011-10-20 11:56:00 +0100842 ALOGV("Session_CreateEffect procId %d, createdMsk %08x", procId, session->createdMsk);
Eric Laurenta9390d42011-06-17 20:17:17 -0700843
844 if (session->createdMsk == 0) {
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530845 session->apm = session->ap_builder.Create();
846 if (session->apm == NULL) {
847 ALOGW("Session_CreateEffect could not get apm engine");
848 goto error;
849 }
Harish Mahendrakard510fdd2021-03-16 13:26:31 -0700850 session->frameCount = kPreprocDefaultSr / 100;
Eric Laurenta9390d42011-06-17 20:17:17 -0700851 session->samplingRate = kPreprocDefaultSr;
852 session->inChannelCount = kPreProcDefaultCnl;
853 session->outChannelCount = kPreProcDefaultCnl;
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530854 session->inputConfig.set_sample_rate_hz(kPreprocDefaultSr);
855 session->inputConfig.set_num_channels(kPreProcDefaultCnl);
856 session->outputConfig.set_sample_rate_hz(kPreprocDefaultSr);
857 session->outputConfig.set_num_channels(kPreProcDefaultCnl);
Eric Laurenta9390d42011-06-17 20:17:17 -0700858 session->revChannelCount = kPreProcDefaultCnl;
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530859 session->revConfig.set_sample_rate_hz(kPreprocDefaultSr);
860 session->revConfig.set_num_channels(kPreProcDefaultCnl);
Eric Laurenta9390d42011-06-17 20:17:17 -0700861 session->enabledMsk = 0;
862 session->processedMsk = 0;
863 session->revEnabledMsk = 0;
864 session->revProcessedMsk = 0;
Eric Laurenta9390d42011-06-17 20:17:17 -0700865 }
866 status = Effect_Create(&session->effects[procId], session, interface);
867 if (status < 0) {
868 goto error;
869 }
Steve Block3856b092011-10-20 11:56:00 +0100870 ALOGV("Session_CreateEffect OK");
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800871 session->createdMsk |= (1 << procId);
Eric Laurenta9390d42011-06-17 20:17:17 -0700872 return status;
873
874error:
875 if (session->createdMsk == 0) {
Jorge E. Moreira9e87e442022-12-22 11:30:27 -0800876 // Scoped_refptr will handle reference counting here
877 session->apm = nullptr;
Eric Laurenta9390d42011-06-17 20:17:17 -0700878 }
879 return status;
880}
881
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800882int Session_ReleaseEffect(preproc_session_t* session, preproc_effect_t* fx) {
Steve Block5ff1dd52012-01-05 23:22:43 +0000883 ALOGW_IF(Effect_Release(fx) != 0, " Effect_Release() failed for proc ID %d", fx->procId);
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800884 session->createdMsk &= ~(1 << fx->procId);
Eric Laurenta9390d42011-06-17 20:17:17 -0700885 if (session->createdMsk == 0) {
Jorge E. Moreira9e87e442022-12-22 11:30:27 -0800886 // Scoped_refptr will handle reference counting here
887 session->apm = nullptr;
Eric Laurentb20cf7d2019-04-05 19:37:34 -0700888 session->id = 0;
Eric Laurenta9390d42011-06-17 20:17:17 -0700889 }
890
891 return 0;
892}
893
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800894int Session_SetConfig(preproc_session_t* session, effect_config_t* config) {
Alex Luebs3f11ef02016-01-15 15:51:58 -0800895 uint32_t inCnl = audio_channel_count_from_in_mask(config->inputCfg.channels);
896 uint32_t outCnl = audio_channel_count_from_in_mask(config->outputCfg.channels);
Eric Laurenta9390d42011-06-17 20:17:17 -0700897
898 if (config->inputCfg.samplingRate != config->outputCfg.samplingRate ||
899 config->inputCfg.format != config->outputCfg.format ||
900 config->inputCfg.format != AUDIO_FORMAT_PCM_16_BIT) {
901 return -EINVAL;
902 }
903
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800904 ALOGV("Session_SetConfig sr %d cnl %08x", config->inputCfg.samplingRate,
905 config->inputCfg.channels);
Eric Laurenta9390d42011-06-17 20:17:17 -0700906
Eric Laurenta9390d42011-06-17 20:17:17 -0700907 session->samplingRate = config->inputCfg.samplingRate;
Harish Mahendrakard510fdd2021-03-16 13:26:31 -0700908 session->frameCount = session->samplingRate / 100;
Eric Laurenta9390d42011-06-17 20:17:17 -0700909 session->inChannelCount = inCnl;
910 session->outChannelCount = outCnl;
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530911 session->inputConfig.set_sample_rate_hz(session->samplingRate);
912 session->inputConfig.set_num_channels(inCnl);
913 session->outputConfig.set_sample_rate_hz(session->samplingRate);
914 session->outputConfig.set_num_channels(inCnl);
Eric Laurenta9390d42011-06-17 20:17:17 -0700915
916 session->revChannelCount = inCnl;
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530917 session->revConfig.set_sample_rate_hz(session->samplingRate);
918 session->revConfig.set_num_channels(inCnl);
Eric Laurenta9390d42011-06-17 20:17:17 -0700919
Eric Laurenta9390d42011-06-17 20:17:17 -0700920 session->state = PREPROC_SESSION_STATE_CONFIG;
921 return 0;
922}
923
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800924void Session_GetConfig(preproc_session_t* session, effect_config_t* config) {
Eric Laurent3d5188b2011-12-16 15:30:36 -0800925 memset(config, 0, sizeof(effect_config_t));
926 config->inputCfg.samplingRate = config->outputCfg.samplingRate = session->samplingRate;
927 config->inputCfg.format = config->outputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
Glenn Kastenab334fd2012-03-14 12:56:06 -0700928 config->inputCfg.channels = audio_channel_in_mask_from_count(session->inChannelCount);
929 // "out" doesn't mean output device, so this is the correct API to convert channel count to mask
930 config->outputCfg.channels = audio_channel_in_mask_from_count(session->outChannelCount);
Eric Laurent3d5188b2011-12-16 15:30:36 -0800931 config->inputCfg.mask = config->outputCfg.mask =
932 (EFFECT_CONFIG_SMP_RATE | EFFECT_CONFIG_CHANNELS | EFFECT_CONFIG_FORMAT);
933}
934
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800935int Session_SetReverseConfig(preproc_session_t* session, effect_config_t* config) {
Eric Laurenta9390d42011-06-17 20:17:17 -0700936 if (config->inputCfg.samplingRate != config->outputCfg.samplingRate ||
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800937 config->inputCfg.format != config->outputCfg.format ||
938 config->inputCfg.format != AUDIO_FORMAT_PCM_16_BIT) {
Eric Laurenta9390d42011-06-17 20:17:17 -0700939 return -EINVAL;
940 }
941
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800942 ALOGV("Session_SetReverseConfig sr %d cnl %08x", config->inputCfg.samplingRate,
943 config->inputCfg.channels);
Eric Laurenta9390d42011-06-17 20:17:17 -0700944
945 if (session->state < PREPROC_SESSION_STATE_CONFIG) {
946 return -ENOSYS;
947 }
948 if (config->inputCfg.samplingRate != session->samplingRate ||
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800949 config->inputCfg.format != AUDIO_FORMAT_PCM_16_BIT) {
Eric Laurenta9390d42011-06-17 20:17:17 -0700950 return -EINVAL;
951 }
Andy Hunge5412692014-05-16 11:25:07 -0700952 uint32_t inCnl = audio_channel_count_from_out_mask(config->inputCfg.channels);
Eric Laurenta9390d42011-06-17 20:17:17 -0700953 session->revChannelCount = inCnl;
Eric Laurent3f9c84c2012-04-03 15:36:53 -0700954
Eric Laurenta9390d42011-06-17 20:17:17 -0700955 return 0;
956}
957
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800958void Session_GetReverseConfig(preproc_session_t* session, effect_config_t* config) {
Eric Laurent3d5188b2011-12-16 15:30:36 -0800959 memset(config, 0, sizeof(effect_config_t));
960 config->inputCfg.samplingRate = config->outputCfg.samplingRate = session->samplingRate;
961 config->inputCfg.format = config->outputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
962 config->inputCfg.channels = config->outputCfg.channels =
Glenn Kastenab334fd2012-03-14 12:56:06 -0700963 audio_channel_in_mask_from_count(session->revChannelCount);
Eric Laurent3d5188b2011-12-16 15:30:36 -0800964 config->inputCfg.mask = config->outputCfg.mask =
965 (EFFECT_CONFIG_SMP_RATE | EFFECT_CONFIG_CHANNELS | EFFECT_CONFIG_FORMAT);
966}
967
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800968void Session_SetProcEnabled(preproc_session_t* session, uint32_t procId, bool enabled) {
Eric Laurenta9390d42011-06-17 20:17:17 -0700969 if (enabled) {
Eric Laurenta9390d42011-06-17 20:17:17 -0700970 session->enabledMsk |= (1 << procId);
971 if (HasReverseStream(procId)) {
Eric Laurenta9390d42011-06-17 20:17:17 -0700972 session->revEnabledMsk |= (1 << procId);
973 }
974 } else {
975 session->enabledMsk &= ~(1 << procId);
976 if (HasReverseStream(procId)) {
977 session->revEnabledMsk &= ~(1 << procId);
978 }
979 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800980 ALOGV("Session_SetProcEnabled proc %d, enabled %d enabledMsk %08x revEnabledMsk %08x", procId,
981 enabled, session->enabledMsk, session->revEnabledMsk);
Eric Laurenta9390d42011-06-17 20:17:17 -0700982 session->processedMsk = 0;
983 if (HasReverseStream(procId)) {
984 session->revProcessedMsk = 0;
985 }
986}
987
988//------------------------------------------------------------------------------
989// Bundle functions
990//------------------------------------------------------------------------------
991
992static int sInitStatus = 1;
993static preproc_session_t sSessions[PREPROC_NUM_SESSIONS];
994
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800995preproc_session_t* PreProc_GetSession(int32_t procId, int32_t sessionId, int32_t ioId) {
Eric Laurenta9390d42011-06-17 20:17:17 -0700996 size_t i;
Eric Laurenta9390d42011-06-17 20:17:17 -0700997 for (i = 0; i < PREPROC_NUM_SESSIONS; i++) {
Eric Laurentb20cf7d2019-04-05 19:37:34 -0700998 if (sSessions[i].id == sessionId) {
Eric Laurenta9390d42011-06-17 20:17:17 -0700999 if (sSessions[i].createdMsk & (1 << procId)) {
1000 return NULL;
1001 }
1002 return &sSessions[i];
1003 }
1004 }
1005 for (i = 0; i < PREPROC_NUM_SESSIONS; i++) {
Eric Laurentb20cf7d2019-04-05 19:37:34 -07001006 if (sSessions[i].id == 0) {
Eric Laurenta9390d42011-06-17 20:17:17 -07001007 sSessions[i].id = sessionId;
1008 sSessions[i].io = ioId;
1009 return &sSessions[i];
1010 }
1011 }
1012 return NULL;
1013}
1014
Eric Laurenta9390d42011-06-17 20:17:17 -07001015int PreProc_Init() {
1016 size_t i;
1017 int status = 0;
1018
1019 if (sInitStatus <= 0) {
1020 return sInitStatus;
1021 }
1022 for (i = 0; i < PREPROC_NUM_SESSIONS && status == 0; i++) {
1023 status = Session_Init(&sSessions[i]);
1024 }
1025 sInitStatus = status;
1026 return sInitStatus;
1027}
1028
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001029const effect_descriptor_t* PreProc_GetDescriptor(const effect_uuid_t* uuid) {
Eric Laurenta9390d42011-06-17 20:17:17 -07001030 size_t i;
1031 for (i = 0; i < PREPROC_NUM_EFFECTS; i++) {
1032 if (memcmp(&sDescriptors[i]->uuid, uuid, sizeof(effect_uuid_t)) == 0) {
1033 return sDescriptors[i];
1034 }
1035 }
1036 return NULL;
1037}
1038
Eric Laurenta9390d42011-06-17 20:17:17 -07001039extern "C" {
1040
1041//------------------------------------------------------------------------------
1042// Effect Control Interface Implementation
1043//------------------------------------------------------------------------------
1044
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001045int PreProcessingFx_Process(effect_handle_t self, audio_buffer_t* inBuffer,
1046 audio_buffer_t* outBuffer) {
1047 preproc_effect_t* effect = (preproc_effect_t*)self;
Eric Laurenta9390d42011-06-17 20:17:17 -07001048
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001049 if (effect == NULL) {
Steve Block3856b092011-10-20 11:56:00 +01001050 ALOGV("PreProcessingFx_Process() ERROR effect == NULL");
Eric Laurenta9390d42011-06-17 20:17:17 -07001051 return -EINVAL;
1052 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001053 preproc_session_t* session = (preproc_session_t*)effect->session;
Eric Laurenta9390d42011-06-17 20:17:17 -07001054
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001055 if (inBuffer == NULL || inBuffer->raw == NULL || outBuffer == NULL || outBuffer->raw == NULL) {
Steve Block5ff1dd52012-01-05 23:22:43 +00001056 ALOGW("PreProcessingFx_Process() ERROR bad pointer");
Eric Laurenta9390d42011-06-17 20:17:17 -07001057 return -EINVAL;
1058 }
1059
Harish Mahendrakard510fdd2021-03-16 13:26:31 -07001060 if (inBuffer->frameCount != outBuffer->frameCount) {
1061 ALOGW("inBuffer->frameCount %zu is not equal to outBuffer->frameCount %zu",
1062 inBuffer->frameCount, outBuffer->frameCount);
1063 return -EINVAL;
1064 }
1065
1066 if (inBuffer->frameCount != session->frameCount) {
1067 ALOGW("inBuffer->frameCount %zu != %zu representing 10ms at sampling rate %d",
1068 inBuffer->frameCount, session->frameCount, session->samplingRate);
1069 return -EINVAL;
1070 }
1071
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001072 session->processedMsk |= (1 << effect->procId);
Eric Laurenta9390d42011-06-17 20:17:17 -07001073
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001074 // ALOGV("PreProcessingFx_Process In %d frames enabledMsk %08x processedMsk %08x",
1075 // inBuffer->frameCount, session->enabledMsk, session->processedMsk);
Eric Laurenta9390d42011-06-17 20:17:17 -07001076 if ((session->processedMsk & session->enabledMsk) == session->enabledMsk) {
1077 effect->session->processedMsk = 0;
Saketh Sathuvalli08337032020-09-22 21:13:45 +05301078 if (int status = effect->session->apm->ProcessStream(
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001079 (const int16_t* const)inBuffer->s16,
1080 (const webrtc::StreamConfig)effect->session->inputConfig,
1081 (const webrtc::StreamConfig)effect->session->outputConfig,
1082 (int16_t* const)outBuffer->s16);
1083 status != 0) {
Saketh Sathuvalli08337032020-09-22 21:13:45 +05301084 ALOGE("Process Stream failed with error %d\n", status);
1085 return status;
1086 }
Eric Laurenta9390d42011-06-17 20:17:17 -07001087 return 0;
1088 } else {
1089 return -ENODATA;
1090 }
1091}
1092
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001093int PreProcessingFx_Command(effect_handle_t self, uint32_t cmdCode, uint32_t cmdSize,
1094 void* pCmdData, uint32_t* replySize, void* pReplyData) {
1095 preproc_effect_t* effect = (preproc_effect_t*)self;
Eric Laurenta9390d42011-06-17 20:17:17 -07001096
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001097 if (effect == NULL) {
Eric Laurenta9390d42011-06-17 20:17:17 -07001098 return -EINVAL;
1099 }
1100
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001101 // ALOGV("PreProcessingFx_Command: command %d cmdSize %d",cmdCode, cmdSize);
Eric Laurenta9390d42011-06-17 20:17:17 -07001102
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001103 switch (cmdCode) {
Eric Laurenta9390d42011-06-17 20:17:17 -07001104 case EFFECT_CMD_INIT:
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001105 if (pReplyData == NULL || *replySize != sizeof(int)) {
Eric Laurenta9390d42011-06-17 20:17:17 -07001106 return -EINVAL;
1107 }
1108 if (effect->ops->init) {
1109 effect->ops->init(effect);
1110 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001111 *(int*)pReplyData = 0;
Eric Laurenta9390d42011-06-17 20:17:17 -07001112 break;
1113
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001114 case EFFECT_CMD_SET_CONFIG: {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001115 if (pCmdData == NULL || cmdSize != sizeof(effect_config_t) || pReplyData == NULL ||
1116 *replySize != sizeof(int)) {
Steve Block3856b092011-10-20 11:56:00 +01001117 ALOGV("PreProcessingFx_Command cmdCode Case: "
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001118 "EFFECT_CMD_SET_CONFIG: ERROR");
Eric Laurenta9390d42011-06-17 20:17:17 -07001119 return -EINVAL;
1120 }
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001121#ifdef DUAL_MIC_TEST
1122 // make sure that the config command is accepted by making as if all effects were
1123 // disabled: this is OK for functional tests
1124 uint32_t enabledMsk = effect->session->enabledMsk;
1125 if (gDualMicEnabled) {
1126 effect->session->enabledMsk = 0;
1127 }
1128#endif
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001129 *(int*)pReplyData = Session_SetConfig(effect->session, (effect_config_t*)pCmdData);
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001130#ifdef DUAL_MIC_TEST
1131 if (gDualMicEnabled) {
1132 effect->session->enabledMsk = enabledMsk;
1133 }
1134#endif
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001135 if (*(int*)pReplyData != 0) {
Eric Laurenta9390d42011-06-17 20:17:17 -07001136 break;
1137 }
Eric Laurent76533e92012-02-17 17:52:04 -08001138 if (effect->state != PREPROC_EFFECT_STATE_ACTIVE) {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001139 *(int*)pReplyData = Effect_SetState(effect, PREPROC_EFFECT_STATE_CONFIG);
Eric Laurent76533e92012-02-17 17:52:04 -08001140 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001141 } break;
Eric Laurenta9390d42011-06-17 20:17:17 -07001142
Eric Laurent3d5188b2011-12-16 15:30:36 -08001143 case EFFECT_CMD_GET_CONFIG:
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001144 if (pReplyData == NULL || *replySize != sizeof(effect_config_t)) {
Eric Laurent3d5188b2011-12-16 15:30:36 -08001145 ALOGV("\tLVM_ERROR : PreProcessingFx_Command cmdCode Case: "
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001146 "EFFECT_CMD_GET_CONFIG: ERROR");
Eric Laurent3d5188b2011-12-16 15:30:36 -08001147 return -EINVAL;
1148 }
1149
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001150 Session_GetConfig(effect->session, (effect_config_t*)pReplyData);
Eric Laurent3d5188b2011-12-16 15:30:36 -08001151 break;
1152
1153 case EFFECT_CMD_SET_CONFIG_REVERSE:
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001154 if (pCmdData == NULL || cmdSize != sizeof(effect_config_t) || pReplyData == NULL ||
Eric Laurent3d5188b2011-12-16 15:30:36 -08001155 *replySize != sizeof(int)) {
Steve Block3856b092011-10-20 11:56:00 +01001156 ALOGV("PreProcessingFx_Command cmdCode Case: "
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001157 "EFFECT_CMD_SET_CONFIG_REVERSE: ERROR");
Eric Laurenta9390d42011-06-17 20:17:17 -07001158 return -EINVAL;
1159 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001160 *(int*)pReplyData =
1161 Session_SetReverseConfig(effect->session, (effect_config_t*)pCmdData);
1162 if (*(int*)pReplyData != 0) {
Eric Laurenta9390d42011-06-17 20:17:17 -07001163 break;
1164 }
1165 break;
1166
Eric Laurent3d5188b2011-12-16 15:30:36 -08001167 case EFFECT_CMD_GET_CONFIG_REVERSE:
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001168 if (pReplyData == NULL || *replySize != sizeof(effect_config_t)) {
Eric Laurent3d5188b2011-12-16 15:30:36 -08001169 ALOGV("PreProcessingFx_Command cmdCode Case: "
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001170 "EFFECT_CMD_GET_CONFIG_REVERSE: ERROR");
Eric Laurent3d5188b2011-12-16 15:30:36 -08001171 return -EINVAL;
1172 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001173 Session_GetReverseConfig(effect->session, (effect_config_t*)pCmdData);
Eric Laurent3d5188b2011-12-16 15:30:36 -08001174 break;
1175
Eric Laurenta9390d42011-06-17 20:17:17 -07001176 case EFFECT_CMD_RESET:
1177 if (effect->ops->reset) {
1178 effect->ops->reset(effect);
1179 }
1180 break;
1181
Eric Laurent0f714a42015-06-19 15:33:57 -07001182 case EFFECT_CMD_GET_PARAM: {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001183 effect_param_t* p = (effect_param_t*)pCmdData;
Eric Laurent0f714a42015-06-19 15:33:57 -07001184
1185 if (pCmdData == NULL || cmdSize < sizeof(effect_param_t) ||
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001186 cmdSize < (sizeof(effect_param_t) + p->psize) || pReplyData == NULL ||
1187 replySize == NULL || *replySize < (sizeof(effect_param_t) + p->psize)) {
Steve Block3856b092011-10-20 11:56:00 +01001188 ALOGV("PreProcessingFx_Command cmdCode Case: "
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001189 "EFFECT_CMD_GET_PARAM: ERROR");
Eric Laurenta9390d42011-06-17 20:17:17 -07001190 return -EINVAL;
1191 }
Eric Laurenta9390d42011-06-17 20:17:17 -07001192
1193 memcpy(pReplyData, pCmdData, sizeof(effect_param_t) + p->psize);
1194
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001195 p = (effect_param_t*)pReplyData;
Eric Laurenta9390d42011-06-17 20:17:17 -07001196
1197 int voffset = ((p->psize - 1) / sizeof(int32_t) + 1) * sizeof(int32_t);
1198
1199 if (effect->ops->get_parameter) {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001200 p->status =
1201 effect->ops->get_parameter(effect, p->data, &p->vsize, p->data + voffset);
Eric Laurenta9390d42011-06-17 20:17:17 -07001202 *replySize = sizeof(effect_param_t) + voffset + p->vsize;
1203 }
1204 } break;
1205
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001206 case EFFECT_CMD_SET_PARAM: {
1207 if (pCmdData == NULL || cmdSize < sizeof(effect_param_t) || pReplyData == NULL ||
1208 replySize == NULL || *replySize != sizeof(int32_t)) {
Steve Block3856b092011-10-20 11:56:00 +01001209 ALOGV("PreProcessingFx_Command cmdCode Case: "
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001210 "EFFECT_CMD_SET_PARAM: ERROR");
Eric Laurenta9390d42011-06-17 20:17:17 -07001211 return -EINVAL;
1212 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001213 effect_param_t* p = (effect_param_t*)pCmdData;
Eric Laurenta9390d42011-06-17 20:17:17 -07001214
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001215 if (p->psize != sizeof(int32_t)) {
Steve Block3856b092011-10-20 11:56:00 +01001216 ALOGV("PreProcessingFx_Command cmdCode Case: "
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001217 "EFFECT_CMD_SET_PARAM: ERROR, psize is not sizeof(int32_t)");
Eric Laurenta9390d42011-06-17 20:17:17 -07001218 return -EINVAL;
1219 }
1220 if (effect->ops->set_parameter) {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001221 *(int*)pReplyData =
1222 effect->ops->set_parameter(effect, (void*)p->data, p->data + p->psize);
Eric Laurenta9390d42011-06-17 20:17:17 -07001223 }
1224 } break;
1225
1226 case EFFECT_CMD_ENABLE:
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001227 if (pReplyData == NULL || replySize == NULL || *replySize != sizeof(int)) {
Steve Block3856b092011-10-20 11:56:00 +01001228 ALOGV("PreProcessingFx_Command cmdCode Case: EFFECT_CMD_ENABLE: ERROR");
Eric Laurenta9390d42011-06-17 20:17:17 -07001229 return -EINVAL;
1230 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001231 *(int*)pReplyData = Effect_SetState(effect, PREPROC_EFFECT_STATE_ACTIVE);
Eric Laurenta9390d42011-06-17 20:17:17 -07001232 break;
1233
1234 case EFFECT_CMD_DISABLE:
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001235 if (pReplyData == NULL || replySize == NULL || *replySize != sizeof(int)) {
Steve Block3856b092011-10-20 11:56:00 +01001236 ALOGV("PreProcessingFx_Command cmdCode Case: EFFECT_CMD_DISABLE: ERROR");
Eric Laurenta9390d42011-06-17 20:17:17 -07001237 return -EINVAL;
1238 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001239 *(int*)pReplyData = Effect_SetState(effect, PREPROC_EFFECT_STATE_CONFIG);
Eric Laurenta9390d42011-06-17 20:17:17 -07001240 break;
1241
1242 case EFFECT_CMD_SET_DEVICE:
1243 case EFFECT_CMD_SET_INPUT_DEVICE:
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001244 if (pCmdData == NULL || cmdSize != sizeof(uint32_t)) {
Steve Block3856b092011-10-20 11:56:00 +01001245 ALOGV("PreProcessingFx_Command cmdCode Case: EFFECT_CMD_SET_DEVICE: ERROR");
Eric Laurenta9390d42011-06-17 20:17:17 -07001246 return -EINVAL;
1247 }
1248
1249 if (effect->ops->set_device) {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001250 effect->ops->set_device(effect, *(uint32_t*)pCmdData);
Eric Laurenta9390d42011-06-17 20:17:17 -07001251 }
1252 break;
1253
1254 case EFFECT_CMD_SET_VOLUME:
1255 case EFFECT_CMD_SET_AUDIO_MODE:
1256 break;
1257
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001258#ifdef DUAL_MIC_TEST
1259 ///// test commands start
1260 case PREPROC_CMD_DUAL_MIC_ENABLE: {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001261 if (pCmdData == NULL || cmdSize != sizeof(uint32_t) || pReplyData == NULL ||
1262 replySize == NULL) {
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001263 ALOGE("PreProcessingFx_Command cmdCode Case: "
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001264 "PREPROC_CMD_DUAL_MIC_ENABLE: ERROR");
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001265 *replySize = 0;
1266 return -EINVAL;
1267 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001268 gDualMicEnabled = *(bool*)pCmdData;
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001269 if (gDualMicEnabled) {
1270 effect->aux_channels_on = sHasAuxChannels[effect->procId];
1271 } else {
1272 effect->aux_channels_on = false;
1273 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001274 effect->cur_channel_config =
1275 (effect->session->inChannelCount == 1) ? CHANNEL_CFG_MONO : CHANNEL_CFG_STEREO;
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001276
1277 ALOGV("PREPROC_CMD_DUAL_MIC_ENABLE: %s", gDualMicEnabled ? "enabled" : "disabled");
1278 *replySize = sizeof(int);
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001279 *(int*)pReplyData = 0;
1280 } break;
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001281 case PREPROC_CMD_DUAL_MIC_PCM_DUMP_START: {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001282 if (pCmdData == NULL || pReplyData == NULL || replySize == NULL) {
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001283 ALOGE("PreProcessingFx_Command cmdCode Case: "
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001284 "PREPROC_CMD_DUAL_MIC_PCM_DUMP_START: ERROR");
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001285 *replySize = 0;
1286 return -EINVAL;
1287 }
1288 pthread_mutex_lock(&gPcmDumpLock);
1289 if (gPcmDumpFh != NULL) {
1290 fclose(gPcmDumpFh);
1291 gPcmDumpFh = NULL;
1292 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001293 char* path = strndup((char*)pCmdData, cmdSize);
1294 gPcmDumpFh = fopen((char*)path, "wb");
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001295 pthread_mutex_unlock(&gPcmDumpLock);
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001296 ALOGV("PREPROC_CMD_DUAL_MIC_PCM_DUMP_START: path %s gPcmDumpFh %p", path, gPcmDumpFh);
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001297 ALOGE_IF(gPcmDumpFh <= 0, "gPcmDumpFh open error %d %s", errno, strerror(errno));
1298 free(path);
1299 *replySize = sizeof(int);
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001300 *(int*)pReplyData = 0;
1301 } break;
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001302 case PREPROC_CMD_DUAL_MIC_PCM_DUMP_STOP: {
1303 if (pReplyData == NULL || replySize == NULL) {
1304 ALOGE("PreProcessingFx_Command cmdCode Case: "
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001305 "PREPROC_CMD_DUAL_MIC_PCM_DUMP_STOP: ERROR");
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001306 *replySize = 0;
1307 return -EINVAL;
1308 }
1309 pthread_mutex_lock(&gPcmDumpLock);
1310 if (gPcmDumpFh != NULL) {
1311 fclose(gPcmDumpFh);
1312 gPcmDumpFh = NULL;
1313 }
1314 pthread_mutex_unlock(&gPcmDumpLock);
1315 ALOGV("PREPROC_CMD_DUAL_MIC_PCM_DUMP_STOP");
1316 *replySize = sizeof(int);
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001317 *(int*)pReplyData = 0;
1318 } break;
1319 ///// test commands end
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001320
1321 case EFFECT_CMD_GET_FEATURE_SUPPORTED_CONFIGS: {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001322 if (!gDualMicEnabled) {
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001323 return -EINVAL;
1324 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001325 if (pCmdData == NULL || cmdSize != 2 * sizeof(uint32_t) || pReplyData == NULL ||
1326 replySize == NULL) {
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001327 ALOGE("PreProcessingFx_Command cmdCode Case: "
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001328 "EFFECT_CMD_GET_FEATURE_SUPPORTED_CONFIGS: ERROR");
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001329 *replySize = 0;
1330 return -EINVAL;
1331 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001332 if (*(uint32_t*)pCmdData != EFFECT_FEATURE_AUX_CHANNELS || !effect->aux_channels_on) {
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001333 ALOGV("PreProcessingFx_Command feature EFFECT_FEATURE_AUX_CHANNELS not supported by"
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001334 " fx %d",
1335 effect->procId);
1336 *(uint32_t*)pReplyData = -ENOSYS;
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001337 *replySize = sizeof(uint32_t);
1338 break;
1339 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001340 size_t num_configs = *((uint32_t*)pCmdData + 1);
1341 if (*replySize < (2 * sizeof(uint32_t) + num_configs * sizeof(channel_config_t))) {
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001342 *replySize = 0;
1343 return -EINVAL;
1344 }
1345
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001346 *((uint32_t*)pReplyData + 1) = CHANNEL_CFG_CNT;
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001347 if (num_configs < CHANNEL_CFG_CNT ||
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001348 *replySize < (2 * sizeof(uint32_t) + CHANNEL_CFG_CNT * sizeof(channel_config_t))) {
1349 *(uint32_t*)pReplyData = -ENOMEM;
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001350 } else {
1351 num_configs = CHANNEL_CFG_CNT;
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001352 *(uint32_t*)pReplyData = 0;
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001353 }
1354 ALOGV("PreProcessingFx_Command EFFECT_CMD_GET_FEATURE_SUPPORTED_CONFIGS num config %d",
1355 num_configs);
1356
1357 *replySize = 2 * sizeof(uint32_t) + num_configs * sizeof(channel_config_t);
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001358 *((uint32_t*)pReplyData + 1) = num_configs;
1359 memcpy((uint32_t*)pReplyData + 2, &sDualMicConfigs,
1360 num_configs * sizeof(channel_config_t));
1361 } break;
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001362 case EFFECT_CMD_GET_FEATURE_CONFIG:
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001363 if (!gDualMicEnabled) {
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001364 return -EINVAL;
1365 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001366 if (pCmdData == NULL || cmdSize != sizeof(uint32_t) || pReplyData == NULL ||
1367 replySize == NULL || *replySize < sizeof(uint32_t) + sizeof(channel_config_t)) {
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001368 ALOGE("PreProcessingFx_Command cmdCode Case: "
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001369 "EFFECT_CMD_GET_FEATURE_CONFIG: ERROR");
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001370 return -EINVAL;
1371 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001372 if (*(uint32_t*)pCmdData != EFFECT_FEATURE_AUX_CHANNELS || !effect->aux_channels_on) {
1373 *(uint32_t*)pReplyData = -ENOSYS;
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001374 *replySize = sizeof(uint32_t);
1375 break;
1376 }
1377 ALOGV("PreProcessingFx_Command EFFECT_CMD_GET_FEATURE_CONFIG");
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001378 *(uint32_t*)pReplyData = 0;
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001379 *replySize = sizeof(uint32_t) + sizeof(channel_config_t);
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001380 memcpy((uint32_t*)pReplyData + 1, &sDualMicConfigs[effect->cur_channel_config],
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001381 sizeof(channel_config_t));
1382 break;
1383 case EFFECT_CMD_SET_FEATURE_CONFIG: {
1384 ALOGV("PreProcessingFx_Command EFFECT_CMD_SET_FEATURE_CONFIG: "
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001385 "gDualMicEnabled %d effect->aux_channels_on %d",
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001386 gDualMicEnabled, effect->aux_channels_on);
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001387 if (!gDualMicEnabled) {
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001388 return -EINVAL;
1389 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001390 if (pCmdData == NULL || cmdSize != (sizeof(uint32_t) + sizeof(channel_config_t)) ||
1391 pReplyData == NULL || replySize == NULL || *replySize < sizeof(uint32_t)) {
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001392 ALOGE("PreProcessingFx_Command cmdCode Case: "
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001393 "EFFECT_CMD_SET_FEATURE_CONFIG: ERROR\n"
1394 "pCmdData %p cmdSize %d pReplyData %p replySize %p *replySize %d",
1395 pCmdData, cmdSize, pReplyData, replySize, replySize ? *replySize : -1);
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001396 return -EINVAL;
1397 }
1398 *replySize = sizeof(uint32_t);
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001399 if (*(uint32_t*)pCmdData != EFFECT_FEATURE_AUX_CHANNELS || !effect->aux_channels_on) {
1400 *(uint32_t*)pReplyData = -ENOSYS;
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001401 ALOGV("PreProcessingFx_Command cmdCode Case: "
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001402 "EFFECT_CMD_SET_FEATURE_CONFIG: ERROR\n"
1403 "CmdData %d effect->aux_channels_on %d",
1404 *(uint32_t*)pCmdData, effect->aux_channels_on);
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001405 break;
1406 }
1407 size_t i;
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001408 for (i = 0; i < CHANNEL_CFG_CNT; i++) {
1409 if (memcmp((uint32_t*)pCmdData + 1, &sDualMicConfigs[i],
1410 sizeof(channel_config_t)) == 0) {
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001411 break;
1412 }
1413 }
1414 if (i == CHANNEL_CFG_CNT) {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001415 *(uint32_t*)pReplyData = -EINVAL;
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001416 ALOGW("PreProcessingFx_Command EFFECT_CMD_SET_FEATURE_CONFIG invalid config"
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001417 "[%08x].[%08x]",
1418 *((uint32_t*)pCmdData + 1), *((uint32_t*)pCmdData + 2));
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001419 } else {
1420 effect->cur_channel_config = i;
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001421 *(uint32_t*)pReplyData = 0;
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001422 ALOGV("PreProcessingFx_Command EFFECT_CMD_SET_FEATURE_CONFIG New config"
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001423 "[%08x].[%08x]",
1424 sDualMicConfigs[i].main_channels, sDualMicConfigs[i].aux_channels);
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001425 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001426 } break;
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001427#endif
Eric Laurenta9390d42011-06-17 20:17:17 -07001428 default:
1429 return -EINVAL;
1430 }
1431 return 0;
1432}
1433
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001434int PreProcessingFx_GetDescriptor(effect_handle_t self, effect_descriptor_t* pDescriptor) {
1435 preproc_effect_t* effect = (preproc_effect_t*)self;
Eric Laurenta9390d42011-06-17 20:17:17 -07001436
1437 if (effect == NULL || pDescriptor == NULL) {
1438 return -EINVAL;
1439 }
1440
Glenn Kastena189a682012-02-20 12:16:30 -08001441 *pDescriptor = *sDescriptors[effect->procId];
Eric Laurenta9390d42011-06-17 20:17:17 -07001442
1443 return 0;
1444}
1445
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001446int PreProcessingFx_ProcessReverse(effect_handle_t self, audio_buffer_t* inBuffer,
Rivukanta Bhattacharya013e02e2021-03-12 05:50:55 +05301447 audio_buffer_t* outBuffer) {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001448 preproc_effect_t* effect = (preproc_effect_t*)self;
Eric Laurenta9390d42011-06-17 20:17:17 -07001449
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001450 if (effect == NULL) {
Steve Block5ff1dd52012-01-05 23:22:43 +00001451 ALOGW("PreProcessingFx_ProcessReverse() ERROR effect == NULL");
Eric Laurenta9390d42011-06-17 20:17:17 -07001452 return -EINVAL;
1453 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001454 preproc_session_t* session = (preproc_session_t*)effect->session;
Eric Laurenta9390d42011-06-17 20:17:17 -07001455
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001456 if (inBuffer == NULL || inBuffer->raw == NULL) {
Steve Block5ff1dd52012-01-05 23:22:43 +00001457 ALOGW("PreProcessingFx_ProcessReverse() ERROR bad pointer");
Eric Laurenta9390d42011-06-17 20:17:17 -07001458 return -EINVAL;
1459 }
1460
Harish Mahendrakard510fdd2021-03-16 13:26:31 -07001461 if (inBuffer->frameCount != outBuffer->frameCount) {
1462 ALOGW("inBuffer->frameCount %zu is not equal to outBuffer->frameCount %zu",
1463 inBuffer->frameCount, outBuffer->frameCount);
1464 return -EINVAL;
1465 }
1466
1467 if (inBuffer->frameCount != session->frameCount) {
1468 ALOGW("inBuffer->frameCount %zu != %zu representing 10ms at sampling rate %d",
1469 inBuffer->frameCount, session->frameCount, session->samplingRate);
1470 return -EINVAL;
1471 }
1472
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001473 session->revProcessedMsk |= (1 << effect->procId);
Eric Laurenta9390d42011-06-17 20:17:17 -07001474
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001475 // ALOGV("PreProcessingFx_ProcessReverse In %d frames revEnabledMsk %08x revProcessedMsk
1476 // %08x",
1477 // inBuffer->frameCount, session->revEnabledMsk, session->revProcessedMsk);
Eric Laurenta9390d42011-06-17 20:17:17 -07001478
1479 if ((session->revProcessedMsk & session->revEnabledMsk) == session->revEnabledMsk) {
1480 effect->session->revProcessedMsk = 0;
Saketh Sathuvalli08337032020-09-22 21:13:45 +05301481 if (int status = effect->session->apm->ProcessReverseStream(
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001482 (const int16_t* const)inBuffer->s16,
1483 (const webrtc::StreamConfig)effect->session->revConfig,
1484 (const webrtc::StreamConfig)effect->session->revConfig,
1485 (int16_t* const)outBuffer->s16);
1486 status != 0) {
Saketh Sathuvalli08337032020-09-22 21:13:45 +05301487 ALOGE("Process Reverse Stream failed with error %d\n", status);
1488 return status;
1489 }
Eric Laurenta9390d42011-06-17 20:17:17 -07001490 return 0;
1491 } else {
1492 return -ENODATA;
1493 }
1494}
1495
Eric Laurenta9390d42011-06-17 20:17:17 -07001496// effect_handle_t interface implementation for effect
1497const struct effect_interface_s sEffectInterface = {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001498 PreProcessingFx_Process, PreProcessingFx_Command, PreProcessingFx_GetDescriptor, NULL};
Eric Laurenta9390d42011-06-17 20:17:17 -07001499
1500const struct effect_interface_s sEffectInterfaceReverse = {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001501 PreProcessingFx_Process, PreProcessingFx_Command, PreProcessingFx_GetDescriptor,
1502 PreProcessingFx_ProcessReverse};
Eric Laurenta9390d42011-06-17 20:17:17 -07001503
1504//------------------------------------------------------------------------------
1505// Effect Library Interface Implementation
1506//------------------------------------------------------------------------------
1507
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001508int PreProcessingLib_Create(const effect_uuid_t* uuid, int32_t sessionId, int32_t ioId,
1509 effect_handle_t* pInterface) {
Steve Block3856b092011-10-20 11:56:00 +01001510 ALOGV("EffectCreate: uuid: %08x session %d IO: %d", uuid->timeLow, sessionId, ioId);
Eric Laurenta9390d42011-06-17 20:17:17 -07001511
1512 int status;
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001513 const effect_descriptor_t* desc;
1514 preproc_session_t* session;
Eric Laurenta9390d42011-06-17 20:17:17 -07001515 uint32_t procId;
1516
1517 if (PreProc_Init() != 0) {
1518 return sInitStatus;
1519 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001520 desc = PreProc_GetDescriptor(uuid);
Eric Laurenta9390d42011-06-17 20:17:17 -07001521 if (desc == NULL) {
Steve Block5ff1dd52012-01-05 23:22:43 +00001522 ALOGW("EffectCreate: fx not found uuid: %08x", uuid->timeLow);
Eric Laurenta9390d42011-06-17 20:17:17 -07001523 return -EINVAL;
1524 }
1525 procId = UuidToProcId(&desc->type);
1526
1527 session = PreProc_GetSession(procId, sessionId, ioId);
1528 if (session == NULL) {
Steve Block5ff1dd52012-01-05 23:22:43 +00001529 ALOGW("EffectCreate: no more session available");
Eric Laurenta9390d42011-06-17 20:17:17 -07001530 return -EINVAL;
1531 }
1532
1533 status = Session_CreateEffect(session, procId, pInterface);
1534
1535 if (status < 0 && session->createdMsk == 0) {
Eric Laurentb20cf7d2019-04-05 19:37:34 -07001536 session->id = 0;
Eric Laurenta9390d42011-06-17 20:17:17 -07001537 }
1538 return status;
1539}
1540
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001541int PreProcessingLib_Release(effect_handle_t interface) {
Steve Block3856b092011-10-20 11:56:00 +01001542 ALOGV("EffectRelease start %p", interface);
Eric Laurenta9390d42011-06-17 20:17:17 -07001543 if (PreProc_Init() != 0) {
1544 return sInitStatus;
1545 }
1546
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001547 preproc_effect_t* fx = (preproc_effect_t*)interface;
Eric Laurenta9390d42011-06-17 20:17:17 -07001548
Eric Laurentb20cf7d2019-04-05 19:37:34 -07001549 if (fx->session->id == 0) {
Eric Laurenta9390d42011-06-17 20:17:17 -07001550 return -EINVAL;
1551 }
1552 return Session_ReleaseEffect(fx->session, fx);
1553}
1554
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001555int PreProcessingLib_GetDescriptor(const effect_uuid_t* uuid, effect_descriptor_t* pDescriptor) {
1556 if (pDescriptor == NULL || uuid == NULL) {
Eric Laurenta9390d42011-06-17 20:17:17 -07001557 return -EINVAL;
1558 }
1559
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001560 const effect_descriptor_t* desc = PreProc_GetDescriptor(uuid);
Eric Laurenta9390d42011-06-17 20:17:17 -07001561 if (desc == NULL) {
Steve Block3856b092011-10-20 11:56:00 +01001562 ALOGV("PreProcessingLib_GetDescriptor() not found");
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001563 return -EINVAL;
Eric Laurenta9390d42011-06-17 20:17:17 -07001564 }
1565
Steve Block3856b092011-10-20 11:56:00 +01001566 ALOGV("PreProcessingLib_GetDescriptor() got fx %s", desc->name);
Eric Laurenta9390d42011-06-17 20:17:17 -07001567
Glenn Kastena189a682012-02-20 12:16:30 -08001568 *pDescriptor = *desc;
Eric Laurenta9390d42011-06-17 20:17:17 -07001569 return 0;
1570}
1571
Marco Nelissen7f16b192012-10-25 16:05:57 -07001572// This is the only symbol that needs to be exported
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001573__attribute__((visibility("default"))) audio_effect_library_t AUDIO_EFFECT_LIBRARY_INFO_SYM = {
1574 .tag = AUDIO_EFFECT_LIBRARY_TAG,
1575 .version = EFFECT_LIBRARY_API_VERSION,
1576 .name = "Audio Preprocessing Library",
1577 .implementor = "The Android Open Source Project",
1578 .create_effect = PreProcessingLib_Create,
1579 .release_effect = PreProcessingLib_Release,
1580 .get_descriptor = PreProcessingLib_GetDescriptor};
Eric Laurenta9390d42011-06-17 20:17:17 -07001581
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001582}; // extern "C"