blob: 03ccc3478fa3b23db02a7139d16c9688d380573c [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 Mahendrakarb6926c72020-11-27 15:22:44 -0800108 size_t apmFrameCount; // buffer size for webRTC process (10 ms)
109 uint32_t apmSamplingRate; // webRTC APM sampling rate (8/16 or 32 kHz)
110 size_t frameCount; // buffer size before input resampler ( <=> apmFrameCount)
111 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 int16_t* inBuf; // input buffer used when resampling
123 size_t inBufSize; // input buffer size in frames
124 size_t framesIn; // number of frames in input buffer
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800125 int16_t* outBuf; // output buffer used when resampling
126 size_t outBufSize; // output buffer size in frames
127 size_t framesOut; // number of frames in output buffer
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800128 uint32_t revChannelCount; // number of channels on reverse stream
129 uint32_t revEnabledMsk; // bit field containing IDs of enabled pre processors
130 // with reverse channel
131 uint32_t revProcessedMsk; // bit field containing IDs of pre processors with reverse
132 // channel already processed in current round
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530133 webrtc::StreamConfig revConfig; // reverse stream configuration.
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800134 int16_t* revBuf; // reverse channel input buffer
135 size_t revBufSize; // reverse channel input buffer size
136 size_t framesRev; // number of frames in reverse channel input buffer
Eric Laurenta9390d42011-06-17 20:17:17 -0700137};
138
Eric Laurent3f9c84c2012-04-03 15:36:53 -0700139#ifdef DUAL_MIC_TEST
140enum {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800141 PREPROC_CMD_DUAL_MIC_ENABLE = EFFECT_CMD_FIRST_PROPRIETARY, // enable dual mic mode
142 PREPROC_CMD_DUAL_MIC_PCM_DUMP_START, // start pcm capture
143 PREPROC_CMD_DUAL_MIC_PCM_DUMP_STOP // stop pcm capture
Eric Laurent3f9c84c2012-04-03 15:36:53 -0700144};
145
146enum {
147 CHANNEL_CFG_MONO,
148 CHANNEL_CFG_STEREO,
149 CHANNEL_CFG_MONO_AUX,
150 CHANNEL_CFG_STEREO_AUX,
151 CHANNEL_CFG_CNT,
152 CHANNEL_CFG_FIRST_AUX = CHANNEL_CFG_MONO_AUX,
153};
154
155const channel_config_t sDualMicConfigs[CHANNEL_CFG_CNT] = {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800156 {AUDIO_CHANNEL_IN_MONO, 0},
157 {AUDIO_CHANNEL_IN_STEREO, 0},
158 {AUDIO_CHANNEL_IN_FRONT, AUDIO_CHANNEL_IN_BACK},
159 {AUDIO_CHANNEL_IN_STEREO, AUDIO_CHANNEL_IN_RIGHT}};
Eric Laurent3f9c84c2012-04-03 15:36:53 -0700160
161bool sHasAuxChannels[PREPROC_NUM_EFFECTS] = {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800162 false, // PREPROC_AGC
Eric Laurent3f9c84c2012-04-03 15:36:53 -0700163 true, // PREPROC_AEC
164 true, // PREPROC_NS
165};
166
167bool gDualMicEnabled;
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800168FILE* gPcmDumpFh;
Eric Laurent3f9c84c2012-04-03 15:36:53 -0700169static pthread_mutex_t gPcmDumpLock = PTHREAD_MUTEX_INITIALIZER;
170#endif
171
Eric Laurenta9390d42011-06-17 20:17:17 -0700172//------------------------------------------------------------------------------
173// Effect descriptors
174//------------------------------------------------------------------------------
175
176// UUIDs for effect types have been generated from http://www.itu.int/ITU-T/asn1/uuid.html
177// as the pre processing effects are not defined by OpenSL ES
178
179// Automatic Gain Control
180static const effect_descriptor_t sAgcDescriptor = {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800181 {0x0a8abfe0, 0x654c, 0x11e0, 0xba26, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, // type
182 {0xaa8130e0, 0x66fc, 0x11e0, 0xbad0, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, // uuid
Eric Laurenta9390d42011-06-17 20:17:17 -0700183 EFFECT_CONTROL_API_VERSION,
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800184 (EFFECT_FLAG_TYPE_PRE_PROC | EFFECT_FLAG_DEVICE_IND),
185 0, // FIXME indicate CPU load
186 0, // FIXME indicate memory usage
Eric Laurenta9390d42011-06-17 20:17:17 -0700187 "Automatic Gain Control",
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800188 "The Android Open Source Project"};
Eric Laurenta9390d42011-06-17 20:17:17 -0700189
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530190// Automatic Gain Control 2
191static const effect_descriptor_t sAgc2Descriptor = {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800192 {0xae3c653b, 0xbe18, 0x4ab8, 0x8938, {0x41, 0x8f, 0x0a, 0x7f, 0x06, 0xac}}, // type
193 {0x89f38e65, 0xd4d2, 0x4d64, 0xad0e, {0x2b, 0x3e, 0x79, 0x9e, 0xa8, 0x86}}, // uuid
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530194 EFFECT_CONTROL_API_VERSION,
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800195 (EFFECT_FLAG_TYPE_PRE_PROC | EFFECT_FLAG_DEVICE_IND),
196 0, // FIXME indicate CPU load
197 0, // FIXME indicate memory usage
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530198 "Automatic Gain Control 2",
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800199 "The Android Open Source Project"};
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530200
Eric Laurenta9390d42011-06-17 20:17:17 -0700201// Acoustic Echo Cancellation
202static const effect_descriptor_t sAecDescriptor = {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800203 {0x7b491460, 0x8d4d, 0x11e0, 0xbd61, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, // type
204 {0xbb392ec0, 0x8d4d, 0x11e0, 0xa896, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, // uuid
Eric Laurenta9390d42011-06-17 20:17:17 -0700205 EFFECT_CONTROL_API_VERSION,
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800206 (EFFECT_FLAG_TYPE_PRE_PROC | EFFECT_FLAG_DEVICE_IND),
207 0, // FIXME indicate CPU load
208 0, // FIXME indicate memory usage
Eric Laurenta9390d42011-06-17 20:17:17 -0700209 "Acoustic Echo Canceler",
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800210 "The Android Open Source Project"};
Eric Laurenta9390d42011-06-17 20:17:17 -0700211
212// Noise suppression
213static const effect_descriptor_t sNsDescriptor = {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800214 {0x58b4b260, 0x8e06, 0x11e0, 0xaa8e, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, // type
215 {0xc06c8400, 0x8e06, 0x11e0, 0x9cb6, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, // uuid
Eric Laurenta9390d42011-06-17 20:17:17 -0700216 EFFECT_CONTROL_API_VERSION,
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800217 (EFFECT_FLAG_TYPE_PRE_PROC | EFFECT_FLAG_DEVICE_IND),
218 0, // FIXME indicate CPU load
219 0, // FIXME indicate memory usage
Eric Laurenta9390d42011-06-17 20:17:17 -0700220 "Noise Suppression",
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800221 "The Android Open Source Project"};
Eric Laurenta9390d42011-06-17 20:17:17 -0700222
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800223static const effect_descriptor_t* sDescriptors[PREPROC_NUM_EFFECTS] = {&sAgcDescriptor,
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800224 &sAgc2Descriptor,
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800225 &sAecDescriptor,
226 &sNsDescriptor};
Eric Laurenta9390d42011-06-17 20:17:17 -0700227
228//------------------------------------------------------------------------------
229// Helper functions
230//------------------------------------------------------------------------------
231
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800232const effect_uuid_t* const sUuidToPreProcTable[PREPROC_NUM_EFFECTS] = {FX_IID_AGC,
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800233 FX_IID_AGC2,
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800234 FX_IID_AEC, FX_IID_NS};
Eric Laurenta9390d42011-06-17 20:17:17 -0700235
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800236const effect_uuid_t* ProcIdToUuid(int procId) {
Eric Laurenta9390d42011-06-17 20:17:17 -0700237 if (procId >= PREPROC_NUM_EFFECTS) {
238 return EFFECT_UUID_NULL;
239 }
240 return sUuidToPreProcTable[procId];
241}
242
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800243uint32_t UuidToProcId(const effect_uuid_t* uuid) {
Eric Laurenta9390d42011-06-17 20:17:17 -0700244 size_t i;
245 for (i = 0; i < PREPROC_NUM_EFFECTS; i++) {
246 if (memcmp(uuid, sUuidToPreProcTable[i], sizeof(*uuid)) == 0) {
247 break;
248 }
249 }
250 return i;
251}
252
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800253bool HasReverseStream(uint32_t procId) {
Eric Laurenta9390d42011-06-17 20:17:17 -0700254 if (procId == PREPROC_AEC) {
255 return true;
256 }
257 return false;
258}
259
Eric Laurenta9390d42011-06-17 20:17:17 -0700260//------------------------------------------------------------------------------
261// Automatic Gain Control (AGC)
262//------------------------------------------------------------------------------
263
Eric Laurent53876962012-01-31 12:35:20 -0800264static const int kAgcDefaultTargetLevel = 3;
265static const int kAgcDefaultCompGain = 9;
Eric Laurenta9390d42011-06-17 20:17:17 -0700266static const bool kAgcDefaultLimiter = true;
267
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800268int Agc2Init(preproc_effect_t* effect) {
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530269 ALOGV("Agc2Init");
270 effect->session->config = effect->session->apm->GetConfig();
271 effect->session->config.gain_controller2.fixed_digital.gain_db = 0.f;
272 effect->session->config.gain_controller2.adaptive_digital.level_estimator =
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800273 effect->session->config.gain_controller2.kRms;
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530274 effect->session->config.gain_controller2.adaptive_digital.extra_saturation_margin_db = 2.f;
275 effect->session->apm->ApplyConfig(effect->session->config);
276 return 0;
277}
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530278
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800279int AgcInit(preproc_effect_t* effect) {
Steve Block3856b092011-10-20 11:56:00 +0100280 ALOGV("AgcInit");
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530281 effect->session->config = effect->session->apm->GetConfig();
282 effect->session->config.gain_controller1.target_level_dbfs = kAgcDefaultTargetLevel;
283 effect->session->config.gain_controller1.compression_gain_db = kAgcDefaultCompGain;
284 effect->session->config.gain_controller1.enable_limiter = kAgcDefaultLimiter;
285 effect->session->apm->ApplyConfig(effect->session->config);
Eric Laurenta9390d42011-06-17 20:17:17 -0700286 return 0;
287}
288
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800289int Agc2Create(preproc_effect_t* effect) {
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530290 Agc2Init(effect);
291 return 0;
292}
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530293
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800294int AgcCreate(preproc_effect_t* effect) {
Eric Laurenta9390d42011-06-17 20:17:17 -0700295 AgcInit(effect);
296 return 0;
297}
298
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800299int Agc2GetParameter(preproc_effect_t* effect, void* pParam, uint32_t* pValueSize, void* pValue) {
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530300 int status = 0;
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800301 uint32_t param = *(uint32_t*)pParam;
302 agc2_settings_t* pProperties = (agc2_settings_t*)pValue;
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530303
304 switch (param) {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800305 case AGC2_PARAM_FIXED_DIGITAL_GAIN:
306 if (*pValueSize < sizeof(float)) {
307 *pValueSize = 0.f;
308 return -EINVAL;
309 }
310 break;
311 case AGC2_PARAM_ADAPT_DIGI_LEVEL_ESTIMATOR:
312 if (*pValueSize < sizeof(int32_t)) {
313 *pValueSize = 0;
314 return -EINVAL;
315 }
316 break;
317 case AGC2_PARAM_ADAPT_DIGI_EXTRA_SATURATION_MARGIN:
318 if (*pValueSize < sizeof(float)) {
319 *pValueSize = 0.f;
320 return -EINVAL;
321 }
322 break;
323 case AGC2_PARAM_PROPERTIES:
324 if (*pValueSize < sizeof(agc2_settings_t)) {
325 *pValueSize = 0;
326 return -EINVAL;
327 }
328 break;
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530329
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800330 default:
331 ALOGW("Agc2GetParameter() unknown param %08x", param);
332 status = -EINVAL;
333 break;
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530334 }
335
336 effect->session->config = effect->session->apm->GetConfig();
337 switch (param) {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800338 case AGC2_PARAM_FIXED_DIGITAL_GAIN:
339 *(float*)pValue =
340 (float)(effect->session->config.gain_controller2.fixed_digital.gain_db);
341 ALOGV("Agc2GetParameter() target level %f dB", *(float*)pValue);
342 break;
343 case AGC2_PARAM_ADAPT_DIGI_LEVEL_ESTIMATOR:
344 *(uint32_t*)pValue = (uint32_t)(
345 effect->session->config.gain_controller2.adaptive_digital.level_estimator);
346 ALOGV("Agc2GetParameter() level estimator %d",
347 *(webrtc::AudioProcessing::Config::GainController2::LevelEstimator*)pValue);
348 break;
349 case AGC2_PARAM_ADAPT_DIGI_EXTRA_SATURATION_MARGIN:
350 *(float*)pValue = (float)(effect->session->config.gain_controller2.adaptive_digital
351 .extra_saturation_margin_db);
352 ALOGV("Agc2GetParameter() extra saturation margin %f dB", *(float*)pValue);
353 break;
354 case AGC2_PARAM_PROPERTIES:
355 pProperties->fixedDigitalGain =
356 (float)(effect->session->config.gain_controller2.fixed_digital.gain_db);
357 pProperties->level_estimator = (uint32_t)(
358 effect->session->config.gain_controller2.adaptive_digital.level_estimator);
359 pProperties->extraSaturationMargin =
360 (float)(effect->session->config.gain_controller2.adaptive_digital
361 .extra_saturation_margin_db);
362 break;
363 default:
364 ALOGW("Agc2GetParameter() unknown param %d", param);
365 status = -EINVAL;
366 break;
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530367 }
368
369 return status;
370}
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530371
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800372int AgcGetParameter(preproc_effect_t* effect, void* pParam, uint32_t* pValueSize, void* pValue) {
Eric Laurenta9390d42011-06-17 20:17:17 -0700373 int status = 0;
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800374 uint32_t param = *(uint32_t*)pParam;
375 t_agc_settings* pProperties = (t_agc_settings*)pValue;
Eric Laurenta9390d42011-06-17 20:17:17 -0700376
377 switch (param) {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800378 case AGC_PARAM_TARGET_LEVEL:
379 case AGC_PARAM_COMP_GAIN:
380 if (*pValueSize < sizeof(int16_t)) {
381 *pValueSize = 0;
382 return -EINVAL;
383 }
384 break;
385 case AGC_PARAM_LIMITER_ENA:
386 if (*pValueSize < sizeof(bool)) {
387 *pValueSize = 0;
388 return -EINVAL;
389 }
390 break;
391 case AGC_PARAM_PROPERTIES:
392 if (*pValueSize < sizeof(t_agc_settings)) {
393 *pValueSize = 0;
394 return -EINVAL;
395 }
396 break;
Eric Laurenta9390d42011-06-17 20:17:17 -0700397
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800398 default:
399 ALOGW("AgcGetParameter() unknown param %08x", param);
400 status = -EINVAL;
401 break;
Eric Laurenta9390d42011-06-17 20:17:17 -0700402 }
403
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530404 effect->session->config = effect->session->apm->GetConfig();
405 switch (param) {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800406 case AGC_PARAM_TARGET_LEVEL:
407 *(int16_t*)pValue =
408 (int16_t)(effect->session->config.gain_controller1.target_level_dbfs * -100);
409 ALOGV("AgcGetParameter() target level %d milliBels", *(int16_t*)pValue);
410 break;
411 case AGC_PARAM_COMP_GAIN:
412 *(int16_t*)pValue =
413 (int16_t)(effect->session->config.gain_controller1.compression_gain_db * -100);
414 ALOGV("AgcGetParameter() comp gain %d milliBels", *(int16_t*)pValue);
415 break;
416 case AGC_PARAM_LIMITER_ENA:
417 *(bool*)pValue = (bool)(effect->session->config.gain_controller1.enable_limiter);
418 ALOGV("AgcGetParameter() limiter enabled %s",
419 (*(int16_t*)pValue != 0) ? "true" : "false");
420 break;
421 case AGC_PARAM_PROPERTIES:
422 pProperties->targetLevel =
423 (int16_t)(effect->session->config.gain_controller1.target_level_dbfs * -100);
424 pProperties->compGain =
425 (int16_t)(effect->session->config.gain_controller1.compression_gain_db * -100);
426 pProperties->limiterEnabled =
427 (bool)(effect->session->config.gain_controller1.enable_limiter);
428 break;
429 default:
430 ALOGW("AgcGetParameter() unknown param %d", param);
431 status = -EINVAL;
432 break;
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530433 }
Eric Laurenta9390d42011-06-17 20:17:17 -0700434 return status;
435}
436
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800437int Agc2SetParameter(preproc_effect_t* effect, void* pParam, void* pValue) {
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530438 int status = 0;
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800439 uint32_t param = *(uint32_t*)pParam;
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530440 float valueFloat = 0.f;
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800441 agc2_settings_t* pProperties = (agc2_settings_t*)pValue;
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530442 effect->session->config = effect->session->apm->GetConfig();
443 switch (param) {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800444 case AGC2_PARAM_FIXED_DIGITAL_GAIN:
445 valueFloat = (float)(*(int32_t*)pValue);
446 ALOGV("Agc2SetParameter() fixed digital gain %f dB", valueFloat);
447 effect->session->config.gain_controller2.fixed_digital.gain_db = valueFloat;
448 break;
449 case AGC2_PARAM_ADAPT_DIGI_LEVEL_ESTIMATOR:
450 ALOGV("Agc2SetParameter() level estimator %d",
451 *(webrtc::AudioProcessing::Config::GainController2::LevelEstimator*)pValue);
452 effect->session->config.gain_controller2.adaptive_digital.level_estimator =
453 (*(webrtc::AudioProcessing::Config::GainController2::LevelEstimator*)pValue);
454 break;
455 case AGC2_PARAM_ADAPT_DIGI_EXTRA_SATURATION_MARGIN:
456 valueFloat = (float)(*(int32_t*)pValue);
457 ALOGV("Agc2SetParameter() extra saturation margin %f dB", valueFloat);
458 effect->session->config.gain_controller2.adaptive_digital.extra_saturation_margin_db =
459 valueFloat;
460 break;
461 case AGC2_PARAM_PROPERTIES:
462 ALOGV("Agc2SetParameter() properties gain %f, level %d margin %f",
463 pProperties->fixedDigitalGain, pProperties->level_estimator,
464 pProperties->extraSaturationMargin);
465 effect->session->config.gain_controller2.fixed_digital.gain_db =
466 pProperties->fixedDigitalGain;
467 effect->session->config.gain_controller2.adaptive_digital.level_estimator =
468 (webrtc::AudioProcessing::Config::GainController2::LevelEstimator)
469 pProperties->level_estimator;
470 effect->session->config.gain_controller2.adaptive_digital.extra_saturation_margin_db =
471 pProperties->extraSaturationMargin;
472 break;
473 default:
474 ALOGW("Agc2SetParameter() unknown param %08x value %08x", param, *(uint32_t*)pValue);
475 status = -EINVAL;
476 break;
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530477 }
478 effect->session->apm->ApplyConfig(effect->session->config);
479
480 ALOGV("Agc2SetParameter() done status %d", status);
481
482 return status;
483}
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530484
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800485int AgcSetParameter(preproc_effect_t* effect, void* pParam, void* pValue) {
Eric Laurenta9390d42011-06-17 20:17:17 -0700486 int status = 0;
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800487 uint32_t param = *(uint32_t*)pParam;
488 t_agc_settings* pProperties = (t_agc_settings*)pValue;
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530489 effect->session->config = effect->session->apm->GetConfig();
490 switch (param) {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800491 case AGC_PARAM_TARGET_LEVEL:
492 ALOGV("AgcSetParameter() target level %d milliBels", *(int16_t*)pValue);
493 effect->session->config.gain_controller1.target_level_dbfs =
494 (-(*(int16_t*)pValue / 100));
495 break;
496 case AGC_PARAM_COMP_GAIN:
497 ALOGV("AgcSetParameter() comp gain %d milliBels", *(int16_t*)pValue);
498 effect->session->config.gain_controller1.compression_gain_db =
499 (*(int16_t*)pValue / 100);
500 break;
501 case AGC_PARAM_LIMITER_ENA:
502 ALOGV("AgcSetParameter() limiter enabled %s", *(bool*)pValue ? "true" : "false");
503 effect->session->config.gain_controller1.enable_limiter = (*(bool*)pValue);
504 break;
505 case AGC_PARAM_PROPERTIES:
506 ALOGV("AgcSetParameter() properties level %d, gain %d limiter %d",
507 pProperties->targetLevel, pProperties->compGain, pProperties->limiterEnabled);
508 effect->session->config.gain_controller1.target_level_dbfs =
509 -(pProperties->targetLevel / 100);
510 effect->session->config.gain_controller1.compression_gain_db =
511 pProperties->compGain / 100;
512 effect->session->config.gain_controller1.enable_limiter = pProperties->limiterEnabled;
513 break;
514 default:
515 ALOGW("AgcSetParameter() unknown param %08x value %08x", param, *(uint32_t*)pValue);
516 status = -EINVAL;
517 break;
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530518 }
519 effect->session->apm->ApplyConfig(effect->session->config);
Eric Laurenta9390d42011-06-17 20:17:17 -0700520
Steve Block3856b092011-10-20 11:56:00 +0100521 ALOGV("AgcSetParameter() done status %d", status);
Eric Laurenta9390d42011-06-17 20:17:17 -0700522
523 return status;
524}
525
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800526void Agc2Enable(preproc_effect_t* effect) {
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530527 effect->session->config = effect->session->apm->GetConfig();
528 effect->session->config.gain_controller2.enabled = true;
529 effect->session->apm->ApplyConfig(effect->session->config);
530}
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530531
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800532void AgcEnable(preproc_effect_t* effect) {
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530533 effect->session->config = effect->session->apm->GetConfig();
534 effect->session->config.gain_controller1.enabled = true;
535 effect->session->apm->ApplyConfig(effect->session->config);
Eric Laurenta9390d42011-06-17 20:17:17 -0700536}
537
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800538void Agc2Disable(preproc_effect_t* effect) {
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530539 effect->session->config = effect->session->apm->GetConfig();
540 effect->session->config.gain_controller2.enabled = false;
541 effect->session->apm->ApplyConfig(effect->session->config);
542}
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530543
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800544void AgcDisable(preproc_effect_t* effect) {
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530545 effect->session->config = effect->session->apm->GetConfig();
546 effect->session->config.gain_controller1.enabled = false;
547 effect->session->apm->ApplyConfig(effect->session->config);
Eric Laurenta9390d42011-06-17 20:17:17 -0700548}
549
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800550static const preproc_ops_t sAgcOps = {AgcCreate, AgcInit, NULL, AgcEnable, AgcDisable,
551 AgcSetParameter, AgcGetParameter, NULL};
Eric Laurenta9390d42011-06-17 20:17:17 -0700552
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800553static const preproc_ops_t sAgc2Ops = {Agc2Create, Agc2Init, NULL,
554 Agc2Enable, Agc2Disable, Agc2SetParameter,
555 Agc2GetParameter, NULL};
Eric Laurenta9390d42011-06-17 20:17:17 -0700556
557//------------------------------------------------------------------------------
558// Acoustic Echo Canceler (AEC)
559//------------------------------------------------------------------------------
560
Eric Laurenta9390d42011-06-17 20:17:17 -0700561
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800562int AecInit(preproc_effect_t* effect) {
Steve Block3856b092011-10-20 11:56:00 +0100563 ALOGV("AecInit");
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800564 effect->session->config = effect->session->apm->GetConfig();
Rivukanta Bhattacharyac4c54172020-11-25 23:55:44 +0530565 effect->session->config.echo_canceller.mobile_mode = true;
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530566 effect->session->apm->ApplyConfig(effect->session->config);
Eric Laurenta9390d42011-06-17 20:17:17 -0700567 return 0;
568}
569
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800570int AecCreate(preproc_effect_t* effect) {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800571 AecInit(effect);
Eric Laurenta9390d42011-06-17 20:17:17 -0700572 return 0;
573}
574
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800575int AecGetParameter(preproc_effect_t* effect, void* pParam, uint32_t* pValueSize, void* pValue) {
Eric Laurenta9390d42011-06-17 20:17:17 -0700576 int status = 0;
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800577 uint32_t param = *(uint32_t*)pParam;
Eric Laurenta9390d42011-06-17 20:17:17 -0700578
579 if (*pValueSize < sizeof(uint32_t)) {
580 return -EINVAL;
581 }
582 switch (param) {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800583 case AEC_PARAM_ECHO_DELAY:
584 case AEC_PARAM_PROPERTIES:
585 *(uint32_t*)pValue = 1000 * effect->session->apm->stream_delay_ms();
586 ALOGV("AecGetParameter() echo delay %d us", *(uint32_t*)pValue);
587 break;
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800588 case AEC_PARAM_MOBILE_MODE:
589 effect->session->config = effect->session->apm->GetConfig();
590 *(uint32_t*)pValue = effect->session->config.echo_canceller.mobile_mode;
591 ALOGV("AecGetParameter() mobile mode %d us", *(uint32_t*)pValue);
592 break;
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800593 default:
594 ALOGW("AecGetParameter() unknown param %08x value %08x", param, *(uint32_t*)pValue);
595 status = -EINVAL;
596 break;
Eric Laurenta9390d42011-06-17 20:17:17 -0700597 }
598 return status;
599}
600
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800601int AecSetParameter(preproc_effect_t* effect, void* pParam, void* pValue) {
Eric Laurenta9390d42011-06-17 20:17:17 -0700602 int status = 0;
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800603 uint32_t param = *(uint32_t*)pParam;
604 uint32_t value = *(uint32_t*)pValue;
Eric Laurenta9390d42011-06-17 20:17:17 -0700605
606 switch (param) {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800607 case AEC_PARAM_ECHO_DELAY:
608 case AEC_PARAM_PROPERTIES:
609 status = effect->session->apm->set_stream_delay_ms(value / 1000);
610 ALOGV("AecSetParameter() echo delay %d us, status %d", value, status);
611 break;
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800612 case AEC_PARAM_MOBILE_MODE:
613 effect->session->config = effect->session->apm->GetConfig();
614 effect->session->config.echo_canceller.mobile_mode = value;
615 ALOGV("AecSetParameter() mobile mode %d us", value);
616 effect->session->apm->ApplyConfig(effect->session->config);
617 break;
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800618 default:
619 ALOGW("AecSetParameter() unknown param %08x value %08x", param, *(uint32_t*)pValue);
620 status = -EINVAL;
621 break;
Eric Laurenta9390d42011-06-17 20:17:17 -0700622 }
623 return status;
624}
625
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800626void AecEnable(preproc_effect_t* effect) {
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530627 effect->session->config = effect->session->apm->GetConfig();
628 effect->session->config.echo_canceller.enabled = true;
629 effect->session->apm->ApplyConfig(effect->session->config);
Eric Laurenta9390d42011-06-17 20:17:17 -0700630}
631
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800632void AecDisable(preproc_effect_t* effect) {
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530633 effect->session->config = effect->session->apm->GetConfig();
634 effect->session->config.echo_canceller.enabled = false;
635 effect->session->apm->ApplyConfig(effect->session->config);
Eric Laurenta9390d42011-06-17 20:17:17 -0700636}
637
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800638int AecSetDevice(preproc_effect_t* effect, uint32_t device) {
Steve Block3856b092011-10-20 11:56:00 +0100639 ALOGV("AecSetDevice %08x", device);
Eric Laurenta9390d42011-06-17 20:17:17 -0700640
Eric Laurent88959252012-08-28 14:26:53 -0700641 if (audio_is_input_device(device)) {
642 return 0;
643 }
644
Eric Laurenta9390d42011-06-17 20:17:17 -0700645 return 0;
646}
647
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800648static const preproc_ops_t sAecOps = {AecCreate, AecInit, NULL,
649 AecEnable, AecDisable, AecSetParameter,
650 AecGetParameter, AecSetDevice};
Eric Laurenta9390d42011-06-17 20:17:17 -0700651
652//------------------------------------------------------------------------------
653// Noise Suppression (NS)
654//------------------------------------------------------------------------------
655
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530656static const webrtc::AudioProcessing::Config::NoiseSuppression::Level kNsDefaultLevel =
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800657 webrtc::AudioProcessing::Config::NoiseSuppression::kModerate;
Eric Laurenta9390d42011-06-17 20:17:17 -0700658
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800659int NsInit(preproc_effect_t* effect) {
Steve Block3856b092011-10-20 11:56:00 +0100660 ALOGV("NsInit");
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800661 effect->session->config = effect->session->apm->GetConfig();
662 effect->session->config.noise_suppression.level = kNsDefaultLevel;
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530663 effect->session->apm->ApplyConfig(effect->session->config);
Alex Luebs766bf732015-12-14 21:32:13 -0800664 effect->type = NS_TYPE_SINGLE_CHANNEL;
Eric Laurenta9390d42011-06-17 20:17:17 -0700665 return 0;
666}
667
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800668int NsCreate(preproc_effect_t* effect) {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800669 NsInit(effect);
Eric Laurenta9390d42011-06-17 20:17:17 -0700670 return 0;
671}
672
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800673int NsGetParameter(preproc_effect_t* effect __unused, void* pParam __unused,
674 uint32_t* pValueSize __unused, void* pValue __unused) {
Eric Laurenta9390d42011-06-17 20:17:17 -0700675 int status = 0;
676 return status;
677}
678
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800679int NsSetParameter(preproc_effect_t* effect, void* pParam, void* pValue) {
Eric Laurenta9390d42011-06-17 20:17:17 -0700680 int status = 0;
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800681 uint32_t param = *(uint32_t*)pParam;
682 uint32_t value = *(uint32_t*)pValue;
683 effect->session->config = effect->session->apm->GetConfig();
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530684 switch (param) {
685 case NS_PARAM_LEVEL:
686 effect->session->config.noise_suppression.level =
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800687 (webrtc::AudioProcessing::Config::NoiseSuppression::Level)value;
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530688 ALOGV("NsSetParameter() level %d", value);
689 break;
690 default:
691 ALOGW("NsSetParameter() unknown param %08x value %08x", param, value);
692 status = -EINVAL;
693 }
694 effect->session->apm->ApplyConfig(effect->session->config);
Alex Luebs766bf732015-12-14 21:32:13 -0800695
Eric Laurenta9390d42011-06-17 20:17:17 -0700696 return status;
697}
698
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800699void NsEnable(preproc_effect_t* effect) {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800700 effect->session->config = effect->session->apm->GetConfig();
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530701 effect->session->config.noise_suppression.enabled = true;
702 effect->session->apm->ApplyConfig(effect->session->config);
Eric Laurenta9390d42011-06-17 20:17:17 -0700703}
704
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800705void NsDisable(preproc_effect_t* effect) {
Steve Block3856b092011-10-20 11:56:00 +0100706 ALOGV("NsDisable");
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800707 effect->session->config = effect->session->apm->GetConfig();
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530708 effect->session->config.noise_suppression.enabled = false;
709 effect->session->apm->ApplyConfig(effect->session->config);
Eric Laurenta9390d42011-06-17 20:17:17 -0700710}
711
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800712static const preproc_ops_t sNsOps = {NsCreate, NsInit, NULL, NsEnable,
713 NsDisable, NsSetParameter, NsGetParameter, NULL};
Eric Laurenta9390d42011-06-17 20:17:17 -0700714
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800715static const preproc_ops_t* sPreProcOps[PREPROC_NUM_EFFECTS] = {&sAgcOps,
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800716 &sAgc2Ops,
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800717 &sAecOps, &sNsOps};
Eric Laurenta9390d42011-06-17 20:17:17 -0700718
719//------------------------------------------------------------------------------
720// Effect functions
721//------------------------------------------------------------------------------
722
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800723void Session_SetProcEnabled(preproc_session_t* session, uint32_t procId, bool enabled);
Eric Laurenta9390d42011-06-17 20:17:17 -0700724
725extern "C" const struct effect_interface_s sEffectInterface;
726extern "C" const struct effect_interface_s sEffectInterfaceReverse;
727
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800728#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 -0700729
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800730int Effect_SetState(preproc_effect_t* effect, uint32_t state) {
Eric Laurenta9390d42011-06-17 20:17:17 -0700731 int status = 0;
Steve Block3856b092011-10-20 11:56:00 +0100732 ALOGV("Effect_SetState proc %d, new %d old %d", effect->procId, state, effect->state);
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800733 switch (state) {
734 case PREPROC_EFFECT_STATE_INIT:
735 switch (effect->state) {
736 case PREPROC_EFFECT_STATE_ACTIVE:
737 effect->ops->disable(effect);
738 Session_SetProcEnabled(effect->session, effect->procId, false);
739 break;
740 case PREPROC_EFFECT_STATE_CONFIG:
741 case PREPROC_EFFECT_STATE_CREATED:
742 case PREPROC_EFFECT_STATE_INIT:
743 break;
744 default:
745 BAD_STATE_ABORT(effect->state, state);
746 }
747 break;
748 case PREPROC_EFFECT_STATE_CREATED:
749 switch (effect->state) {
750 case PREPROC_EFFECT_STATE_INIT:
751 status = effect->ops->create(effect);
752 break;
753 case PREPROC_EFFECT_STATE_CREATED:
754 case PREPROC_EFFECT_STATE_ACTIVE:
755 case PREPROC_EFFECT_STATE_CONFIG:
756 ALOGE("Effect_SetState invalid transition");
757 status = -ENOSYS;
758 break;
759 default:
760 BAD_STATE_ABORT(effect->state, state);
761 }
Andy Hung320fd852018-10-09 14:06:37 -0700762 break;
Eric Laurenta9390d42011-06-17 20:17:17 -0700763 case PREPROC_EFFECT_STATE_CONFIG:
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800764 switch (effect->state) {
765 case PREPROC_EFFECT_STATE_INIT:
766 ALOGE("Effect_SetState invalid transition");
767 status = -ENOSYS;
768 break;
769 case PREPROC_EFFECT_STATE_ACTIVE:
770 effect->ops->disable(effect);
771 Session_SetProcEnabled(effect->session, effect->procId, false);
772 break;
773 case PREPROC_EFFECT_STATE_CREATED:
774 case PREPROC_EFFECT_STATE_CONFIG:
775 break;
776 default:
777 BAD_STATE_ABORT(effect->state, state);
778 }
779 break;
780 case PREPROC_EFFECT_STATE_ACTIVE:
781 switch (effect->state) {
782 case PREPROC_EFFECT_STATE_INIT:
783 case PREPROC_EFFECT_STATE_CREATED:
784 ALOGE("Effect_SetState invalid transition");
785 status = -ENOSYS;
786 break;
787 case PREPROC_EFFECT_STATE_ACTIVE:
788 // enabling an already enabled effect is just ignored
789 break;
790 case PREPROC_EFFECT_STATE_CONFIG:
791 effect->ops->enable(effect);
792 Session_SetProcEnabled(effect->session, effect->procId, true);
793 break;
794 default:
795 BAD_STATE_ABORT(effect->state, state);
796 }
Eric Laurenta9390d42011-06-17 20:17:17 -0700797 break;
798 default:
799 BAD_STATE_ABORT(effect->state, state);
Eric Laurenta9390d42011-06-17 20:17:17 -0700800 }
801 if (status == 0) {
802 effect->state = state;
803 }
804 return status;
805}
806
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800807int Effect_Init(preproc_effect_t* effect, uint32_t procId) {
Eric Laurenta9390d42011-06-17 20:17:17 -0700808 if (HasReverseStream(procId)) {
809 effect->itfe = &sEffectInterfaceReverse;
810 } else {
811 effect->itfe = &sEffectInterface;
812 }
813 effect->ops = sPreProcOps[procId];
814 effect->procId = procId;
815 effect->state = PREPROC_EFFECT_STATE_INIT;
816 return 0;
817}
818
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800819int Effect_Create(preproc_effect_t* effect, preproc_session_t* session,
820 effect_handle_t* interface) {
Eric Laurenta9390d42011-06-17 20:17:17 -0700821 effect->session = session;
822 *interface = (effect_handle_t)&effect->itfe;
823 return Effect_SetState(effect, PREPROC_EFFECT_STATE_CREATED);
824}
825
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800826int Effect_Release(preproc_effect_t* effect) {
Eric Laurenta9390d42011-06-17 20:17:17 -0700827 return Effect_SetState(effect, PREPROC_EFFECT_STATE_INIT);
828}
829
Eric Laurenta9390d42011-06-17 20:17:17 -0700830//------------------------------------------------------------------------------
831// Session functions
832//------------------------------------------------------------------------------
833
834#define RESAMPLER_QUALITY SPEEX_RESAMPLER_QUALITY_VOIP
835
836static const int kPreprocDefaultSr = 16000;
837static const int kPreProcDefaultCnl = 1;
838
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800839int Session_Init(preproc_session_t* session) {
Eric Laurenta9390d42011-06-17 20:17:17 -0700840 size_t i;
841 int status = 0;
842
843 session->state = PREPROC_SESSION_STATE_INIT;
844 session->id = 0;
845 session->io = 0;
846 session->createdMsk = 0;
Eric Laurenta9390d42011-06-17 20:17:17 -0700847 for (i = 0; i < PREPROC_NUM_EFFECTS && status == 0; i++) {
848 status = Effect_Init(&session->effects[i], i);
849 }
850 return status;
851}
852
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800853extern "C" int Session_CreateEffect(preproc_session_t* session, int32_t procId,
854 effect_handle_t* interface) {
Eric Laurenta9390d42011-06-17 20:17:17 -0700855 int status = -ENOMEM;
856
Steve Block3856b092011-10-20 11:56:00 +0100857 ALOGV("Session_CreateEffect procId %d, createdMsk %08x", procId, session->createdMsk);
Eric Laurenta9390d42011-06-17 20:17:17 -0700858
859 if (session->createdMsk == 0) {
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530860 session->apm = session->ap_builder.Create();
861 if (session->apm == NULL) {
862 ALOGW("Session_CreateEffect could not get apm engine");
863 goto error;
864 }
Eric Laurenta9390d42011-06-17 20:17:17 -0700865 session->apmSamplingRate = kPreprocDefaultSr;
866 session->apmFrameCount = (kPreprocDefaultSr) / 100;
867 session->frameCount = session->apmFrameCount;
868 session->samplingRate = kPreprocDefaultSr;
869 session->inChannelCount = kPreProcDefaultCnl;
870 session->outChannelCount = kPreProcDefaultCnl;
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530871 session->inputConfig.set_sample_rate_hz(kPreprocDefaultSr);
872 session->inputConfig.set_num_channels(kPreProcDefaultCnl);
873 session->outputConfig.set_sample_rate_hz(kPreprocDefaultSr);
874 session->outputConfig.set_num_channels(kPreProcDefaultCnl);
Eric Laurenta9390d42011-06-17 20:17:17 -0700875 session->revChannelCount = kPreProcDefaultCnl;
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530876 session->revConfig.set_sample_rate_hz(kPreprocDefaultSr);
877 session->revConfig.set_num_channels(kPreProcDefaultCnl);
Eric Laurenta9390d42011-06-17 20:17:17 -0700878 session->enabledMsk = 0;
879 session->processedMsk = 0;
880 session->revEnabledMsk = 0;
881 session->revProcessedMsk = 0;
Eric Laurenta9390d42011-06-17 20:17:17 -0700882 session->inBuf = NULL;
883 session->inBufSize = 0;
Eric Laurenta9390d42011-06-17 20:17:17 -0700884 session->outBuf = NULL;
885 session->outBufSize = 0;
Eric Laurenta9390d42011-06-17 20:17:17 -0700886 session->revBuf = NULL;
887 session->revBufSize = 0;
888 }
889 status = Effect_Create(&session->effects[procId], session, interface);
890 if (status < 0) {
891 goto error;
892 }
Steve Block3856b092011-10-20 11:56:00 +0100893 ALOGV("Session_CreateEffect OK");
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800894 session->createdMsk |= (1 << procId);
Eric Laurenta9390d42011-06-17 20:17:17 -0700895 return status;
896
897error:
898 if (session->createdMsk == 0) {
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530899 delete session->apm;
900 session->apm = NULL;
Eric Laurenta9390d42011-06-17 20:17:17 -0700901 }
902 return status;
903}
904
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800905int Session_ReleaseEffect(preproc_session_t* session, preproc_effect_t* fx) {
Steve Block5ff1dd52012-01-05 23:22:43 +0000906 ALOGW_IF(Effect_Release(fx) != 0, " Effect_Release() failed for proc ID %d", fx->procId);
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800907 session->createdMsk &= ~(1 << fx->procId);
Eric Laurenta9390d42011-06-17 20:17:17 -0700908 if (session->createdMsk == 0) {
Alex Luebs9718b7d2015-11-24 14:33:14 -0800909 delete session->apm;
Eric Laurenta9390d42011-06-17 20:17:17 -0700910 session->apm = NULL;
Eric Laurenta9390d42011-06-17 20:17:17 -0700911 delete session->inBuf;
912 session->inBuf = NULL;
913 delete session->outBuf;
914 session->outBuf = NULL;
915 delete session->revBuf;
916 session->revBuf = NULL;
917
Eric Laurentb20cf7d2019-04-05 19:37:34 -0700918 session->id = 0;
Eric Laurenta9390d42011-06-17 20:17:17 -0700919 }
920
921 return 0;
922}
923
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800924int Session_SetConfig(preproc_session_t* session, effect_config_t* config) {
Alex Luebs3f11ef02016-01-15 15:51:58 -0800925 uint32_t inCnl = audio_channel_count_from_in_mask(config->inputCfg.channels);
926 uint32_t outCnl = audio_channel_count_from_in_mask(config->outputCfg.channels);
Eric Laurenta9390d42011-06-17 20:17:17 -0700927
928 if (config->inputCfg.samplingRate != config->outputCfg.samplingRate ||
929 config->inputCfg.format != config->outputCfg.format ||
930 config->inputCfg.format != AUDIO_FORMAT_PCM_16_BIT) {
931 return -EINVAL;
932 }
933
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800934 ALOGV("Session_SetConfig sr %d cnl %08x", config->inputCfg.samplingRate,
935 config->inputCfg.channels);
Eric Laurenta9390d42011-06-17 20:17:17 -0700936
937 // AEC implementation is limited to 16kHz
938 if (config->inputCfg.samplingRate >= 32000 && !(session->createdMsk & (1 << PREPROC_AEC))) {
939 session->apmSamplingRate = 32000;
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800940 } else if (config->inputCfg.samplingRate >= 16000) {
Eric Laurenta9390d42011-06-17 20:17:17 -0700941 session->apmSamplingRate = 16000;
942 } else if (config->inputCfg.samplingRate >= 8000) {
943 session->apmSamplingRate = 8000;
944 }
Alex Luebs9718b7d2015-11-24 14:33:14 -0800945
Eric Laurenta9390d42011-06-17 20:17:17 -0700946
947 session->samplingRate = config->inputCfg.samplingRate;
948 session->apmFrameCount = session->apmSamplingRate / 100;
949 if (session->samplingRate == session->apmSamplingRate) {
950 session->frameCount = session->apmFrameCount;
951 } else {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800952 session->frameCount =
953 (session->apmFrameCount * session->samplingRate) / session->apmSamplingRate;
Eric Laurenta9390d42011-06-17 20:17:17 -0700954 }
955 session->inChannelCount = inCnl;
956 session->outChannelCount = outCnl;
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530957 session->inputConfig.set_sample_rate_hz(session->samplingRate);
958 session->inputConfig.set_num_channels(inCnl);
959 session->outputConfig.set_sample_rate_hz(session->samplingRate);
960 session->outputConfig.set_num_channels(inCnl);
Eric Laurenta9390d42011-06-17 20:17:17 -0700961
962 session->revChannelCount = inCnl;
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530963 session->revConfig.set_sample_rate_hz(session->samplingRate);
964 session->revConfig.set_num_channels(inCnl);
Eric Laurenta9390d42011-06-17 20:17:17 -0700965
Eric Laurent3f9c84c2012-04-03 15:36:53 -0700966 // force process buffer reallocation
967 session->inBufSize = 0;
968 session->outBufSize = 0;
969 session->framesIn = 0;
970 session->framesOut = 0;
971
Eric Laurenta9390d42011-06-17 20:17:17 -0700972
973 session->state = PREPROC_SESSION_STATE_CONFIG;
974 return 0;
975}
976
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800977void Session_GetConfig(preproc_session_t* session, effect_config_t* config) {
Eric Laurent3d5188b2011-12-16 15:30:36 -0800978 memset(config, 0, sizeof(effect_config_t));
979 config->inputCfg.samplingRate = config->outputCfg.samplingRate = session->samplingRate;
980 config->inputCfg.format = config->outputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
Glenn Kastenab334fd2012-03-14 12:56:06 -0700981 config->inputCfg.channels = audio_channel_in_mask_from_count(session->inChannelCount);
982 // "out" doesn't mean output device, so this is the correct API to convert channel count to mask
983 config->outputCfg.channels = audio_channel_in_mask_from_count(session->outChannelCount);
Eric Laurent3d5188b2011-12-16 15:30:36 -0800984 config->inputCfg.mask = config->outputCfg.mask =
985 (EFFECT_CONFIG_SMP_RATE | EFFECT_CONFIG_CHANNELS | EFFECT_CONFIG_FORMAT);
986}
987
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800988int Session_SetReverseConfig(preproc_session_t* session, effect_config_t* config) {
Eric Laurenta9390d42011-06-17 20:17:17 -0700989 if (config->inputCfg.samplingRate != config->outputCfg.samplingRate ||
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800990 config->inputCfg.format != config->outputCfg.format ||
991 config->inputCfg.format != AUDIO_FORMAT_PCM_16_BIT) {
Eric Laurenta9390d42011-06-17 20:17:17 -0700992 return -EINVAL;
993 }
994
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800995 ALOGV("Session_SetReverseConfig sr %d cnl %08x", config->inputCfg.samplingRate,
996 config->inputCfg.channels);
Eric Laurenta9390d42011-06-17 20:17:17 -0700997
998 if (session->state < PREPROC_SESSION_STATE_CONFIG) {
999 return -ENOSYS;
1000 }
1001 if (config->inputCfg.samplingRate != session->samplingRate ||
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001002 config->inputCfg.format != AUDIO_FORMAT_PCM_16_BIT) {
Eric Laurenta9390d42011-06-17 20:17:17 -07001003 return -EINVAL;
1004 }
Andy Hunge5412692014-05-16 11:25:07 -07001005 uint32_t inCnl = audio_channel_count_from_out_mask(config->inputCfg.channels);
Eric Laurenta9390d42011-06-17 20:17:17 -07001006 session->revChannelCount = inCnl;
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001007 // force process buffer reallocation
1008 session->revBufSize = 0;
1009 session->framesRev = 0;
1010
Eric Laurenta9390d42011-06-17 20:17:17 -07001011 return 0;
1012}
1013
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001014void Session_GetReverseConfig(preproc_session_t* session, effect_config_t* config) {
Eric Laurent3d5188b2011-12-16 15:30:36 -08001015 memset(config, 0, sizeof(effect_config_t));
1016 config->inputCfg.samplingRate = config->outputCfg.samplingRate = session->samplingRate;
1017 config->inputCfg.format = config->outputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
1018 config->inputCfg.channels = config->outputCfg.channels =
Glenn Kastenab334fd2012-03-14 12:56:06 -07001019 audio_channel_in_mask_from_count(session->revChannelCount);
Eric Laurent3d5188b2011-12-16 15:30:36 -08001020 config->inputCfg.mask = config->outputCfg.mask =
1021 (EFFECT_CONFIG_SMP_RATE | EFFECT_CONFIG_CHANNELS | EFFECT_CONFIG_FORMAT);
1022}
1023
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001024void Session_SetProcEnabled(preproc_session_t* session, uint32_t procId, bool enabled) {
Eric Laurenta9390d42011-06-17 20:17:17 -07001025 if (enabled) {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001026 if (session->enabledMsk == 0) {
Eric Laurenta9390d42011-06-17 20:17:17 -07001027 session->framesIn = 0;
Eric Laurenta9390d42011-06-17 20:17:17 -07001028 }
1029 session->enabledMsk |= (1 << procId);
1030 if (HasReverseStream(procId)) {
1031 session->framesRev = 0;
Eric Laurenta9390d42011-06-17 20:17:17 -07001032 session->revEnabledMsk |= (1 << procId);
1033 }
1034 } else {
1035 session->enabledMsk &= ~(1 << procId);
1036 if (HasReverseStream(procId)) {
1037 session->revEnabledMsk &= ~(1 << procId);
1038 }
1039 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001040 ALOGV("Session_SetProcEnabled proc %d, enabled %d enabledMsk %08x revEnabledMsk %08x", procId,
1041 enabled, session->enabledMsk, session->revEnabledMsk);
Eric Laurenta9390d42011-06-17 20:17:17 -07001042 session->processedMsk = 0;
1043 if (HasReverseStream(procId)) {
1044 session->revProcessedMsk = 0;
1045 }
1046}
1047
1048//------------------------------------------------------------------------------
1049// Bundle functions
1050//------------------------------------------------------------------------------
1051
1052static int sInitStatus = 1;
1053static preproc_session_t sSessions[PREPROC_NUM_SESSIONS];
1054
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001055preproc_session_t* PreProc_GetSession(int32_t procId, int32_t sessionId, int32_t ioId) {
Eric Laurenta9390d42011-06-17 20:17:17 -07001056 size_t i;
Eric Laurenta9390d42011-06-17 20:17:17 -07001057 for (i = 0; i < PREPROC_NUM_SESSIONS; i++) {
Eric Laurentb20cf7d2019-04-05 19:37:34 -07001058 if (sSessions[i].id == sessionId) {
Eric Laurenta9390d42011-06-17 20:17:17 -07001059 if (sSessions[i].createdMsk & (1 << procId)) {
1060 return NULL;
1061 }
1062 return &sSessions[i];
1063 }
1064 }
1065 for (i = 0; i < PREPROC_NUM_SESSIONS; i++) {
Eric Laurentb20cf7d2019-04-05 19:37:34 -07001066 if (sSessions[i].id == 0) {
Eric Laurenta9390d42011-06-17 20:17:17 -07001067 sSessions[i].id = sessionId;
1068 sSessions[i].io = ioId;
1069 return &sSessions[i];
1070 }
1071 }
1072 return NULL;
1073}
1074
Eric Laurenta9390d42011-06-17 20:17:17 -07001075int PreProc_Init() {
1076 size_t i;
1077 int status = 0;
1078
1079 if (sInitStatus <= 0) {
1080 return sInitStatus;
1081 }
1082 for (i = 0; i < PREPROC_NUM_SESSIONS && status == 0; i++) {
1083 status = Session_Init(&sSessions[i]);
1084 }
1085 sInitStatus = status;
1086 return sInitStatus;
1087}
1088
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001089const effect_descriptor_t* PreProc_GetDescriptor(const effect_uuid_t* uuid) {
Eric Laurenta9390d42011-06-17 20:17:17 -07001090 size_t i;
1091 for (i = 0; i < PREPROC_NUM_EFFECTS; i++) {
1092 if (memcmp(&sDescriptors[i]->uuid, uuid, sizeof(effect_uuid_t)) == 0) {
1093 return sDescriptors[i];
1094 }
1095 }
1096 return NULL;
1097}
1098
Eric Laurenta9390d42011-06-17 20:17:17 -07001099extern "C" {
1100
1101//------------------------------------------------------------------------------
1102// Effect Control Interface Implementation
1103//------------------------------------------------------------------------------
1104
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001105int PreProcessingFx_Process(effect_handle_t self, audio_buffer_t* inBuffer,
1106 audio_buffer_t* outBuffer) {
1107 preproc_effect_t* effect = (preproc_effect_t*)self;
Eric Laurenta9390d42011-06-17 20:17:17 -07001108
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001109 if (effect == NULL) {
Steve Block3856b092011-10-20 11:56:00 +01001110 ALOGV("PreProcessingFx_Process() ERROR effect == NULL");
Eric Laurenta9390d42011-06-17 20:17:17 -07001111 return -EINVAL;
1112 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001113 preproc_session_t* session = (preproc_session_t*)effect->session;
Eric Laurenta9390d42011-06-17 20:17:17 -07001114
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001115 if (inBuffer == NULL || inBuffer->raw == NULL || outBuffer == NULL || outBuffer->raw == NULL) {
Steve Block5ff1dd52012-01-05 23:22:43 +00001116 ALOGW("PreProcessingFx_Process() ERROR bad pointer");
Eric Laurenta9390d42011-06-17 20:17:17 -07001117 return -EINVAL;
1118 }
1119
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001120 session->processedMsk |= (1 << effect->procId);
Eric Laurenta9390d42011-06-17 20:17:17 -07001121
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001122 // ALOGV("PreProcessingFx_Process In %d frames enabledMsk %08x processedMsk %08x",
1123 // inBuffer->frameCount, session->enabledMsk, session->processedMsk);
Eric Laurenta9390d42011-06-17 20:17:17 -07001124
1125 if ((session->processedMsk & session->enabledMsk) == session->enabledMsk) {
1126 effect->session->processedMsk = 0;
1127 size_t framesRq = outBuffer->frameCount;
1128 size_t framesWr = 0;
1129 if (session->framesOut) {
1130 size_t fr = session->framesOut;
1131 if (outBuffer->frameCount < fr) {
1132 fr = outBuffer->frameCount;
1133 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001134 memcpy(outBuffer->s16, session->outBuf,
1135 fr * session->outChannelCount * sizeof(int16_t));
1136 memmove(session->outBuf, session->outBuf + fr * session->outChannelCount,
Jiabin Huang0c9544a2020-06-04 00:46:19 +00001137 (session->framesOut - fr) * session->outChannelCount * sizeof(int16_t));
Eric Laurenta9390d42011-06-17 20:17:17 -07001138 session->framesOut -= fr;
1139 framesWr += fr;
1140 }
1141 outBuffer->frameCount = framesWr;
1142 if (framesWr == framesRq) {
1143 inBuffer->frameCount = 0;
1144 return 0;
1145 }
1146
Saketh Sathuvalli08337032020-09-22 21:13:45 +05301147 size_t fr = session->frameCount - session->framesIn;
1148 if (inBuffer->frameCount < fr) {
1149 fr = inBuffer->frameCount;
1150 }
1151 session->framesIn += fr;
1152 inBuffer->frameCount = fr;
1153 if (session->framesIn < session->frameCount) {
1154 return 0;
1155 }
1156 session->framesIn = 0;
1157 if (int status = effect->session->apm->ProcessStream(
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001158 (const int16_t* const)inBuffer->s16,
1159 (const webrtc::StreamConfig)effect->session->inputConfig,
1160 (const webrtc::StreamConfig)effect->session->outputConfig,
1161 (int16_t* const)outBuffer->s16);
1162 status != 0) {
Saketh Sathuvalli08337032020-09-22 21:13:45 +05301163 ALOGE("Process Stream failed with error %d\n", status);
1164 return status;
1165 }
1166 outBuffer->frameCount = inBuffer->frameCount;
Eric Laurenta9390d42011-06-17 20:17:17 -07001167
1168 if (session->outBufSize < session->framesOut + session->frameCount) {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001169 int16_t* buf;
Eric Laurenta9390d42011-06-17 20:17:17 -07001170 session->outBufSize = session->framesOut + session->frameCount;
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001171 buf = (int16_t*)realloc(
1172 session->outBuf,
1173 session->outBufSize * session->outChannelCount * sizeof(int16_t));
Eric Laurent679650f2015-08-21 14:01:50 -07001174 if (buf == NULL) {
1175 session->framesOut = 0;
1176 free(session->outBuf);
1177 session->outBuf = NULL;
1178 return -ENOMEM;
1179 }
1180 session->outBuf = buf;
Eric Laurenta9390d42011-06-17 20:17:17 -07001181 }
1182
Saketh Sathuvalli08337032020-09-22 21:13:45 +05301183 fr = session->framesOut;
Eric Laurenta9390d42011-06-17 20:17:17 -07001184 if (framesRq - framesWr < fr) {
1185 fr = framesRq - framesWr;
1186 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001187 memcpy(outBuffer->s16 + framesWr * session->outChannelCount, session->outBuf,
1188 fr * session->outChannelCount * sizeof(int16_t));
1189 memmove(session->outBuf, session->outBuf + fr * session->outChannelCount,
Jiabin Huang0c9544a2020-06-04 00:46:19 +00001190 (session->framesOut - fr) * session->outChannelCount * sizeof(int16_t));
Eric Laurenta9390d42011-06-17 20:17:17 -07001191 session->framesOut -= fr;
1192 outBuffer->frameCount += fr;
1193
1194 return 0;
1195 } else {
1196 return -ENODATA;
1197 }
1198}
1199
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001200int PreProcessingFx_Command(effect_handle_t self, uint32_t cmdCode, uint32_t cmdSize,
1201 void* pCmdData, uint32_t* replySize, void* pReplyData) {
1202 preproc_effect_t* effect = (preproc_effect_t*)self;
Eric Laurenta9390d42011-06-17 20:17:17 -07001203
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001204 if (effect == NULL) {
Eric Laurenta9390d42011-06-17 20:17:17 -07001205 return -EINVAL;
1206 }
1207
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001208 // ALOGV("PreProcessingFx_Command: command %d cmdSize %d",cmdCode, cmdSize);
Eric Laurenta9390d42011-06-17 20:17:17 -07001209
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001210 switch (cmdCode) {
Eric Laurenta9390d42011-06-17 20:17:17 -07001211 case EFFECT_CMD_INIT:
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001212 if (pReplyData == NULL || *replySize != sizeof(int)) {
Eric Laurenta9390d42011-06-17 20:17:17 -07001213 return -EINVAL;
1214 }
1215 if (effect->ops->init) {
1216 effect->ops->init(effect);
1217 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001218 *(int*)pReplyData = 0;
Eric Laurenta9390d42011-06-17 20:17:17 -07001219 break;
1220
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001221 case EFFECT_CMD_SET_CONFIG: {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001222 if (pCmdData == NULL || cmdSize != sizeof(effect_config_t) || pReplyData == NULL ||
1223 *replySize != sizeof(int)) {
Steve Block3856b092011-10-20 11:56:00 +01001224 ALOGV("PreProcessingFx_Command cmdCode Case: "
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001225 "EFFECT_CMD_SET_CONFIG: ERROR");
Eric Laurenta9390d42011-06-17 20:17:17 -07001226 return -EINVAL;
1227 }
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001228#ifdef DUAL_MIC_TEST
1229 // make sure that the config command is accepted by making as if all effects were
1230 // disabled: this is OK for functional tests
1231 uint32_t enabledMsk = effect->session->enabledMsk;
1232 if (gDualMicEnabled) {
1233 effect->session->enabledMsk = 0;
1234 }
1235#endif
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001236 *(int*)pReplyData = Session_SetConfig(effect->session, (effect_config_t*)pCmdData);
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001237#ifdef DUAL_MIC_TEST
1238 if (gDualMicEnabled) {
1239 effect->session->enabledMsk = enabledMsk;
1240 }
1241#endif
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001242 if (*(int*)pReplyData != 0) {
Eric Laurenta9390d42011-06-17 20:17:17 -07001243 break;
1244 }
Eric Laurent76533e92012-02-17 17:52:04 -08001245 if (effect->state != PREPROC_EFFECT_STATE_ACTIVE) {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001246 *(int*)pReplyData = Effect_SetState(effect, PREPROC_EFFECT_STATE_CONFIG);
Eric Laurent76533e92012-02-17 17:52:04 -08001247 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001248 } break;
Eric Laurenta9390d42011-06-17 20:17:17 -07001249
Eric Laurent3d5188b2011-12-16 15:30:36 -08001250 case EFFECT_CMD_GET_CONFIG:
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001251 if (pReplyData == NULL || *replySize != sizeof(effect_config_t)) {
Eric Laurent3d5188b2011-12-16 15:30:36 -08001252 ALOGV("\tLVM_ERROR : PreProcessingFx_Command cmdCode Case: "
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001253 "EFFECT_CMD_GET_CONFIG: ERROR");
Eric Laurent3d5188b2011-12-16 15:30:36 -08001254 return -EINVAL;
1255 }
1256
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001257 Session_GetConfig(effect->session, (effect_config_t*)pReplyData);
Eric Laurent3d5188b2011-12-16 15:30:36 -08001258 break;
1259
1260 case EFFECT_CMD_SET_CONFIG_REVERSE:
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001261 if (pCmdData == NULL || cmdSize != sizeof(effect_config_t) || pReplyData == NULL ||
Eric Laurent3d5188b2011-12-16 15:30:36 -08001262 *replySize != sizeof(int)) {
Steve Block3856b092011-10-20 11:56:00 +01001263 ALOGV("PreProcessingFx_Command cmdCode Case: "
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001264 "EFFECT_CMD_SET_CONFIG_REVERSE: ERROR");
Eric Laurenta9390d42011-06-17 20:17:17 -07001265 return -EINVAL;
1266 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001267 *(int*)pReplyData =
1268 Session_SetReverseConfig(effect->session, (effect_config_t*)pCmdData);
1269 if (*(int*)pReplyData != 0) {
Eric Laurenta9390d42011-06-17 20:17:17 -07001270 break;
1271 }
1272 break;
1273
Eric Laurent3d5188b2011-12-16 15:30:36 -08001274 case EFFECT_CMD_GET_CONFIG_REVERSE:
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001275 if (pReplyData == NULL || *replySize != sizeof(effect_config_t)) {
Eric Laurent3d5188b2011-12-16 15:30:36 -08001276 ALOGV("PreProcessingFx_Command cmdCode Case: "
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001277 "EFFECT_CMD_GET_CONFIG_REVERSE: ERROR");
Eric Laurent3d5188b2011-12-16 15:30:36 -08001278 return -EINVAL;
1279 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001280 Session_GetReverseConfig(effect->session, (effect_config_t*)pCmdData);
Eric Laurent3d5188b2011-12-16 15:30:36 -08001281 break;
1282
Eric Laurenta9390d42011-06-17 20:17:17 -07001283 case EFFECT_CMD_RESET:
1284 if (effect->ops->reset) {
1285 effect->ops->reset(effect);
1286 }
1287 break;
1288
Eric Laurent0f714a42015-06-19 15:33:57 -07001289 case EFFECT_CMD_GET_PARAM: {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001290 effect_param_t* p = (effect_param_t*)pCmdData;
Eric Laurent0f714a42015-06-19 15:33:57 -07001291
1292 if (pCmdData == NULL || cmdSize < sizeof(effect_param_t) ||
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001293 cmdSize < (sizeof(effect_param_t) + p->psize) || pReplyData == NULL ||
1294 replySize == NULL || *replySize < (sizeof(effect_param_t) + p->psize)) {
Steve Block3856b092011-10-20 11:56:00 +01001295 ALOGV("PreProcessingFx_Command cmdCode Case: "
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001296 "EFFECT_CMD_GET_PARAM: ERROR");
Eric Laurenta9390d42011-06-17 20:17:17 -07001297 return -EINVAL;
1298 }
Eric Laurenta9390d42011-06-17 20:17:17 -07001299
1300 memcpy(pReplyData, pCmdData, sizeof(effect_param_t) + p->psize);
1301
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001302 p = (effect_param_t*)pReplyData;
Eric Laurenta9390d42011-06-17 20:17:17 -07001303
1304 int voffset = ((p->psize - 1) / sizeof(int32_t) + 1) * sizeof(int32_t);
1305
1306 if (effect->ops->get_parameter) {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001307 p->status =
1308 effect->ops->get_parameter(effect, p->data, &p->vsize, p->data + voffset);
Eric Laurenta9390d42011-06-17 20:17:17 -07001309 *replySize = sizeof(effect_param_t) + voffset + p->vsize;
1310 }
1311 } break;
1312
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001313 case EFFECT_CMD_SET_PARAM: {
1314 if (pCmdData == NULL || cmdSize < sizeof(effect_param_t) || pReplyData == NULL ||
1315 replySize == NULL || *replySize != sizeof(int32_t)) {
Steve Block3856b092011-10-20 11:56:00 +01001316 ALOGV("PreProcessingFx_Command cmdCode Case: "
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001317 "EFFECT_CMD_SET_PARAM: ERROR");
Eric Laurenta9390d42011-06-17 20:17:17 -07001318 return -EINVAL;
1319 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001320 effect_param_t* p = (effect_param_t*)pCmdData;
Eric Laurenta9390d42011-06-17 20:17:17 -07001321
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001322 if (p->psize != sizeof(int32_t)) {
Steve Block3856b092011-10-20 11:56:00 +01001323 ALOGV("PreProcessingFx_Command cmdCode Case: "
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001324 "EFFECT_CMD_SET_PARAM: ERROR, psize is not sizeof(int32_t)");
Eric Laurenta9390d42011-06-17 20:17:17 -07001325 return -EINVAL;
1326 }
1327 if (effect->ops->set_parameter) {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001328 *(int*)pReplyData =
1329 effect->ops->set_parameter(effect, (void*)p->data, p->data + p->psize);
Eric Laurenta9390d42011-06-17 20:17:17 -07001330 }
1331 } break;
1332
1333 case EFFECT_CMD_ENABLE:
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001334 if (pReplyData == NULL || replySize == NULL || *replySize != sizeof(int)) {
Steve Block3856b092011-10-20 11:56:00 +01001335 ALOGV("PreProcessingFx_Command cmdCode Case: EFFECT_CMD_ENABLE: ERROR");
Eric Laurenta9390d42011-06-17 20:17:17 -07001336 return -EINVAL;
1337 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001338 *(int*)pReplyData = Effect_SetState(effect, PREPROC_EFFECT_STATE_ACTIVE);
Eric Laurenta9390d42011-06-17 20:17:17 -07001339 break;
1340
1341 case EFFECT_CMD_DISABLE:
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001342 if (pReplyData == NULL || replySize == NULL || *replySize != sizeof(int)) {
Steve Block3856b092011-10-20 11:56:00 +01001343 ALOGV("PreProcessingFx_Command cmdCode Case: EFFECT_CMD_DISABLE: ERROR");
Eric Laurenta9390d42011-06-17 20:17:17 -07001344 return -EINVAL;
1345 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001346 *(int*)pReplyData = Effect_SetState(effect, PREPROC_EFFECT_STATE_CONFIG);
Eric Laurenta9390d42011-06-17 20:17:17 -07001347 break;
1348
1349 case EFFECT_CMD_SET_DEVICE:
1350 case EFFECT_CMD_SET_INPUT_DEVICE:
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001351 if (pCmdData == NULL || cmdSize != sizeof(uint32_t)) {
Steve Block3856b092011-10-20 11:56:00 +01001352 ALOGV("PreProcessingFx_Command cmdCode Case: EFFECT_CMD_SET_DEVICE: ERROR");
Eric Laurenta9390d42011-06-17 20:17:17 -07001353 return -EINVAL;
1354 }
1355
1356 if (effect->ops->set_device) {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001357 effect->ops->set_device(effect, *(uint32_t*)pCmdData);
Eric Laurenta9390d42011-06-17 20:17:17 -07001358 }
1359 break;
1360
1361 case EFFECT_CMD_SET_VOLUME:
1362 case EFFECT_CMD_SET_AUDIO_MODE:
1363 break;
1364
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001365#ifdef DUAL_MIC_TEST
1366 ///// test commands start
1367 case PREPROC_CMD_DUAL_MIC_ENABLE: {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001368 if (pCmdData == NULL || cmdSize != sizeof(uint32_t) || pReplyData == NULL ||
1369 replySize == NULL) {
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001370 ALOGE("PreProcessingFx_Command cmdCode Case: "
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001371 "PREPROC_CMD_DUAL_MIC_ENABLE: ERROR");
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001372 *replySize = 0;
1373 return -EINVAL;
1374 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001375 gDualMicEnabled = *(bool*)pCmdData;
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001376 if (gDualMicEnabled) {
1377 effect->aux_channels_on = sHasAuxChannels[effect->procId];
1378 } else {
1379 effect->aux_channels_on = false;
1380 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001381 effect->cur_channel_config =
1382 (effect->session->inChannelCount == 1) ? CHANNEL_CFG_MONO : CHANNEL_CFG_STEREO;
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001383
1384 ALOGV("PREPROC_CMD_DUAL_MIC_ENABLE: %s", gDualMicEnabled ? "enabled" : "disabled");
1385 *replySize = sizeof(int);
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001386 *(int*)pReplyData = 0;
1387 } break;
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001388 case PREPROC_CMD_DUAL_MIC_PCM_DUMP_START: {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001389 if (pCmdData == NULL || pReplyData == NULL || replySize == NULL) {
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001390 ALOGE("PreProcessingFx_Command cmdCode Case: "
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001391 "PREPROC_CMD_DUAL_MIC_PCM_DUMP_START: ERROR");
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001392 *replySize = 0;
1393 return -EINVAL;
1394 }
1395 pthread_mutex_lock(&gPcmDumpLock);
1396 if (gPcmDumpFh != NULL) {
1397 fclose(gPcmDumpFh);
1398 gPcmDumpFh = NULL;
1399 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001400 char* path = strndup((char*)pCmdData, cmdSize);
1401 gPcmDumpFh = fopen((char*)path, "wb");
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001402 pthread_mutex_unlock(&gPcmDumpLock);
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001403 ALOGV("PREPROC_CMD_DUAL_MIC_PCM_DUMP_START: path %s gPcmDumpFh %p", path, gPcmDumpFh);
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001404 ALOGE_IF(gPcmDumpFh <= 0, "gPcmDumpFh open error %d %s", errno, strerror(errno));
1405 free(path);
1406 *replySize = sizeof(int);
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001407 *(int*)pReplyData = 0;
1408 } break;
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001409 case PREPROC_CMD_DUAL_MIC_PCM_DUMP_STOP: {
1410 if (pReplyData == NULL || replySize == NULL) {
1411 ALOGE("PreProcessingFx_Command cmdCode Case: "
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001412 "PREPROC_CMD_DUAL_MIC_PCM_DUMP_STOP: ERROR");
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001413 *replySize = 0;
1414 return -EINVAL;
1415 }
1416 pthread_mutex_lock(&gPcmDumpLock);
1417 if (gPcmDumpFh != NULL) {
1418 fclose(gPcmDumpFh);
1419 gPcmDumpFh = NULL;
1420 }
1421 pthread_mutex_unlock(&gPcmDumpLock);
1422 ALOGV("PREPROC_CMD_DUAL_MIC_PCM_DUMP_STOP");
1423 *replySize = sizeof(int);
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001424 *(int*)pReplyData = 0;
1425 } break;
1426 ///// test commands end
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001427
1428 case EFFECT_CMD_GET_FEATURE_SUPPORTED_CONFIGS: {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001429 if (!gDualMicEnabled) {
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001430 return -EINVAL;
1431 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001432 if (pCmdData == NULL || cmdSize != 2 * sizeof(uint32_t) || pReplyData == NULL ||
1433 replySize == NULL) {
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001434 ALOGE("PreProcessingFx_Command cmdCode Case: "
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001435 "EFFECT_CMD_GET_FEATURE_SUPPORTED_CONFIGS: ERROR");
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001436 *replySize = 0;
1437 return -EINVAL;
1438 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001439 if (*(uint32_t*)pCmdData != EFFECT_FEATURE_AUX_CHANNELS || !effect->aux_channels_on) {
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001440 ALOGV("PreProcessingFx_Command feature EFFECT_FEATURE_AUX_CHANNELS not supported by"
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001441 " fx %d",
1442 effect->procId);
1443 *(uint32_t*)pReplyData = -ENOSYS;
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001444 *replySize = sizeof(uint32_t);
1445 break;
1446 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001447 size_t num_configs = *((uint32_t*)pCmdData + 1);
1448 if (*replySize < (2 * sizeof(uint32_t) + num_configs * sizeof(channel_config_t))) {
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001449 *replySize = 0;
1450 return -EINVAL;
1451 }
1452
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001453 *((uint32_t*)pReplyData + 1) = CHANNEL_CFG_CNT;
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001454 if (num_configs < CHANNEL_CFG_CNT ||
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001455 *replySize < (2 * sizeof(uint32_t) + CHANNEL_CFG_CNT * sizeof(channel_config_t))) {
1456 *(uint32_t*)pReplyData = -ENOMEM;
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001457 } else {
1458 num_configs = CHANNEL_CFG_CNT;
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001459 *(uint32_t*)pReplyData = 0;
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001460 }
1461 ALOGV("PreProcessingFx_Command EFFECT_CMD_GET_FEATURE_SUPPORTED_CONFIGS num config %d",
1462 num_configs);
1463
1464 *replySize = 2 * sizeof(uint32_t) + num_configs * sizeof(channel_config_t);
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001465 *((uint32_t*)pReplyData + 1) = num_configs;
1466 memcpy((uint32_t*)pReplyData + 2, &sDualMicConfigs,
1467 num_configs * sizeof(channel_config_t));
1468 } break;
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001469 case EFFECT_CMD_GET_FEATURE_CONFIG:
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001470 if (!gDualMicEnabled) {
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001471 return -EINVAL;
1472 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001473 if (pCmdData == NULL || cmdSize != sizeof(uint32_t) || pReplyData == NULL ||
1474 replySize == NULL || *replySize < sizeof(uint32_t) + sizeof(channel_config_t)) {
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001475 ALOGE("PreProcessingFx_Command cmdCode Case: "
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001476 "EFFECT_CMD_GET_FEATURE_CONFIG: ERROR");
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001477 return -EINVAL;
1478 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001479 if (*(uint32_t*)pCmdData != EFFECT_FEATURE_AUX_CHANNELS || !effect->aux_channels_on) {
1480 *(uint32_t*)pReplyData = -ENOSYS;
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001481 *replySize = sizeof(uint32_t);
1482 break;
1483 }
1484 ALOGV("PreProcessingFx_Command EFFECT_CMD_GET_FEATURE_CONFIG");
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001485 *(uint32_t*)pReplyData = 0;
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001486 *replySize = sizeof(uint32_t) + sizeof(channel_config_t);
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001487 memcpy((uint32_t*)pReplyData + 1, &sDualMicConfigs[effect->cur_channel_config],
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001488 sizeof(channel_config_t));
1489 break;
1490 case EFFECT_CMD_SET_FEATURE_CONFIG: {
1491 ALOGV("PreProcessingFx_Command EFFECT_CMD_SET_FEATURE_CONFIG: "
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001492 "gDualMicEnabled %d effect->aux_channels_on %d",
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001493 gDualMicEnabled, effect->aux_channels_on);
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001494 if (!gDualMicEnabled) {
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001495 return -EINVAL;
1496 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001497 if (pCmdData == NULL || cmdSize != (sizeof(uint32_t) + sizeof(channel_config_t)) ||
1498 pReplyData == NULL || replySize == NULL || *replySize < sizeof(uint32_t)) {
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001499 ALOGE("PreProcessingFx_Command cmdCode Case: "
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001500 "EFFECT_CMD_SET_FEATURE_CONFIG: ERROR\n"
1501 "pCmdData %p cmdSize %d pReplyData %p replySize %p *replySize %d",
1502 pCmdData, cmdSize, pReplyData, replySize, replySize ? *replySize : -1);
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001503 return -EINVAL;
1504 }
1505 *replySize = sizeof(uint32_t);
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001506 if (*(uint32_t*)pCmdData != EFFECT_FEATURE_AUX_CHANNELS || !effect->aux_channels_on) {
1507 *(uint32_t*)pReplyData = -ENOSYS;
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001508 ALOGV("PreProcessingFx_Command cmdCode Case: "
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001509 "EFFECT_CMD_SET_FEATURE_CONFIG: ERROR\n"
1510 "CmdData %d effect->aux_channels_on %d",
1511 *(uint32_t*)pCmdData, effect->aux_channels_on);
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001512 break;
1513 }
1514 size_t i;
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001515 for (i = 0; i < CHANNEL_CFG_CNT; i++) {
1516 if (memcmp((uint32_t*)pCmdData + 1, &sDualMicConfigs[i],
1517 sizeof(channel_config_t)) == 0) {
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001518 break;
1519 }
1520 }
1521 if (i == CHANNEL_CFG_CNT) {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001522 *(uint32_t*)pReplyData = -EINVAL;
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001523 ALOGW("PreProcessingFx_Command EFFECT_CMD_SET_FEATURE_CONFIG invalid config"
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001524 "[%08x].[%08x]",
1525 *((uint32_t*)pCmdData + 1), *((uint32_t*)pCmdData + 2));
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001526 } else {
1527 effect->cur_channel_config = i;
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001528 *(uint32_t*)pReplyData = 0;
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001529 ALOGV("PreProcessingFx_Command EFFECT_CMD_SET_FEATURE_CONFIG New config"
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001530 "[%08x].[%08x]",
1531 sDualMicConfigs[i].main_channels, sDualMicConfigs[i].aux_channels);
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001532 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001533 } break;
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001534#endif
Eric Laurenta9390d42011-06-17 20:17:17 -07001535 default:
1536 return -EINVAL;
1537 }
1538 return 0;
1539}
1540
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001541int PreProcessingFx_GetDescriptor(effect_handle_t self, effect_descriptor_t* pDescriptor) {
1542 preproc_effect_t* effect = (preproc_effect_t*)self;
Eric Laurenta9390d42011-06-17 20:17:17 -07001543
1544 if (effect == NULL || pDescriptor == NULL) {
1545 return -EINVAL;
1546 }
1547
Glenn Kastena189a682012-02-20 12:16:30 -08001548 *pDescriptor = *sDescriptors[effect->procId];
Eric Laurenta9390d42011-06-17 20:17:17 -07001549
1550 return 0;
1551}
1552
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001553int PreProcessingFx_ProcessReverse(effect_handle_t self, audio_buffer_t* inBuffer,
1554 audio_buffer_t* outBuffer __unused) {
1555 preproc_effect_t* effect = (preproc_effect_t*)self;
Eric Laurenta9390d42011-06-17 20:17:17 -07001556
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001557 if (effect == NULL) {
Steve Block5ff1dd52012-01-05 23:22:43 +00001558 ALOGW("PreProcessingFx_ProcessReverse() ERROR effect == NULL");
Eric Laurenta9390d42011-06-17 20:17:17 -07001559 return -EINVAL;
1560 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001561 preproc_session_t* session = (preproc_session_t*)effect->session;
Eric Laurenta9390d42011-06-17 20:17:17 -07001562
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001563 if (inBuffer == NULL || inBuffer->raw == NULL) {
Steve Block5ff1dd52012-01-05 23:22:43 +00001564 ALOGW("PreProcessingFx_ProcessReverse() ERROR bad pointer");
Eric Laurenta9390d42011-06-17 20:17:17 -07001565 return -EINVAL;
1566 }
1567
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001568 session->revProcessedMsk |= (1 << effect->procId);
Eric Laurenta9390d42011-06-17 20:17:17 -07001569
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001570 // ALOGV("PreProcessingFx_ProcessReverse In %d frames revEnabledMsk %08x revProcessedMsk
1571 // %08x",
1572 // inBuffer->frameCount, session->revEnabledMsk, session->revProcessedMsk);
Eric Laurenta9390d42011-06-17 20:17:17 -07001573
1574 if ((session->revProcessedMsk & session->revEnabledMsk) == session->revEnabledMsk) {
1575 effect->session->revProcessedMsk = 0;
Saketh Sathuvalli08337032020-09-22 21:13:45 +05301576 size_t fr = session->frameCount - session->framesRev;
1577 if (inBuffer->frameCount < fr) {
1578 fr = inBuffer->frameCount;
1579 }
1580 session->framesRev += fr;
1581 inBuffer->frameCount = fr;
1582 if (session->framesRev < session->frameCount) {
1583 return 0;
1584 }
1585 session->framesRev = 0;
1586 if (int status = effect->session->apm->ProcessReverseStream(
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001587 (const int16_t* const)inBuffer->s16,
1588 (const webrtc::StreamConfig)effect->session->revConfig,
1589 (const webrtc::StreamConfig)effect->session->revConfig,
1590 (int16_t* const)outBuffer->s16);
1591 status != 0) {
Saketh Sathuvalli08337032020-09-22 21:13:45 +05301592 ALOGE("Process Reverse Stream failed with error %d\n", status);
1593 return status;
1594 }
Eric Laurenta9390d42011-06-17 20:17:17 -07001595 return 0;
1596 } else {
1597 return -ENODATA;
1598 }
1599}
1600
Eric Laurenta9390d42011-06-17 20:17:17 -07001601// effect_handle_t interface implementation for effect
1602const struct effect_interface_s sEffectInterface = {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001603 PreProcessingFx_Process, PreProcessingFx_Command, PreProcessingFx_GetDescriptor, NULL};
Eric Laurenta9390d42011-06-17 20:17:17 -07001604
1605const struct effect_interface_s sEffectInterfaceReverse = {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001606 PreProcessingFx_Process, PreProcessingFx_Command, PreProcessingFx_GetDescriptor,
1607 PreProcessingFx_ProcessReverse};
Eric Laurenta9390d42011-06-17 20:17:17 -07001608
1609//------------------------------------------------------------------------------
1610// Effect Library Interface Implementation
1611//------------------------------------------------------------------------------
1612
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001613int PreProcessingLib_Create(const effect_uuid_t* uuid, int32_t sessionId, int32_t ioId,
1614 effect_handle_t* pInterface) {
Steve Block3856b092011-10-20 11:56:00 +01001615 ALOGV("EffectCreate: uuid: %08x session %d IO: %d", uuid->timeLow, sessionId, ioId);
Eric Laurenta9390d42011-06-17 20:17:17 -07001616
1617 int status;
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001618 const effect_descriptor_t* desc;
1619 preproc_session_t* session;
Eric Laurenta9390d42011-06-17 20:17:17 -07001620 uint32_t procId;
1621
1622 if (PreProc_Init() != 0) {
1623 return sInitStatus;
1624 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001625 desc = PreProc_GetDescriptor(uuid);
Eric Laurenta9390d42011-06-17 20:17:17 -07001626 if (desc == NULL) {
Steve Block5ff1dd52012-01-05 23:22:43 +00001627 ALOGW("EffectCreate: fx not found uuid: %08x", uuid->timeLow);
Eric Laurenta9390d42011-06-17 20:17:17 -07001628 return -EINVAL;
1629 }
1630 procId = UuidToProcId(&desc->type);
1631
1632 session = PreProc_GetSession(procId, sessionId, ioId);
1633 if (session == NULL) {
Steve Block5ff1dd52012-01-05 23:22:43 +00001634 ALOGW("EffectCreate: no more session available");
Eric Laurenta9390d42011-06-17 20:17:17 -07001635 return -EINVAL;
1636 }
1637
1638 status = Session_CreateEffect(session, procId, pInterface);
1639
1640 if (status < 0 && session->createdMsk == 0) {
Eric Laurentb20cf7d2019-04-05 19:37:34 -07001641 session->id = 0;
Eric Laurenta9390d42011-06-17 20:17:17 -07001642 }
1643 return status;
1644}
1645
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001646int PreProcessingLib_Release(effect_handle_t interface) {
Steve Block3856b092011-10-20 11:56:00 +01001647 ALOGV("EffectRelease start %p", interface);
Eric Laurenta9390d42011-06-17 20:17:17 -07001648 if (PreProc_Init() != 0) {
1649 return sInitStatus;
1650 }
1651
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001652 preproc_effect_t* fx = (preproc_effect_t*)interface;
Eric Laurenta9390d42011-06-17 20:17:17 -07001653
Eric Laurentb20cf7d2019-04-05 19:37:34 -07001654 if (fx->session->id == 0) {
Eric Laurenta9390d42011-06-17 20:17:17 -07001655 return -EINVAL;
1656 }
1657 return Session_ReleaseEffect(fx->session, fx);
1658}
1659
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001660int PreProcessingLib_GetDescriptor(const effect_uuid_t* uuid, effect_descriptor_t* pDescriptor) {
1661 if (pDescriptor == NULL || uuid == NULL) {
Eric Laurenta9390d42011-06-17 20:17:17 -07001662 return -EINVAL;
1663 }
1664
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001665 const effect_descriptor_t* desc = PreProc_GetDescriptor(uuid);
Eric Laurenta9390d42011-06-17 20:17:17 -07001666 if (desc == NULL) {
Steve Block3856b092011-10-20 11:56:00 +01001667 ALOGV("PreProcessingLib_GetDescriptor() not found");
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001668 return -EINVAL;
Eric Laurenta9390d42011-06-17 20:17:17 -07001669 }
1670
Steve Block3856b092011-10-20 11:56:00 +01001671 ALOGV("PreProcessingLib_GetDescriptor() got fx %s", desc->name);
Eric Laurenta9390d42011-06-17 20:17:17 -07001672
Glenn Kastena189a682012-02-20 12:16:30 -08001673 *pDescriptor = *desc;
Eric Laurenta9390d42011-06-17 20:17:17 -07001674 return 0;
1675}
1676
Marco Nelissen7f16b192012-10-25 16:05:57 -07001677// This is the only symbol that needs to be exported
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001678__attribute__((visibility("default"))) audio_effect_library_t AUDIO_EFFECT_LIBRARY_INFO_SYM = {
1679 .tag = AUDIO_EFFECT_LIBRARY_TAG,
1680 .version = EFFECT_LIBRARY_API_VERSION,
1681 .name = "Audio Preprocessing Library",
1682 .implementor = "The Android Open Source Project",
1683 .create_effect = PreProcessingLib_Create,
1684 .release_effect = PreProcessingLib_Release,
1685 .get_descriptor = PreProcessingLib_GetDescriptor};
Eric Laurenta9390d42011-06-17 20:17:17 -07001686
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001687}; // extern "C"