blob: 5f223c9936c869b712af7ceb9d70f120976d419d [file] [log] [blame]
Saketh Sathuvalli4ece3e02020-07-19 21:19:39 +05301/*
2 * Copyright (C) 2020 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
Saketh Sathuvalli08337032020-09-22 21:13:45 +053017#include <getopt.h>
18#include <stddef.h>
19#include <stdint.h>
20#include <sys/stat.h>
21#include <vector>
22
Saketh Sathuvalli4ece3e02020-07-19 21:19:39 +053023#include <audio_effects/effect_aec.h>
24#include <audio_effects/effect_agc.h>
Saketh Sathuvalli08337032020-09-22 21:13:45 +053025#include <audio_effects/effect_agc2.h>
Saketh Sathuvalli4ece3e02020-07-19 21:19:39 +053026#include <audio_effects/effect_ns.h>
Saketh Sathuvalli4ece3e02020-07-19 21:19:39 +053027#include <log/log.h>
Saketh Sathuvalli4ece3e02020-07-19 21:19:39 +053028
29// This is the only symbol that needs to be imported
30extern audio_effect_library_t AUDIO_EFFECT_LIBRARY_INFO_SYM;
31
32//------------------------------------------------------------------------------
33// local definitions
34//------------------------------------------------------------------------------
35
36// types of pre processing modules
37enum PreProcId {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -080038 PREPROC_AGC, // Automatic Gain Control
Harish Mahendrakarb6926c72020-11-27 15:22:44 -080039 PREPROC_AGC2, // Automatic Gain Control 2
Harish Mahendrakarb6926c72020-11-27 15:22:44 -080040 PREPROC_AEC, // Acoustic Echo Canceler
41 PREPROC_NS, // Noise Suppressor
42 PREPROC_NUM_EFFECTS
Saketh Sathuvalli4ece3e02020-07-19 21:19:39 +053043};
44
45enum PreProcParams {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -080046 ARG_HELP = 1,
47 ARG_INPUT,
48 ARG_OUTPUT,
49 ARG_FAR,
50 ARG_FS,
51 ARG_CH_MASK,
52 ARG_AGC_TGT_LVL,
53 ARG_AGC_COMP_LVL,
54 ARG_AEC_DELAY,
55 ARG_NS_LVL,
Harish Mahendrakarb6926c72020-11-27 15:22:44 -080056 ARG_AGC2_GAIN,
57 ARG_AGC2_LVL,
58 ARG_AGC2_SAT_MGN
Saketh Sathuvalli4ece3e02020-07-19 21:19:39 +053059};
60
61struct preProcConfigParams_t {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -080062 int samplingFreq = 16000;
63 audio_channel_mask_t chMask = AUDIO_CHANNEL_IN_MONO;
64 int nsLevel = 0; // a value between 0-3
65 int agcTargetLevel = 3; // in dB
66 int agcCompLevel = 9; // in dB
Harish Mahendrakarb6926c72020-11-27 15:22:44 -080067 float agc2Gain = 0.f; // in dB
68 float agc2SaturationMargin = 2.f; // in dB
69 int agc2Level = 0; // either kRms(0) or kPeak(1)
Harish Mahendrakarb6926c72020-11-27 15:22:44 -080070 int aecDelay = 0; // in ms
Saketh Sathuvalli4ece3e02020-07-19 21:19:39 +053071};
72
73const effect_uuid_t kPreProcUuids[PREPROC_NUM_EFFECTS] = {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -080074 {0xaa8130e0, 0x66fc, 0x11e0, 0xbad0, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, // agc uuid
Harish Mahendrakarb6926c72020-11-27 15:22:44 -080075 {0x89f38e65, 0xd4d2, 0x4d64, 0xad0e, {0x2b, 0x3e, 0x79, 0x9e, 0xa8, 0x86}}, // agc2 uuid
Harish Mahendrakarb6926c72020-11-27 15:22:44 -080076 {0xbb392ec0, 0x8d4d, 0x11e0, 0xa896, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, // aec uuid
77 {0xc06c8400, 0x8e06, 0x11e0, 0x9cb6, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, // ns uuid
Saketh Sathuvalli4ece3e02020-07-19 21:19:39 +053078};
79
80constexpr audio_channel_mask_t kPreProcConfigChMask[] = {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -080081 AUDIO_CHANNEL_IN_MONO,
82 AUDIO_CHANNEL_IN_STEREO,
83 AUDIO_CHANNEL_IN_FRONT_BACK,
84 AUDIO_CHANNEL_IN_6,
85 AUDIO_CHANNEL_IN_2POINT0POINT2,
86 AUDIO_CHANNEL_IN_2POINT1POINT2,
87 AUDIO_CHANNEL_IN_3POINT0POINT2,
88 AUDIO_CHANNEL_IN_3POINT1POINT2,
89 AUDIO_CHANNEL_IN_5POINT1,
90 AUDIO_CHANNEL_IN_VOICE_UPLINK_MONO,
91 AUDIO_CHANNEL_IN_VOICE_DNLINK_MONO,
92 AUDIO_CHANNEL_IN_VOICE_CALL_MONO,
Saketh Sathuvalli4ece3e02020-07-19 21:19:39 +053093};
94
95constexpr int kPreProcConfigChMaskCount = std::size(kPreProcConfigChMask);
96
97void printUsage() {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -080098 printf("\nUsage: ");
99 printf("\n <executable> [options]\n");
100 printf("\nwhere options are, ");
101 printf("\n --input <inputfile>");
102 printf("\n path to the input file");
103 printf("\n --output <outputfile>");
104 printf("\n path to the output file");
105 printf("\n --help");
106 printf("\n Prints this usage information");
107 printf("\n --fs <sampling_freq>");
108 printf("\n Sampling frequency in Hz, default 16000.");
109 printf("\n -ch_mask <channel_mask>\n");
110 printf("\n 0 - AUDIO_CHANNEL_IN_MONO");
111 printf("\n 1 - AUDIO_CHANNEL_IN_STEREO");
112 printf("\n 2 - AUDIO_CHANNEL_IN_FRONT_BACK");
113 printf("\n 3 - AUDIO_CHANNEL_IN_6");
114 printf("\n 4 - AUDIO_CHANNEL_IN_2POINT0POINT2");
115 printf("\n 5 - AUDIO_CHANNEL_IN_2POINT1POINT2");
116 printf("\n 6 - AUDIO_CHANNEL_IN_3POINT0POINT2");
117 printf("\n 7 - AUDIO_CHANNEL_IN_3POINT1POINT2");
118 printf("\n 8 - AUDIO_CHANNEL_IN_5POINT1");
119 printf("\n 9 - AUDIO_CHANNEL_IN_VOICE_UPLINK_MONO");
120 printf("\n 10 - AUDIO_CHANNEL_IN_VOICE_DNLINK_MONO ");
121 printf("\n 11 - AUDIO_CHANNEL_IN_VOICE_CALL_MONO ");
122 printf("\n default 0");
123 printf("\n --far <farend_file>");
124 printf("\n Path to far-end file needed for echo cancellation");
125 printf("\n --aec");
126 printf("\n Enable Echo Cancellation, default disabled");
127 printf("\n --ns");
128 printf("\n Enable Noise Suppression, default disabled");
129 printf("\n --agc");
130 printf("\n Enable Gain Control, default disabled");
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800131 printf("\n --agc2");
132 printf("\n Enable Gain Controller 2, default disabled");
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800133 printf("\n --ns_lvl <ns_level>");
134 printf("\n Noise Suppression level in dB, default value 0dB");
135 printf("\n --agc_tgt_lvl <target_level>");
136 printf("\n AGC Target Level in dB, default value 3dB");
137 printf("\n --agc_comp_lvl <comp_level>");
138 printf("\n AGC Comp Level in dB, default value 9dB");
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800139 printf("\n --agc2_gain <fixed_digital_gain>");
140 printf("\n AGC Fixed Digital Gain in dB, default value 0dB");
141 printf("\n --agc2_lvl <level_estimator>");
142 printf("\n AGC Adaptive Digital Level Estimator, default value kRms");
143 printf("\n --agc2_sat_mgn <saturation_margin>");
144 printf("\n AGC Adaptive Digital Saturation Margin in dB, default value 2dB");
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800145 printf("\n --aec_delay <delay>");
146 printf("\n AEC delay value in ms, default value 0ms");
147 printf("\n");
Saketh Sathuvalli4ece3e02020-07-19 21:19:39 +0530148}
149
150constexpr float kTenMilliSecVal = 0.01;
151
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800152int preProcCreateEffect(effect_handle_t* pEffectHandle, uint32_t effectType,
153 effect_config_t* pConfig, int sessionId, int ioId) {
154 if (int status = AUDIO_EFFECT_LIBRARY_INFO_SYM.create_effect(&kPreProcUuids[effectType],
155 sessionId, ioId, pEffectHandle);
156 status != 0) {
157 ALOGE("Audio Preprocessing create returned an error = %d\n", status);
158 return EXIT_FAILURE;
159 }
160 int reply = 0;
161 uint32_t replySize = sizeof(reply);
162 if (effectType == PREPROC_AEC) {
163 (**pEffectHandle)
164 ->command(*pEffectHandle, EFFECT_CMD_SET_CONFIG_REVERSE, sizeof(effect_config_t),
165 pConfig, &replySize, &reply);
166 }
Saketh Sathuvalli4ece3e02020-07-19 21:19:39 +0530167 (**pEffectHandle)
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800168 ->command(*pEffectHandle, EFFECT_CMD_SET_CONFIG, sizeof(effect_config_t), pConfig,
169 &replySize, &reply);
170 return reply;
Saketh Sathuvalli4ece3e02020-07-19 21:19:39 +0530171}
172
173int preProcSetConfigParam(uint32_t paramType, uint32_t paramValue, effect_handle_t effectHandle) {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800174 int reply = 0;
175 uint32_t replySize = sizeof(reply);
176 uint32_t paramData[2] = {paramType, paramValue};
177 effect_param_t* effectParam = (effect_param_t*)malloc(sizeof(*effectParam) + sizeof(paramData));
178 memcpy(&effectParam->data[0], &paramData[0], sizeof(paramData));
179 effectParam->psize = sizeof(paramData[0]);
180 (*effectHandle)
181 ->command(effectHandle, EFFECT_CMD_SET_PARAM, sizeof(effect_param_t), effectParam,
182 &replySize, &reply);
183 free(effectParam);
184 return reply;
Saketh Sathuvalli4ece3e02020-07-19 21:19:39 +0530185}
186
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800187int main(int argc, const char* argv[]) {
188 if (argc == 1) {
Saketh Sathuvalli4ece3e02020-07-19 21:19:39 +0530189 printUsage();
Saketh Sathuvalli4ece3e02020-07-19 21:19:39 +0530190 return EXIT_FAILURE;
Saketh Sathuvalli4ece3e02020-07-19 21:19:39 +0530191 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800192 const char* inputFile = nullptr;
193 const char* outputFile = nullptr;
194 const char* farFile = nullptr;
195 int effectEn[PREPROC_NUM_EFFECTS] = {0};
Saketh Sathuvalli4ece3e02020-07-19 21:19:39 +0530196
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800197 const option long_opts[] = {
198 {"help", no_argument, nullptr, ARG_HELP},
199 {"input", required_argument, nullptr, ARG_INPUT},
200 {"output", required_argument, nullptr, ARG_OUTPUT},
201 {"far", required_argument, nullptr, ARG_FAR},
202 {"fs", required_argument, nullptr, ARG_FS},
203 {"ch_mask", required_argument, nullptr, ARG_CH_MASK},
204 {"agc_tgt_lvl", required_argument, nullptr, ARG_AGC_TGT_LVL},
205 {"agc_comp_lvl", required_argument, nullptr, ARG_AGC_COMP_LVL},
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800206 {"agc2_gain", required_argument, nullptr, ARG_AGC2_GAIN},
207 {"agc2_lvl", required_argument, nullptr, ARG_AGC2_LVL},
208 {"agc2_sat_mgn", required_argument, nullptr, ARG_AGC2_SAT_MGN},
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800209 {"aec_delay", required_argument, nullptr, ARG_AEC_DELAY},
210 {"ns_lvl", required_argument, nullptr, ARG_NS_LVL},
211 {"aec", no_argument, &effectEn[PREPROC_AEC], 1},
212 {"agc", no_argument, &effectEn[PREPROC_AGC], 1},
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800213 {"agc2", no_argument, &effectEn[PREPROC_AGC2], 1},
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800214 {"ns", no_argument, &effectEn[PREPROC_NS], 1},
215 {nullptr, 0, nullptr, 0},
216 };
217 struct preProcConfigParams_t preProcCfgParams {};
Saketh Sathuvalli4ece3e02020-07-19 21:19:39 +0530218
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800219 while (true) {
220 const int opt = getopt_long(argc, (char* const*)argv, "i:o:", long_opts, nullptr);
221 if (opt == -1) {
222 break;
223 }
224 switch (opt) {
225 case ARG_HELP:
226 printUsage();
227 return 0;
228 case ARG_INPUT: {
229 inputFile = (char*)optarg;
230 break;
231 }
232 case ARG_OUTPUT: {
233 outputFile = (char*)optarg;
234 break;
235 }
236 case ARG_FAR: {
237 farFile = (char*)optarg;
238 break;
239 }
240 case ARG_FS: {
241 preProcCfgParams.samplingFreq = atoi(optarg);
242 break;
243 }
244 case ARG_CH_MASK: {
245 int chMaskIdx = atoi(optarg);
246 if (chMaskIdx < 0 or chMaskIdx > kPreProcConfigChMaskCount) {
247 ALOGE("Channel Mask index not in correct range\n");
248 printUsage();
249 return EXIT_FAILURE;
250 }
251 preProcCfgParams.chMask = kPreProcConfigChMask[chMaskIdx];
252 break;
253 }
254 case ARG_AGC_TGT_LVL: {
255 preProcCfgParams.agcTargetLevel = atoi(optarg);
256 break;
257 }
258 case ARG_AGC_COMP_LVL: {
259 preProcCfgParams.agcCompLevel = atoi(optarg);
260 break;
261 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800262 case ARG_AGC2_GAIN: {
263 preProcCfgParams.agc2Gain = atof(optarg);
264 break;
265 }
266 case ARG_AGC2_LVL: {
267 preProcCfgParams.agc2Level = atoi(optarg);
268 break;
269 }
270 case ARG_AGC2_SAT_MGN: {
271 preProcCfgParams.agc2SaturationMargin = atof(optarg);
272 break;
273 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800274 case ARG_AEC_DELAY: {
275 preProcCfgParams.aecDelay = atoi(optarg);
276 break;
277 }
278 case ARG_NS_LVL: {
279 preProcCfgParams.nsLevel = atoi(optarg);
280 break;
281 }
282 default:
283 break;
284 }
Saketh Sathuvalli4ece3e02020-07-19 21:19:39 +0530285 }
Saketh Sathuvalli4ece3e02020-07-19 21:19:39 +0530286
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800287 if (inputFile == nullptr) {
288 ALOGE("Error: missing input file\n");
289 printUsage();
290 return EXIT_FAILURE;
291 }
292
293 std::unique_ptr<FILE, decltype(&fclose)> inputFp(fopen(inputFile, "rb"), &fclose);
294 if (inputFp == nullptr) {
295 ALOGE("Cannot open input file %s\n", inputFile);
296 return EXIT_FAILURE;
297 }
298
299 std::unique_ptr<FILE, decltype(&fclose)> farFp(fopen(farFile, "rb"), &fclose);
300 std::unique_ptr<FILE, decltype(&fclose)> outputFp(fopen(outputFile, "wb"), &fclose);
301 if (effectEn[PREPROC_AEC]) {
302 if (farFile == nullptr) {
303 ALOGE("Far end signal file required for echo cancellation \n");
304 return EXIT_FAILURE;
305 }
306 if (farFp == nullptr) {
307 ALOGE("Cannot open far end stream file %s\n", farFile);
308 return EXIT_FAILURE;
309 }
310 struct stat statInput, statFar;
311 (void)fstat(fileno(inputFp.get()), &statInput);
312 (void)fstat(fileno(farFp.get()), &statFar);
313 if (statInput.st_size != statFar.st_size) {
314 ALOGE("Near and far end signals are of different sizes");
315 return EXIT_FAILURE;
316 }
317 }
318 if (outputFile != nullptr && outputFp == nullptr) {
319 ALOGE("Cannot open output file %s\n", outputFile);
320 return EXIT_FAILURE;
321 }
322
323 int32_t sessionId = 1;
324 int32_t ioId = 1;
325 effect_handle_t effectHandle[PREPROC_NUM_EFFECTS] = {nullptr};
326 effect_config_t config;
327 config.inputCfg.samplingRate = config.outputCfg.samplingRate = preProcCfgParams.samplingFreq;
328 config.inputCfg.channels = config.outputCfg.channels = preProcCfgParams.chMask;
329 config.inputCfg.format = config.outputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
330
331 // Create all the effect handles
332 for (int i = 0; i < PREPROC_NUM_EFFECTS; i++) {
333 if (int status = preProcCreateEffect(&effectHandle[i], i, &config, sessionId, ioId);
334 status != 0) {
335 ALOGE("Create effect call returned error %i", status);
336 return EXIT_FAILURE;
337 }
Saketh Sathuvalli4ece3e02020-07-19 21:19:39 +0530338 }
339
340 for (int i = 0; i < PREPROC_NUM_EFFECTS; i++) {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800341 if (effectEn[i] == 1) {
342 int reply = 0;
343 uint32_t replySize = sizeof(reply);
344 (*effectHandle[i])
345 ->command(effectHandle[i], EFFECT_CMD_ENABLE, 0, nullptr, &replySize, &reply);
346 if (reply != 0) {
347 ALOGE("Command enable call returned error %d\n", reply);
348 return EXIT_FAILURE;
349 }
Saketh Sathuvalli4ece3e02020-07-19 21:19:39 +0530350 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800351 }
352
353 // Set Config Params of the effects
354 if (effectEn[PREPROC_AGC]) {
355 if (int status = preProcSetConfigParam(AGC_PARAM_TARGET_LEVEL,
356 (uint32_t)preProcCfgParams.agcTargetLevel,
357 effectHandle[PREPROC_AGC]);
Saketh Sathuvalli4ece3e02020-07-19 21:19:39 +0530358 status != 0) {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800359 ALOGE("Invalid AGC Target Level. Error %d\n", status);
Saketh Sathuvalli4ece3e02020-07-19 21:19:39 +0530360 return EXIT_FAILURE;
Saketh Sathuvalli4ece3e02020-07-19 21:19:39 +0530361 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800362 if (int status = preProcSetConfigParam(AGC_PARAM_COMP_GAIN,
363 (uint32_t)preProcCfgParams.agcCompLevel,
364 effectHandle[PREPROC_AGC]);
365 status != 0) {
366 ALOGE("Invalid AGC Comp Gain. Error %d\n", status);
367 return EXIT_FAILURE;
368 }
Saketh Sathuvalli4ece3e02020-07-19 21:19:39 +0530369 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800370 if (effectEn[PREPROC_AGC2]) {
371 if (int status = preProcSetConfigParam(AGC2_PARAM_FIXED_DIGITAL_GAIN,
372 (float)preProcCfgParams.agc2Gain,
373 effectHandle[PREPROC_AGC2]);
374 status != 0) {
375 ALOGE("Invalid AGC2 Fixed Digital Gain. Error %d\n", status);
376 return EXIT_FAILURE;
377 }
378 if (int status = preProcSetConfigParam(AGC2_PARAM_ADAPT_DIGI_LEVEL_ESTIMATOR,
379 (uint32_t)preProcCfgParams.agc2Level,
380 effectHandle[PREPROC_AGC2]);
381 status != 0) {
382 ALOGE("Invalid AGC2 Level Estimator. Error %d\n", status);
383 return EXIT_FAILURE;
384 }
385 if (int status = preProcSetConfigParam(AGC2_PARAM_ADAPT_DIGI_EXTRA_SATURATION_MARGIN,
386 (float)preProcCfgParams.agc2SaturationMargin,
387 effectHandle[PREPROC_AGC2]);
388 status != 0) {
389 ALOGE("Invalid AGC2 Saturation Margin. Error %d\n", status);
390 return EXIT_FAILURE;
391 }
Saketh Sathuvalli4ece3e02020-07-19 21:19:39 +0530392 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800393 if (effectEn[PREPROC_NS]) {
394 if (int status = preProcSetConfigParam(NS_PARAM_LEVEL, (uint32_t)preProcCfgParams.nsLevel,
395 effectHandle[PREPROC_NS]);
396 status != 0) {
397 ALOGE("Invalid Noise Suppression level Error %d\n", status);
398 return EXIT_FAILURE;
399 }
Saketh Sathuvalli4ece3e02020-07-19 21:19:39 +0530400 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800401
402 // Process Call
403 const int frameLength = (int)(preProcCfgParams.samplingFreq * kTenMilliSecVal);
404 const int ioChannelCount = audio_channel_count_from_in_mask(preProcCfgParams.chMask);
405 const int ioFrameSize = ioChannelCount * sizeof(short);
406 int frameCounter = 0;
407 while (true) {
408 std::vector<short> in(frameLength * ioChannelCount);
409 std::vector<short> out(frameLength * ioChannelCount);
410 std::vector<short> farIn(frameLength * ioChannelCount);
411 size_t samplesRead = fread(in.data(), ioFrameSize, frameLength, inputFp.get());
412 if (samplesRead == 0) {
413 break;
414 }
415 audio_buffer_t inputBuffer, outputBuffer;
416 audio_buffer_t farInBuffer{};
417 inputBuffer.frameCount = samplesRead;
418 outputBuffer.frameCount = samplesRead;
419 inputBuffer.s16 = in.data();
420 outputBuffer.s16 = out.data();
421
422 if (farFp != nullptr) {
423 samplesRead = fread(farIn.data(), ioFrameSize, frameLength, farFp.get());
424 if (samplesRead == 0) {
425 break;
426 }
427 farInBuffer.frameCount = samplesRead;
428 farInBuffer.s16 = farIn.data();
429 }
430
431 for (int i = 0; i < PREPROC_NUM_EFFECTS; i++) {
432 if (effectEn[i] == 1) {
433 if (i == PREPROC_AEC) {
434 if (int status = preProcSetConfigParam(AEC_PARAM_ECHO_DELAY,
435 (uint32_t)preProcCfgParams.aecDelay,
436 effectHandle[PREPROC_AEC]);
437 status != 0) {
438 ALOGE("preProcSetConfigParam returned Error %d\n", status);
439 return EXIT_FAILURE;
440 }
441 }
442 if (int status = (*effectHandle[i])
443 ->process(effectHandle[i], &inputBuffer, &outputBuffer);
444 status != 0) {
445 ALOGE("\nError: Process i = %d returned with error %d\n", i, status);
446 return EXIT_FAILURE;
447 }
448 if (i == PREPROC_AEC) {
449 if (int status = (*effectHandle[i])
450 ->process_reverse(effectHandle[i], &farInBuffer,
451 &outputBuffer);
452 status != 0) {
453 ALOGE("\nError: Process reverse i = %d returned with error %d\n", i,
454 status);
455 return EXIT_FAILURE;
456 }
457 }
458 }
459 }
460 if (outputFp != nullptr) {
461 size_t samplesWritten =
462 fwrite(out.data(), ioFrameSize, outputBuffer.frameCount, outputFp.get());
463 if (samplesWritten != outputBuffer.frameCount) {
464 ALOGE("\nError: Output file writing failed");
465 break;
466 }
467 }
468 frameCounter += frameLength;
469 }
470 // Release all the effect handles created
471 for (int i = 0; i < PREPROC_NUM_EFFECTS; i++) {
472 if (int status = AUDIO_EFFECT_LIBRARY_INFO_SYM.release_effect(effectHandle[i]);
473 status != 0) {
474 ALOGE("Audio Preprocessing release returned an error = %d\n", status);
475 return EXIT_FAILURE;
476 }
477 }
478 return EXIT_SUCCESS;
Saketh Sathuvalli4ece3e02020-07-19 21:19:39 +0530479}