blob: 65b9469ab8439fb730d459b1de60658847710a56 [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#ifndef WEBRTC_LEGACY
26#include <audio_effects/effect_agc2.h>
27#endif
Saketh Sathuvalli4ece3e02020-07-19 21:19:39 +053028#include <audio_effects/effect_ns.h>
Saketh Sathuvalli4ece3e02020-07-19 21:19:39 +053029#include <log/log.h>
Saketh Sathuvalli4ece3e02020-07-19 21:19:39 +053030
31// This is the only symbol that needs to be imported
32extern audio_effect_library_t AUDIO_EFFECT_LIBRARY_INFO_SYM;
33
34//------------------------------------------------------------------------------
35// local definitions
36//------------------------------------------------------------------------------
37
38// types of pre processing modules
39enum PreProcId {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -080040 PREPROC_AGC, // Automatic Gain Control
Saketh Sathuvalli08337032020-09-22 21:13:45 +053041#ifndef WEBRTC_LEGACY
Harish Mahendrakarb6926c72020-11-27 15:22:44 -080042 PREPROC_AGC2, // Automatic Gain Control 2
Saketh Sathuvalli08337032020-09-22 21:13:45 +053043#endif
Harish Mahendrakarb6926c72020-11-27 15:22:44 -080044 PREPROC_AEC, // Acoustic Echo Canceler
45 PREPROC_NS, // Noise Suppressor
46 PREPROC_NUM_EFFECTS
Saketh Sathuvalli4ece3e02020-07-19 21:19:39 +053047};
48
49enum PreProcParams {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -080050 ARG_HELP = 1,
51 ARG_INPUT,
52 ARG_OUTPUT,
53 ARG_FAR,
54 ARG_FS,
55 ARG_CH_MASK,
56 ARG_AGC_TGT_LVL,
57 ARG_AGC_COMP_LVL,
58 ARG_AEC_DELAY,
59 ARG_NS_LVL,
Saketh Sathuvalli08337032020-09-22 21:13:45 +053060#ifndef WEBRTC_LEGACY
Harish Mahendrakarb6926c72020-11-27 15:22:44 -080061 ARG_AGC2_GAIN,
62 ARG_AGC2_LVL,
63 ARG_AGC2_SAT_MGN
Saketh Sathuvalli08337032020-09-22 21:13:45 +053064#endif
Saketh Sathuvalli4ece3e02020-07-19 21:19:39 +053065};
66
67struct preProcConfigParams_t {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -080068 int samplingFreq = 16000;
69 audio_channel_mask_t chMask = AUDIO_CHANNEL_IN_MONO;
70 int nsLevel = 0; // a value between 0-3
71 int agcTargetLevel = 3; // in dB
72 int agcCompLevel = 9; // in dB
Saketh Sathuvalli08337032020-09-22 21:13:45 +053073#ifndef WEBRTC_LEGACY
Harish Mahendrakarb6926c72020-11-27 15:22:44 -080074 float agc2Gain = 0.f; // in dB
75 float agc2SaturationMargin = 2.f; // in dB
76 int agc2Level = 0; // either kRms(0) or kPeak(1)
Saketh Sathuvalli08337032020-09-22 21:13:45 +053077#endif
Harish Mahendrakarb6926c72020-11-27 15:22:44 -080078 int aecDelay = 0; // in ms
Saketh Sathuvalli4ece3e02020-07-19 21:19:39 +053079};
80
81const effect_uuid_t kPreProcUuids[PREPROC_NUM_EFFECTS] = {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -080082 {0xaa8130e0, 0x66fc, 0x11e0, 0xbad0, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, // agc uuid
Saketh Sathuvalli08337032020-09-22 21:13:45 +053083#ifndef WEBRTC_LEGACY
Harish Mahendrakarb6926c72020-11-27 15:22:44 -080084 {0x89f38e65, 0xd4d2, 0x4d64, 0xad0e, {0x2b, 0x3e, 0x79, 0x9e, 0xa8, 0x86}}, // agc2 uuid
Saketh Sathuvalli08337032020-09-22 21:13:45 +053085#endif
Harish Mahendrakarb6926c72020-11-27 15:22:44 -080086 {0xbb392ec0, 0x8d4d, 0x11e0, 0xa896, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, // aec uuid
87 {0xc06c8400, 0x8e06, 0x11e0, 0x9cb6, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, // ns uuid
Saketh Sathuvalli4ece3e02020-07-19 21:19:39 +053088};
89
90constexpr audio_channel_mask_t kPreProcConfigChMask[] = {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -080091 AUDIO_CHANNEL_IN_MONO,
92 AUDIO_CHANNEL_IN_STEREO,
93 AUDIO_CHANNEL_IN_FRONT_BACK,
94 AUDIO_CHANNEL_IN_6,
95 AUDIO_CHANNEL_IN_2POINT0POINT2,
96 AUDIO_CHANNEL_IN_2POINT1POINT2,
97 AUDIO_CHANNEL_IN_3POINT0POINT2,
98 AUDIO_CHANNEL_IN_3POINT1POINT2,
99 AUDIO_CHANNEL_IN_5POINT1,
100 AUDIO_CHANNEL_IN_VOICE_UPLINK_MONO,
101 AUDIO_CHANNEL_IN_VOICE_DNLINK_MONO,
102 AUDIO_CHANNEL_IN_VOICE_CALL_MONO,
Saketh Sathuvalli4ece3e02020-07-19 21:19:39 +0530103};
104
105constexpr int kPreProcConfigChMaskCount = std::size(kPreProcConfigChMask);
106
107void printUsage() {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800108 printf("\nUsage: ");
109 printf("\n <executable> [options]\n");
110 printf("\nwhere options are, ");
111 printf("\n --input <inputfile>");
112 printf("\n path to the input file");
113 printf("\n --output <outputfile>");
114 printf("\n path to the output file");
115 printf("\n --help");
116 printf("\n Prints this usage information");
117 printf("\n --fs <sampling_freq>");
118 printf("\n Sampling frequency in Hz, default 16000.");
119 printf("\n -ch_mask <channel_mask>\n");
120 printf("\n 0 - AUDIO_CHANNEL_IN_MONO");
121 printf("\n 1 - AUDIO_CHANNEL_IN_STEREO");
122 printf("\n 2 - AUDIO_CHANNEL_IN_FRONT_BACK");
123 printf("\n 3 - AUDIO_CHANNEL_IN_6");
124 printf("\n 4 - AUDIO_CHANNEL_IN_2POINT0POINT2");
125 printf("\n 5 - AUDIO_CHANNEL_IN_2POINT1POINT2");
126 printf("\n 6 - AUDIO_CHANNEL_IN_3POINT0POINT2");
127 printf("\n 7 - AUDIO_CHANNEL_IN_3POINT1POINT2");
128 printf("\n 8 - AUDIO_CHANNEL_IN_5POINT1");
129 printf("\n 9 - AUDIO_CHANNEL_IN_VOICE_UPLINK_MONO");
130 printf("\n 10 - AUDIO_CHANNEL_IN_VOICE_DNLINK_MONO ");
131 printf("\n 11 - AUDIO_CHANNEL_IN_VOICE_CALL_MONO ");
132 printf("\n default 0");
133 printf("\n --far <farend_file>");
134 printf("\n Path to far-end file needed for echo cancellation");
135 printf("\n --aec");
136 printf("\n Enable Echo Cancellation, default disabled");
137 printf("\n --ns");
138 printf("\n Enable Noise Suppression, default disabled");
139 printf("\n --agc");
140 printf("\n Enable Gain Control, default disabled");
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530141#ifndef WEBRTC_LEGACY
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800142 printf("\n --agc2");
143 printf("\n Enable Gain Controller 2, default disabled");
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530144#endif
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800145 printf("\n --ns_lvl <ns_level>");
146 printf("\n Noise Suppression level in dB, default value 0dB");
147 printf("\n --agc_tgt_lvl <target_level>");
148 printf("\n AGC Target Level in dB, default value 3dB");
149 printf("\n --agc_comp_lvl <comp_level>");
150 printf("\n AGC Comp Level in dB, default value 9dB");
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530151#ifndef WEBRTC_LEGACY
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800152 printf("\n --agc2_gain <fixed_digital_gain>");
153 printf("\n AGC Fixed Digital Gain in dB, default value 0dB");
154 printf("\n --agc2_lvl <level_estimator>");
155 printf("\n AGC Adaptive Digital Level Estimator, default value kRms");
156 printf("\n --agc2_sat_mgn <saturation_margin>");
157 printf("\n AGC Adaptive Digital Saturation Margin in dB, default value 2dB");
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530158#endif
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800159 printf("\n --aec_delay <delay>");
160 printf("\n AEC delay value in ms, default value 0ms");
161 printf("\n");
Saketh Sathuvalli4ece3e02020-07-19 21:19:39 +0530162}
163
164constexpr float kTenMilliSecVal = 0.01;
165
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800166int preProcCreateEffect(effect_handle_t* pEffectHandle, uint32_t effectType,
167 effect_config_t* pConfig, int sessionId, int ioId) {
168 if (int status = AUDIO_EFFECT_LIBRARY_INFO_SYM.create_effect(&kPreProcUuids[effectType],
169 sessionId, ioId, pEffectHandle);
170 status != 0) {
171 ALOGE("Audio Preprocessing create returned an error = %d\n", status);
172 return EXIT_FAILURE;
173 }
174 int reply = 0;
175 uint32_t replySize = sizeof(reply);
176 if (effectType == PREPROC_AEC) {
177 (**pEffectHandle)
178 ->command(*pEffectHandle, EFFECT_CMD_SET_CONFIG_REVERSE, sizeof(effect_config_t),
179 pConfig, &replySize, &reply);
180 }
Saketh Sathuvalli4ece3e02020-07-19 21:19:39 +0530181 (**pEffectHandle)
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800182 ->command(*pEffectHandle, EFFECT_CMD_SET_CONFIG, sizeof(effect_config_t), pConfig,
183 &replySize, &reply);
184 return reply;
Saketh Sathuvalli4ece3e02020-07-19 21:19:39 +0530185}
186
187int preProcSetConfigParam(uint32_t paramType, uint32_t paramValue, effect_handle_t effectHandle) {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800188 int reply = 0;
189 uint32_t replySize = sizeof(reply);
190 uint32_t paramData[2] = {paramType, paramValue};
191 effect_param_t* effectParam = (effect_param_t*)malloc(sizeof(*effectParam) + sizeof(paramData));
192 memcpy(&effectParam->data[0], &paramData[0], sizeof(paramData));
193 effectParam->psize = sizeof(paramData[0]);
194 (*effectHandle)
195 ->command(effectHandle, EFFECT_CMD_SET_PARAM, sizeof(effect_param_t), effectParam,
196 &replySize, &reply);
197 free(effectParam);
198 return reply;
Saketh Sathuvalli4ece3e02020-07-19 21:19:39 +0530199}
200
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800201int main(int argc, const char* argv[]) {
202 if (argc == 1) {
Saketh Sathuvalli4ece3e02020-07-19 21:19:39 +0530203 printUsage();
Saketh Sathuvalli4ece3e02020-07-19 21:19:39 +0530204 return EXIT_FAILURE;
Saketh Sathuvalli4ece3e02020-07-19 21:19:39 +0530205 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800206 const char* inputFile = nullptr;
207 const char* outputFile = nullptr;
208 const char* farFile = nullptr;
209 int effectEn[PREPROC_NUM_EFFECTS] = {0};
Saketh Sathuvalli4ece3e02020-07-19 21:19:39 +0530210
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800211 const option long_opts[] = {
212 {"help", no_argument, nullptr, ARG_HELP},
213 {"input", required_argument, nullptr, ARG_INPUT},
214 {"output", required_argument, nullptr, ARG_OUTPUT},
215 {"far", required_argument, nullptr, ARG_FAR},
216 {"fs", required_argument, nullptr, ARG_FS},
217 {"ch_mask", required_argument, nullptr, ARG_CH_MASK},
218 {"agc_tgt_lvl", required_argument, nullptr, ARG_AGC_TGT_LVL},
219 {"agc_comp_lvl", required_argument, nullptr, ARG_AGC_COMP_LVL},
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530220#ifndef WEBRTC_LEGACY
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800221 {"agc2_gain", required_argument, nullptr, ARG_AGC2_GAIN},
222 {"agc2_lvl", required_argument, nullptr, ARG_AGC2_LVL},
223 {"agc2_sat_mgn", required_argument, nullptr, ARG_AGC2_SAT_MGN},
Saketh Sathuvalli08337032020-09-22 21:13:45 +0530224#endif
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800225 {"aec_delay", required_argument, nullptr, ARG_AEC_DELAY},
226 {"ns_lvl", required_argument, nullptr, ARG_NS_LVL},
227 {"aec", no_argument, &effectEn[PREPROC_AEC], 1},
228 {"agc", no_argument, &effectEn[PREPROC_AGC], 1},
229#ifndef WEBRTC_LEGACY
230 {"agc2", no_argument, &effectEn[PREPROC_AGC2], 1},
231#endif
232 {"ns", no_argument, &effectEn[PREPROC_NS], 1},
233 {nullptr, 0, nullptr, 0},
234 };
235 struct preProcConfigParams_t preProcCfgParams {};
Saketh Sathuvalli4ece3e02020-07-19 21:19:39 +0530236
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800237 while (true) {
238 const int opt = getopt_long(argc, (char* const*)argv, "i:o:", long_opts, nullptr);
239 if (opt == -1) {
240 break;
241 }
242 switch (opt) {
243 case ARG_HELP:
244 printUsage();
245 return 0;
246 case ARG_INPUT: {
247 inputFile = (char*)optarg;
248 break;
249 }
250 case ARG_OUTPUT: {
251 outputFile = (char*)optarg;
252 break;
253 }
254 case ARG_FAR: {
255 farFile = (char*)optarg;
256 break;
257 }
258 case ARG_FS: {
259 preProcCfgParams.samplingFreq = atoi(optarg);
260 break;
261 }
262 case ARG_CH_MASK: {
263 int chMaskIdx = atoi(optarg);
264 if (chMaskIdx < 0 or chMaskIdx > kPreProcConfigChMaskCount) {
265 ALOGE("Channel Mask index not in correct range\n");
266 printUsage();
267 return EXIT_FAILURE;
268 }
269 preProcCfgParams.chMask = kPreProcConfigChMask[chMaskIdx];
270 break;
271 }
272 case ARG_AGC_TGT_LVL: {
273 preProcCfgParams.agcTargetLevel = atoi(optarg);
274 break;
275 }
276 case ARG_AGC_COMP_LVL: {
277 preProcCfgParams.agcCompLevel = atoi(optarg);
278 break;
279 }
280#ifndef WEBRTC_LEGACY
281 case ARG_AGC2_GAIN: {
282 preProcCfgParams.agc2Gain = atof(optarg);
283 break;
284 }
285 case ARG_AGC2_LVL: {
286 preProcCfgParams.agc2Level = atoi(optarg);
287 break;
288 }
289 case ARG_AGC2_SAT_MGN: {
290 preProcCfgParams.agc2SaturationMargin = atof(optarg);
291 break;
292 }
293#endif
294 case ARG_AEC_DELAY: {
295 preProcCfgParams.aecDelay = atoi(optarg);
296 break;
297 }
298 case ARG_NS_LVL: {
299 preProcCfgParams.nsLevel = atoi(optarg);
300 break;
301 }
302 default:
303 break;
304 }
Saketh Sathuvalli4ece3e02020-07-19 21:19:39 +0530305 }
Saketh Sathuvalli4ece3e02020-07-19 21:19:39 +0530306
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800307 if (inputFile == nullptr) {
308 ALOGE("Error: missing input file\n");
309 printUsage();
310 return EXIT_FAILURE;
311 }
312
313 std::unique_ptr<FILE, decltype(&fclose)> inputFp(fopen(inputFile, "rb"), &fclose);
314 if (inputFp == nullptr) {
315 ALOGE("Cannot open input file %s\n", inputFile);
316 return EXIT_FAILURE;
317 }
318
319 std::unique_ptr<FILE, decltype(&fclose)> farFp(fopen(farFile, "rb"), &fclose);
320 std::unique_ptr<FILE, decltype(&fclose)> outputFp(fopen(outputFile, "wb"), &fclose);
321 if (effectEn[PREPROC_AEC]) {
322 if (farFile == nullptr) {
323 ALOGE("Far end signal file required for echo cancellation \n");
324 return EXIT_FAILURE;
325 }
326 if (farFp == nullptr) {
327 ALOGE("Cannot open far end stream file %s\n", farFile);
328 return EXIT_FAILURE;
329 }
330 struct stat statInput, statFar;
331 (void)fstat(fileno(inputFp.get()), &statInput);
332 (void)fstat(fileno(farFp.get()), &statFar);
333 if (statInput.st_size != statFar.st_size) {
334 ALOGE("Near and far end signals are of different sizes");
335 return EXIT_FAILURE;
336 }
337 }
338 if (outputFile != nullptr && outputFp == nullptr) {
339 ALOGE("Cannot open output file %s\n", outputFile);
340 return EXIT_FAILURE;
341 }
342
343 int32_t sessionId = 1;
344 int32_t ioId = 1;
345 effect_handle_t effectHandle[PREPROC_NUM_EFFECTS] = {nullptr};
346 effect_config_t config;
347 config.inputCfg.samplingRate = config.outputCfg.samplingRate = preProcCfgParams.samplingFreq;
348 config.inputCfg.channels = config.outputCfg.channels = preProcCfgParams.chMask;
349 config.inputCfg.format = config.outputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
350
351 // Create all the effect handles
352 for (int i = 0; i < PREPROC_NUM_EFFECTS; i++) {
353 if (int status = preProcCreateEffect(&effectHandle[i], i, &config, sessionId, ioId);
354 status != 0) {
355 ALOGE("Create effect call returned error %i", status);
356 return EXIT_FAILURE;
357 }
Saketh Sathuvalli4ece3e02020-07-19 21:19:39 +0530358 }
359
360 for (int i = 0; i < PREPROC_NUM_EFFECTS; i++) {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800361 if (effectEn[i] == 1) {
362 int reply = 0;
363 uint32_t replySize = sizeof(reply);
364 (*effectHandle[i])
365 ->command(effectHandle[i], EFFECT_CMD_ENABLE, 0, nullptr, &replySize, &reply);
366 if (reply != 0) {
367 ALOGE("Command enable call returned error %d\n", reply);
368 return EXIT_FAILURE;
369 }
Saketh Sathuvalli4ece3e02020-07-19 21:19:39 +0530370 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800371 }
372
373 // Set Config Params of the effects
374 if (effectEn[PREPROC_AGC]) {
375 if (int status = preProcSetConfigParam(AGC_PARAM_TARGET_LEVEL,
376 (uint32_t)preProcCfgParams.agcTargetLevel,
377 effectHandle[PREPROC_AGC]);
Saketh Sathuvalli4ece3e02020-07-19 21:19:39 +0530378 status != 0) {
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800379 ALOGE("Invalid AGC Target Level. Error %d\n", status);
Saketh Sathuvalli4ece3e02020-07-19 21:19:39 +0530380 return EXIT_FAILURE;
Saketh Sathuvalli4ece3e02020-07-19 21:19:39 +0530381 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800382 if (int status = preProcSetConfigParam(AGC_PARAM_COMP_GAIN,
383 (uint32_t)preProcCfgParams.agcCompLevel,
384 effectHandle[PREPROC_AGC]);
385 status != 0) {
386 ALOGE("Invalid AGC Comp Gain. Error %d\n", status);
387 return EXIT_FAILURE;
388 }
Saketh Sathuvalli4ece3e02020-07-19 21:19:39 +0530389 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800390#ifndef WEBRTC_LEGACY
391 if (effectEn[PREPROC_AGC2]) {
392 if (int status = preProcSetConfigParam(AGC2_PARAM_FIXED_DIGITAL_GAIN,
393 (float)preProcCfgParams.agc2Gain,
394 effectHandle[PREPROC_AGC2]);
395 status != 0) {
396 ALOGE("Invalid AGC2 Fixed Digital Gain. Error %d\n", status);
397 return EXIT_FAILURE;
398 }
399 if (int status = preProcSetConfigParam(AGC2_PARAM_ADAPT_DIGI_LEVEL_ESTIMATOR,
400 (uint32_t)preProcCfgParams.agc2Level,
401 effectHandle[PREPROC_AGC2]);
402 status != 0) {
403 ALOGE("Invalid AGC2 Level Estimator. Error %d\n", status);
404 return EXIT_FAILURE;
405 }
406 if (int status = preProcSetConfigParam(AGC2_PARAM_ADAPT_DIGI_EXTRA_SATURATION_MARGIN,
407 (float)preProcCfgParams.agc2SaturationMargin,
408 effectHandle[PREPROC_AGC2]);
409 status != 0) {
410 ALOGE("Invalid AGC2 Saturation Margin. Error %d\n", status);
411 return EXIT_FAILURE;
412 }
Saketh Sathuvalli4ece3e02020-07-19 21:19:39 +0530413 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800414#endif
415 if (effectEn[PREPROC_NS]) {
416 if (int status = preProcSetConfigParam(NS_PARAM_LEVEL, (uint32_t)preProcCfgParams.nsLevel,
417 effectHandle[PREPROC_NS]);
418 status != 0) {
419 ALOGE("Invalid Noise Suppression level Error %d\n", status);
420 return EXIT_FAILURE;
421 }
Saketh Sathuvalli4ece3e02020-07-19 21:19:39 +0530422 }
Harish Mahendrakarb6926c72020-11-27 15:22:44 -0800423
424 // Process Call
425 const int frameLength = (int)(preProcCfgParams.samplingFreq * kTenMilliSecVal);
426 const int ioChannelCount = audio_channel_count_from_in_mask(preProcCfgParams.chMask);
427 const int ioFrameSize = ioChannelCount * sizeof(short);
428 int frameCounter = 0;
429 while (true) {
430 std::vector<short> in(frameLength * ioChannelCount);
431 std::vector<short> out(frameLength * ioChannelCount);
432 std::vector<short> farIn(frameLength * ioChannelCount);
433 size_t samplesRead = fread(in.data(), ioFrameSize, frameLength, inputFp.get());
434 if (samplesRead == 0) {
435 break;
436 }
437 audio_buffer_t inputBuffer, outputBuffer;
438 audio_buffer_t farInBuffer{};
439 inputBuffer.frameCount = samplesRead;
440 outputBuffer.frameCount = samplesRead;
441 inputBuffer.s16 = in.data();
442 outputBuffer.s16 = out.data();
443
444 if (farFp != nullptr) {
445 samplesRead = fread(farIn.data(), ioFrameSize, frameLength, farFp.get());
446 if (samplesRead == 0) {
447 break;
448 }
449 farInBuffer.frameCount = samplesRead;
450 farInBuffer.s16 = farIn.data();
451 }
452
453 for (int i = 0; i < PREPROC_NUM_EFFECTS; i++) {
454 if (effectEn[i] == 1) {
455 if (i == PREPROC_AEC) {
456 if (int status = preProcSetConfigParam(AEC_PARAM_ECHO_DELAY,
457 (uint32_t)preProcCfgParams.aecDelay,
458 effectHandle[PREPROC_AEC]);
459 status != 0) {
460 ALOGE("preProcSetConfigParam returned Error %d\n", status);
461 return EXIT_FAILURE;
462 }
463 }
464 if (int status = (*effectHandle[i])
465 ->process(effectHandle[i], &inputBuffer, &outputBuffer);
466 status != 0) {
467 ALOGE("\nError: Process i = %d returned with error %d\n", i, status);
468 return EXIT_FAILURE;
469 }
470 if (i == PREPROC_AEC) {
471 if (int status = (*effectHandle[i])
472 ->process_reverse(effectHandle[i], &farInBuffer,
473 &outputBuffer);
474 status != 0) {
475 ALOGE("\nError: Process reverse i = %d returned with error %d\n", i,
476 status);
477 return EXIT_FAILURE;
478 }
479 }
480 }
481 }
482 if (outputFp != nullptr) {
483 size_t samplesWritten =
484 fwrite(out.data(), ioFrameSize, outputBuffer.frameCount, outputFp.get());
485 if (samplesWritten != outputBuffer.frameCount) {
486 ALOGE("\nError: Output file writing failed");
487 break;
488 }
489 }
490 frameCounter += frameLength;
491 }
492 // Release all the effect handles created
493 for (int i = 0; i < PREPROC_NUM_EFFECTS; i++) {
494 if (int status = AUDIO_EFFECT_LIBRARY_INFO_SYM.release_effect(effectHandle[i]);
495 status != 0) {
496 ALOGE("Audio Preprocessing release returned an error = %d\n", status);
497 return EXIT_FAILURE;
498 }
499 }
500 return EXIT_SUCCESS;
Saketh Sathuvalli4ece3e02020-07-19 21:19:39 +0530501}