blob: 1a5547b035514d83e56381aa9363496203797437 [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#ifndef WEBRTC_LEGACY
27#include <audio_effects/effect_agc2.h>
28#endif
Eric Laurenta9390d42011-06-17 20:17:17 -070029#include <audio_effects/effect_ns.h>
Eric Laurent53876962012-01-31 12:35:20 -080030#include <audio_processing.h>
Harish Mahendrakarb6926c72020-11-27 15:22:44 -080031#include <module_common_types.h>
Saketh Sathuvalli08337032020-09-22 21:13:45 +053032#ifdef WEBRTC_LEGACY
Eric Laurenta9390d42011-06-17 20:17:17 -070033#include "speex/speex_resampler.h"
Saketh Sathuvalli08337032020-09-22 21:13:45 +053034#endif
Eric Laurenta9390d42011-06-17 20:17:17 -070035
Eric Laurent3f9c84c2012-04-03 15:36:53 -070036// undefine to perform multi channels API functional tests
37//#define DUAL_MIC_TEST
Eric Laurenta9390d42011-06-17 20:17:17 -070038
39//------------------------------------------------------------------------------
40// local definitions
41//------------------------------------------------------------------------------
42
43// maximum number of sessions
44#define PREPROC_NUM_SESSIONS 8
45
46// types of pre processing modules
Harish Mahendrakarb6926c72020-11-27 15:22:44 -080047enum preproc_id {
48 PREPROC_AGC, // Automatic Gain Control
Saketh Sathuvalli08337032020-09-22 21:13:45 +053049#ifndef WEBRTC_LEGACY
Harish Mahendrakarb6926c72020-11-27 15:22:44 -080050 PREPROC_AGC2, // Automatic Gain Control 2
Saketh Sathuvalli08337032020-09-22 21:13:45 +053051#endif
Harish Mahendrakarb6926c72020-11-27 15:22:44 -080052 PREPROC_AEC, // Acoustic Echo Canceler
53 PREPROC_NS, // Noise Suppressor
Eric Laurenta9390d42011-06-17 20:17:17 -070054 PREPROC_NUM_EFFECTS
55};
56
57// Session state
58enum preproc_session_state {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -080059 PREPROC_SESSION_STATE_INIT, // initialized
60 PREPROC_SESSION_STATE_CONFIG // configuration received
Eric Laurenta9390d42011-06-17 20:17:17 -070061};
62
63// Effect/Preprocessor state
64enum preproc_effect_state {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -080065 PREPROC_EFFECT_STATE_INIT, // initialized
66 PREPROC_EFFECT_STATE_CREATED, // webRTC engine created
67 PREPROC_EFFECT_STATE_CONFIG, // configuration received/disabled
68 PREPROC_EFFECT_STATE_ACTIVE // active/enabled
Eric Laurenta9390d42011-06-17 20:17:17 -070069};
70
71// handle on webRTC engine
72typedef void* preproc_fx_handle_t;
73
74typedef struct preproc_session_s preproc_session_t;
75typedef struct preproc_effect_s preproc_effect_t;
76typedef struct preproc_ops_s preproc_ops_t;
77
78// Effect operation table. Functions for all pre processors are declared in sPreProcOps[] table.
79// Function pointer can be null if no action required.
80struct preproc_ops_s {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -080081 int (*create)(preproc_effect_t* fx);
82 int (*init)(preproc_effect_t* fx);
83 int (*reset)(preproc_effect_t* fx);
84 void (*enable)(preproc_effect_t* fx);
85 void (*disable)(preproc_effect_t* fx);
86 int (*set_parameter)(preproc_effect_t* fx, void* param, void* value);
87 int (*get_parameter)(preproc_effect_t* fx, void* param, uint32_t* size, void* value);
88 int (*set_device)(preproc_effect_t* fx, uint32_t device);
Eric Laurenta9390d42011-06-17 20:17:17 -070089};
90
91// Effect context
92struct preproc_effect_s {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -080093 const struct effect_interface_s* itfe;
94 uint32_t procId; // type of pre processor (enum preproc_id)
95 uint32_t state; // current state (enum preproc_effect_state)
96 preproc_session_t* session; // session the effect is on
97 const preproc_ops_t* ops; // effect ops table
98 preproc_fx_handle_t engine; // handle on webRTC engine
99 uint32_t type; // subtype of effect
Eric Laurent3f9c84c2012-04-03 15:36:53 -0700100#ifdef DUAL_MIC_TEST
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800101 bool aux_channels_on; // support auxiliary channels
102 size_t cur_channel_config; // current auciliary channel configuration
Eric Laurent3f9c84c2012-04-03 15:36:53 -0700103#endif
Eric Laurenta9390d42011-06-17 20:17:17 -0700104};
105
106// Session context
107struct preproc_session_s {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800108 struct preproc_effect_s effects[PREPROC_NUM_EFFECTS]; // effects in this session
109 uint32_t state; // current state (enum preproc_session_state)
110 int id; // audio session ID
111 int io; // handle of input stream this session is on
112 webrtc::AudioProcessing* apm; // handle on webRTC audio processing module (APM)
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530113#ifndef WEBRTC_LEGACY
114 // Audio Processing module builder
115 webrtc::AudioProcessingBuilder ap_builder;
116#endif
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800117 size_t apmFrameCount; // buffer size for webRTC process (10 ms)
118 uint32_t apmSamplingRate; // webRTC APM sampling rate (8/16 or 32 kHz)
119 size_t frameCount; // buffer size before input resampler ( <=> apmFrameCount)
120 uint32_t samplingRate; // sampling rate at effect process interface
121 uint32_t inChannelCount; // input channel count
122 uint32_t outChannelCount; // output channel count
123 uint32_t createdMsk; // bit field containing IDs of crested pre processors
124 uint32_t enabledMsk; // bit field containing IDs of enabled pre processors
125 uint32_t processedMsk; // bit field containing IDs of pre processors already
126 // processed in current round
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530127#ifdef WEBRTC_LEGACY
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800128 webrtc::AudioFrame* procFrame; // audio frame passed to webRTC AMP ProcessStream()
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530129#else
130 // audio config strucutre
131 webrtc::AudioProcessing::Config config;
132 webrtc::StreamConfig inputConfig; // input stream configuration
133 webrtc::StreamConfig outputConfig; // output stream configuration
134#endif
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800135 int16_t* inBuf; // input buffer used when resampling
136 size_t inBufSize; // input buffer size in frames
137 size_t framesIn; // number of frames in input buffer
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530138#ifdef WEBRTC_LEGACY
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800139 SpeexResamplerState* inResampler; // handle on input speex resampler
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530140#endif
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800141 int16_t* outBuf; // output buffer used when resampling
142 size_t outBufSize; // output buffer size in frames
143 size_t framesOut; // number of frames in output buffer
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530144#ifdef WEBRTC_LEGACY
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800145 SpeexResamplerState* outResampler; // handle on output speex resampler
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530146#endif
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800147 uint32_t revChannelCount; // number of channels on reverse stream
148 uint32_t revEnabledMsk; // bit field containing IDs of enabled pre processors
149 // with reverse channel
150 uint32_t revProcessedMsk; // bit field containing IDs of pre processors with reverse
151 // channel already processed in current round
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530152#ifdef WEBRTC_LEGACY
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800153 webrtc::AudioFrame* revFrame; // audio frame passed to webRTC AMP AnalyzeReverseStream()
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530154#else
155 webrtc::StreamConfig revConfig; // reverse stream configuration.
156#endif
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800157 int16_t* revBuf; // reverse channel input buffer
158 size_t revBufSize; // reverse channel input buffer size
159 size_t framesRev; // number of frames in reverse channel input buffer
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530160#ifdef WEBRTC_LEGACY
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800161 SpeexResamplerState* revResampler; // handle on reverse channel input speex resampler
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530162#endif
Eric Laurenta9390d42011-06-17 20:17:17 -0700163};
164
Eric Laurent3f9c84c2012-04-03 15:36:53 -0700165#ifdef DUAL_MIC_TEST
166enum {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800167 PREPROC_CMD_DUAL_MIC_ENABLE = EFFECT_CMD_FIRST_PROPRIETARY, // enable dual mic mode
168 PREPROC_CMD_DUAL_MIC_PCM_DUMP_START, // start pcm capture
169 PREPROC_CMD_DUAL_MIC_PCM_DUMP_STOP // stop pcm capture
Eric Laurent3f9c84c2012-04-03 15:36:53 -0700170};
171
172enum {
173 CHANNEL_CFG_MONO,
174 CHANNEL_CFG_STEREO,
175 CHANNEL_CFG_MONO_AUX,
176 CHANNEL_CFG_STEREO_AUX,
177 CHANNEL_CFG_CNT,
178 CHANNEL_CFG_FIRST_AUX = CHANNEL_CFG_MONO_AUX,
179};
180
181const channel_config_t sDualMicConfigs[CHANNEL_CFG_CNT] = {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800182 {AUDIO_CHANNEL_IN_MONO, 0},
183 {AUDIO_CHANNEL_IN_STEREO, 0},
184 {AUDIO_CHANNEL_IN_FRONT, AUDIO_CHANNEL_IN_BACK},
185 {AUDIO_CHANNEL_IN_STEREO, AUDIO_CHANNEL_IN_RIGHT}};
Eric Laurent3f9c84c2012-04-03 15:36:53 -0700186
187bool sHasAuxChannels[PREPROC_NUM_EFFECTS] = {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800188 false, // PREPROC_AGC
Eric Laurent3f9c84c2012-04-03 15:36:53 -0700189 true, // PREPROC_AEC
190 true, // PREPROC_NS
191};
192
193bool gDualMicEnabled;
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800194FILE* gPcmDumpFh;
Eric Laurent3f9c84c2012-04-03 15:36:53 -0700195static pthread_mutex_t gPcmDumpLock = PTHREAD_MUTEX_INITIALIZER;
196#endif
197
Eric Laurenta9390d42011-06-17 20:17:17 -0700198//------------------------------------------------------------------------------
199// Effect descriptors
200//------------------------------------------------------------------------------
201
202// UUIDs for effect types have been generated from http://www.itu.int/ITU-T/asn1/uuid.html
203// as the pre processing effects are not defined by OpenSL ES
204
205// Automatic Gain Control
206static const effect_descriptor_t sAgcDescriptor = {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800207 {0x0a8abfe0, 0x654c, 0x11e0, 0xba26, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, // type
208 {0xaa8130e0, 0x66fc, 0x11e0, 0xbad0, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, // uuid
Eric Laurenta9390d42011-06-17 20:17:17 -0700209 EFFECT_CONTROL_API_VERSION,
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800210 (EFFECT_FLAG_TYPE_PRE_PROC | EFFECT_FLAG_DEVICE_IND),
211 0, // FIXME indicate CPU load
212 0, // FIXME indicate memory usage
Eric Laurenta9390d42011-06-17 20:17:17 -0700213 "Automatic Gain Control",
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800214 "The Android Open Source Project"};
Eric Laurenta9390d42011-06-17 20:17:17 -0700215
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530216#ifndef WEBRTC_LEGACY
217// Automatic Gain Control 2
218static const effect_descriptor_t sAgc2Descriptor = {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800219 {0xae3c653b, 0xbe18, 0x4ab8, 0x8938, {0x41, 0x8f, 0x0a, 0x7f, 0x06, 0xac}}, // type
220 {0x89f38e65, 0xd4d2, 0x4d64, 0xad0e, {0x2b, 0x3e, 0x79, 0x9e, 0xa8, 0x86}}, // uuid
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530221 EFFECT_CONTROL_API_VERSION,
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800222 (EFFECT_FLAG_TYPE_PRE_PROC | EFFECT_FLAG_DEVICE_IND),
223 0, // FIXME indicate CPU load
224 0, // FIXME indicate memory usage
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530225 "Automatic Gain Control 2",
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800226 "The Android Open Source Project"};
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530227#endif
228
Eric Laurenta9390d42011-06-17 20:17:17 -0700229// Acoustic Echo Cancellation
230static const effect_descriptor_t sAecDescriptor = {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800231 {0x7b491460, 0x8d4d, 0x11e0, 0xbd61, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, // type
232 {0xbb392ec0, 0x8d4d, 0x11e0, 0xa896, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, // uuid
Eric Laurenta9390d42011-06-17 20:17:17 -0700233 EFFECT_CONTROL_API_VERSION,
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800234 (EFFECT_FLAG_TYPE_PRE_PROC | EFFECT_FLAG_DEVICE_IND),
235 0, // FIXME indicate CPU load
236 0, // FIXME indicate memory usage
Eric Laurenta9390d42011-06-17 20:17:17 -0700237 "Acoustic Echo Canceler",
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800238 "The Android Open Source Project"};
Eric Laurenta9390d42011-06-17 20:17:17 -0700239
240// Noise suppression
241static const effect_descriptor_t sNsDescriptor = {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800242 {0x58b4b260, 0x8e06, 0x11e0, 0xaa8e, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, // type
243 {0xc06c8400, 0x8e06, 0x11e0, 0x9cb6, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, // uuid
Eric Laurenta9390d42011-06-17 20:17:17 -0700244 EFFECT_CONTROL_API_VERSION,
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800245 (EFFECT_FLAG_TYPE_PRE_PROC | EFFECT_FLAG_DEVICE_IND),
246 0, // FIXME indicate CPU load
247 0, // FIXME indicate memory usage
Eric Laurenta9390d42011-06-17 20:17:17 -0700248 "Noise Suppression",
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800249 "The Android Open Source Project"};
Eric Laurenta9390d42011-06-17 20:17:17 -0700250
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800251static const effect_descriptor_t* sDescriptors[PREPROC_NUM_EFFECTS] = {&sAgcDescriptor,
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530252#ifndef WEBRTC_LEGACY
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800253 &sAgc2Descriptor,
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530254#endif
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800255 &sAecDescriptor,
256 &sNsDescriptor};
Eric Laurenta9390d42011-06-17 20:17:17 -0700257
258//------------------------------------------------------------------------------
259// Helper functions
260//------------------------------------------------------------------------------
261
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800262const effect_uuid_t* const sUuidToPreProcTable[PREPROC_NUM_EFFECTS] = {FX_IID_AGC,
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530263#ifndef WEBRTC_LEGACY
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800264 FX_IID_AGC2,
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530265#endif
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800266 FX_IID_AEC, FX_IID_NS};
Eric Laurenta9390d42011-06-17 20:17:17 -0700267
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800268const effect_uuid_t* ProcIdToUuid(int procId) {
Eric Laurenta9390d42011-06-17 20:17:17 -0700269 if (procId >= PREPROC_NUM_EFFECTS) {
270 return EFFECT_UUID_NULL;
271 }
272 return sUuidToPreProcTable[procId];
273}
274
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800275uint32_t UuidToProcId(const effect_uuid_t* uuid) {
Eric Laurenta9390d42011-06-17 20:17:17 -0700276 size_t i;
277 for (i = 0; i < PREPROC_NUM_EFFECTS; i++) {
278 if (memcmp(uuid, sUuidToPreProcTable[i], sizeof(*uuid)) == 0) {
279 break;
280 }
281 }
282 return i;
283}
284
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800285bool HasReverseStream(uint32_t procId) {
Eric Laurenta9390d42011-06-17 20:17:17 -0700286 if (procId == PREPROC_AEC) {
287 return true;
288 }
289 return false;
290}
291
Eric Laurenta9390d42011-06-17 20:17:17 -0700292//------------------------------------------------------------------------------
293// Automatic Gain Control (AGC)
294//------------------------------------------------------------------------------
295
Eric Laurent53876962012-01-31 12:35:20 -0800296static const int kAgcDefaultTargetLevel = 3;
297static const int kAgcDefaultCompGain = 9;
Eric Laurenta9390d42011-06-17 20:17:17 -0700298static const bool kAgcDefaultLimiter = true;
299
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530300#ifndef WEBRTC_LEGACY
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800301int Agc2Init(preproc_effect_t* effect) {
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530302 ALOGV("Agc2Init");
303 effect->session->config = effect->session->apm->GetConfig();
304 effect->session->config.gain_controller2.fixed_digital.gain_db = 0.f;
305 effect->session->config.gain_controller2.adaptive_digital.level_estimator =
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800306 effect->session->config.gain_controller2.kRms;
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530307 effect->session->config.gain_controller2.adaptive_digital.extra_saturation_margin_db = 2.f;
308 effect->session->apm->ApplyConfig(effect->session->config);
309 return 0;
310}
311#endif
312
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800313int AgcInit(preproc_effect_t* effect) {
Steve Block3856b092011-10-20 11:56:00 +0100314 ALOGV("AgcInit");
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530315#ifdef WEBRTC_LEGACY
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800316 webrtc::GainControl* agc = static_cast<webrtc::GainControl*>(effect->engine);
Eric Laurenta9390d42011-06-17 20:17:17 -0700317 agc->set_mode(webrtc::GainControl::kFixedDigital);
318 agc->set_target_level_dbfs(kAgcDefaultTargetLevel);
319 agc->set_compression_gain_db(kAgcDefaultCompGain);
320 agc->enable_limiter(kAgcDefaultLimiter);
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530321#else
322 effect->session->config = effect->session->apm->GetConfig();
323 effect->session->config.gain_controller1.target_level_dbfs = kAgcDefaultTargetLevel;
324 effect->session->config.gain_controller1.compression_gain_db = kAgcDefaultCompGain;
325 effect->session->config.gain_controller1.enable_limiter = kAgcDefaultLimiter;
326 effect->session->apm->ApplyConfig(effect->session->config);
327#endif
Eric Laurenta9390d42011-06-17 20:17:17 -0700328 return 0;
329}
330
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530331#ifndef WEBRTC_LEGACY
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800332int Agc2Create(preproc_effect_t* effect) {
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530333 Agc2Init(effect);
334 return 0;
335}
336#endif
337
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800338int AgcCreate(preproc_effect_t* effect) {
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530339#ifdef WEBRTC_LEGACY
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800340 webrtc::GainControl* agc = effect->session->apm->gain_control();
Steve Block3856b092011-10-20 11:56:00 +0100341 ALOGV("AgcCreate got agc %p", agc);
Eric Laurenta9390d42011-06-17 20:17:17 -0700342 if (agc == NULL) {
Steve Block5ff1dd52012-01-05 23:22:43 +0000343 ALOGW("AgcCreate Error");
Eric Laurenta9390d42011-06-17 20:17:17 -0700344 return -ENOMEM;
345 }
346 effect->engine = static_cast<preproc_fx_handle_t>(agc);
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530347#endif
Eric Laurenta9390d42011-06-17 20:17:17 -0700348 AgcInit(effect);
349 return 0;
350}
351
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530352#ifndef WEBRTC_LEGACY
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800353int Agc2GetParameter(preproc_effect_t* effect, void* pParam, uint32_t* pValueSize, void* pValue) {
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530354 int status = 0;
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800355 uint32_t param = *(uint32_t*)pParam;
356 agc2_settings_t* pProperties = (agc2_settings_t*)pValue;
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530357
358 switch (param) {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800359 case AGC2_PARAM_FIXED_DIGITAL_GAIN:
360 if (*pValueSize < sizeof(float)) {
361 *pValueSize = 0.f;
362 return -EINVAL;
363 }
364 break;
365 case AGC2_PARAM_ADAPT_DIGI_LEVEL_ESTIMATOR:
366 if (*pValueSize < sizeof(int32_t)) {
367 *pValueSize = 0;
368 return -EINVAL;
369 }
370 break;
371 case AGC2_PARAM_ADAPT_DIGI_EXTRA_SATURATION_MARGIN:
372 if (*pValueSize < sizeof(float)) {
373 *pValueSize = 0.f;
374 return -EINVAL;
375 }
376 break;
377 case AGC2_PARAM_PROPERTIES:
378 if (*pValueSize < sizeof(agc2_settings_t)) {
379 *pValueSize = 0;
380 return -EINVAL;
381 }
382 break;
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530383
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800384 default:
385 ALOGW("Agc2GetParameter() unknown param %08x", param);
386 status = -EINVAL;
387 break;
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530388 }
389
390 effect->session->config = effect->session->apm->GetConfig();
391 switch (param) {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800392 case AGC2_PARAM_FIXED_DIGITAL_GAIN:
393 *(float*)pValue =
394 (float)(effect->session->config.gain_controller2.fixed_digital.gain_db);
395 ALOGV("Agc2GetParameter() target level %f dB", *(float*)pValue);
396 break;
397 case AGC2_PARAM_ADAPT_DIGI_LEVEL_ESTIMATOR:
398 *(uint32_t*)pValue = (uint32_t)(
399 effect->session->config.gain_controller2.adaptive_digital.level_estimator);
400 ALOGV("Agc2GetParameter() level estimator %d",
401 *(webrtc::AudioProcessing::Config::GainController2::LevelEstimator*)pValue);
402 break;
403 case AGC2_PARAM_ADAPT_DIGI_EXTRA_SATURATION_MARGIN:
404 *(float*)pValue = (float)(effect->session->config.gain_controller2.adaptive_digital
405 .extra_saturation_margin_db);
406 ALOGV("Agc2GetParameter() extra saturation margin %f dB", *(float*)pValue);
407 break;
408 case AGC2_PARAM_PROPERTIES:
409 pProperties->fixedDigitalGain =
410 (float)(effect->session->config.gain_controller2.fixed_digital.gain_db);
411 pProperties->level_estimator = (uint32_t)(
412 effect->session->config.gain_controller2.adaptive_digital.level_estimator);
413 pProperties->extraSaturationMargin =
414 (float)(effect->session->config.gain_controller2.adaptive_digital
415 .extra_saturation_margin_db);
416 break;
417 default:
418 ALOGW("Agc2GetParameter() unknown param %d", param);
419 status = -EINVAL;
420 break;
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530421 }
422
423 return status;
424}
425#endif
426
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800427int AgcGetParameter(preproc_effect_t* effect, void* pParam, uint32_t* pValueSize, void* pValue) {
Eric Laurenta9390d42011-06-17 20:17:17 -0700428 int status = 0;
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800429 uint32_t param = *(uint32_t*)pParam;
430 t_agc_settings* pProperties = (t_agc_settings*)pValue;
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530431#ifdef WEBRTC_LEGACY
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800432 webrtc::GainControl* agc = static_cast<webrtc::GainControl*>(effect->engine);
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530433#endif
Eric Laurenta9390d42011-06-17 20:17:17 -0700434
435 switch (param) {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800436 case AGC_PARAM_TARGET_LEVEL:
437 case AGC_PARAM_COMP_GAIN:
438 if (*pValueSize < sizeof(int16_t)) {
439 *pValueSize = 0;
440 return -EINVAL;
441 }
442 break;
443 case AGC_PARAM_LIMITER_ENA:
444 if (*pValueSize < sizeof(bool)) {
445 *pValueSize = 0;
446 return -EINVAL;
447 }
448 break;
449 case AGC_PARAM_PROPERTIES:
450 if (*pValueSize < sizeof(t_agc_settings)) {
451 *pValueSize = 0;
452 return -EINVAL;
453 }
454 break;
Eric Laurenta9390d42011-06-17 20:17:17 -0700455
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800456 default:
457 ALOGW("AgcGetParameter() unknown param %08x", param);
458 status = -EINVAL;
459 break;
Eric Laurenta9390d42011-06-17 20:17:17 -0700460 }
461
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530462#ifdef WEBRTC_LEGACY
Eric Laurenta9390d42011-06-17 20:17:17 -0700463 switch (param) {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800464 case AGC_PARAM_TARGET_LEVEL:
465 *(int16_t*)pValue = (int16_t)(agc->target_level_dbfs() * -100);
466 ALOGV("AgcGetParameter() target level %d milliBels", *(int16_t*)pValue);
467 break;
468 case AGC_PARAM_COMP_GAIN:
469 *(int16_t*)pValue = (int16_t)(agc->compression_gain_db() * 100);
470 ALOGV("AgcGetParameter() comp gain %d milliBels", *(int16_t*)pValue);
471 break;
472 case AGC_PARAM_LIMITER_ENA:
473 *(bool*)pValue = (bool)agc->is_limiter_enabled();
474 ALOGV("AgcGetParameter() limiter enabled %s",
475 (*(int16_t*)pValue != 0) ? "true" : "false");
476 break;
477 case AGC_PARAM_PROPERTIES:
478 pProperties->targetLevel = (int16_t)(agc->target_level_dbfs() * -100);
479 pProperties->compGain = (int16_t)(agc->compression_gain_db() * 100);
480 pProperties->limiterEnabled = (bool)agc->is_limiter_enabled();
481 break;
482 default:
483 ALOGW("AgcGetParameter() unknown param %d", param);
484 status = -EINVAL;
485 break;
Eric Laurenta9390d42011-06-17 20:17:17 -0700486 }
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530487#else
488 effect->session->config = effect->session->apm->GetConfig();
489 switch (param) {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800490 case AGC_PARAM_TARGET_LEVEL:
491 *(int16_t*)pValue =
492 (int16_t)(effect->session->config.gain_controller1.target_level_dbfs * -100);
493 ALOGV("AgcGetParameter() target level %d milliBels", *(int16_t*)pValue);
494 break;
495 case AGC_PARAM_COMP_GAIN:
496 *(int16_t*)pValue =
497 (int16_t)(effect->session->config.gain_controller1.compression_gain_db * -100);
498 ALOGV("AgcGetParameter() comp gain %d milliBels", *(int16_t*)pValue);
499 break;
500 case AGC_PARAM_LIMITER_ENA:
501 *(bool*)pValue = (bool)(effect->session->config.gain_controller1.enable_limiter);
502 ALOGV("AgcGetParameter() limiter enabled %s",
503 (*(int16_t*)pValue != 0) ? "true" : "false");
504 break;
505 case AGC_PARAM_PROPERTIES:
506 pProperties->targetLevel =
507 (int16_t)(effect->session->config.gain_controller1.target_level_dbfs * -100);
508 pProperties->compGain =
509 (int16_t)(effect->session->config.gain_controller1.compression_gain_db * -100);
510 pProperties->limiterEnabled =
511 (bool)(effect->session->config.gain_controller1.enable_limiter);
512 break;
513 default:
514 ALOGW("AgcGetParameter() unknown param %d", param);
515 status = -EINVAL;
516 break;
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530517 }
518#endif
Eric Laurenta9390d42011-06-17 20:17:17 -0700519 return status;
520}
521
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530522#ifndef WEBRTC_LEGACY
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800523int Agc2SetParameter(preproc_effect_t* effect, void* pParam, void* pValue) {
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530524 int status = 0;
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800525 uint32_t param = *(uint32_t*)pParam;
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530526 float valueFloat = 0.f;
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800527 agc2_settings_t* pProperties = (agc2_settings_t*)pValue;
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530528 effect->session->config = effect->session->apm->GetConfig();
529 switch (param) {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800530 case AGC2_PARAM_FIXED_DIGITAL_GAIN:
531 valueFloat = (float)(*(int32_t*)pValue);
532 ALOGV("Agc2SetParameter() fixed digital gain %f dB", valueFloat);
533 effect->session->config.gain_controller2.fixed_digital.gain_db = valueFloat;
534 break;
535 case AGC2_PARAM_ADAPT_DIGI_LEVEL_ESTIMATOR:
536 ALOGV("Agc2SetParameter() level estimator %d",
537 *(webrtc::AudioProcessing::Config::GainController2::LevelEstimator*)pValue);
538 effect->session->config.gain_controller2.adaptive_digital.level_estimator =
539 (*(webrtc::AudioProcessing::Config::GainController2::LevelEstimator*)pValue);
540 break;
541 case AGC2_PARAM_ADAPT_DIGI_EXTRA_SATURATION_MARGIN:
542 valueFloat = (float)(*(int32_t*)pValue);
543 ALOGV("Agc2SetParameter() extra saturation margin %f dB", valueFloat);
544 effect->session->config.gain_controller2.adaptive_digital.extra_saturation_margin_db =
545 valueFloat;
546 break;
547 case AGC2_PARAM_PROPERTIES:
548 ALOGV("Agc2SetParameter() properties gain %f, level %d margin %f",
549 pProperties->fixedDigitalGain, pProperties->level_estimator,
550 pProperties->extraSaturationMargin);
551 effect->session->config.gain_controller2.fixed_digital.gain_db =
552 pProperties->fixedDigitalGain;
553 effect->session->config.gain_controller2.adaptive_digital.level_estimator =
554 (webrtc::AudioProcessing::Config::GainController2::LevelEstimator)
555 pProperties->level_estimator;
556 effect->session->config.gain_controller2.adaptive_digital.extra_saturation_margin_db =
557 pProperties->extraSaturationMargin;
558 break;
559 default:
560 ALOGW("Agc2SetParameter() unknown param %08x value %08x", param, *(uint32_t*)pValue);
561 status = -EINVAL;
562 break;
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530563 }
564 effect->session->apm->ApplyConfig(effect->session->config);
565
566 ALOGV("Agc2SetParameter() done status %d", status);
567
568 return status;
569}
570#endif
571
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800572int AgcSetParameter(preproc_effect_t* effect, void* pParam, void* pValue) {
Eric Laurenta9390d42011-06-17 20:17:17 -0700573 int status = 0;
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530574#ifdef WEBRTC_LEGACY
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800575 uint32_t param = *(uint32_t*)pParam;
576 t_agc_settings* pProperties = (t_agc_settings*)pValue;
577 webrtc::GainControl* agc = static_cast<webrtc::GainControl*>(effect->engine);
Eric Laurenta9390d42011-06-17 20:17:17 -0700578
579 switch (param) {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800580 case AGC_PARAM_TARGET_LEVEL:
581 ALOGV("AgcSetParameter() target level %d milliBels", *(int16_t*)pValue);
582 status = agc->set_target_level_dbfs(-(*(int16_t*)pValue / 100));
583 break;
584 case AGC_PARAM_COMP_GAIN:
585 ALOGV("AgcSetParameter() comp gain %d milliBels", *(int16_t*)pValue);
586 status = agc->set_compression_gain_db(*(int16_t*)pValue / 100);
587 break;
588 case AGC_PARAM_LIMITER_ENA:
589 ALOGV("AgcSetParameter() limiter enabled %s", *(bool*)pValue ? "true" : "false");
590 status = agc->enable_limiter(*(bool*)pValue);
591 break;
592 case AGC_PARAM_PROPERTIES:
593 ALOGV("AgcSetParameter() properties level %d, gain %d limiter %d",
594 pProperties->targetLevel, pProperties->compGain, pProperties->limiterEnabled);
595 status = agc->set_target_level_dbfs(-(pProperties->targetLevel / 100));
596 if (status != 0) break;
597 status = agc->set_compression_gain_db(pProperties->compGain / 100);
598 if (status != 0) break;
599 status = agc->enable_limiter(pProperties->limiterEnabled);
600 break;
601 default:
602 ALOGW("AgcSetParameter() unknown param %08x value %08x", param, *(uint32_t*)pValue);
603 status = -EINVAL;
604 break;
Eric Laurenta9390d42011-06-17 20:17:17 -0700605 }
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530606#else
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800607 uint32_t param = *(uint32_t*)pParam;
608 t_agc_settings* pProperties = (t_agc_settings*)pValue;
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530609 effect->session->config = effect->session->apm->GetConfig();
610 switch (param) {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800611 case AGC_PARAM_TARGET_LEVEL:
612 ALOGV("AgcSetParameter() target level %d milliBels", *(int16_t*)pValue);
613 effect->session->config.gain_controller1.target_level_dbfs =
614 (-(*(int16_t*)pValue / 100));
615 break;
616 case AGC_PARAM_COMP_GAIN:
617 ALOGV("AgcSetParameter() comp gain %d milliBels", *(int16_t*)pValue);
618 effect->session->config.gain_controller1.compression_gain_db =
619 (*(int16_t*)pValue / 100);
620 break;
621 case AGC_PARAM_LIMITER_ENA:
622 ALOGV("AgcSetParameter() limiter enabled %s", *(bool*)pValue ? "true" : "false");
623 effect->session->config.gain_controller1.enable_limiter = (*(bool*)pValue);
624 break;
625 case AGC_PARAM_PROPERTIES:
626 ALOGV("AgcSetParameter() properties level %d, gain %d limiter %d",
627 pProperties->targetLevel, pProperties->compGain, pProperties->limiterEnabled);
628 effect->session->config.gain_controller1.target_level_dbfs =
629 -(pProperties->targetLevel / 100);
630 effect->session->config.gain_controller1.compression_gain_db =
631 pProperties->compGain / 100;
632 effect->session->config.gain_controller1.enable_limiter = pProperties->limiterEnabled;
633 break;
634 default:
635 ALOGW("AgcSetParameter() unknown param %08x value %08x", param, *(uint32_t*)pValue);
636 status = -EINVAL;
637 break;
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530638 }
639 effect->session->apm->ApplyConfig(effect->session->config);
640#endif
Eric Laurenta9390d42011-06-17 20:17:17 -0700641
Steve Block3856b092011-10-20 11:56:00 +0100642 ALOGV("AgcSetParameter() done status %d", status);
Eric Laurenta9390d42011-06-17 20:17:17 -0700643
644 return status;
645}
646
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530647#ifndef WEBRTC_LEGACY
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800648void Agc2Enable(preproc_effect_t* effect) {
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530649 effect->session->config = effect->session->apm->GetConfig();
650 effect->session->config.gain_controller2.enabled = true;
651 effect->session->apm->ApplyConfig(effect->session->config);
652}
653#endif
654
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800655void AgcEnable(preproc_effect_t* effect) {
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530656#ifdef WEBRTC_LEGACY
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800657 webrtc::GainControl* agc = static_cast<webrtc::GainControl*>(effect->engine);
Steve Block3856b092011-10-20 11:56:00 +0100658 ALOGV("AgcEnable agc %p", agc);
Eric Laurenta9390d42011-06-17 20:17:17 -0700659 agc->Enable(true);
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530660#else
661 effect->session->config = effect->session->apm->GetConfig();
662 effect->session->config.gain_controller1.enabled = true;
663 effect->session->apm->ApplyConfig(effect->session->config);
664#endif
Eric Laurenta9390d42011-06-17 20:17:17 -0700665}
666
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530667#ifndef WEBRTC_LEGACY
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800668void Agc2Disable(preproc_effect_t* effect) {
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530669 effect->session->config = effect->session->apm->GetConfig();
670 effect->session->config.gain_controller2.enabled = false;
671 effect->session->apm->ApplyConfig(effect->session->config);
672}
673#endif
674
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800675void AgcDisable(preproc_effect_t* effect) {
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530676#ifdef WEBRTC_LEGACY
Steve Block3856b092011-10-20 11:56:00 +0100677 ALOGV("AgcDisable");
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800678 webrtc::GainControl* agc = static_cast<webrtc::GainControl*>(effect->engine);
Eric Laurenta9390d42011-06-17 20:17:17 -0700679 agc->Enable(false);
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530680#else
681 effect->session->config = effect->session->apm->GetConfig();
682 effect->session->config.gain_controller1.enabled = false;
683 effect->session->apm->ApplyConfig(effect->session->config);
684#endif
Eric Laurenta9390d42011-06-17 20:17:17 -0700685}
686
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800687static const preproc_ops_t sAgcOps = {AgcCreate, AgcInit, NULL, AgcEnable, AgcDisable,
688 AgcSetParameter, AgcGetParameter, NULL};
Eric Laurenta9390d42011-06-17 20:17:17 -0700689
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530690#ifndef WEBRTC_LEGACY
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800691static const preproc_ops_t sAgc2Ops = {Agc2Create, Agc2Init, NULL,
692 Agc2Enable, Agc2Disable, Agc2SetParameter,
693 Agc2GetParameter, NULL};
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530694#endif
Eric Laurenta9390d42011-06-17 20:17:17 -0700695
696//------------------------------------------------------------------------------
697// Acoustic Echo Canceler (AEC)
698//------------------------------------------------------------------------------
699
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530700#ifdef WEBRTC_LEGACY
Eric Laurenta9390d42011-06-17 20:17:17 -0700701static const webrtc::EchoControlMobile::RoutingMode kAecDefaultMode =
702 webrtc::EchoControlMobile::kEarpiece;
703static const bool kAecDefaultComfortNoise = true;
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530704#endif
Eric Laurenta9390d42011-06-17 20:17:17 -0700705
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800706int AecInit(preproc_effect_t* effect) {
Steve Block3856b092011-10-20 11:56:00 +0100707 ALOGV("AecInit");
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530708#ifdef WEBRTC_LEGACY
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800709 webrtc::EchoControlMobile* aec = static_cast<webrtc::EchoControlMobile*>(effect->engine);
Eric Laurenta9390d42011-06-17 20:17:17 -0700710 aec->set_routing_mode(kAecDefaultMode);
711 aec->enable_comfort_noise(kAecDefaultComfortNoise);
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530712#else
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800713 effect->session->config = effect->session->apm->GetConfig();
Rivukanta Bhattacharyac4c54172020-11-25 23:55:44 +0530714 effect->session->config.echo_canceller.mobile_mode = true;
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530715 effect->session->apm->ApplyConfig(effect->session->config);
716#endif
Eric Laurenta9390d42011-06-17 20:17:17 -0700717 return 0;
718}
719
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800720int AecCreate(preproc_effect_t* effect) {
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530721#ifdef WEBRTC_LEGACY
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800722 webrtc::EchoControlMobile* aec = effect->session->apm->echo_control_mobile();
Steve Block3856b092011-10-20 11:56:00 +0100723 ALOGV("AecCreate got aec %p", aec);
Eric Laurenta9390d42011-06-17 20:17:17 -0700724 if (aec == NULL) {
Steve Block5ff1dd52012-01-05 23:22:43 +0000725 ALOGW("AgcCreate Error");
Eric Laurenta9390d42011-06-17 20:17:17 -0700726 return -ENOMEM;
727 }
728 effect->engine = static_cast<preproc_fx_handle_t>(aec);
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530729#endif
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800730 AecInit(effect);
Eric Laurenta9390d42011-06-17 20:17:17 -0700731 return 0;
732}
733
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800734int AecGetParameter(preproc_effect_t* effect, void* pParam, uint32_t* pValueSize, void* pValue) {
Eric Laurenta9390d42011-06-17 20:17:17 -0700735 int status = 0;
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800736 uint32_t param = *(uint32_t*)pParam;
Eric Laurenta9390d42011-06-17 20:17:17 -0700737
738 if (*pValueSize < sizeof(uint32_t)) {
739 return -EINVAL;
740 }
741 switch (param) {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800742 case AEC_PARAM_ECHO_DELAY:
743 case AEC_PARAM_PROPERTIES:
744 *(uint32_t*)pValue = 1000 * effect->session->apm->stream_delay_ms();
745 ALOGV("AecGetParameter() echo delay %d us", *(uint32_t*)pValue);
746 break;
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530747#ifndef WEBRTC_LEGACY
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800748 case AEC_PARAM_MOBILE_MODE:
749 effect->session->config = effect->session->apm->GetConfig();
750 *(uint32_t*)pValue = effect->session->config.echo_canceller.mobile_mode;
751 ALOGV("AecGetParameter() mobile mode %d us", *(uint32_t*)pValue);
752 break;
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530753#endif
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800754 default:
755 ALOGW("AecGetParameter() unknown param %08x value %08x", param, *(uint32_t*)pValue);
756 status = -EINVAL;
757 break;
Eric Laurenta9390d42011-06-17 20:17:17 -0700758 }
759 return status;
760}
761
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800762int AecSetParameter(preproc_effect_t* effect, void* pParam, void* pValue) {
Eric Laurenta9390d42011-06-17 20:17:17 -0700763 int status = 0;
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800764 uint32_t param = *(uint32_t*)pParam;
765 uint32_t value = *(uint32_t*)pValue;
Eric Laurenta9390d42011-06-17 20:17:17 -0700766
767 switch (param) {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800768 case AEC_PARAM_ECHO_DELAY:
769 case AEC_PARAM_PROPERTIES:
770 status = effect->session->apm->set_stream_delay_ms(value / 1000);
771 ALOGV("AecSetParameter() echo delay %d us, status %d", value, status);
772 break;
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530773#ifndef WEBRTC_LEGACY
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800774 case AEC_PARAM_MOBILE_MODE:
775 effect->session->config = effect->session->apm->GetConfig();
776 effect->session->config.echo_canceller.mobile_mode = value;
777 ALOGV("AecSetParameter() mobile mode %d us", value);
778 effect->session->apm->ApplyConfig(effect->session->config);
779 break;
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530780#endif
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800781 default:
782 ALOGW("AecSetParameter() unknown param %08x value %08x", param, *(uint32_t*)pValue);
783 status = -EINVAL;
784 break;
Eric Laurenta9390d42011-06-17 20:17:17 -0700785 }
786 return status;
787}
788
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800789void AecEnable(preproc_effect_t* effect) {
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530790#ifdef WEBRTC_LEGACY
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800791 webrtc::EchoControlMobile* aec = static_cast<webrtc::EchoControlMobile*>(effect->engine);
Steve Block3856b092011-10-20 11:56:00 +0100792 ALOGV("AecEnable aec %p", aec);
Eric Laurenta9390d42011-06-17 20:17:17 -0700793 aec->Enable(true);
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530794#else
795 effect->session->config = effect->session->apm->GetConfig();
796 effect->session->config.echo_canceller.enabled = true;
797 effect->session->apm->ApplyConfig(effect->session->config);
798#endif
Eric Laurenta9390d42011-06-17 20:17:17 -0700799}
800
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800801void AecDisable(preproc_effect_t* effect) {
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530802#ifdef WEBRTC_LEGACY
Steve Block3856b092011-10-20 11:56:00 +0100803 ALOGV("AecDisable");
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800804 webrtc::EchoControlMobile* aec = static_cast<webrtc::EchoControlMobile*>(effect->engine);
Eric Laurenta9390d42011-06-17 20:17:17 -0700805 aec->Enable(false);
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530806#else
807 effect->session->config = effect->session->apm->GetConfig();
808 effect->session->config.echo_canceller.enabled = false;
809 effect->session->apm->ApplyConfig(effect->session->config);
810#endif
Eric Laurenta9390d42011-06-17 20:17:17 -0700811}
812
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800813int AecSetDevice(preproc_effect_t* effect, uint32_t device) {
Steve Block3856b092011-10-20 11:56:00 +0100814 ALOGV("AecSetDevice %08x", device);
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530815#ifdef WEBRTC_LEGACY
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800816 webrtc::EchoControlMobile* aec = static_cast<webrtc::EchoControlMobile*>(effect->engine);
817 webrtc::EchoControlMobile::RoutingMode mode =
818 webrtc::EchoControlMobile::kQuietEarpieceOrHeadset;
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530819#endif
Eric Laurenta9390d42011-06-17 20:17:17 -0700820
Eric Laurent88959252012-08-28 14:26:53 -0700821 if (audio_is_input_device(device)) {
822 return 0;
823 }
824
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530825#ifdef WEBRTC_LEGACY
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800826 switch (device) {
827 case AUDIO_DEVICE_OUT_EARPIECE:
828 mode = webrtc::EchoControlMobile::kEarpiece;
829 break;
830 case AUDIO_DEVICE_OUT_SPEAKER:
831 mode = webrtc::EchoControlMobile::kSpeakerphone;
832 break;
833 case AUDIO_DEVICE_OUT_WIRED_HEADSET:
834 case AUDIO_DEVICE_OUT_WIRED_HEADPHONE:
835 case AUDIO_DEVICE_OUT_USB_HEADSET:
836 default:
837 break;
Eric Laurenta9390d42011-06-17 20:17:17 -0700838 }
839 aec->set_routing_mode(mode);
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530840#endif
Eric Laurenta9390d42011-06-17 20:17:17 -0700841 return 0;
842}
843
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800844static const preproc_ops_t sAecOps = {AecCreate, AecInit, NULL,
845 AecEnable, AecDisable, AecSetParameter,
846 AecGetParameter, AecSetDevice};
Eric Laurenta9390d42011-06-17 20:17:17 -0700847
848//------------------------------------------------------------------------------
849// Noise Suppression (NS)
850//------------------------------------------------------------------------------
851
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530852#ifdef WEBRTC_LEGACY
Eric Laurenta9390d42011-06-17 20:17:17 -0700853static const webrtc::NoiseSuppression::Level kNsDefaultLevel = webrtc::NoiseSuppression::kModerate;
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530854#else
855static const webrtc::AudioProcessing::Config::NoiseSuppression::Level kNsDefaultLevel =
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800856 webrtc::AudioProcessing::Config::NoiseSuppression::kModerate;
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530857#endif
Eric Laurenta9390d42011-06-17 20:17:17 -0700858
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800859int NsInit(preproc_effect_t* effect) {
Steve Block3856b092011-10-20 11:56:00 +0100860 ALOGV("NsInit");
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530861#ifdef WEBRTC_LEGACY
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800862 webrtc::NoiseSuppression* ns = static_cast<webrtc::NoiseSuppression*>(effect->engine);
Eric Laurenta9390d42011-06-17 20:17:17 -0700863 ns->set_level(kNsDefaultLevel);
Alex Luebs766bf732015-12-14 21:32:13 -0800864 webrtc::Config config;
865 std::vector<webrtc::Point> geometry;
866 // TODO(aluebs): Make the geometry settable.
867 geometry.push_back(webrtc::Point(-0.03f, 0.f, 0.f));
868 geometry.push_back(webrtc::Point(-0.01f, 0.f, 0.f));
869 geometry.push_back(webrtc::Point(0.01f, 0.f, 0.f));
870 geometry.push_back(webrtc::Point(0.03f, 0.f, 0.f));
871 // The geometry needs to be set with Beamforming enabled.
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800872 config.Set<webrtc::Beamforming>(new webrtc::Beamforming(true, geometry));
Alex Luebs766bf732015-12-14 21:32:13 -0800873 effect->session->apm->SetExtraOptions(config);
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800874 config.Set<webrtc::Beamforming>(new webrtc::Beamforming(false, geometry));
Alex Luebs766bf732015-12-14 21:32:13 -0800875 effect->session->apm->SetExtraOptions(config);
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530876#else
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800877 effect->session->config = effect->session->apm->GetConfig();
878 effect->session->config.noise_suppression.level = kNsDefaultLevel;
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530879 effect->session->apm->ApplyConfig(effect->session->config);
880#endif
Alex Luebs766bf732015-12-14 21:32:13 -0800881 effect->type = NS_TYPE_SINGLE_CHANNEL;
Eric Laurenta9390d42011-06-17 20:17:17 -0700882 return 0;
883}
884
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800885int NsCreate(preproc_effect_t* effect) {
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530886#ifdef WEBRTC_LEGACY
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800887 webrtc::NoiseSuppression* ns = effect->session->apm->noise_suppression();
Steve Block3856b092011-10-20 11:56:00 +0100888 ALOGV("NsCreate got ns %p", ns);
Eric Laurenta9390d42011-06-17 20:17:17 -0700889 if (ns == NULL) {
Steve Block5ff1dd52012-01-05 23:22:43 +0000890 ALOGW("AgcCreate Error");
Eric Laurenta9390d42011-06-17 20:17:17 -0700891 return -ENOMEM;
892 }
893 effect->engine = static_cast<preproc_fx_handle_t>(ns);
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530894#endif
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800895 NsInit(effect);
Eric Laurenta9390d42011-06-17 20:17:17 -0700896 return 0;
897}
898
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800899int NsGetParameter(preproc_effect_t* effect __unused, void* pParam __unused,
900 uint32_t* pValueSize __unused, void* pValue __unused) {
Eric Laurenta9390d42011-06-17 20:17:17 -0700901 int status = 0;
902 return status;
903}
904
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800905int NsSetParameter(preproc_effect_t* effect, void* pParam, void* pValue) {
Eric Laurenta9390d42011-06-17 20:17:17 -0700906 int status = 0;
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530907#ifdef WEBRTC_LEGACY
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800908 webrtc::NoiseSuppression* ns = static_cast<webrtc::NoiseSuppression*>(effect->engine);
909 uint32_t param = *(uint32_t*)pParam;
910 uint32_t value = *(uint32_t*)pValue;
911 switch (param) {
Alex Luebs766bf732015-12-14 21:32:13 -0800912 case NS_PARAM_LEVEL:
913 ns->set_level((webrtc::NoiseSuppression::Level)value);
914 ALOGV("NsSetParameter() level %d", value);
915 break;
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800916 case NS_PARAM_TYPE: {
Alex Luebs766bf732015-12-14 21:32:13 -0800917 webrtc::Config config;
918 std::vector<webrtc::Point> geometry;
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800919 bool is_beamforming_enabled = value == NS_TYPE_MULTI_CHANNEL && ns->is_enabled();
Alex Luebs766bf732015-12-14 21:32:13 -0800920 config.Set<webrtc::Beamforming>(
921 new webrtc::Beamforming(is_beamforming_enabled, geometry));
922 effect->session->apm->SetExtraOptions(config);
923 effect->type = value;
924 ALOGV("NsSetParameter() type %d", value);
925 break;
926 }
927 default:
928 ALOGW("NsSetParameter() unknown param %08x value %08x", param, value);
929 status = -EINVAL;
930 }
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530931#else
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800932 uint32_t param = *(uint32_t*)pParam;
933 uint32_t value = *(uint32_t*)pValue;
934 effect->session->config = effect->session->apm->GetConfig();
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530935 switch (param) {
936 case NS_PARAM_LEVEL:
937 effect->session->config.noise_suppression.level =
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800938 (webrtc::AudioProcessing::Config::NoiseSuppression::Level)value;
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530939 ALOGV("NsSetParameter() level %d", value);
940 break;
941 default:
942 ALOGW("NsSetParameter() unknown param %08x value %08x", param, value);
943 status = -EINVAL;
944 }
945 effect->session->apm->ApplyConfig(effect->session->config);
946#endif
Alex Luebs766bf732015-12-14 21:32:13 -0800947
Eric Laurenta9390d42011-06-17 20:17:17 -0700948 return status;
949}
950
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800951void NsEnable(preproc_effect_t* effect) {
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530952#ifdef WEBRTC_LEGACY
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800953 webrtc::NoiseSuppression* ns = static_cast<webrtc::NoiseSuppression*>(effect->engine);
Steve Block3856b092011-10-20 11:56:00 +0100954 ALOGV("NsEnable ns %p", ns);
Eric Laurenta9390d42011-06-17 20:17:17 -0700955 ns->Enable(true);
Alex Luebs766bf732015-12-14 21:32:13 -0800956 if (effect->type == NS_TYPE_MULTI_CHANNEL) {
957 webrtc::Config config;
958 std::vector<webrtc::Point> geometry;
959 config.Set<webrtc::Beamforming>(new webrtc::Beamforming(true, geometry));
960 effect->session->apm->SetExtraOptions(config);
961 }
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530962#else
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800963 effect->session->config = effect->session->apm->GetConfig();
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530964 effect->session->config.noise_suppression.enabled = true;
965 effect->session->apm->ApplyConfig(effect->session->config);
966#endif
Eric Laurenta9390d42011-06-17 20:17:17 -0700967}
968
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800969void NsDisable(preproc_effect_t* effect) {
Steve Block3856b092011-10-20 11:56:00 +0100970 ALOGV("NsDisable");
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530971#ifdef WEBRTC_LEGACY
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800972 webrtc::NoiseSuppression* ns = static_cast<webrtc::NoiseSuppression*>(effect->engine);
Eric Laurenta9390d42011-06-17 20:17:17 -0700973 ns->Enable(false);
Alex Luebs766bf732015-12-14 21:32:13 -0800974 webrtc::Config config;
975 std::vector<webrtc::Point> geometry;
976 config.Set<webrtc::Beamforming>(new webrtc::Beamforming(false, geometry));
977 effect->session->apm->SetExtraOptions(config);
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530978#else
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800979 effect->session->config = effect->session->apm->GetConfig();
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530980 effect->session->config.noise_suppression.enabled = false;
981 effect->session->apm->ApplyConfig(effect->session->config);
982#endif
Eric Laurenta9390d42011-06-17 20:17:17 -0700983}
984
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800985static const preproc_ops_t sNsOps = {NsCreate, NsInit, NULL, NsEnable,
986 NsDisable, NsSetParameter, NsGetParameter, NULL};
Eric Laurenta9390d42011-06-17 20:17:17 -0700987
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800988static const preproc_ops_t* sPreProcOps[PREPROC_NUM_EFFECTS] = {&sAgcOps,
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530989#ifndef WEBRTC_LEGACY
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800990 &sAgc2Ops,
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530991#endif
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800992 &sAecOps, &sNsOps};
Eric Laurenta9390d42011-06-17 20:17:17 -0700993
994//------------------------------------------------------------------------------
995// Effect functions
996//------------------------------------------------------------------------------
997
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800998void Session_SetProcEnabled(preproc_session_t* session, uint32_t procId, bool enabled);
Eric Laurenta9390d42011-06-17 20:17:17 -0700999
1000extern "C" const struct effect_interface_s sEffectInterface;
1001extern "C" const struct effect_interface_s sEffectInterfaceReverse;
1002
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001003#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 -07001004
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001005int Effect_SetState(preproc_effect_t* effect, uint32_t state) {
Eric Laurenta9390d42011-06-17 20:17:17 -07001006 int status = 0;
Steve Block3856b092011-10-20 11:56:00 +01001007 ALOGV("Effect_SetState proc %d, new %d old %d", effect->procId, state, effect->state);
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001008 switch (state) {
1009 case PREPROC_EFFECT_STATE_INIT:
1010 switch (effect->state) {
1011 case PREPROC_EFFECT_STATE_ACTIVE:
1012 effect->ops->disable(effect);
1013 Session_SetProcEnabled(effect->session, effect->procId, false);
1014 break;
1015 case PREPROC_EFFECT_STATE_CONFIG:
1016 case PREPROC_EFFECT_STATE_CREATED:
1017 case PREPROC_EFFECT_STATE_INIT:
1018 break;
1019 default:
1020 BAD_STATE_ABORT(effect->state, state);
1021 }
1022 break;
1023 case PREPROC_EFFECT_STATE_CREATED:
1024 switch (effect->state) {
1025 case PREPROC_EFFECT_STATE_INIT:
1026 status = effect->ops->create(effect);
1027 break;
1028 case PREPROC_EFFECT_STATE_CREATED:
1029 case PREPROC_EFFECT_STATE_ACTIVE:
1030 case PREPROC_EFFECT_STATE_CONFIG:
1031 ALOGE("Effect_SetState invalid transition");
1032 status = -ENOSYS;
1033 break;
1034 default:
1035 BAD_STATE_ABORT(effect->state, state);
1036 }
Andy Hung320fd852018-10-09 14:06:37 -07001037 break;
Eric Laurenta9390d42011-06-17 20:17:17 -07001038 case PREPROC_EFFECT_STATE_CONFIG:
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001039 switch (effect->state) {
1040 case PREPROC_EFFECT_STATE_INIT:
1041 ALOGE("Effect_SetState invalid transition");
1042 status = -ENOSYS;
1043 break;
1044 case PREPROC_EFFECT_STATE_ACTIVE:
1045 effect->ops->disable(effect);
1046 Session_SetProcEnabled(effect->session, effect->procId, false);
1047 break;
1048 case PREPROC_EFFECT_STATE_CREATED:
1049 case PREPROC_EFFECT_STATE_CONFIG:
1050 break;
1051 default:
1052 BAD_STATE_ABORT(effect->state, state);
1053 }
1054 break;
1055 case PREPROC_EFFECT_STATE_ACTIVE:
1056 switch (effect->state) {
1057 case PREPROC_EFFECT_STATE_INIT:
1058 case PREPROC_EFFECT_STATE_CREATED:
1059 ALOGE("Effect_SetState invalid transition");
1060 status = -ENOSYS;
1061 break;
1062 case PREPROC_EFFECT_STATE_ACTIVE:
1063 // enabling an already enabled effect is just ignored
1064 break;
1065 case PREPROC_EFFECT_STATE_CONFIG:
1066 effect->ops->enable(effect);
1067 Session_SetProcEnabled(effect->session, effect->procId, true);
1068 break;
1069 default:
1070 BAD_STATE_ABORT(effect->state, state);
1071 }
Eric Laurenta9390d42011-06-17 20:17:17 -07001072 break;
1073 default:
1074 BAD_STATE_ABORT(effect->state, state);
Eric Laurenta9390d42011-06-17 20:17:17 -07001075 }
1076 if (status == 0) {
1077 effect->state = state;
1078 }
1079 return status;
1080}
1081
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001082int Effect_Init(preproc_effect_t* effect, uint32_t procId) {
Eric Laurenta9390d42011-06-17 20:17:17 -07001083 if (HasReverseStream(procId)) {
1084 effect->itfe = &sEffectInterfaceReverse;
1085 } else {
1086 effect->itfe = &sEffectInterface;
1087 }
1088 effect->ops = sPreProcOps[procId];
1089 effect->procId = procId;
1090 effect->state = PREPROC_EFFECT_STATE_INIT;
1091 return 0;
1092}
1093
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001094int Effect_Create(preproc_effect_t* effect, preproc_session_t* session,
1095 effect_handle_t* interface) {
Eric Laurenta9390d42011-06-17 20:17:17 -07001096 effect->session = session;
1097 *interface = (effect_handle_t)&effect->itfe;
1098 return Effect_SetState(effect, PREPROC_EFFECT_STATE_CREATED);
1099}
1100
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001101int Effect_Release(preproc_effect_t* effect) {
Eric Laurenta9390d42011-06-17 20:17:17 -07001102 return Effect_SetState(effect, PREPROC_EFFECT_STATE_INIT);
1103}
1104
Eric Laurenta9390d42011-06-17 20:17:17 -07001105//------------------------------------------------------------------------------
1106// Session functions
1107//------------------------------------------------------------------------------
1108
1109#define RESAMPLER_QUALITY SPEEX_RESAMPLER_QUALITY_VOIP
1110
1111static const int kPreprocDefaultSr = 16000;
1112static const int kPreProcDefaultCnl = 1;
1113
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001114int Session_Init(preproc_session_t* session) {
Eric Laurenta9390d42011-06-17 20:17:17 -07001115 size_t i;
1116 int status = 0;
1117
1118 session->state = PREPROC_SESSION_STATE_INIT;
1119 session->id = 0;
1120 session->io = 0;
1121 session->createdMsk = 0;
Saketh Sathuvalli08337032020-09-22 21:13:45 +05301122#ifdef WEBRTC_LEGACY
Eric Laurenta9390d42011-06-17 20:17:17 -07001123 session->apm = NULL;
Saketh Sathuvalli08337032020-09-22 21:13:45 +05301124#endif
Eric Laurenta9390d42011-06-17 20:17:17 -07001125 for (i = 0; i < PREPROC_NUM_EFFECTS && status == 0; i++) {
1126 status = Effect_Init(&session->effects[i], i);
1127 }
1128 return status;
1129}
1130
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001131extern "C" int Session_CreateEffect(preproc_session_t* session, int32_t procId,
1132 effect_handle_t* interface) {
Eric Laurenta9390d42011-06-17 20:17:17 -07001133 int status = -ENOMEM;
1134
Steve Block3856b092011-10-20 11:56:00 +01001135 ALOGV("Session_CreateEffect procId %d, createdMsk %08x", procId, session->createdMsk);
Eric Laurenta9390d42011-06-17 20:17:17 -07001136
1137 if (session->createdMsk == 0) {
Saketh Sathuvalli08337032020-09-22 21:13:45 +05301138#ifdef WEBRTC_LEGACY
Alex Luebs9718b7d2015-11-24 14:33:14 -08001139 session->apm = webrtc::AudioProcessing::Create();
Eric Laurenta9390d42011-06-17 20:17:17 -07001140 if (session->apm == NULL) {
Steve Block5ff1dd52012-01-05 23:22:43 +00001141 ALOGW("Session_CreateEffect could not get apm engine");
Eric Laurenta9390d42011-06-17 20:17:17 -07001142 goto error;
1143 }
Alex Luebs9718b7d2015-11-24 14:33:14 -08001144 const webrtc::ProcessingConfig processing_config = {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001145 {{kPreprocDefaultSr, kPreProcDefaultCnl},
1146 {kPreprocDefaultSr, kPreProcDefaultCnl},
1147 {kPreprocDefaultSr, kPreProcDefaultCnl},
1148 {kPreprocDefaultSr, kPreProcDefaultCnl}}};
Alex Luebs9718b7d2015-11-24 14:33:14 -08001149 session->apm->Initialize(processing_config);
Eric Laurenta9390d42011-06-17 20:17:17 -07001150 session->procFrame = new webrtc::AudioFrame();
1151 if (session->procFrame == NULL) {
Steve Block5ff1dd52012-01-05 23:22:43 +00001152 ALOGW("Session_CreateEffect could not allocate audio frame");
Eric Laurenta9390d42011-06-17 20:17:17 -07001153 goto error;
1154 }
1155 session->revFrame = new webrtc::AudioFrame();
1156 if (session->revFrame == NULL) {
Steve Block5ff1dd52012-01-05 23:22:43 +00001157 ALOGW("Session_CreateEffect could not allocate reverse audio frame");
Eric Laurenta9390d42011-06-17 20:17:17 -07001158 goto error;
1159 }
Saketh Sathuvalli08337032020-09-22 21:13:45 +05301160#else
1161 session->apm = session->ap_builder.Create();
1162 if (session->apm == NULL) {
1163 ALOGW("Session_CreateEffect could not get apm engine");
1164 goto error;
1165 }
1166#endif
Eric Laurenta9390d42011-06-17 20:17:17 -07001167 session->apmSamplingRate = kPreprocDefaultSr;
1168 session->apmFrameCount = (kPreprocDefaultSr) / 100;
1169 session->frameCount = session->apmFrameCount;
1170 session->samplingRate = kPreprocDefaultSr;
1171 session->inChannelCount = kPreProcDefaultCnl;
1172 session->outChannelCount = kPreProcDefaultCnl;
Saketh Sathuvalli08337032020-09-22 21:13:45 +05301173#ifdef WEBRTC_LEGACY
Chih-Hung Hsiehde7fa312015-10-13 10:58:08 -07001174 session->procFrame->sample_rate_hz_ = kPreprocDefaultSr;
1175 session->procFrame->num_channels_ = kPreProcDefaultCnl;
Saketh Sathuvalli08337032020-09-22 21:13:45 +05301176#else
1177 session->inputConfig.set_sample_rate_hz(kPreprocDefaultSr);
1178 session->inputConfig.set_num_channels(kPreProcDefaultCnl);
1179 session->outputConfig.set_sample_rate_hz(kPreprocDefaultSr);
1180 session->outputConfig.set_num_channels(kPreProcDefaultCnl);
1181#endif
Eric Laurenta9390d42011-06-17 20:17:17 -07001182 session->revChannelCount = kPreProcDefaultCnl;
Saketh Sathuvalli08337032020-09-22 21:13:45 +05301183#ifdef WEBRTC_LEGACY
Chih-Hung Hsiehde7fa312015-10-13 10:58:08 -07001184 session->revFrame->sample_rate_hz_ = kPreprocDefaultSr;
1185 session->revFrame->num_channels_ = kPreProcDefaultCnl;
Saketh Sathuvalli08337032020-09-22 21:13:45 +05301186#else
1187 session->revConfig.set_sample_rate_hz(kPreprocDefaultSr);
1188 session->revConfig.set_num_channels(kPreProcDefaultCnl);
1189#endif
Eric Laurenta9390d42011-06-17 20:17:17 -07001190 session->enabledMsk = 0;
1191 session->processedMsk = 0;
1192 session->revEnabledMsk = 0;
1193 session->revProcessedMsk = 0;
Saketh Sathuvalli08337032020-09-22 21:13:45 +05301194#ifdef WEBRTC_LEGACY
Eric Laurenta9390d42011-06-17 20:17:17 -07001195 session->inResampler = NULL;
Saketh Sathuvalli08337032020-09-22 21:13:45 +05301196#endif
Eric Laurenta9390d42011-06-17 20:17:17 -07001197 session->inBuf = NULL;
1198 session->inBufSize = 0;
Saketh Sathuvalli08337032020-09-22 21:13:45 +05301199#ifdef WEBRTC_LEGACY
Eric Laurenta9390d42011-06-17 20:17:17 -07001200 session->outResampler = NULL;
Saketh Sathuvalli08337032020-09-22 21:13:45 +05301201#endif
Eric Laurenta9390d42011-06-17 20:17:17 -07001202 session->outBuf = NULL;
1203 session->outBufSize = 0;
Saketh Sathuvalli08337032020-09-22 21:13:45 +05301204#ifdef WEBRTC_LEGACY
Eric Laurenta9390d42011-06-17 20:17:17 -07001205 session->revResampler = NULL;
Saketh Sathuvalli08337032020-09-22 21:13:45 +05301206#endif
Eric Laurenta9390d42011-06-17 20:17:17 -07001207 session->revBuf = NULL;
1208 session->revBufSize = 0;
1209 }
1210 status = Effect_Create(&session->effects[procId], session, interface);
1211 if (status < 0) {
1212 goto error;
1213 }
Steve Block3856b092011-10-20 11:56:00 +01001214 ALOGV("Session_CreateEffect OK");
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001215 session->createdMsk |= (1 << procId);
Eric Laurenta9390d42011-06-17 20:17:17 -07001216 return status;
1217
1218error:
1219 if (session->createdMsk == 0) {
Saketh Sathuvalli08337032020-09-22 21:13:45 +05301220#ifdef WEBRTC_LEGACY
Eric Laurenta9390d42011-06-17 20:17:17 -07001221 delete session->revFrame;
1222 session->revFrame = NULL;
1223 delete session->procFrame;
1224 session->procFrame = NULL;
Alex Luebs9718b7d2015-11-24 14:33:14 -08001225 delete session->apm;
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001226 session->apm = NULL; // NOLINT(clang-analyzer-cplusplus.NewDelete)
Saketh Sathuvalli08337032020-09-22 21:13:45 +05301227#else
1228 delete session->apm;
1229 session->apm = NULL;
1230#endif
Eric Laurenta9390d42011-06-17 20:17:17 -07001231 }
1232 return status;
1233}
1234
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001235int Session_ReleaseEffect(preproc_session_t* session, preproc_effect_t* fx) {
Steve Block5ff1dd52012-01-05 23:22:43 +00001236 ALOGW_IF(Effect_Release(fx) != 0, " Effect_Release() failed for proc ID %d", fx->procId);
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001237 session->createdMsk &= ~(1 << fx->procId);
Eric Laurenta9390d42011-06-17 20:17:17 -07001238 if (session->createdMsk == 0) {
Saketh Sathuvalli08337032020-09-22 21:13:45 +05301239#ifdef WEBRTC_LEGACY
Alex Luebs9718b7d2015-11-24 14:33:14 -08001240 delete session->apm;
Eric Laurenta9390d42011-06-17 20:17:17 -07001241 session->apm = NULL;
1242 delete session->procFrame;
1243 session->procFrame = NULL;
1244 delete session->revFrame;
1245 session->revFrame = NULL;
1246 if (session->inResampler != NULL) {
1247 speex_resampler_destroy(session->inResampler);
1248 session->inResampler = NULL;
1249 }
1250 if (session->outResampler != NULL) {
1251 speex_resampler_destroy(session->outResampler);
1252 session->outResampler = NULL;
1253 }
1254 if (session->revResampler != NULL) {
1255 speex_resampler_destroy(session->revResampler);
1256 session->revResampler = NULL;
1257 }
Saketh Sathuvalli08337032020-09-22 21:13:45 +05301258#else
1259 delete session->apm;
1260 session->apm = NULL;
1261#endif
Eric Laurenta9390d42011-06-17 20:17:17 -07001262 delete session->inBuf;
1263 session->inBuf = NULL;
1264 delete session->outBuf;
1265 session->outBuf = NULL;
1266 delete session->revBuf;
1267 session->revBuf = NULL;
1268
Eric Laurentb20cf7d2019-04-05 19:37:34 -07001269 session->id = 0;
Eric Laurenta9390d42011-06-17 20:17:17 -07001270 }
1271
1272 return 0;
1273}
1274
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001275int Session_SetConfig(preproc_session_t* session, effect_config_t* config) {
Alex Luebs3f11ef02016-01-15 15:51:58 -08001276 uint32_t inCnl = audio_channel_count_from_in_mask(config->inputCfg.channels);
1277 uint32_t outCnl = audio_channel_count_from_in_mask(config->outputCfg.channels);
Eric Laurenta9390d42011-06-17 20:17:17 -07001278
1279 if (config->inputCfg.samplingRate != config->outputCfg.samplingRate ||
1280 config->inputCfg.format != config->outputCfg.format ||
1281 config->inputCfg.format != AUDIO_FORMAT_PCM_16_BIT) {
1282 return -EINVAL;
1283 }
1284
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001285 ALOGV("Session_SetConfig sr %d cnl %08x", config->inputCfg.samplingRate,
1286 config->inputCfg.channels);
Saketh Sathuvalli08337032020-09-22 21:13:45 +05301287#ifdef WEBRTC_LEGACY
Eric Laurenta9390d42011-06-17 20:17:17 -07001288 int status;
Saketh Sathuvalli08337032020-09-22 21:13:45 +05301289#endif
Eric Laurenta9390d42011-06-17 20:17:17 -07001290
1291 // AEC implementation is limited to 16kHz
1292 if (config->inputCfg.samplingRate >= 32000 && !(session->createdMsk & (1 << PREPROC_AEC))) {
1293 session->apmSamplingRate = 32000;
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001294 } else if (config->inputCfg.samplingRate >= 16000) {
Eric Laurenta9390d42011-06-17 20:17:17 -07001295 session->apmSamplingRate = 16000;
1296 } else if (config->inputCfg.samplingRate >= 8000) {
1297 session->apmSamplingRate = 8000;
1298 }
Alex Luebs9718b7d2015-11-24 14:33:14 -08001299
Saketh Sathuvalli08337032020-09-22 21:13:45 +05301300#ifdef WEBRTC_LEGACY
Alex Luebs9718b7d2015-11-24 14:33:14 -08001301 const webrtc::ProcessingConfig processing_config = {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001302 {{static_cast<int>(session->apmSamplingRate), inCnl},
1303 {static_cast<int>(session->apmSamplingRate), outCnl},
1304 {static_cast<int>(session->apmSamplingRate), inCnl},
1305 {static_cast<int>(session->apmSamplingRate), inCnl}}};
Alex Luebs9718b7d2015-11-24 14:33:14 -08001306 status = session->apm->Initialize(processing_config);
Eric Laurenta9390d42011-06-17 20:17:17 -07001307 if (status < 0) {
1308 return -EINVAL;
1309 }
Saketh Sathuvalli08337032020-09-22 21:13:45 +05301310#endif
Eric Laurenta9390d42011-06-17 20:17:17 -07001311
1312 session->samplingRate = config->inputCfg.samplingRate;
1313 session->apmFrameCount = session->apmSamplingRate / 100;
1314 if (session->samplingRate == session->apmSamplingRate) {
1315 session->frameCount = session->apmFrameCount;
1316 } else {
Saketh Sathuvalli08337032020-09-22 21:13:45 +05301317#ifdef WEBRTC_LEGACY
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001318 session->frameCount =
1319 (session->apmFrameCount * session->samplingRate) / session->apmSamplingRate + 1;
Saketh Sathuvalli08337032020-09-22 21:13:45 +05301320#else
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001321 session->frameCount =
1322 (session->apmFrameCount * session->samplingRate) / session->apmSamplingRate;
Saketh Sathuvalli08337032020-09-22 21:13:45 +05301323#endif
Eric Laurenta9390d42011-06-17 20:17:17 -07001324 }
1325 session->inChannelCount = inCnl;
1326 session->outChannelCount = outCnl;
Saketh Sathuvalli08337032020-09-22 21:13:45 +05301327#ifdef WEBRTC_LEGACY
Chih-Hung Hsiehde7fa312015-10-13 10:58:08 -07001328 session->procFrame->num_channels_ = inCnl;
1329 session->procFrame->sample_rate_hz_ = session->apmSamplingRate;
Saketh Sathuvalli08337032020-09-22 21:13:45 +05301330#else
1331 session->inputConfig.set_sample_rate_hz(session->samplingRate);
1332 session->inputConfig.set_num_channels(inCnl);
1333 session->outputConfig.set_sample_rate_hz(session->samplingRate);
1334 session->outputConfig.set_num_channels(inCnl);
1335#endif
Eric Laurenta9390d42011-06-17 20:17:17 -07001336
1337 session->revChannelCount = inCnl;
Saketh Sathuvalli08337032020-09-22 21:13:45 +05301338#ifdef WEBRTC_LEGACY
Chih-Hung Hsiehde7fa312015-10-13 10:58:08 -07001339 session->revFrame->num_channels_ = inCnl;
1340 session->revFrame->sample_rate_hz_ = session->apmSamplingRate;
Saketh Sathuvalli08337032020-09-22 21:13:45 +05301341#else
1342 session->revConfig.set_sample_rate_hz(session->samplingRate);
1343 session->revConfig.set_num_channels(inCnl);
1344#endif
Eric Laurenta9390d42011-06-17 20:17:17 -07001345
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001346 // force process buffer reallocation
1347 session->inBufSize = 0;
1348 session->outBufSize = 0;
1349 session->framesIn = 0;
1350 session->framesOut = 0;
1351
Saketh Sathuvalli08337032020-09-22 21:13:45 +05301352#ifdef WEBRTC_LEGACY
Eric Laurenta9390d42011-06-17 20:17:17 -07001353 if (session->inResampler != NULL) {
1354 speex_resampler_destroy(session->inResampler);
1355 session->inResampler = NULL;
1356 }
1357 if (session->outResampler != NULL) {
1358 speex_resampler_destroy(session->outResampler);
1359 session->outResampler = NULL;
1360 }
1361 if (session->revResampler != NULL) {
1362 speex_resampler_destroy(session->revResampler);
1363 session->revResampler = NULL;
1364 }
1365 if (session->samplingRate != session->apmSamplingRate) {
1366 int error;
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001367 session->inResampler =
1368 speex_resampler_init(session->inChannelCount, session->samplingRate,
1369 session->apmSamplingRate, RESAMPLER_QUALITY, &error);
Eric Laurenta9390d42011-06-17 20:17:17 -07001370 if (session->inResampler == NULL) {
Steve Block5ff1dd52012-01-05 23:22:43 +00001371 ALOGW("Session_SetConfig Cannot create speex resampler: %s",
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001372 speex_resampler_strerror(error));
Eric Laurenta9390d42011-06-17 20:17:17 -07001373 return -EINVAL;
1374 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001375 session->outResampler =
1376 speex_resampler_init(session->outChannelCount, session->apmSamplingRate,
1377 session->samplingRate, RESAMPLER_QUALITY, &error);
Eric Laurenta9390d42011-06-17 20:17:17 -07001378 if (session->outResampler == NULL) {
Steve Block5ff1dd52012-01-05 23:22:43 +00001379 ALOGW("Session_SetConfig Cannot create speex resampler: %s",
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001380 speex_resampler_strerror(error));
Eric Laurenta9390d42011-06-17 20:17:17 -07001381 speex_resampler_destroy(session->inResampler);
1382 session->inResampler = NULL;
1383 return -EINVAL;
1384 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001385 session->revResampler =
1386 speex_resampler_init(session->inChannelCount, session->samplingRate,
1387 session->apmSamplingRate, RESAMPLER_QUALITY, &error);
Eric Laurenta9390d42011-06-17 20:17:17 -07001388 if (session->revResampler == NULL) {
Steve Block5ff1dd52012-01-05 23:22:43 +00001389 ALOGW("Session_SetConfig Cannot create speex resampler: %s",
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001390 speex_resampler_strerror(error));
Eric Laurenta9390d42011-06-17 20:17:17 -07001391 speex_resampler_destroy(session->inResampler);
1392 session->inResampler = NULL;
1393 speex_resampler_destroy(session->outResampler);
1394 session->outResampler = NULL;
1395 return -EINVAL;
1396 }
1397 }
Saketh Sathuvalli08337032020-09-22 21:13:45 +05301398#endif
Eric Laurenta9390d42011-06-17 20:17:17 -07001399
1400 session->state = PREPROC_SESSION_STATE_CONFIG;
1401 return 0;
1402}
1403
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001404void Session_GetConfig(preproc_session_t* session, effect_config_t* config) {
Eric Laurent3d5188b2011-12-16 15:30:36 -08001405 memset(config, 0, sizeof(effect_config_t));
1406 config->inputCfg.samplingRate = config->outputCfg.samplingRate = session->samplingRate;
1407 config->inputCfg.format = config->outputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
Glenn Kastenab334fd2012-03-14 12:56:06 -07001408 config->inputCfg.channels = audio_channel_in_mask_from_count(session->inChannelCount);
1409 // "out" doesn't mean output device, so this is the correct API to convert channel count to mask
1410 config->outputCfg.channels = audio_channel_in_mask_from_count(session->outChannelCount);
Eric Laurent3d5188b2011-12-16 15:30:36 -08001411 config->inputCfg.mask = config->outputCfg.mask =
1412 (EFFECT_CONFIG_SMP_RATE | EFFECT_CONFIG_CHANNELS | EFFECT_CONFIG_FORMAT);
1413}
1414
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001415int Session_SetReverseConfig(preproc_session_t* session, effect_config_t* config) {
Eric Laurenta9390d42011-06-17 20:17:17 -07001416 if (config->inputCfg.samplingRate != config->outputCfg.samplingRate ||
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001417 config->inputCfg.format != config->outputCfg.format ||
1418 config->inputCfg.format != AUDIO_FORMAT_PCM_16_BIT) {
Eric Laurenta9390d42011-06-17 20:17:17 -07001419 return -EINVAL;
1420 }
1421
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001422 ALOGV("Session_SetReverseConfig sr %d cnl %08x", config->inputCfg.samplingRate,
1423 config->inputCfg.channels);
Eric Laurenta9390d42011-06-17 20:17:17 -07001424
1425 if (session->state < PREPROC_SESSION_STATE_CONFIG) {
1426 return -ENOSYS;
1427 }
1428 if (config->inputCfg.samplingRate != session->samplingRate ||
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001429 config->inputCfg.format != AUDIO_FORMAT_PCM_16_BIT) {
Eric Laurenta9390d42011-06-17 20:17:17 -07001430 return -EINVAL;
1431 }
Andy Hunge5412692014-05-16 11:25:07 -07001432 uint32_t inCnl = audio_channel_count_from_out_mask(config->inputCfg.channels);
Saketh Sathuvalli08337032020-09-22 21:13:45 +05301433#ifdef WEBRTC_LEGACY
Alex Luebs9718b7d2015-11-24 14:33:14 -08001434 const webrtc::ProcessingConfig processing_config = {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001435 {{static_cast<int>(session->apmSamplingRate), session->inChannelCount},
1436 {static_cast<int>(session->apmSamplingRate), session->outChannelCount},
1437 {static_cast<int>(session->apmSamplingRate), inCnl},
1438 {static_cast<int>(session->apmSamplingRate), inCnl}}};
Alex Luebs9718b7d2015-11-24 14:33:14 -08001439 int status = session->apm->Initialize(processing_config);
Eric Laurenta9390d42011-06-17 20:17:17 -07001440 if (status < 0) {
1441 return -EINVAL;
1442 }
Saketh Sathuvalli08337032020-09-22 21:13:45 +05301443#endif
Eric Laurenta9390d42011-06-17 20:17:17 -07001444 session->revChannelCount = inCnl;
Saketh Sathuvalli08337032020-09-22 21:13:45 +05301445#ifdef WEBRTC_LEGACY
Chih-Hung Hsiehde7fa312015-10-13 10:58:08 -07001446 session->revFrame->num_channels_ = inCnl;
1447 session->revFrame->sample_rate_hz_ = session->apmSamplingRate;
Saketh Sathuvalli08337032020-09-22 21:13:45 +05301448#endif
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001449 // force process buffer reallocation
1450 session->revBufSize = 0;
1451 session->framesRev = 0;
1452
Eric Laurenta9390d42011-06-17 20:17:17 -07001453 return 0;
1454}
1455
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001456void Session_GetReverseConfig(preproc_session_t* session, effect_config_t* config) {
Eric Laurent3d5188b2011-12-16 15:30:36 -08001457 memset(config, 0, sizeof(effect_config_t));
1458 config->inputCfg.samplingRate = config->outputCfg.samplingRate = session->samplingRate;
1459 config->inputCfg.format = config->outputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
1460 config->inputCfg.channels = config->outputCfg.channels =
Glenn Kastenab334fd2012-03-14 12:56:06 -07001461 audio_channel_in_mask_from_count(session->revChannelCount);
Eric Laurent3d5188b2011-12-16 15:30:36 -08001462 config->inputCfg.mask = config->outputCfg.mask =
1463 (EFFECT_CONFIG_SMP_RATE | EFFECT_CONFIG_CHANNELS | EFFECT_CONFIG_FORMAT);
1464}
1465
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001466void Session_SetProcEnabled(preproc_session_t* session, uint32_t procId, bool enabled) {
Eric Laurenta9390d42011-06-17 20:17:17 -07001467 if (enabled) {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001468 if (session->enabledMsk == 0) {
Eric Laurenta9390d42011-06-17 20:17:17 -07001469 session->framesIn = 0;
Saketh Sathuvalli08337032020-09-22 21:13:45 +05301470#ifdef WEBRTC_LEGACY
Eric Laurenta9390d42011-06-17 20:17:17 -07001471 if (session->inResampler != NULL) {
1472 speex_resampler_reset_mem(session->inResampler);
1473 }
1474 session->framesOut = 0;
1475 if (session->outResampler != NULL) {
1476 speex_resampler_reset_mem(session->outResampler);
1477 }
Saketh Sathuvalli08337032020-09-22 21:13:45 +05301478#endif
Eric Laurenta9390d42011-06-17 20:17:17 -07001479 }
1480 session->enabledMsk |= (1 << procId);
1481 if (HasReverseStream(procId)) {
1482 session->framesRev = 0;
Saketh Sathuvalli08337032020-09-22 21:13:45 +05301483#ifdef WEBRTC_LEGACY
Eric Laurenta9390d42011-06-17 20:17:17 -07001484 if (session->revResampler != NULL) {
1485 speex_resampler_reset_mem(session->revResampler);
1486 }
Saketh Sathuvalli08337032020-09-22 21:13:45 +05301487#endif
Eric Laurenta9390d42011-06-17 20:17:17 -07001488 session->revEnabledMsk |= (1 << procId);
1489 }
1490 } else {
1491 session->enabledMsk &= ~(1 << procId);
1492 if (HasReverseStream(procId)) {
1493 session->revEnabledMsk &= ~(1 << procId);
1494 }
1495 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001496 ALOGV("Session_SetProcEnabled proc %d, enabled %d enabledMsk %08x revEnabledMsk %08x", procId,
1497 enabled, session->enabledMsk, session->revEnabledMsk);
Eric Laurenta9390d42011-06-17 20:17:17 -07001498 session->processedMsk = 0;
1499 if (HasReverseStream(procId)) {
1500 session->revProcessedMsk = 0;
1501 }
1502}
1503
1504//------------------------------------------------------------------------------
1505// Bundle functions
1506//------------------------------------------------------------------------------
1507
1508static int sInitStatus = 1;
1509static preproc_session_t sSessions[PREPROC_NUM_SESSIONS];
1510
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001511preproc_session_t* PreProc_GetSession(int32_t procId, int32_t sessionId, int32_t ioId) {
Eric Laurenta9390d42011-06-17 20:17:17 -07001512 size_t i;
Eric Laurenta9390d42011-06-17 20:17:17 -07001513 for (i = 0; i < PREPROC_NUM_SESSIONS; i++) {
Eric Laurentb20cf7d2019-04-05 19:37:34 -07001514 if (sSessions[i].id == sessionId) {
Eric Laurenta9390d42011-06-17 20:17:17 -07001515 if (sSessions[i].createdMsk & (1 << procId)) {
1516 return NULL;
1517 }
1518 return &sSessions[i];
1519 }
1520 }
1521 for (i = 0; i < PREPROC_NUM_SESSIONS; i++) {
Eric Laurentb20cf7d2019-04-05 19:37:34 -07001522 if (sSessions[i].id == 0) {
Eric Laurenta9390d42011-06-17 20:17:17 -07001523 sSessions[i].id = sessionId;
1524 sSessions[i].io = ioId;
1525 return &sSessions[i];
1526 }
1527 }
1528 return NULL;
1529}
1530
Eric Laurenta9390d42011-06-17 20:17:17 -07001531int PreProc_Init() {
1532 size_t i;
1533 int status = 0;
1534
1535 if (sInitStatus <= 0) {
1536 return sInitStatus;
1537 }
1538 for (i = 0; i < PREPROC_NUM_SESSIONS && status == 0; i++) {
1539 status = Session_Init(&sSessions[i]);
1540 }
1541 sInitStatus = status;
1542 return sInitStatus;
1543}
1544
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001545const effect_descriptor_t* PreProc_GetDescriptor(const effect_uuid_t* uuid) {
Eric Laurenta9390d42011-06-17 20:17:17 -07001546 size_t i;
1547 for (i = 0; i < PREPROC_NUM_EFFECTS; i++) {
1548 if (memcmp(&sDescriptors[i]->uuid, uuid, sizeof(effect_uuid_t)) == 0) {
1549 return sDescriptors[i];
1550 }
1551 }
1552 return NULL;
1553}
1554
Eric Laurenta9390d42011-06-17 20:17:17 -07001555extern "C" {
1556
1557//------------------------------------------------------------------------------
1558// Effect Control Interface Implementation
1559//------------------------------------------------------------------------------
1560
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001561int PreProcessingFx_Process(effect_handle_t self, audio_buffer_t* inBuffer,
1562 audio_buffer_t* outBuffer) {
1563 preproc_effect_t* effect = (preproc_effect_t*)self;
Eric Laurenta9390d42011-06-17 20:17:17 -07001564
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001565 if (effect == NULL) {
Steve Block3856b092011-10-20 11:56:00 +01001566 ALOGV("PreProcessingFx_Process() ERROR effect == NULL");
Eric Laurenta9390d42011-06-17 20:17:17 -07001567 return -EINVAL;
1568 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001569 preproc_session_t* session = (preproc_session_t*)effect->session;
Eric Laurenta9390d42011-06-17 20:17:17 -07001570
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001571 if (inBuffer == NULL || inBuffer->raw == NULL || outBuffer == NULL || outBuffer->raw == NULL) {
Steve Block5ff1dd52012-01-05 23:22:43 +00001572 ALOGW("PreProcessingFx_Process() ERROR bad pointer");
Eric Laurenta9390d42011-06-17 20:17:17 -07001573 return -EINVAL;
1574 }
1575
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001576 session->processedMsk |= (1 << effect->procId);
Eric Laurenta9390d42011-06-17 20:17:17 -07001577
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001578 // ALOGV("PreProcessingFx_Process In %d frames enabledMsk %08x processedMsk %08x",
1579 // inBuffer->frameCount, session->enabledMsk, session->processedMsk);
Eric Laurenta9390d42011-06-17 20:17:17 -07001580
1581 if ((session->processedMsk & session->enabledMsk) == session->enabledMsk) {
1582 effect->session->processedMsk = 0;
1583 size_t framesRq = outBuffer->frameCount;
1584 size_t framesWr = 0;
1585 if (session->framesOut) {
1586 size_t fr = session->framesOut;
1587 if (outBuffer->frameCount < fr) {
1588 fr = outBuffer->frameCount;
1589 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001590 memcpy(outBuffer->s16, session->outBuf,
1591 fr * session->outChannelCount * sizeof(int16_t));
1592 memmove(session->outBuf, session->outBuf + fr * session->outChannelCount,
Jiabin Huang0c9544a2020-06-04 00:46:19 +00001593 (session->framesOut - fr) * session->outChannelCount * sizeof(int16_t));
Eric Laurenta9390d42011-06-17 20:17:17 -07001594 session->framesOut -= fr;
1595 framesWr += fr;
1596 }
1597 outBuffer->frameCount = framesWr;
1598 if (framesWr == framesRq) {
1599 inBuffer->frameCount = 0;
1600 return 0;
1601 }
1602
Saketh Sathuvalli08337032020-09-22 21:13:45 +05301603#ifdef WEBRTC_LEGACY
Eric Laurenta9390d42011-06-17 20:17:17 -07001604 if (session->inResampler != NULL) {
1605 size_t fr = session->frameCount - session->framesIn;
1606 if (inBuffer->frameCount < fr) {
1607 fr = inBuffer->frameCount;
1608 }
1609 if (session->inBufSize < session->framesIn + fr) {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001610 int16_t* buf;
Eric Laurenta9390d42011-06-17 20:17:17 -07001611 session->inBufSize = session->framesIn + fr;
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001612 buf = (int16_t*)realloc(
1613 session->inBuf,
1614 session->inBufSize * session->inChannelCount * sizeof(int16_t));
Eric Laurent679650f2015-08-21 14:01:50 -07001615 if (buf == NULL) {
1616 session->framesIn = 0;
1617 free(session->inBuf);
1618 session->inBuf = NULL;
1619 return -ENOMEM;
1620 }
1621 session->inBuf = buf;
Eric Laurenta9390d42011-06-17 20:17:17 -07001622 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001623 memcpy(session->inBuf + session->framesIn * session->inChannelCount, inBuffer->s16,
Eric Laurenta9390d42011-06-17 20:17:17 -07001624 fr * session->inChannelCount * sizeof(int16_t));
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001625#ifdef DUAL_MIC_TEST
1626 pthread_mutex_lock(&gPcmDumpLock);
1627 if (gPcmDumpFh != NULL) {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001628 fwrite(inBuffer->raw, fr * session->inChannelCount * sizeof(int16_t), 1,
1629 gPcmDumpFh);
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001630 }
1631 pthread_mutex_unlock(&gPcmDumpLock);
1632#endif
Eric Laurenta9390d42011-06-17 20:17:17 -07001633
1634 session->framesIn += fr;
1635 inBuffer->frameCount = fr;
1636 if (session->framesIn < session->frameCount) {
1637 return 0;
1638 }
Kévin PETIT377b2ec2014-02-03 12:35:36 +00001639 spx_uint32_t frIn = session->framesIn;
1640 spx_uint32_t frOut = session->apmFrameCount;
Eric Laurenta9390d42011-06-17 20:17:17 -07001641 if (session->inChannelCount == 1) {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001642 speex_resampler_process_int(session->inResampler, 0, session->inBuf, &frIn,
1643 session->procFrame->data_, &frOut);
Eric Laurenta9390d42011-06-17 20:17:17 -07001644 } else {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001645 speex_resampler_process_interleaved_int(session->inResampler, session->inBuf, &frIn,
1646 session->procFrame->data_, &frOut);
Eric Laurenta9390d42011-06-17 20:17:17 -07001647 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001648 memmove(session->inBuf, session->inBuf + frIn * session->inChannelCount,
Jiabin Huang0c9544a2020-06-04 00:46:19 +00001649 (session->framesIn - frIn) * session->inChannelCount * sizeof(int16_t));
Eric Laurenta9390d42011-06-17 20:17:17 -07001650 session->framesIn -= frIn;
1651 } else {
1652 size_t fr = session->frameCount - session->framesIn;
1653 if (inBuffer->frameCount < fr) {
1654 fr = inBuffer->frameCount;
1655 }
Chih-Hung Hsiehde7fa312015-10-13 10:58:08 -07001656 memcpy(session->procFrame->data_ + session->framesIn * session->inChannelCount,
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001657 inBuffer->s16, fr * session->inChannelCount * sizeof(int16_t));
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001658
1659#ifdef DUAL_MIC_TEST
1660 pthread_mutex_lock(&gPcmDumpLock);
1661 if (gPcmDumpFh != NULL) {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001662 fwrite(inBuffer->raw, fr * session->inChannelCount * sizeof(int16_t), 1,
1663 gPcmDumpFh);
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001664 }
1665 pthread_mutex_unlock(&gPcmDumpLock);
1666#endif
1667
Eric Laurenta9390d42011-06-17 20:17:17 -07001668 session->framesIn += fr;
1669 inBuffer->frameCount = fr;
1670 if (session->framesIn < session->frameCount) {
1671 return 0;
1672 }
1673 session->framesIn = 0;
1674 }
Alex Luebs766bf732015-12-14 21:32:13 -08001675 session->procFrame->samples_per_channel_ = session->apmFrameCount;
Eric Laurenta9390d42011-06-17 20:17:17 -07001676
1677 effect->session->apm->ProcessStream(session->procFrame);
Saketh Sathuvalli08337032020-09-22 21:13:45 +05301678#else
1679 size_t fr = session->frameCount - session->framesIn;
1680 if (inBuffer->frameCount < fr) {
1681 fr = inBuffer->frameCount;
1682 }
1683 session->framesIn += fr;
1684 inBuffer->frameCount = fr;
1685 if (session->framesIn < session->frameCount) {
1686 return 0;
1687 }
1688 session->framesIn = 0;
1689 if (int status = effect->session->apm->ProcessStream(
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001690 (const int16_t* const)inBuffer->s16,
1691 (const webrtc::StreamConfig)effect->session->inputConfig,
1692 (const webrtc::StreamConfig)effect->session->outputConfig,
1693 (int16_t* const)outBuffer->s16);
1694 status != 0) {
Saketh Sathuvalli08337032020-09-22 21:13:45 +05301695 ALOGE("Process Stream failed with error %d\n", status);
1696 return status;
1697 }
1698 outBuffer->frameCount = inBuffer->frameCount;
1699#endif
Eric Laurenta9390d42011-06-17 20:17:17 -07001700
1701 if (session->outBufSize < session->framesOut + session->frameCount) {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001702 int16_t* buf;
Eric Laurenta9390d42011-06-17 20:17:17 -07001703 session->outBufSize = session->framesOut + session->frameCount;
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001704 buf = (int16_t*)realloc(
1705 session->outBuf,
1706 session->outBufSize * session->outChannelCount * sizeof(int16_t));
Eric Laurent679650f2015-08-21 14:01:50 -07001707 if (buf == NULL) {
1708 session->framesOut = 0;
1709 free(session->outBuf);
1710 session->outBuf = NULL;
1711 return -ENOMEM;
1712 }
1713 session->outBuf = buf;
Eric Laurenta9390d42011-06-17 20:17:17 -07001714 }
1715
Saketh Sathuvalli08337032020-09-22 21:13:45 +05301716#ifdef WEBRTC_LEGACY
Eric Laurenta9390d42011-06-17 20:17:17 -07001717 if (session->outResampler != NULL) {
Kévin PETIT377b2ec2014-02-03 12:35:36 +00001718 spx_uint32_t frIn = session->apmFrameCount;
1719 spx_uint32_t frOut = session->frameCount;
Eric Laurenta9390d42011-06-17 20:17:17 -07001720 if (session->inChannelCount == 1) {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001721 speex_resampler_process_int(
1722 session->outResampler, 0, session->procFrame->data_, &frIn,
1723 session->outBuf + session->framesOut * session->outChannelCount, &frOut);
Eric Laurenta9390d42011-06-17 20:17:17 -07001724 } else {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001725 speex_resampler_process_interleaved_int(
1726 session->outResampler, session->procFrame->data_, &frIn,
1727 session->outBuf + session->framesOut * session->outChannelCount, &frOut);
Eric Laurenta9390d42011-06-17 20:17:17 -07001728 }
1729 session->framesOut += frOut;
1730 } else {
1731 memcpy(session->outBuf + session->framesOut * session->outChannelCount,
Chih-Hung Hsiehde7fa312015-10-13 10:58:08 -07001732 session->procFrame->data_,
Eric Laurenta9390d42011-06-17 20:17:17 -07001733 session->frameCount * session->outChannelCount * sizeof(int16_t));
1734 session->framesOut += session->frameCount;
1735 }
1736 size_t fr = session->framesOut;
Saketh Sathuvalli08337032020-09-22 21:13:45 +05301737#else
1738 fr = session->framesOut;
1739#endif
Eric Laurenta9390d42011-06-17 20:17:17 -07001740 if (framesRq - framesWr < fr) {
1741 fr = framesRq - framesWr;
1742 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001743 memcpy(outBuffer->s16 + framesWr * session->outChannelCount, session->outBuf,
1744 fr * session->outChannelCount * sizeof(int16_t));
1745 memmove(session->outBuf, session->outBuf + fr * session->outChannelCount,
Jiabin Huang0c9544a2020-06-04 00:46:19 +00001746 (session->framesOut - fr) * session->outChannelCount * sizeof(int16_t));
Eric Laurenta9390d42011-06-17 20:17:17 -07001747 session->framesOut -= fr;
1748 outBuffer->frameCount += fr;
1749
1750 return 0;
1751 } else {
1752 return -ENODATA;
1753 }
1754}
1755
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001756int PreProcessingFx_Command(effect_handle_t self, uint32_t cmdCode, uint32_t cmdSize,
1757 void* pCmdData, uint32_t* replySize, void* pReplyData) {
1758 preproc_effect_t* effect = (preproc_effect_t*)self;
Eric Laurenta9390d42011-06-17 20:17:17 -07001759
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001760 if (effect == NULL) {
Eric Laurenta9390d42011-06-17 20:17:17 -07001761 return -EINVAL;
1762 }
1763
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001764 // ALOGV("PreProcessingFx_Command: command %d cmdSize %d",cmdCode, cmdSize);
Eric Laurenta9390d42011-06-17 20:17:17 -07001765
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001766 switch (cmdCode) {
Eric Laurenta9390d42011-06-17 20:17:17 -07001767 case EFFECT_CMD_INIT:
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001768 if (pReplyData == NULL || *replySize != sizeof(int)) {
Eric Laurenta9390d42011-06-17 20:17:17 -07001769 return -EINVAL;
1770 }
1771 if (effect->ops->init) {
1772 effect->ops->init(effect);
1773 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001774 *(int*)pReplyData = 0;
Eric Laurenta9390d42011-06-17 20:17:17 -07001775 break;
1776
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001777 case EFFECT_CMD_SET_CONFIG: {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001778 if (pCmdData == NULL || cmdSize != sizeof(effect_config_t) || pReplyData == NULL ||
1779 *replySize != sizeof(int)) {
Steve Block3856b092011-10-20 11:56:00 +01001780 ALOGV("PreProcessingFx_Command cmdCode Case: "
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001781 "EFFECT_CMD_SET_CONFIG: ERROR");
Eric Laurenta9390d42011-06-17 20:17:17 -07001782 return -EINVAL;
1783 }
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001784#ifdef DUAL_MIC_TEST
1785 // make sure that the config command is accepted by making as if all effects were
1786 // disabled: this is OK for functional tests
1787 uint32_t enabledMsk = effect->session->enabledMsk;
1788 if (gDualMicEnabled) {
1789 effect->session->enabledMsk = 0;
1790 }
1791#endif
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001792 *(int*)pReplyData = Session_SetConfig(effect->session, (effect_config_t*)pCmdData);
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001793#ifdef DUAL_MIC_TEST
1794 if (gDualMicEnabled) {
1795 effect->session->enabledMsk = enabledMsk;
1796 }
1797#endif
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001798 if (*(int*)pReplyData != 0) {
Eric Laurenta9390d42011-06-17 20:17:17 -07001799 break;
1800 }
Eric Laurent76533e92012-02-17 17:52:04 -08001801 if (effect->state != PREPROC_EFFECT_STATE_ACTIVE) {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001802 *(int*)pReplyData = Effect_SetState(effect, PREPROC_EFFECT_STATE_CONFIG);
Eric Laurent76533e92012-02-17 17:52:04 -08001803 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001804 } break;
Eric Laurenta9390d42011-06-17 20:17:17 -07001805
Eric Laurent3d5188b2011-12-16 15:30:36 -08001806 case EFFECT_CMD_GET_CONFIG:
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001807 if (pReplyData == NULL || *replySize != sizeof(effect_config_t)) {
Eric Laurent3d5188b2011-12-16 15:30:36 -08001808 ALOGV("\tLVM_ERROR : PreProcessingFx_Command cmdCode Case: "
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001809 "EFFECT_CMD_GET_CONFIG: ERROR");
Eric Laurent3d5188b2011-12-16 15:30:36 -08001810 return -EINVAL;
1811 }
1812
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001813 Session_GetConfig(effect->session, (effect_config_t*)pReplyData);
Eric Laurent3d5188b2011-12-16 15:30:36 -08001814 break;
1815
1816 case EFFECT_CMD_SET_CONFIG_REVERSE:
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001817 if (pCmdData == NULL || cmdSize != sizeof(effect_config_t) || pReplyData == NULL ||
Eric Laurent3d5188b2011-12-16 15:30:36 -08001818 *replySize != sizeof(int)) {
Steve Block3856b092011-10-20 11:56:00 +01001819 ALOGV("PreProcessingFx_Command cmdCode Case: "
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001820 "EFFECT_CMD_SET_CONFIG_REVERSE: ERROR");
Eric Laurenta9390d42011-06-17 20:17:17 -07001821 return -EINVAL;
1822 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001823 *(int*)pReplyData =
1824 Session_SetReverseConfig(effect->session, (effect_config_t*)pCmdData);
1825 if (*(int*)pReplyData != 0) {
Eric Laurenta9390d42011-06-17 20:17:17 -07001826 break;
1827 }
1828 break;
1829
Eric Laurent3d5188b2011-12-16 15:30:36 -08001830 case EFFECT_CMD_GET_CONFIG_REVERSE:
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001831 if (pReplyData == NULL || *replySize != sizeof(effect_config_t)) {
Eric Laurent3d5188b2011-12-16 15:30:36 -08001832 ALOGV("PreProcessingFx_Command cmdCode Case: "
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001833 "EFFECT_CMD_GET_CONFIG_REVERSE: ERROR");
Eric Laurent3d5188b2011-12-16 15:30:36 -08001834 return -EINVAL;
1835 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001836 Session_GetReverseConfig(effect->session, (effect_config_t*)pCmdData);
Eric Laurent3d5188b2011-12-16 15:30:36 -08001837 break;
1838
Eric Laurenta9390d42011-06-17 20:17:17 -07001839 case EFFECT_CMD_RESET:
1840 if (effect->ops->reset) {
1841 effect->ops->reset(effect);
1842 }
1843 break;
1844
Eric Laurent0f714a42015-06-19 15:33:57 -07001845 case EFFECT_CMD_GET_PARAM: {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001846 effect_param_t* p = (effect_param_t*)pCmdData;
Eric Laurent0f714a42015-06-19 15:33:57 -07001847
1848 if (pCmdData == NULL || cmdSize < sizeof(effect_param_t) ||
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001849 cmdSize < (sizeof(effect_param_t) + p->psize) || pReplyData == NULL ||
1850 replySize == NULL || *replySize < (sizeof(effect_param_t) + p->psize)) {
Steve Block3856b092011-10-20 11:56:00 +01001851 ALOGV("PreProcessingFx_Command cmdCode Case: "
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001852 "EFFECT_CMD_GET_PARAM: ERROR");
Eric Laurenta9390d42011-06-17 20:17:17 -07001853 return -EINVAL;
1854 }
Eric Laurenta9390d42011-06-17 20:17:17 -07001855
1856 memcpy(pReplyData, pCmdData, sizeof(effect_param_t) + p->psize);
1857
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001858 p = (effect_param_t*)pReplyData;
Eric Laurenta9390d42011-06-17 20:17:17 -07001859
1860 int voffset = ((p->psize - 1) / sizeof(int32_t) + 1) * sizeof(int32_t);
1861
1862 if (effect->ops->get_parameter) {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001863 p->status =
1864 effect->ops->get_parameter(effect, p->data, &p->vsize, p->data + voffset);
Eric Laurenta9390d42011-06-17 20:17:17 -07001865 *replySize = sizeof(effect_param_t) + voffset + p->vsize;
1866 }
1867 } break;
1868
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001869 case EFFECT_CMD_SET_PARAM: {
1870 if (pCmdData == NULL || cmdSize < sizeof(effect_param_t) || pReplyData == NULL ||
1871 replySize == NULL || *replySize != sizeof(int32_t)) {
Steve Block3856b092011-10-20 11:56:00 +01001872 ALOGV("PreProcessingFx_Command cmdCode Case: "
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001873 "EFFECT_CMD_SET_PARAM: ERROR");
Eric Laurenta9390d42011-06-17 20:17:17 -07001874 return -EINVAL;
1875 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001876 effect_param_t* p = (effect_param_t*)pCmdData;
Eric Laurenta9390d42011-06-17 20:17:17 -07001877
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001878 if (p->psize != sizeof(int32_t)) {
Steve Block3856b092011-10-20 11:56:00 +01001879 ALOGV("PreProcessingFx_Command cmdCode Case: "
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001880 "EFFECT_CMD_SET_PARAM: ERROR, psize is not sizeof(int32_t)");
Eric Laurenta9390d42011-06-17 20:17:17 -07001881 return -EINVAL;
1882 }
1883 if (effect->ops->set_parameter) {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001884 *(int*)pReplyData =
1885 effect->ops->set_parameter(effect, (void*)p->data, p->data + p->psize);
Eric Laurenta9390d42011-06-17 20:17:17 -07001886 }
1887 } break;
1888
1889 case EFFECT_CMD_ENABLE:
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001890 if (pReplyData == NULL || replySize == NULL || *replySize != sizeof(int)) {
Steve Block3856b092011-10-20 11:56:00 +01001891 ALOGV("PreProcessingFx_Command cmdCode Case: EFFECT_CMD_ENABLE: ERROR");
Eric Laurenta9390d42011-06-17 20:17:17 -07001892 return -EINVAL;
1893 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001894 *(int*)pReplyData = Effect_SetState(effect, PREPROC_EFFECT_STATE_ACTIVE);
Eric Laurenta9390d42011-06-17 20:17:17 -07001895 break;
1896
1897 case EFFECT_CMD_DISABLE:
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001898 if (pReplyData == NULL || replySize == NULL || *replySize != sizeof(int)) {
Steve Block3856b092011-10-20 11:56:00 +01001899 ALOGV("PreProcessingFx_Command cmdCode Case: EFFECT_CMD_DISABLE: ERROR");
Eric Laurenta9390d42011-06-17 20:17:17 -07001900 return -EINVAL;
1901 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001902 *(int*)pReplyData = Effect_SetState(effect, PREPROC_EFFECT_STATE_CONFIG);
Eric Laurenta9390d42011-06-17 20:17:17 -07001903 break;
1904
1905 case EFFECT_CMD_SET_DEVICE:
1906 case EFFECT_CMD_SET_INPUT_DEVICE:
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001907 if (pCmdData == NULL || cmdSize != sizeof(uint32_t)) {
Steve Block3856b092011-10-20 11:56:00 +01001908 ALOGV("PreProcessingFx_Command cmdCode Case: EFFECT_CMD_SET_DEVICE: ERROR");
Eric Laurenta9390d42011-06-17 20:17:17 -07001909 return -EINVAL;
1910 }
1911
1912 if (effect->ops->set_device) {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001913 effect->ops->set_device(effect, *(uint32_t*)pCmdData);
Eric Laurenta9390d42011-06-17 20:17:17 -07001914 }
1915 break;
1916
1917 case EFFECT_CMD_SET_VOLUME:
1918 case EFFECT_CMD_SET_AUDIO_MODE:
1919 break;
1920
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001921#ifdef DUAL_MIC_TEST
1922 ///// test commands start
1923 case PREPROC_CMD_DUAL_MIC_ENABLE: {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001924 if (pCmdData == NULL || cmdSize != sizeof(uint32_t) || pReplyData == NULL ||
1925 replySize == NULL) {
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001926 ALOGE("PreProcessingFx_Command cmdCode Case: "
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001927 "PREPROC_CMD_DUAL_MIC_ENABLE: ERROR");
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001928 *replySize = 0;
1929 return -EINVAL;
1930 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001931 gDualMicEnabled = *(bool*)pCmdData;
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001932 if (gDualMicEnabled) {
1933 effect->aux_channels_on = sHasAuxChannels[effect->procId];
1934 } else {
1935 effect->aux_channels_on = false;
1936 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001937 effect->cur_channel_config =
1938 (effect->session->inChannelCount == 1) ? CHANNEL_CFG_MONO : CHANNEL_CFG_STEREO;
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001939
1940 ALOGV("PREPROC_CMD_DUAL_MIC_ENABLE: %s", gDualMicEnabled ? "enabled" : "disabled");
1941 *replySize = sizeof(int);
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001942 *(int*)pReplyData = 0;
1943 } break;
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001944 case PREPROC_CMD_DUAL_MIC_PCM_DUMP_START: {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001945 if (pCmdData == NULL || pReplyData == NULL || replySize == NULL) {
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001946 ALOGE("PreProcessingFx_Command cmdCode Case: "
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001947 "PREPROC_CMD_DUAL_MIC_PCM_DUMP_START: ERROR");
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001948 *replySize = 0;
1949 return -EINVAL;
1950 }
1951 pthread_mutex_lock(&gPcmDumpLock);
1952 if (gPcmDumpFh != NULL) {
1953 fclose(gPcmDumpFh);
1954 gPcmDumpFh = NULL;
1955 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001956 char* path = strndup((char*)pCmdData, cmdSize);
1957 gPcmDumpFh = fopen((char*)path, "wb");
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001958 pthread_mutex_unlock(&gPcmDumpLock);
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001959 ALOGV("PREPROC_CMD_DUAL_MIC_PCM_DUMP_START: path %s gPcmDumpFh %p", path, gPcmDumpFh);
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001960 ALOGE_IF(gPcmDumpFh <= 0, "gPcmDumpFh open error %d %s", errno, strerror(errno));
1961 free(path);
1962 *replySize = sizeof(int);
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001963 *(int*)pReplyData = 0;
1964 } break;
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001965 case PREPROC_CMD_DUAL_MIC_PCM_DUMP_STOP: {
1966 if (pReplyData == NULL || replySize == NULL) {
1967 ALOGE("PreProcessingFx_Command cmdCode Case: "
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001968 "PREPROC_CMD_DUAL_MIC_PCM_DUMP_STOP: ERROR");
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001969 *replySize = 0;
1970 return -EINVAL;
1971 }
1972 pthread_mutex_lock(&gPcmDumpLock);
1973 if (gPcmDumpFh != NULL) {
1974 fclose(gPcmDumpFh);
1975 gPcmDumpFh = NULL;
1976 }
1977 pthread_mutex_unlock(&gPcmDumpLock);
1978 ALOGV("PREPROC_CMD_DUAL_MIC_PCM_DUMP_STOP");
1979 *replySize = sizeof(int);
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001980 *(int*)pReplyData = 0;
1981 } break;
1982 ///// test commands end
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001983
1984 case EFFECT_CMD_GET_FEATURE_SUPPORTED_CONFIGS: {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001985 if (!gDualMicEnabled) {
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001986 return -EINVAL;
1987 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001988 if (pCmdData == NULL || cmdSize != 2 * sizeof(uint32_t) || pReplyData == NULL ||
1989 replySize == NULL) {
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001990 ALOGE("PreProcessingFx_Command cmdCode Case: "
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001991 "EFFECT_CMD_GET_FEATURE_SUPPORTED_CONFIGS: ERROR");
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001992 *replySize = 0;
1993 return -EINVAL;
1994 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001995 if (*(uint32_t*)pCmdData != EFFECT_FEATURE_AUX_CHANNELS || !effect->aux_channels_on) {
Eric Laurent3f9c84c2012-04-03 15:36:53 -07001996 ALOGV("PreProcessingFx_Command feature EFFECT_FEATURE_AUX_CHANNELS not supported by"
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08001997 " fx %d",
1998 effect->procId);
1999 *(uint32_t*)pReplyData = -ENOSYS;
Eric Laurent3f9c84c2012-04-03 15:36:53 -07002000 *replySize = sizeof(uint32_t);
2001 break;
2002 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08002003 size_t num_configs = *((uint32_t*)pCmdData + 1);
2004 if (*replySize < (2 * sizeof(uint32_t) + num_configs * sizeof(channel_config_t))) {
Eric Laurent3f9c84c2012-04-03 15:36:53 -07002005 *replySize = 0;
2006 return -EINVAL;
2007 }
2008
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08002009 *((uint32_t*)pReplyData + 1) = CHANNEL_CFG_CNT;
Eric Laurent3f9c84c2012-04-03 15:36:53 -07002010 if (num_configs < CHANNEL_CFG_CNT ||
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08002011 *replySize < (2 * sizeof(uint32_t) + CHANNEL_CFG_CNT * sizeof(channel_config_t))) {
2012 *(uint32_t*)pReplyData = -ENOMEM;
Eric Laurent3f9c84c2012-04-03 15:36:53 -07002013 } else {
2014 num_configs = CHANNEL_CFG_CNT;
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08002015 *(uint32_t*)pReplyData = 0;
Eric Laurent3f9c84c2012-04-03 15:36:53 -07002016 }
2017 ALOGV("PreProcessingFx_Command EFFECT_CMD_GET_FEATURE_SUPPORTED_CONFIGS num config %d",
2018 num_configs);
2019
2020 *replySize = 2 * sizeof(uint32_t) + num_configs * sizeof(channel_config_t);
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08002021 *((uint32_t*)pReplyData + 1) = num_configs;
2022 memcpy((uint32_t*)pReplyData + 2, &sDualMicConfigs,
2023 num_configs * sizeof(channel_config_t));
2024 } break;
Eric Laurent3f9c84c2012-04-03 15:36:53 -07002025 case EFFECT_CMD_GET_FEATURE_CONFIG:
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08002026 if (!gDualMicEnabled) {
Eric Laurent3f9c84c2012-04-03 15:36:53 -07002027 return -EINVAL;
2028 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08002029 if (pCmdData == NULL || cmdSize != sizeof(uint32_t) || pReplyData == NULL ||
2030 replySize == NULL || *replySize < sizeof(uint32_t) + sizeof(channel_config_t)) {
Eric Laurent3f9c84c2012-04-03 15:36:53 -07002031 ALOGE("PreProcessingFx_Command cmdCode Case: "
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08002032 "EFFECT_CMD_GET_FEATURE_CONFIG: ERROR");
Eric Laurent3f9c84c2012-04-03 15:36:53 -07002033 return -EINVAL;
2034 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08002035 if (*(uint32_t*)pCmdData != EFFECT_FEATURE_AUX_CHANNELS || !effect->aux_channels_on) {
2036 *(uint32_t*)pReplyData = -ENOSYS;
Eric Laurent3f9c84c2012-04-03 15:36:53 -07002037 *replySize = sizeof(uint32_t);
2038 break;
2039 }
2040 ALOGV("PreProcessingFx_Command EFFECT_CMD_GET_FEATURE_CONFIG");
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08002041 *(uint32_t*)pReplyData = 0;
Eric Laurent3f9c84c2012-04-03 15:36:53 -07002042 *replySize = sizeof(uint32_t) + sizeof(channel_config_t);
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08002043 memcpy((uint32_t*)pReplyData + 1, &sDualMicConfigs[effect->cur_channel_config],
Eric Laurent3f9c84c2012-04-03 15:36:53 -07002044 sizeof(channel_config_t));
2045 break;
2046 case EFFECT_CMD_SET_FEATURE_CONFIG: {
2047 ALOGV("PreProcessingFx_Command EFFECT_CMD_SET_FEATURE_CONFIG: "
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08002048 "gDualMicEnabled %d effect->aux_channels_on %d",
Eric Laurent3f9c84c2012-04-03 15:36:53 -07002049 gDualMicEnabled, effect->aux_channels_on);
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08002050 if (!gDualMicEnabled) {
Eric Laurent3f9c84c2012-04-03 15:36:53 -07002051 return -EINVAL;
2052 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08002053 if (pCmdData == NULL || cmdSize != (sizeof(uint32_t) + sizeof(channel_config_t)) ||
2054 pReplyData == NULL || replySize == NULL || *replySize < sizeof(uint32_t)) {
Eric Laurent3f9c84c2012-04-03 15:36:53 -07002055 ALOGE("PreProcessingFx_Command cmdCode Case: "
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08002056 "EFFECT_CMD_SET_FEATURE_CONFIG: ERROR\n"
2057 "pCmdData %p cmdSize %d pReplyData %p replySize %p *replySize %d",
2058 pCmdData, cmdSize, pReplyData, replySize, replySize ? *replySize : -1);
Eric Laurent3f9c84c2012-04-03 15:36:53 -07002059 return -EINVAL;
2060 }
2061 *replySize = sizeof(uint32_t);
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08002062 if (*(uint32_t*)pCmdData != EFFECT_FEATURE_AUX_CHANNELS || !effect->aux_channels_on) {
2063 *(uint32_t*)pReplyData = -ENOSYS;
Eric Laurent3f9c84c2012-04-03 15:36:53 -07002064 ALOGV("PreProcessingFx_Command cmdCode Case: "
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08002065 "EFFECT_CMD_SET_FEATURE_CONFIG: ERROR\n"
2066 "CmdData %d effect->aux_channels_on %d",
2067 *(uint32_t*)pCmdData, effect->aux_channels_on);
Eric Laurent3f9c84c2012-04-03 15:36:53 -07002068 break;
2069 }
2070 size_t i;
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08002071 for (i = 0; i < CHANNEL_CFG_CNT; i++) {
2072 if (memcmp((uint32_t*)pCmdData + 1, &sDualMicConfigs[i],
2073 sizeof(channel_config_t)) == 0) {
Eric Laurent3f9c84c2012-04-03 15:36:53 -07002074 break;
2075 }
2076 }
2077 if (i == CHANNEL_CFG_CNT) {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08002078 *(uint32_t*)pReplyData = -EINVAL;
Eric Laurent3f9c84c2012-04-03 15:36:53 -07002079 ALOGW("PreProcessingFx_Command EFFECT_CMD_SET_FEATURE_CONFIG invalid config"
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08002080 "[%08x].[%08x]",
2081 *((uint32_t*)pCmdData + 1), *((uint32_t*)pCmdData + 2));
Eric Laurent3f9c84c2012-04-03 15:36:53 -07002082 } else {
2083 effect->cur_channel_config = i;
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08002084 *(uint32_t*)pReplyData = 0;
Eric Laurent3f9c84c2012-04-03 15:36:53 -07002085 ALOGV("PreProcessingFx_Command EFFECT_CMD_SET_FEATURE_CONFIG New config"
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08002086 "[%08x].[%08x]",
2087 sDualMicConfigs[i].main_channels, sDualMicConfigs[i].aux_channels);
Eric Laurent3f9c84c2012-04-03 15:36:53 -07002088 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08002089 } break;
Eric Laurent3f9c84c2012-04-03 15:36:53 -07002090#endif
Eric Laurenta9390d42011-06-17 20:17:17 -07002091 default:
2092 return -EINVAL;
2093 }
2094 return 0;
2095}
2096
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08002097int PreProcessingFx_GetDescriptor(effect_handle_t self, effect_descriptor_t* pDescriptor) {
2098 preproc_effect_t* effect = (preproc_effect_t*)self;
Eric Laurenta9390d42011-06-17 20:17:17 -07002099
2100 if (effect == NULL || pDescriptor == NULL) {
2101 return -EINVAL;
2102 }
2103
Glenn Kastena189a682012-02-20 12:16:30 -08002104 *pDescriptor = *sDescriptors[effect->procId];
Eric Laurenta9390d42011-06-17 20:17:17 -07002105
2106 return 0;
2107}
2108
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08002109int PreProcessingFx_ProcessReverse(effect_handle_t self, audio_buffer_t* inBuffer,
2110 audio_buffer_t* outBuffer __unused) {
2111 preproc_effect_t* effect = (preproc_effect_t*)self;
Eric Laurenta9390d42011-06-17 20:17:17 -07002112
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08002113 if (effect == NULL) {
Steve Block5ff1dd52012-01-05 23:22:43 +00002114 ALOGW("PreProcessingFx_ProcessReverse() ERROR effect == NULL");
Eric Laurenta9390d42011-06-17 20:17:17 -07002115 return -EINVAL;
2116 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08002117 preproc_session_t* session = (preproc_session_t*)effect->session;
Eric Laurenta9390d42011-06-17 20:17:17 -07002118
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08002119 if (inBuffer == NULL || inBuffer->raw == NULL) {
Steve Block5ff1dd52012-01-05 23:22:43 +00002120 ALOGW("PreProcessingFx_ProcessReverse() ERROR bad pointer");
Eric Laurenta9390d42011-06-17 20:17:17 -07002121 return -EINVAL;
2122 }
2123
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08002124 session->revProcessedMsk |= (1 << effect->procId);
Eric Laurenta9390d42011-06-17 20:17:17 -07002125
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08002126 // ALOGV("PreProcessingFx_ProcessReverse In %d frames revEnabledMsk %08x revProcessedMsk
2127 // %08x",
2128 // inBuffer->frameCount, session->revEnabledMsk, session->revProcessedMsk);
Eric Laurenta9390d42011-06-17 20:17:17 -07002129
2130 if ((session->revProcessedMsk & session->revEnabledMsk) == session->revEnabledMsk) {
2131 effect->session->revProcessedMsk = 0;
Saketh Sathuvalli08337032020-09-22 21:13:45 +05302132#ifdef WEBRTC_LEGACY
Eric Laurenta9390d42011-06-17 20:17:17 -07002133 if (session->revResampler != NULL) {
2134 size_t fr = session->frameCount - session->framesRev;
2135 if (inBuffer->frameCount < fr) {
2136 fr = inBuffer->frameCount;
2137 }
2138 if (session->revBufSize < session->framesRev + fr) {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08002139 int16_t* buf;
Eric Laurenta9390d42011-06-17 20:17:17 -07002140 session->revBufSize = session->framesRev + fr;
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08002141 buf = (int16_t*)realloc(
2142 session->revBuf,
2143 session->revBufSize * session->inChannelCount * sizeof(int16_t));
Eric Laurent679650f2015-08-21 14:01:50 -07002144 if (buf == NULL) {
2145 session->framesRev = 0;
2146 free(session->revBuf);
2147 session->revBuf = NULL;
2148 return -ENOMEM;
2149 }
2150 session->revBuf = buf;
Eric Laurenta9390d42011-06-17 20:17:17 -07002151 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08002152 memcpy(session->revBuf + session->framesRev * session->inChannelCount, inBuffer->s16,
Eric Laurenta9390d42011-06-17 20:17:17 -07002153 fr * session->inChannelCount * sizeof(int16_t));
2154
2155 session->framesRev += fr;
2156 inBuffer->frameCount = fr;
2157 if (session->framesRev < session->frameCount) {
2158 return 0;
2159 }
Kévin PETIT377b2ec2014-02-03 12:35:36 +00002160 spx_uint32_t frIn = session->framesRev;
2161 spx_uint32_t frOut = session->apmFrameCount;
Eric Laurenta9390d42011-06-17 20:17:17 -07002162 if (session->inChannelCount == 1) {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08002163 speex_resampler_process_int(session->revResampler, 0, session->revBuf, &frIn,
2164 session->revFrame->data_, &frOut);
Eric Laurenta9390d42011-06-17 20:17:17 -07002165 } else {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08002166 speex_resampler_process_interleaved_int(session->revResampler, session->revBuf,
2167 &frIn, session->revFrame->data_, &frOut);
Eric Laurenta9390d42011-06-17 20:17:17 -07002168 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08002169 memmove(session->revBuf, session->revBuf + frIn * session->inChannelCount,
Jiabin Huang0c9544a2020-06-04 00:46:19 +00002170 (session->framesRev - frIn) * session->inChannelCount * sizeof(int16_t));
Eric Laurenta9390d42011-06-17 20:17:17 -07002171 session->framesRev -= frIn;
2172 } else {
2173 size_t fr = session->frameCount - session->framesRev;
2174 if (inBuffer->frameCount < fr) {
2175 fr = inBuffer->frameCount;
2176 }
Chih-Hung Hsiehde7fa312015-10-13 10:58:08 -07002177 memcpy(session->revFrame->data_ + session->framesRev * session->inChannelCount,
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08002178 inBuffer->s16, fr * session->inChannelCount * sizeof(int16_t));
Eric Laurenta9390d42011-06-17 20:17:17 -07002179 session->framesRev += fr;
2180 inBuffer->frameCount = fr;
2181 if (session->framesRev < session->frameCount) {
2182 return 0;
2183 }
2184 session->framesRev = 0;
2185 }
Alex Luebs766bf732015-12-14 21:32:13 -08002186 session->revFrame->samples_per_channel_ = session->apmFrameCount;
Eric Laurenta9390d42011-06-17 20:17:17 -07002187 effect->session->apm->AnalyzeReverseStream(session->revFrame);
Saketh Sathuvalli08337032020-09-22 21:13:45 +05302188#else
2189 size_t fr = session->frameCount - session->framesRev;
2190 if (inBuffer->frameCount < fr) {
2191 fr = inBuffer->frameCount;
2192 }
2193 session->framesRev += fr;
2194 inBuffer->frameCount = fr;
2195 if (session->framesRev < session->frameCount) {
2196 return 0;
2197 }
2198 session->framesRev = 0;
2199 if (int status = effect->session->apm->ProcessReverseStream(
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08002200 (const int16_t* const)inBuffer->s16,
2201 (const webrtc::StreamConfig)effect->session->revConfig,
2202 (const webrtc::StreamConfig)effect->session->revConfig,
2203 (int16_t* const)outBuffer->s16);
2204 status != 0) {
Saketh Sathuvalli08337032020-09-22 21:13:45 +05302205 ALOGE("Process Reverse Stream failed with error %d\n", status);
2206 return status;
2207 }
2208#endif
Eric Laurenta9390d42011-06-17 20:17:17 -07002209 return 0;
2210 } else {
2211 return -ENODATA;
2212 }
2213}
2214
Eric Laurenta9390d42011-06-17 20:17:17 -07002215// effect_handle_t interface implementation for effect
2216const struct effect_interface_s sEffectInterface = {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08002217 PreProcessingFx_Process, PreProcessingFx_Command, PreProcessingFx_GetDescriptor, NULL};
Eric Laurenta9390d42011-06-17 20:17:17 -07002218
2219const struct effect_interface_s sEffectInterfaceReverse = {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08002220 PreProcessingFx_Process, PreProcessingFx_Command, PreProcessingFx_GetDescriptor,
2221 PreProcessingFx_ProcessReverse};
Eric Laurenta9390d42011-06-17 20:17:17 -07002222
2223//------------------------------------------------------------------------------
2224// Effect Library Interface Implementation
2225//------------------------------------------------------------------------------
2226
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08002227int PreProcessingLib_Create(const effect_uuid_t* uuid, int32_t sessionId, int32_t ioId,
2228 effect_handle_t* pInterface) {
Steve Block3856b092011-10-20 11:56:00 +01002229 ALOGV("EffectCreate: uuid: %08x session %d IO: %d", uuid->timeLow, sessionId, ioId);
Eric Laurenta9390d42011-06-17 20:17:17 -07002230
2231 int status;
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08002232 const effect_descriptor_t* desc;
2233 preproc_session_t* session;
Eric Laurenta9390d42011-06-17 20:17:17 -07002234 uint32_t procId;
2235
2236 if (PreProc_Init() != 0) {
2237 return sInitStatus;
2238 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08002239 desc = PreProc_GetDescriptor(uuid);
Eric Laurenta9390d42011-06-17 20:17:17 -07002240 if (desc == NULL) {
Steve Block5ff1dd52012-01-05 23:22:43 +00002241 ALOGW("EffectCreate: fx not found uuid: %08x", uuid->timeLow);
Eric Laurenta9390d42011-06-17 20:17:17 -07002242 return -EINVAL;
2243 }
2244 procId = UuidToProcId(&desc->type);
2245
2246 session = PreProc_GetSession(procId, sessionId, ioId);
2247 if (session == NULL) {
Steve Block5ff1dd52012-01-05 23:22:43 +00002248 ALOGW("EffectCreate: no more session available");
Eric Laurenta9390d42011-06-17 20:17:17 -07002249 return -EINVAL;
2250 }
2251
2252 status = Session_CreateEffect(session, procId, pInterface);
2253
2254 if (status < 0 && session->createdMsk == 0) {
Eric Laurentb20cf7d2019-04-05 19:37:34 -07002255 session->id = 0;
Eric Laurenta9390d42011-06-17 20:17:17 -07002256 }
2257 return status;
2258}
2259
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08002260int PreProcessingLib_Release(effect_handle_t interface) {
Steve Block3856b092011-10-20 11:56:00 +01002261 ALOGV("EffectRelease start %p", interface);
Eric Laurenta9390d42011-06-17 20:17:17 -07002262 if (PreProc_Init() != 0) {
2263 return sInitStatus;
2264 }
2265
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08002266 preproc_effect_t* fx = (preproc_effect_t*)interface;
Eric Laurenta9390d42011-06-17 20:17:17 -07002267
Eric Laurentb20cf7d2019-04-05 19:37:34 -07002268 if (fx->session->id == 0) {
Eric Laurenta9390d42011-06-17 20:17:17 -07002269 return -EINVAL;
2270 }
2271 return Session_ReleaseEffect(fx->session, fx);
2272}
2273
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08002274int PreProcessingLib_GetDescriptor(const effect_uuid_t* uuid, effect_descriptor_t* pDescriptor) {
2275 if (pDescriptor == NULL || uuid == NULL) {
Eric Laurenta9390d42011-06-17 20:17:17 -07002276 return -EINVAL;
2277 }
2278
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08002279 const effect_descriptor_t* desc = PreProc_GetDescriptor(uuid);
Eric Laurenta9390d42011-06-17 20:17:17 -07002280 if (desc == NULL) {
Steve Block3856b092011-10-20 11:56:00 +01002281 ALOGV("PreProcessingLib_GetDescriptor() not found");
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08002282 return -EINVAL;
Eric Laurenta9390d42011-06-17 20:17:17 -07002283 }
2284
Steve Block3856b092011-10-20 11:56:00 +01002285 ALOGV("PreProcessingLib_GetDescriptor() got fx %s", desc->name);
Eric Laurenta9390d42011-06-17 20:17:17 -07002286
Glenn Kastena189a682012-02-20 12:16:30 -08002287 *pDescriptor = *desc;
Eric Laurenta9390d42011-06-17 20:17:17 -07002288 return 0;
2289}
2290
Marco Nelissen7f16b192012-10-25 16:05:57 -07002291// This is the only symbol that needs to be exported
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08002292__attribute__((visibility("default"))) audio_effect_library_t AUDIO_EFFECT_LIBRARY_INFO_SYM = {
2293 .tag = AUDIO_EFFECT_LIBRARY_TAG,
2294 .version = EFFECT_LIBRARY_API_VERSION,
2295 .name = "Audio Preprocessing Library",
2296 .implementor = "The Android Open Source Project",
2297 .create_effect = PreProcessingLib_Create,
2298 .release_effect = PreProcessingLib_Release,
2299 .get_descriptor = PreProcessingLib_GetDescriptor};
Eric Laurenta9390d42011-06-17 20:17:17 -07002300
Harish Mahendrakarb6926c72020-11-27 15:22:44 -08002301}; // extern "C"