tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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