audioproc_float_impl.cc (36082B)
1 /* 2 * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #include "modules/audio_processing/test/audioproc_float_impl.h" 12 13 #include <cstdint> 14 #include <cstdio> 15 #include <cstdlib> 16 #include <fstream> 17 #include <iostream> 18 #include <memory> 19 #include <optional> 20 #include <string> 21 #include <utility> 22 #include <vector> 23 24 #include "absl/base/nullability.h" 25 #include "absl/flags/flag.h" 26 #include "absl/flags/parse.h" 27 #include "absl/strings/string_view.h" 28 #include "api/audio/audio_processing.h" 29 #include "api/audio/builtin_audio_processing_builder.h" 30 #include "api/audio/echo_canceller3_config.h" 31 #include "api/audio/echo_detector_creator.h" 32 #include "api/environment/environment.h" 33 #include "api/environment/environment_factory.h" 34 #include "api/field_trials.h" 35 #include "api/scoped_refptr.h" 36 #include "common_audio/wav_file.h" 37 #include "modules/audio_processing/aec3/neural_residual_echo_estimator_impl.h" 38 #include "modules/audio_processing/test/aec_dump_based_simulator.h" 39 #include "modules/audio_processing/test/audio_processing_simulator.h" 40 #include "modules/audio_processing/test/echo_canceller3_config_json.h" 41 #include "modules/audio_processing/test/wav_based_simulator.h" 42 #include "rtc_base/checks.h" 43 44 constexpr int kParameterNotSpecifiedValue = -10000; 45 46 ABSL_FLAG(std::string, dump_input, "", "Aec dump input filename"); 47 ABSL_FLAG(std::string, dump_output, "", "Aec dump output filename"); 48 ABSL_FLAG(std::string, i, "", "Forward stream input wav filename"); 49 ABSL_FLAG(std::string, o, "", "Forward stream output wav filename"); 50 ABSL_FLAG(std::string, ri, "", "Reverse stream input wav filename"); 51 ABSL_FLAG(std::string, ro, "", "Reverse stream output wav filename"); 52 ABSL_FLAG(std::string, 53 artificial_nearend, 54 "", 55 "Artificial nearend wav filename"); 56 ABSL_FLAG(std::string, linear_aec_output, "", "Linear AEC output wav filename"); 57 ABSL_FLAG(int, 58 output_num_channels, 59 kParameterNotSpecifiedValue, 60 "Number of forward stream output channels"); 61 ABSL_FLAG(int, 62 reverse_output_num_channels, 63 kParameterNotSpecifiedValue, 64 "Number of Reverse stream output channels"); 65 ABSL_FLAG(int, 66 output_sample_rate_hz, 67 kParameterNotSpecifiedValue, 68 "Forward stream output sample rate in Hz"); 69 ABSL_FLAG(int, 70 reverse_output_sample_rate_hz, 71 kParameterNotSpecifiedValue, 72 "Reverse stream output sample rate in Hz"); 73 ABSL_FLAG(bool, 74 fixed_interface, 75 false, 76 "Use the fixed interface when operating on wav files"); 77 ABSL_FLAG(int, 78 aec, 79 kParameterNotSpecifiedValue, 80 "Activate (1) or deactivate (0) the echo canceller"); 81 ABSL_FLAG(int, 82 aecm, 83 kParameterNotSpecifiedValue, 84 "Activate (1) or deactivate (0) the mobile echo controller"); 85 ABSL_FLAG(int, 86 ed, 87 kParameterNotSpecifiedValue, 88 "Activate (1) or deactivate (0) the residual echo detector"); 89 ABSL_FLAG(std::string, 90 ed_graph, 91 "", 92 "Output filename for graph of echo likelihood"); 93 ABSL_FLAG(int, 94 agc, 95 kParameterNotSpecifiedValue, 96 "Activate (1) or deactivate (0) the AGC"); 97 ABSL_FLAG(int, 98 agc2, 99 kParameterNotSpecifiedValue, 100 "Activate (1) or deactivate (0) the AGC2"); 101 ABSL_FLAG(int, 102 pre_amplifier, 103 kParameterNotSpecifiedValue, 104 "Activate (1) or deactivate(0) the pre amplifier"); 105 ABSL_FLAG( 106 int, 107 capture_level_adjustment, 108 kParameterNotSpecifiedValue, 109 "Activate (1) or deactivate(0) the capture level adjustment functionality"); 110 ABSL_FLAG(int, 111 analog_mic_gain_emulation, 112 kParameterNotSpecifiedValue, 113 "Activate (1) or deactivate(0) the analog mic gain emulation in the " 114 "production (non-test) code."); 115 ABSL_FLAG(int, 116 hpf, 117 kParameterNotSpecifiedValue, 118 "Activate (1) or deactivate (0) the high-pass filter"); 119 ABSL_FLAG(int, 120 ns, 121 kParameterNotSpecifiedValue, 122 "Activate (1) or deactivate (0) the noise suppressor"); 123 ABSL_FLAG(int, 124 ts, 125 kParameterNotSpecifiedValue, 126 "Activate (1) or deactivate (0) the transient suppressor"); 127 ABSL_FLAG(int, 128 analog_agc, 129 kParameterNotSpecifiedValue, 130 "Activate (1) or deactivate (0) the analog AGC"); 131 ABSL_FLAG(bool, 132 all_default, 133 false, 134 "Activate all of the default components (will be overridden by any " 135 "other settings)"); 136 ABSL_FLAG(int, 137 analog_agc_use_digital_adaptive_controller, 138 kParameterNotSpecifiedValue, 139 "Activate (1) or deactivate (0) digital adaptation in AGC1. " 140 "Digital adaptation is active by default."); 141 ABSL_FLAG(int, 142 agc_mode, 143 kParameterNotSpecifiedValue, 144 "Specify the AGC mode (0-2)"); 145 ABSL_FLAG(int, 146 agc_target_level, 147 kParameterNotSpecifiedValue, 148 "Specify the AGC target level (0-31)"); 149 ABSL_FLAG(int, 150 agc_limiter, 151 kParameterNotSpecifiedValue, 152 "Activate (1) or deactivate (0) the level estimator"); 153 ABSL_FLAG(int, 154 agc_compression_gain, 155 kParameterNotSpecifiedValue, 156 "Specify the AGC compression gain (0-90)"); 157 ABSL_FLAG(int, 158 agc2_enable_adaptive_gain, 159 kParameterNotSpecifiedValue, 160 "Activate (1) or deactivate (0) the AGC2 adaptive gain"); 161 ABSL_FLAG(float, 162 agc2_fixed_gain_db, 163 kParameterNotSpecifiedValue, 164 "AGC2 fixed gain (dB) to apply"); 165 ABSL_FLAG(int, 166 agc2_enable_input_volume_controller, 167 kParameterNotSpecifiedValue, 168 "Activate (1) or deactivate (0) the AGC2 input volume adjustments"); 169 ABSL_FLAG(float, 170 pre_amplifier_gain_factor, 171 kParameterNotSpecifiedValue, 172 "Pre-amplifier gain factor (linear) to apply"); 173 ABSL_FLAG(float, 174 pre_gain_factor, 175 kParameterNotSpecifiedValue, 176 "Pre-gain factor (linear) to apply in the capture level adjustment"); 177 ABSL_FLAG(float, 178 post_gain_factor, 179 kParameterNotSpecifiedValue, 180 "Post-gain factor (linear) to apply in the capture level adjustment"); 181 ABSL_FLAG(float, 182 analog_mic_gain_emulation_initial_level, 183 kParameterNotSpecifiedValue, 184 "Emulated analog mic level to apply initially in the production " 185 "(non-test) code."); 186 ABSL_FLAG(int, 187 ns_level, 188 kParameterNotSpecifiedValue, 189 "Specify the NS level (0-3)"); 190 ABSL_FLAG(int, 191 ns_analysis_on_linear_aec_output, 192 kParameterNotSpecifiedValue, 193 "Specifies whether the noise suppression analysis is done on the " 194 "linear AEC output"); 195 ABSL_FLAG(int, 196 maximum_internal_processing_rate, 197 kParameterNotSpecifiedValue, 198 "Set a maximum internal processing rate (32000 or 48000) to override " 199 "the default rate"); 200 ABSL_FLAG(int, 201 stream_delay, 202 kParameterNotSpecifiedValue, 203 "Specify the stream delay in ms to use"); 204 ABSL_FLAG(int, 205 use_stream_delay, 206 kParameterNotSpecifiedValue, 207 "Activate (1) or deactivate (0) reporting the stream delay"); 208 ABSL_FLAG(int, 209 stream_drift_samples, 210 kParameterNotSpecifiedValue, 211 "Specify the number of stream drift samples to use"); 212 ABSL_FLAG(int, 213 initial_mic_level, 214 100, 215 "Initial mic level (0-255) for the analog mic gain simulation in the " 216 "test code"); 217 ABSL_FLAG(int, 218 simulate_mic_gain, 219 0, 220 "Activate (1) or deactivate(0) the analog mic gain simulation in the " 221 "test code"); 222 ABSL_FLAG(int, 223 multi_channel_render, 224 kParameterNotSpecifiedValue, 225 "Activate (1) or deactivate (0) multi-channel render processing in " 226 "APM pipeline"); 227 ABSL_FLAG(int, 228 multi_channel_capture, 229 kParameterNotSpecifiedValue, 230 "Activate (1) or deactivate (0) multi-channel capture processing in " 231 "APM pipeline"); 232 ABSL_FLAG(int, 233 simulated_mic_kind, 234 kParameterNotSpecifiedValue, 235 "Specify which microphone kind to use for microphone simulation"); 236 ABSL_FLAG(int, 237 override_key_pressed, 238 kParameterNotSpecifiedValue, 239 "Always set to true (1) or to false (0) the key press state. If " 240 "unspecified, false is set with Wav files or, with AEC dumps, the " 241 "recorded event is used."); 242 ABSL_FLAG(int, 243 frame_for_sending_capture_output_used_false, 244 kParameterNotSpecifiedValue, 245 "Capture frame index for sending a runtime setting for that the " 246 "capture output is not used."); 247 ABSL_FLAG(int, 248 frame_for_sending_capture_output_used_true, 249 kParameterNotSpecifiedValue, 250 "Capture frame index for sending a runtime setting for that the " 251 "capture output is used."); 252 ABSL_FLAG(bool, performance_report, false, "Report the APM performance "); 253 ABSL_FLAG(std::string, 254 performance_report_output_file, 255 "", 256 "Generate a CSV file with the API call durations"); 257 ABSL_FLAG(bool, verbose, false, "Produce verbose output"); 258 ABSL_FLAG(bool, 259 quiet, 260 false, 261 "Avoid producing information about the progress."); 262 ABSL_FLAG(bool, 263 bitexactness_report, 264 false, 265 "Report bitexactness for aec dump result reproduction"); 266 ABSL_FLAG(bool, 267 discard_settings_in_aecdump, 268 false, 269 "Discard any config settings specified in the aec dump"); 270 ABSL_FLAG(bool, 271 store_intermediate_output, 272 false, 273 "Creates new output files after each init"); 274 ABSL_FLAG(std::string, 275 custom_call_order_file, 276 "", 277 "Custom process API call order file"); 278 ABSL_FLAG(std::string, 279 output_custom_call_order_file, 280 "", 281 "Generate custom process API call order file from AEC dump"); 282 ABSL_FLAG(bool, 283 print_aec_parameter_values, 284 false, 285 "Print parameter values used in AEC in JSON-format"); 286 ABSL_FLAG(std::string, 287 aec_settings, 288 "", 289 "File in JSON-format with custom AEC settings"); 290 ABSL_FLAG(bool, 291 dump_data, 292 false, 293 "Dump internal data during the call (requires build flag)"); 294 ABSL_FLAG(std::string, 295 dump_data_output_dir, 296 "", 297 "Internal data dump output directory"); 298 ABSL_FLAG(int, 299 dump_set_to_use, 300 kParameterNotSpecifiedValue, 301 "Specifies the dump set to use (if not all the dump sets will " 302 "be used"); 303 ABSL_FLAG(bool, 304 analyze, 305 false, 306 "Only analyze the call setup behavior (no processing)"); 307 ABSL_FLAG(float, 308 dump_start_seconds, 309 kParameterNotSpecifiedValue, 310 "Start of when to dump data (seconds)."); 311 ABSL_FLAG(float, 312 dump_end_seconds, 313 kParameterNotSpecifiedValue, 314 "End of when to dump data (seconds)."); 315 ABSL_FLAG(int, 316 dump_start_frame, 317 kParameterNotSpecifiedValue, 318 "Start of when to dump data (frames)."); 319 ABSL_FLAG(int, 320 dump_end_frame, 321 kParameterNotSpecifiedValue, 322 "End of when to dump data (frames)."); 323 ABSL_FLAG(int, 324 init_to_process, 325 kParameterNotSpecifiedValue, 326 "Init index to process."); 327 328 ABSL_FLAG(bool, 329 float_wav_output, 330 false, 331 "Produce floating point wav output files."); 332 333 ABSL_FLAG(std::string, 334 force_fieldtrials, 335 "", 336 "Field trials control experimental feature code which can be forced. " 337 "E.g. running with --force_fieldtrials=WebRTC-FooFeature/Enable/" 338 " will assign the group Enable to field trial WebRTC-FooFeature."); 339 340 ABSL_FLAG(std::string, 341 ree_model, 342 "", 343 "When running with a neural residual echo estimator, the path to the " 344 "model binary."); 345 346 namespace webrtc { 347 namespace test { 348 namespace { 349 350 const char kUsageDescription[] = 351 "Usage: audioproc_f [options] -i <input.wav>\n" 352 " or\n" 353 " audioproc_f [options] -dump_input <aec_dump>\n" 354 "\n\n" 355 "Command-line tool to simulate a call using the audio " 356 "processing module, either based on wav files or " 357 "protobuf debug dump recordings.\n"; 358 359 void SetSettingIfSpecified(absl::string_view value, 360 std::optional<std::string>* parameter) { 361 if (value.compare("") != 0) { 362 *parameter = std::string(value); 363 } 364 } 365 366 void SetSettingIfSpecified(int value, std::optional<int>* parameter) { 367 if (value != kParameterNotSpecifiedValue) { 368 *parameter = value; 369 } 370 } 371 372 void SetSettingIfSpecified(float value, std::optional<float>* parameter) { 373 constexpr float kFloatParameterNotSpecifiedValue = 374 kParameterNotSpecifiedValue; 375 if (value != kFloatParameterNotSpecifiedValue) { 376 *parameter = value; 377 } 378 } 379 380 void SetSettingIfFlagSet(int32_t flag, std::optional<bool>* parameter) { 381 if (flag == 0) { 382 *parameter = false; 383 } else if (flag == 1) { 384 *parameter = true; 385 } 386 } 387 388 SimulationSettings CreateSettings() { 389 SimulationSettings settings; 390 if (absl::GetFlag(FLAGS_all_default)) { 391 settings.use_ts = true; 392 settings.use_analog_agc = true; 393 settings.use_ns = true; 394 settings.use_hpf = true; 395 settings.use_agc = true; 396 settings.use_agc2 = false; 397 settings.use_pre_amplifier = false; 398 settings.use_aec = true; 399 settings.use_aecm = false; 400 settings.use_ed = false; 401 } 402 SetSettingIfSpecified(absl::GetFlag(FLAGS_dump_input), 403 &settings.aec_dump_input_filename); 404 SetSettingIfSpecified(absl::GetFlag(FLAGS_dump_output), 405 &settings.aec_dump_output_filename); 406 SetSettingIfSpecified(absl::GetFlag(FLAGS_i), &settings.input_filename); 407 SetSettingIfSpecified(absl::GetFlag(FLAGS_o), &settings.output_filename); 408 SetSettingIfSpecified(absl::GetFlag(FLAGS_ri), 409 &settings.reverse_input_filename); 410 SetSettingIfSpecified(absl::GetFlag(FLAGS_ro), 411 &settings.reverse_output_filename); 412 SetSettingIfSpecified(absl::GetFlag(FLAGS_artificial_nearend), 413 &settings.artificial_nearend_filename); 414 SetSettingIfSpecified(absl::GetFlag(FLAGS_linear_aec_output), 415 &settings.linear_aec_output_filename); 416 SetSettingIfSpecified(absl::GetFlag(FLAGS_output_num_channels), 417 &settings.output_num_channels); 418 SetSettingIfSpecified(absl::GetFlag(FLAGS_reverse_output_num_channels), 419 &settings.reverse_output_num_channels); 420 SetSettingIfSpecified(absl::GetFlag(FLAGS_output_sample_rate_hz), 421 &settings.output_sample_rate_hz); 422 SetSettingIfSpecified(absl::GetFlag(FLAGS_reverse_output_sample_rate_hz), 423 &settings.reverse_output_sample_rate_hz); 424 SetSettingIfFlagSet(absl::GetFlag(FLAGS_aec), &settings.use_aec); 425 SetSettingIfFlagSet(absl::GetFlag(FLAGS_aecm), &settings.use_aecm); 426 SetSettingIfFlagSet(absl::GetFlag(FLAGS_ed), &settings.use_ed); 427 SetSettingIfSpecified(absl::GetFlag(FLAGS_ed_graph), 428 &settings.ed_graph_output_filename); 429 SetSettingIfFlagSet(absl::GetFlag(FLAGS_agc), &settings.use_agc); 430 SetSettingIfFlagSet(absl::GetFlag(FLAGS_agc2), &settings.use_agc2); 431 SetSettingIfFlagSet(absl::GetFlag(FLAGS_pre_amplifier), 432 &settings.use_pre_amplifier); 433 SetSettingIfFlagSet(absl::GetFlag(FLAGS_capture_level_adjustment), 434 &settings.use_capture_level_adjustment); 435 SetSettingIfFlagSet(absl::GetFlag(FLAGS_analog_mic_gain_emulation), 436 &settings.use_analog_mic_gain_emulation); 437 SetSettingIfFlagSet(absl::GetFlag(FLAGS_hpf), &settings.use_hpf); 438 SetSettingIfFlagSet(absl::GetFlag(FLAGS_ns), &settings.use_ns); 439 SetSettingIfSpecified(absl::GetFlag(FLAGS_ts), &settings.use_ts); 440 SetSettingIfFlagSet(absl::GetFlag(FLAGS_analog_agc), 441 &settings.use_analog_agc); 442 SetSettingIfFlagSet( 443 absl::GetFlag(FLAGS_analog_agc_use_digital_adaptive_controller), 444 &settings.analog_agc_use_digital_adaptive_controller); 445 SetSettingIfSpecified(absl::GetFlag(FLAGS_agc_mode), &settings.agc_mode); 446 SetSettingIfSpecified(absl::GetFlag(FLAGS_agc_target_level), 447 &settings.agc_target_level); 448 SetSettingIfFlagSet(absl::GetFlag(FLAGS_agc_limiter), 449 &settings.use_agc_limiter); 450 SetSettingIfSpecified(absl::GetFlag(FLAGS_agc_compression_gain), 451 &settings.agc_compression_gain); 452 SetSettingIfFlagSet(absl::GetFlag(FLAGS_agc2_enable_adaptive_gain), 453 &settings.agc2_use_adaptive_gain); 454 SetSettingIfSpecified(absl::GetFlag(FLAGS_agc2_fixed_gain_db), 455 &settings.agc2_fixed_gain_db); 456 SetSettingIfFlagSet(absl::GetFlag(FLAGS_agc2_enable_input_volume_controller), 457 &settings.agc2_use_input_volume_controller); 458 SetSettingIfSpecified(absl::GetFlag(FLAGS_pre_amplifier_gain_factor), 459 &settings.pre_amplifier_gain_factor); 460 SetSettingIfSpecified(absl::GetFlag(FLAGS_pre_gain_factor), 461 &settings.pre_gain_factor); 462 SetSettingIfSpecified(absl::GetFlag(FLAGS_post_gain_factor), 463 &settings.post_gain_factor); 464 SetSettingIfSpecified( 465 absl::GetFlag(FLAGS_analog_mic_gain_emulation_initial_level), 466 &settings.analog_mic_gain_emulation_initial_level); 467 SetSettingIfSpecified(absl::GetFlag(FLAGS_ns_level), &settings.ns_level); 468 SetSettingIfFlagSet(absl::GetFlag(FLAGS_ns_analysis_on_linear_aec_output), 469 &settings.ns_analysis_on_linear_aec_output); 470 SetSettingIfSpecified(absl::GetFlag(FLAGS_maximum_internal_processing_rate), 471 &settings.maximum_internal_processing_rate); 472 SetSettingIfSpecified(absl::GetFlag(FLAGS_stream_delay), 473 &settings.stream_delay); 474 SetSettingIfFlagSet(absl::GetFlag(FLAGS_use_stream_delay), 475 &settings.use_stream_delay); 476 SetSettingIfSpecified(absl::GetFlag(FLAGS_custom_call_order_file), 477 &settings.call_order_input_filename); 478 SetSettingIfSpecified(absl::GetFlag(FLAGS_output_custom_call_order_file), 479 &settings.call_order_output_filename); 480 SetSettingIfSpecified(absl::GetFlag(FLAGS_aec_settings), 481 &settings.aec_settings_filename); 482 settings.initial_mic_level = absl::GetFlag(FLAGS_initial_mic_level); 483 SetSettingIfFlagSet(absl::GetFlag(FLAGS_multi_channel_render), 484 &settings.multi_channel_render); 485 SetSettingIfFlagSet(absl::GetFlag(FLAGS_multi_channel_capture), 486 &settings.multi_channel_capture); 487 settings.simulate_mic_gain = absl::GetFlag(FLAGS_simulate_mic_gain); 488 SetSettingIfSpecified(absl::GetFlag(FLAGS_simulated_mic_kind), 489 &settings.simulated_mic_kind); 490 SetSettingIfFlagSet(absl::GetFlag(FLAGS_override_key_pressed), 491 &settings.override_key_pressed); 492 SetSettingIfSpecified( 493 absl::GetFlag(FLAGS_frame_for_sending_capture_output_used_false), 494 &settings.frame_for_sending_capture_output_used_false); 495 SetSettingIfSpecified( 496 absl::GetFlag(FLAGS_frame_for_sending_capture_output_used_true), 497 &settings.frame_for_sending_capture_output_used_true); 498 settings.report_performance = absl::GetFlag(FLAGS_performance_report); 499 SetSettingIfSpecified(absl::GetFlag(FLAGS_performance_report_output_file), 500 &settings.performance_report_output_filename); 501 settings.use_verbose_logging = absl::GetFlag(FLAGS_verbose); 502 settings.use_quiet_output = absl::GetFlag(FLAGS_quiet); 503 settings.report_bitexactness = absl::GetFlag(FLAGS_bitexactness_report); 504 settings.discard_all_settings_in_aecdump = 505 absl::GetFlag(FLAGS_discard_settings_in_aecdump); 506 settings.fixed_interface = absl::GetFlag(FLAGS_fixed_interface); 507 settings.store_intermediate_output = 508 absl::GetFlag(FLAGS_store_intermediate_output); 509 settings.print_aec_parameter_values = 510 absl::GetFlag(FLAGS_print_aec_parameter_values); 511 settings.dump_internal_data = absl::GetFlag(FLAGS_dump_data); 512 SetSettingIfSpecified(absl::GetFlag(FLAGS_dump_data_output_dir), 513 &settings.dump_internal_data_output_dir); 514 SetSettingIfSpecified(absl::GetFlag(FLAGS_dump_set_to_use), 515 &settings.dump_set_to_use); 516 settings.wav_output_format = absl::GetFlag(FLAGS_float_wav_output) 517 ? WavFile::SampleFormat::kFloat 518 : WavFile::SampleFormat::kInt16; 519 520 settings.analysis_only = absl::GetFlag(FLAGS_analyze); 521 522 SetSettingIfSpecified(absl::GetFlag(FLAGS_dump_start_frame), 523 &settings.dump_start_frame); 524 SetSettingIfSpecified(absl::GetFlag(FLAGS_dump_end_frame), 525 &settings.dump_end_frame); 526 527 constexpr int kFramesPerSecond = 100; 528 std::optional<float> start_seconds; 529 SetSettingIfSpecified(absl::GetFlag(FLAGS_dump_start_seconds), 530 &start_seconds); 531 if (start_seconds) { 532 settings.dump_start_frame = *start_seconds * kFramesPerSecond; 533 } 534 535 std::optional<float> end_seconds; 536 SetSettingIfSpecified(absl::GetFlag(FLAGS_dump_end_seconds), &end_seconds); 537 if (end_seconds) { 538 settings.dump_end_frame = *end_seconds * kFramesPerSecond; 539 } 540 541 SetSettingIfSpecified(absl::GetFlag(FLAGS_init_to_process), 542 &settings.init_to_process); 543 SetSettingIfSpecified(absl::GetFlag(FLAGS_ree_model), 544 &settings.neural_echo_residual_estimator_model); 545 546 return settings; 547 } 548 549 void ReportConditionalErrorAndExit(bool condition, absl::string_view message) { 550 if (condition) { 551 std::cerr << message << std::endl; 552 exit(1); 553 } 554 } 555 556 void PerformBasicParameterSanityChecks(const SimulationSettings& settings) { 557 if (settings.input_filename || settings.reverse_input_filename) { 558 ReportConditionalErrorAndExit( 559 !!settings.aec_dump_input_filename, 560 "Error: The aec dump file cannot be specified " 561 "together with input wav files!\n"); 562 563 ReportConditionalErrorAndExit( 564 !!settings.aec_dump_input_string, 565 "Error: The aec dump input string cannot be specified " 566 "together with input wav files!\n"); 567 568 ReportConditionalErrorAndExit(!!settings.artificial_nearend_filename, 569 "Error: The artificial nearend cannot be " 570 "specified together with input wav files!\n"); 571 572 ReportConditionalErrorAndExit(!settings.input_filename, 573 "Error: When operating at wav files, the " 574 "input wav filename must be " 575 "specified!\n"); 576 577 ReportConditionalErrorAndExit( 578 settings.reverse_output_filename && !settings.reverse_input_filename, 579 "Error: When operating at wav files, the reverse input wav filename " 580 "must be specified if the reverse output wav filename is specified!\n"); 581 } else { 582 ReportConditionalErrorAndExit( 583 !settings.aec_dump_input_filename && !settings.aec_dump_input_string, 584 "Error: Either the aec dump input file, the wav " 585 "input file or the aec dump input string must be specified!\n"); 586 ReportConditionalErrorAndExit( 587 settings.aec_dump_input_filename && settings.aec_dump_input_string, 588 "Error: The aec dump input file cannot be specified together with the " 589 "aec dump input string!\n"); 590 } 591 592 ReportConditionalErrorAndExit(settings.use_aec && !(*settings.use_aec) && 593 settings.linear_aec_output_filename, 594 "Error: The linear AEC ouput filename cannot " 595 "be specified without the AEC being active"); 596 597 ReportConditionalErrorAndExit( 598 settings.use_aec && *settings.use_aec && settings.use_aecm && 599 *settings.use_aecm, 600 "Error: The AEC and the AECM cannot be activated at the same time!\n"); 601 602 ReportConditionalErrorAndExit( 603 settings.output_sample_rate_hz && *settings.output_sample_rate_hz <= 0, 604 "Error: --output_sample_rate_hz must be positive!\n"); 605 606 ReportConditionalErrorAndExit( 607 settings.reverse_output_sample_rate_hz && 608 settings.output_sample_rate_hz && 609 *settings.output_sample_rate_hz <= 0, 610 "Error: --reverse_output_sample_rate_hz must be positive!\n"); 611 612 ReportConditionalErrorAndExit( 613 settings.output_num_channels && *settings.output_num_channels <= 0, 614 "Error: --output_num_channels must be positive!\n"); 615 616 ReportConditionalErrorAndExit( 617 settings.reverse_output_num_channels && 618 *settings.reverse_output_num_channels <= 0, 619 "Error: --reverse_output_num_channels must be positive!\n"); 620 621 ReportConditionalErrorAndExit( 622 settings.agc_target_level && ((*settings.agc_target_level) < 0 || 623 (*settings.agc_target_level) > 31), 624 "Error: --agc_target_level must be specified between 0 and 31.\n"); 625 626 ReportConditionalErrorAndExit( 627 settings.agc_compression_gain && ((*settings.agc_compression_gain) < 0 || 628 (*settings.agc_compression_gain) > 90), 629 "Error: --agc_compression_gain must be specified between 0 and 90.\n"); 630 631 ReportConditionalErrorAndExit( 632 settings.agc2_fixed_gain_db && ((*settings.agc2_fixed_gain_db) < 0 || 633 (*settings.agc2_fixed_gain_db) > 90), 634 "Error: --agc2_fixed_gain_db must be specified between 0 and 90.\n"); 635 636 ReportConditionalErrorAndExit( 637 settings.ns_level && 638 ((*settings.ns_level) < 0 || (*settings.ns_level) > 3), 639 "Error: --ns_level must be specified between 0 and 3.\n"); 640 641 ReportConditionalErrorAndExit( 642 settings.report_bitexactness && !settings.aec_dump_input_filename, 643 "Error: --bitexactness_report can only be used when operating on an " 644 "aecdump\n"); 645 646 ReportConditionalErrorAndExit( 647 settings.call_order_input_filename && settings.aec_dump_input_filename, 648 "Error: --custom_call_order_file cannot be used when operating on an " 649 "aecdump\n"); 650 651 ReportConditionalErrorAndExit( 652 (settings.initial_mic_level < 0 || settings.initial_mic_level > 255), 653 "Error: --initial_mic_level must be specified between 0 and 255.\n"); 654 655 ReportConditionalErrorAndExit( 656 settings.simulated_mic_kind && !settings.simulate_mic_gain, 657 "Error: --simulated_mic_kind cannot be specified when mic simulation is " 658 "disabled\n"); 659 660 ReportConditionalErrorAndExit( 661 !settings.simulated_mic_kind && settings.simulate_mic_gain, 662 "Error: --simulated_mic_kind must be specified when mic simulation is " 663 "enabled\n"); 664 665 // TODO(bugs.webrtc.org/7494): Document how the two settings below differ. 666 ReportConditionalErrorAndExit( 667 settings.simulate_mic_gain && settings.use_analog_mic_gain_emulation, 668 "Error: --simulate_mic_gain and --use_analog_mic_gain_emulation cannot " 669 "be enabled at the same time\n"); 670 671 auto valid_wav_name = [](absl::string_view wav_file_name) { 672 if (wav_file_name.size() < 5) { 673 return false; 674 } 675 if ((wav_file_name.compare(wav_file_name.size() - 4, 4, ".wav") == 0) || 676 (wav_file_name.compare(wav_file_name.size() - 4, 4, ".WAV") == 0)) { 677 return true; 678 } 679 return false; 680 }; 681 682 ReportConditionalErrorAndExit( 683 settings.input_filename && (!valid_wav_name(*settings.input_filename)), 684 "Error: --i must be a valid .wav file name.\n"); 685 686 ReportConditionalErrorAndExit( 687 settings.output_filename && (!valid_wav_name(*settings.output_filename)), 688 "Error: --o must be a valid .wav file name.\n"); 689 690 ReportConditionalErrorAndExit( 691 settings.reverse_input_filename && 692 (!valid_wav_name(*settings.reverse_input_filename)), 693 "Error: --ri must be a valid .wav file name.\n"); 694 695 ReportConditionalErrorAndExit( 696 settings.reverse_output_filename && 697 (!valid_wav_name(*settings.reverse_output_filename)), 698 "Error: --ro must be a valid .wav file name.\n"); 699 700 ReportConditionalErrorAndExit( 701 settings.artificial_nearend_filename && 702 !valid_wav_name(*settings.artificial_nearend_filename), 703 "Error: --artifical_nearend must be a valid .wav file name.\n"); 704 705 ReportConditionalErrorAndExit( 706 settings.linear_aec_output_filename && 707 (!valid_wav_name(*settings.linear_aec_output_filename)), 708 "Error: --linear_aec_output must be a valid .wav file name.\n"); 709 710 ReportConditionalErrorAndExit( 711 WEBRTC_APM_DEBUG_DUMP == 0 && settings.dump_internal_data, 712 "Error: --dump_data cannot be set without proper build support.\n"); 713 714 ReportConditionalErrorAndExit(settings.init_to_process && 715 *settings.init_to_process != 1 && 716 !settings.aec_dump_input_filename, 717 "Error: --init_to_process must be set to 1 for " 718 "wav-file based simulations.\n"); 719 720 ReportConditionalErrorAndExit( 721 !settings.init_to_process && 722 (settings.dump_start_frame || settings.dump_end_frame), 723 "Error: --init_to_process must be set when specifying a start and/or end " 724 "frame for when to dump internal data.\n"); 725 726 ReportConditionalErrorAndExit( 727 !settings.dump_internal_data && 728 settings.dump_internal_data_output_dir.has_value(), 729 "Error: --dump_data_output_dir cannot be set without --dump_data.\n"); 730 731 ReportConditionalErrorAndExit( 732 !settings.aec_dump_input_filename && 733 settings.call_order_output_filename.has_value(), 734 "Error: --output_custom_call_order_file needs an AEC dump input file.\n"); 735 736 ReportConditionalErrorAndExit( 737 (!settings.use_pre_amplifier || !(*settings.use_pre_amplifier)) && 738 settings.pre_amplifier_gain_factor.has_value(), 739 "Error: --pre_amplifier_gain_factor needs --pre_amplifier to be " 740 "specified and set.\n"); 741 } 742 743 void CheckSettingsForBuiltinBuilderAreUnused( 744 const SimulationSettings& settings) { 745 ReportConditionalErrorAndExit( 746 settings.aec_settings_filename.has_value(), 747 "Error: The aec_settings_filename cannot be specified when a " 748 "pre-constructed audio processing object is provided.\n"); 749 750 ReportConditionalErrorAndExit( 751 settings.print_aec_parameter_values, 752 "Error: The print_aec_parameter_values cannot be set when a " 753 "pre-constructed audio processing object is provided.\n"); 754 755 if (settings.linear_aec_output_filename) { 756 std::cout << "Warning: For the linear AEC output to be stored, this must " 757 "be configured in the AEC that is part of the provided " 758 "AudioProcessing object." 759 << std::endl; 760 } 761 } 762 763 // Helper for reading JSON from a file and parsing it to an AEC3 configuration. 764 EchoCanceller3Config ReadAec3ConfigFromJsonFile(absl::string_view filename) { 765 std::string json_string; 766 std::string s; 767 std::ifstream f(std::string(filename).c_str()); 768 if (f.fail()) { 769 std::cout << "Failed to open the file " << filename << std::endl; 770 RTC_CHECK_NOTREACHED(); 771 } 772 while (std::getline(f, s)) { 773 json_string += s; 774 } 775 776 bool parsing_successful; 777 EchoCanceller3Config cfg; 778 Aec3ConfigFromJsonString(json_string, &cfg, &parsing_successful); 779 if (!parsing_successful) { 780 std::cout << "Parsing of json string failed: " << std::endl 781 << json_string << std::endl; 782 RTC_CHECK_NOTREACHED(); 783 } 784 RTC_CHECK(EchoCanceller3Config::Validate(&cfg)); 785 786 return cfg; 787 } 788 789 void SetDependencies(const SimulationSettings& settings, 790 BuiltinAudioProcessingBuilder& builder) { 791 EchoCanceller3Config aec3_config; 792 if (settings.aec_settings_filename) { 793 if (settings.use_verbose_logging) { 794 std::cout << "Reading AEC Parameters from JSON input." << std::endl; 795 } 796 aec3_config = ReadAec3ConfigFromJsonFile(*settings.aec_settings_filename); 797 } 798 799 if (settings.linear_aec_output_filename) { 800 aec3_config.filter.export_linear_aec_output = true; 801 } 802 803 if (settings.print_aec_parameter_values) { 804 if (!settings.use_quiet_output) { 805 std::cout << "AEC settings:" << std::endl; 806 } 807 std::cout << Aec3ConfigToJsonString(aec3_config) << std::endl; 808 } 809 builder.SetEchoCancellerConfig( 810 aec3_config, /*echo_canceller_multichannel_config=*/std::nullopt); 811 812 if (settings.neural_echo_residual_estimator_model) { 813 auto model_runner = NeuralResidualEchoEstimatorImpl::LoadTfLiteModel( 814 *settings.neural_echo_residual_estimator_model); 815 RTC_CHECK(model_runner); 816 builder.SetNeuralResidualEchoEstimator( 817 std::make_unique<NeuralResidualEchoEstimatorImpl>( 818 std::move(model_runner))); 819 } 820 821 if (settings.use_ed && *settings.use_ed) { 822 builder.SetEchoDetector(CreateEchoDetector()); 823 } 824 } 825 826 int RunSimulation( 827 absl_nonnull std::unique_ptr<AudioProcessingBuilderInterface> ap_builder, 828 bool builtin_builder_provided, 829 int argc, 830 char* argv[]) { 831 std::vector<char*> args = absl::ParseCommandLine(argc, argv); 832 if (args.size() != 1) { 833 printf("%s", kUsageDescription); 834 return 1; 835 } 836 FieldTrials field_trials(absl::GetFlag(FLAGS_force_fieldtrials)); 837 const Environment env = CreateEnvironment(&field_trials); 838 839 SimulationSettings settings = CreateSettings(); 840 PerformBasicParameterSanityChecks(settings); 841 if (builtin_builder_provided) { 842 SetDependencies(settings, 843 static_cast<BuiltinAudioProcessingBuilder&>(*ap_builder)); 844 } else { 845 CheckSettingsForBuiltinBuilderAreUnused(settings); 846 } 847 scoped_refptr<AudioProcessing> audio_processing = ap_builder->Build(env); 848 RTC_CHECK(audio_processing); 849 850 std::unique_ptr<AudioProcessingSimulator> processor; 851 if (settings.aec_dump_input_filename || settings.aec_dump_input_string) { 852 processor = std::make_unique<AecDumpBasedSimulator>( 853 settings, std::move(audio_processing)); 854 } else { 855 processor = std::make_unique<WavBasedSimulator>( 856 settings, std::move(audio_processing)); 857 } 858 859 if (settings.analysis_only) { 860 processor->Analyze(); 861 } else { 862 processor->Process(); 863 } 864 865 if (settings.report_performance) { 866 processor->GetApiCallStatistics().PrintReport(); 867 } 868 if (settings.performance_report_output_filename) { 869 processor->GetApiCallStatistics().WriteReportToFile( 870 *settings.performance_report_output_filename); 871 } 872 873 if (settings.report_bitexactness && settings.aec_dump_input_filename) { 874 if (processor->OutputWasBitexact()) { 875 std::cout << "The processing was bitexact."; 876 } else { 877 std::cout << "The processing was not bitexact."; 878 } 879 } 880 return 0; 881 } 882 883 } // namespace 884 885 int AudioprocFloatImpl( 886 absl_nonnull std::unique_ptr<BuiltinAudioProcessingBuilder> ap_builder, 887 int argc, 888 char* argv[]) { 889 return RunSimulation(std::move(ap_builder), /*builtin_builder_provided=*/true, 890 argc, argv); 891 } 892 893 int AudioprocFloatImpl( 894 absl_nonnull std::unique_ptr<AudioProcessingBuilderInterface> ap_builder, 895 int argc, 896 char* argv[]) { 897 return RunSimulation(std::move(ap_builder), 898 /*builtin_builder_provided=*/false, argc, argv); 899 } 900 901 } // namespace test 902 } // namespace webrtc