tor-browser

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

echo_canceller3_config_json.cc (32819B)


      1 /*
      2 *  Copyright (c) 2018 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 #include "modules/audio_processing/test/echo_canceller3_config_json.h"
     11 
     12 #include <cstddef>
     13 #include <memory>
     14 #include <string>
     15 #include <vector>
     16 
     17 #include "absl/strings/string_view.h"
     18 #include "api/audio/echo_canceller3_config.h"
     19 #include "rtc_base/checks.h"
     20 #include "rtc_base/logging.h"
     21 #include "rtc_base/strings/json.h"
     22 #include "rtc_base/strings/string_builder.h"
     23 
     24 namespace webrtc {
     25 namespace {
     26 void ReadParam(const Json::Value& root, std::string param_name, bool* param) {
     27  RTC_DCHECK(param);
     28  bool v;
     29  if (GetBoolFromJsonObject(root, param_name, &v)) {
     30    *param = v;
     31  }
     32 }
     33 
     34 void ReadParam(const Json::Value& root, std::string param_name, size_t* param) {
     35  RTC_DCHECK(param);
     36  int v;
     37  if (GetIntFromJsonObject(root, param_name, &v) && v >= 0) {
     38    *param = v;
     39  }
     40 }
     41 
     42 void ReadParam(const Json::Value& root, std::string param_name, int* param) {
     43  RTC_DCHECK(param);
     44  int v;
     45  if (GetIntFromJsonObject(root, param_name, &v)) {
     46    *param = v;
     47  }
     48 }
     49 
     50 void ReadParam(const Json::Value& root, std::string param_name, float* param) {
     51  RTC_DCHECK(param);
     52  double v;
     53  if (GetDoubleFromJsonObject(root, param_name, &v)) {
     54    *param = static_cast<float>(v);
     55  }
     56 }
     57 
     58 void ReadParam(const Json::Value& root,
     59               std::string param_name,
     60               EchoCanceller3Config::Filter::RefinedConfiguration* param) {
     61  RTC_DCHECK(param);
     62  Json::Value json_array;
     63  if (GetValueFromJsonObject(root, param_name, &json_array)) {
     64    std::vector<double> v;
     65    JsonArrayToDoubleVector(json_array, &v);
     66    if (v.size() != 6) {
     67      RTC_LOG(LS_ERROR) << "Incorrect array size for " << param_name;
     68      return;
     69    }
     70    param->length_blocks = static_cast<size_t>(v[0]);
     71    param->leakage_converged = static_cast<float>(v[1]);
     72    param->leakage_diverged = static_cast<float>(v[2]);
     73    param->error_floor = static_cast<float>(v[3]);
     74    param->error_ceil = static_cast<float>(v[4]);
     75    param->noise_gate = static_cast<float>(v[5]);
     76  }
     77 }
     78 
     79 void ReadParam(const Json::Value& root,
     80               std::string param_name,
     81               EchoCanceller3Config::Filter::CoarseConfiguration* param) {
     82  RTC_DCHECK(param);
     83  Json::Value json_array;
     84  if (GetValueFromJsonObject(root, param_name, &json_array)) {
     85    std::vector<double> v;
     86    JsonArrayToDoubleVector(json_array, &v);
     87    if (v.size() != 3) {
     88      RTC_LOG(LS_ERROR) << "Incorrect array size for " << param_name;
     89      return;
     90    }
     91    param->length_blocks = static_cast<size_t>(v[0]);
     92    param->rate = static_cast<float>(v[1]);
     93    param->noise_gate = static_cast<float>(v[2]);
     94  }
     95 }
     96 
     97 void ReadParam(const Json::Value& root,
     98               std::string param_name,
     99               EchoCanceller3Config::Delay::AlignmentMixing* param) {
    100  RTC_DCHECK(param);
    101 
    102  Json::Value subsection;
    103  if (GetValueFromJsonObject(root, param_name, &subsection)) {
    104    ReadParam(subsection, "downmix", &param->downmix);
    105    ReadParam(subsection, "adaptive_selection", &param->adaptive_selection);
    106    ReadParam(subsection, "activity_power_threshold",
    107              &param->activity_power_threshold);
    108    ReadParam(subsection, "prefer_first_two_channels",
    109              &param->prefer_first_two_channels);
    110  }
    111 }
    112 
    113 void ReadParam(
    114    const Json::Value& root,
    115    std::string param_name,
    116    EchoCanceller3Config::Suppressor::SubbandNearendDetection::SubbandRegion*
    117        param) {
    118  RTC_DCHECK(param);
    119  Json::Value json_array;
    120  if (GetValueFromJsonObject(root, param_name, &json_array)) {
    121    std::vector<int> v;
    122    JsonArrayToIntVector(json_array, &v);
    123    if (v.size() != 2) {
    124      RTC_LOG(LS_ERROR) << "Incorrect array size for " << param_name;
    125      return;
    126    }
    127    param->low = static_cast<size_t>(v[0]);
    128    param->high = static_cast<size_t>(v[1]);
    129  }
    130 }
    131 
    132 void ReadParam(const Json::Value& root,
    133               std::string param_name,
    134               EchoCanceller3Config::Suppressor::MaskingThresholds* param) {
    135  RTC_DCHECK(param);
    136  Json::Value json_array;
    137  if (GetValueFromJsonObject(root, param_name, &json_array)) {
    138    std::vector<double> v;
    139    JsonArrayToDoubleVector(json_array, &v);
    140    if (v.size() != 3) {
    141      RTC_LOG(LS_ERROR) << "Incorrect array size for " << param_name;
    142      return;
    143    }
    144    param->enr_transparent = static_cast<float>(v[0]);
    145    param->enr_suppress = static_cast<float>(v[1]);
    146    param->emr_transparent = static_cast<float>(v[2]);
    147  }
    148 }
    149 }  // namespace
    150 
    151 void Aec3ConfigFromJsonString(absl::string_view json_string,
    152                              EchoCanceller3Config* config,
    153                              bool* parsing_successful) {
    154  RTC_DCHECK(config);
    155  RTC_DCHECK(parsing_successful);
    156  EchoCanceller3Config& cfg = *config;
    157  cfg = EchoCanceller3Config();
    158  *parsing_successful = true;
    159 
    160  Json::Value root;
    161  Json::CharReaderBuilder builder;
    162  std::string error_message;
    163  std::unique_ptr<Json::CharReader> reader(builder.newCharReader());
    164  bool success =
    165      reader->parse(json_string.data(), json_string.data() + json_string.size(),
    166                    &root, &error_message);
    167  if (!success) {
    168    RTC_LOG(LS_ERROR) << "Incorrect JSON format: " << error_message;
    169    *parsing_successful = false;
    170    return;
    171  }
    172 
    173  Json::Value aec3_root;
    174  success = GetValueFromJsonObject(root, "aec3", &aec3_root);
    175  if (!success) {
    176    RTC_LOG(LS_ERROR) << "Missing AEC3 config field: " << json_string;
    177    *parsing_successful = false;
    178    return;
    179  }
    180 
    181  Json::Value section;
    182  if (GetValueFromJsonObject(aec3_root, "buffering", &section)) {
    183    ReadParam(section, "excess_render_detection_interval_blocks",
    184              &cfg.buffering.excess_render_detection_interval_blocks);
    185    ReadParam(section, "max_allowed_excess_render_blocks",
    186              &cfg.buffering.max_allowed_excess_render_blocks);
    187  }
    188 
    189  if (GetValueFromJsonObject(aec3_root, "delay", &section)) {
    190    ReadParam(section, "default_delay", &cfg.delay.default_delay);
    191    ReadParam(section, "down_sampling_factor", &cfg.delay.down_sampling_factor);
    192    ReadParam(section, "num_filters", &cfg.delay.num_filters);
    193    ReadParam(section, "delay_headroom_samples",
    194              &cfg.delay.delay_headroom_samples);
    195    ReadParam(section, "hysteresis_limit_blocks",
    196              &cfg.delay.hysteresis_limit_blocks);
    197    ReadParam(section, "fixed_capture_delay_samples",
    198              &cfg.delay.fixed_capture_delay_samples);
    199    ReadParam(section, "delay_estimate_smoothing",
    200              &cfg.delay.delay_estimate_smoothing);
    201    ReadParam(section, "delay_estimate_smoothing_delay_found",
    202              &cfg.delay.delay_estimate_smoothing_delay_found);
    203    ReadParam(section, "delay_candidate_detection_threshold",
    204              &cfg.delay.delay_candidate_detection_threshold);
    205 
    206    Json::Value subsection;
    207    if (GetValueFromJsonObject(section, "delay_selection_thresholds",
    208                               &subsection)) {
    209      ReadParam(subsection, "initial",
    210                &cfg.delay.delay_selection_thresholds.initial);
    211      ReadParam(subsection, "converged",
    212                &cfg.delay.delay_selection_thresholds.converged);
    213    }
    214 
    215    ReadParam(section, "use_external_delay_estimator",
    216              &cfg.delay.use_external_delay_estimator);
    217    ReadParam(section, "log_warning_on_delay_changes",
    218              &cfg.delay.log_warning_on_delay_changes);
    219 
    220    ReadParam(section, "render_alignment_mixing",
    221              &cfg.delay.render_alignment_mixing);
    222    ReadParam(section, "capture_alignment_mixing",
    223              &cfg.delay.capture_alignment_mixing);
    224    ReadParam(section, "detect_pre_echo", &cfg.delay.detect_pre_echo);
    225  }
    226 
    227  if (GetValueFromJsonObject(aec3_root, "filter", &section)) {
    228    ReadParam(section, "refined", &cfg.filter.refined);
    229    ReadParam(section, "coarse", &cfg.filter.coarse);
    230    ReadParam(section, "refined_initial", &cfg.filter.refined_initial);
    231    ReadParam(section, "coarse_initial", &cfg.filter.coarse_initial);
    232    ReadParam(section, "config_change_duration_blocks",
    233              &cfg.filter.config_change_duration_blocks);
    234    ReadParam(section, "initial_state_seconds",
    235              &cfg.filter.initial_state_seconds);
    236    ReadParam(section, "coarse_reset_hangover_blocks",
    237              &cfg.filter.coarse_reset_hangover_blocks);
    238    ReadParam(section, "conservative_initial_phase",
    239              &cfg.filter.conservative_initial_phase);
    240    ReadParam(section, "enable_coarse_filter_output_usage",
    241              &cfg.filter.enable_coarse_filter_output_usage);
    242    ReadParam(section, "use_linear_filter", &cfg.filter.use_linear_filter);
    243    ReadParam(section, "high_pass_filter_echo_reference",
    244              &cfg.filter.high_pass_filter_echo_reference);
    245    ReadParam(section, "export_linear_aec_output",
    246              &cfg.filter.export_linear_aec_output);
    247  }
    248 
    249  if (GetValueFromJsonObject(aec3_root, "erle", &section)) {
    250    ReadParam(section, "min", &cfg.erle.min);
    251    ReadParam(section, "max_l", &cfg.erle.max_l);
    252    ReadParam(section, "max_h", &cfg.erle.max_h);
    253    ReadParam(section, "onset_detection", &cfg.erle.onset_detection);
    254    ReadParam(section, "num_sections", &cfg.erle.num_sections);
    255    ReadParam(section, "clamp_quality_estimate_to_zero",
    256              &cfg.erle.clamp_quality_estimate_to_zero);
    257    ReadParam(section, "clamp_quality_estimate_to_one",
    258              &cfg.erle.clamp_quality_estimate_to_one);
    259  }
    260 
    261  if (GetValueFromJsonObject(aec3_root, "ep_strength", &section)) {
    262    ReadParam(section, "default_gain", &cfg.ep_strength.default_gain);
    263    ReadParam(section, "default_len", &cfg.ep_strength.default_len);
    264    ReadParam(section, "nearend_len", &cfg.ep_strength.nearend_len);
    265    ReadParam(section, "echo_can_saturate", &cfg.ep_strength.echo_can_saturate);
    266    ReadParam(section, "bounded_erl", &cfg.ep_strength.bounded_erl);
    267    ReadParam(section, "erle_onset_compensation_in_dominant_nearend",
    268              &cfg.ep_strength.erle_onset_compensation_in_dominant_nearend);
    269    ReadParam(section, "use_conservative_tail_frequency_response",
    270              &cfg.ep_strength.use_conservative_tail_frequency_response);
    271  }
    272 
    273  if (GetValueFromJsonObject(aec3_root, "echo_audibility", &section)) {
    274    ReadParam(section, "low_render_limit",
    275              &cfg.echo_audibility.low_render_limit);
    276    ReadParam(section, "normal_render_limit",
    277              &cfg.echo_audibility.normal_render_limit);
    278 
    279    ReadParam(section, "floor_power", &cfg.echo_audibility.floor_power);
    280    ReadParam(section, "audibility_threshold_lf",
    281              &cfg.echo_audibility.audibility_threshold_lf);
    282    ReadParam(section, "audibility_threshold_mf",
    283              &cfg.echo_audibility.audibility_threshold_mf);
    284    ReadParam(section, "audibility_threshold_hf",
    285              &cfg.echo_audibility.audibility_threshold_hf);
    286    ReadParam(section, "use_stationarity_properties",
    287              &cfg.echo_audibility.use_stationarity_properties);
    288    ReadParam(section, "use_stationarity_properties_at_init",
    289              &cfg.echo_audibility.use_stationarity_properties_at_init);
    290  }
    291 
    292  if (GetValueFromJsonObject(aec3_root, "render_levels", &section)) {
    293    ReadParam(section, "active_render_limit",
    294              &cfg.render_levels.active_render_limit);
    295    ReadParam(section, "poor_excitation_render_limit",
    296              &cfg.render_levels.poor_excitation_render_limit);
    297    ReadParam(section, "poor_excitation_render_limit_ds8",
    298              &cfg.render_levels.poor_excitation_render_limit_ds8);
    299    ReadParam(section, "render_power_gain_db",
    300              &cfg.render_levels.render_power_gain_db);
    301  }
    302 
    303  if (GetValueFromJsonObject(aec3_root, "echo_removal_control", &section)) {
    304    ReadParam(section, "has_clock_drift",
    305              &cfg.echo_removal_control.has_clock_drift);
    306    ReadParam(section, "linear_and_stable_echo_path",
    307              &cfg.echo_removal_control.linear_and_stable_echo_path);
    308  }
    309 
    310  if (GetValueFromJsonObject(aec3_root, "echo_model", &section)) {
    311    Json::Value subsection;
    312    ReadParam(section, "noise_floor_hold", &cfg.echo_model.noise_floor_hold);
    313    ReadParam(section, "min_noise_floor_power",
    314              &cfg.echo_model.min_noise_floor_power);
    315    ReadParam(section, "stationary_gate_slope",
    316              &cfg.echo_model.stationary_gate_slope);
    317    ReadParam(section, "noise_gate_power", &cfg.echo_model.noise_gate_power);
    318    ReadParam(section, "noise_gate_slope", &cfg.echo_model.noise_gate_slope);
    319    ReadParam(section, "render_pre_window_size",
    320              &cfg.echo_model.render_pre_window_size);
    321    ReadParam(section, "render_post_window_size",
    322              &cfg.echo_model.render_post_window_size);
    323    ReadParam(section, "model_reverb_in_nonlinear_mode",
    324              &cfg.echo_model.model_reverb_in_nonlinear_mode);
    325  }
    326 
    327  if (GetValueFromJsonObject(aec3_root, "comfort_noise", &section)) {
    328    ReadParam(section, "noise_floor_dbfs", &cfg.comfort_noise.noise_floor_dbfs);
    329  }
    330 
    331  Json::Value subsection;
    332  if (GetValueFromJsonObject(aec3_root, "suppressor", &section)) {
    333    ReadParam(section, "nearend_average_blocks",
    334              &cfg.suppressor.nearend_average_blocks);
    335 
    336    if (GetValueFromJsonObject(section, "normal_tuning", &subsection)) {
    337      ReadParam(subsection, "mask_lf", &cfg.suppressor.normal_tuning.mask_lf);
    338      ReadParam(subsection, "mask_hf", &cfg.suppressor.normal_tuning.mask_hf);
    339      ReadParam(subsection, "max_inc_factor",
    340                &cfg.suppressor.normal_tuning.max_inc_factor);
    341      ReadParam(subsection, "max_dec_factor_lf",
    342                &cfg.suppressor.normal_tuning.max_dec_factor_lf);
    343    }
    344 
    345    if (GetValueFromJsonObject(section, "nearend_tuning", &subsection)) {
    346      ReadParam(subsection, "mask_lf", &cfg.suppressor.nearend_tuning.mask_lf);
    347      ReadParam(subsection, "mask_hf", &cfg.suppressor.nearend_tuning.mask_hf);
    348      ReadParam(subsection, "max_inc_factor",
    349                &cfg.suppressor.nearend_tuning.max_inc_factor);
    350      ReadParam(subsection, "max_dec_factor_lf",
    351                &cfg.suppressor.nearend_tuning.max_dec_factor_lf);
    352    }
    353 
    354    ReadParam(section, "lf_smoothing_during_initial_phase",
    355              &cfg.suppressor.lf_smoothing_during_initial_phase);
    356    ReadParam(section, "last_permanent_lf_smoothing_band",
    357              &cfg.suppressor.last_permanent_lf_smoothing_band);
    358    ReadParam(section, "last_lf_smoothing_band",
    359              &cfg.suppressor.last_lf_smoothing_band);
    360    ReadParam(section, "last_lf_band", &cfg.suppressor.last_lf_band);
    361    ReadParam(section, "first_hf_band", &cfg.suppressor.first_hf_band);
    362 
    363    if (GetValueFromJsonObject(section, "dominant_nearend_detection",
    364                               &subsection)) {
    365      ReadParam(subsection, "enr_threshold",
    366                &cfg.suppressor.dominant_nearend_detection.enr_threshold);
    367      ReadParam(subsection, "enr_exit_threshold",
    368                &cfg.suppressor.dominant_nearend_detection.enr_exit_threshold);
    369      ReadParam(subsection, "snr_threshold",
    370                &cfg.suppressor.dominant_nearend_detection.snr_threshold);
    371      ReadParam(subsection, "hold_duration",
    372                &cfg.suppressor.dominant_nearend_detection.hold_duration);
    373      ReadParam(subsection, "trigger_threshold",
    374                &cfg.suppressor.dominant_nearend_detection.trigger_threshold);
    375      ReadParam(
    376          subsection, "use_during_initial_phase",
    377          &cfg.suppressor.dominant_nearend_detection.use_during_initial_phase);
    378      ReadParam(subsection, "use_unbounded_echo_spectrum",
    379                &cfg.suppressor.dominant_nearend_detection
    380                     .use_unbounded_echo_spectrum);
    381    }
    382 
    383    if (GetValueFromJsonObject(section, "subband_nearend_detection",
    384                               &subsection)) {
    385      ReadParam(
    386          subsection, "nearend_average_blocks",
    387          &cfg.suppressor.subband_nearend_detection.nearend_average_blocks);
    388      ReadParam(subsection, "subband1",
    389                &cfg.suppressor.subband_nearend_detection.subband1);
    390      ReadParam(subsection, "subband2",
    391                &cfg.suppressor.subband_nearend_detection.subband2);
    392      ReadParam(subsection, "nearend_threshold",
    393                &cfg.suppressor.subband_nearend_detection.nearend_threshold);
    394      ReadParam(subsection, "snr_threshold",
    395                &cfg.suppressor.subband_nearend_detection.snr_threshold);
    396    }
    397 
    398    ReadParam(section, "use_subband_nearend_detection",
    399              &cfg.suppressor.use_subband_nearend_detection);
    400 
    401    if (GetValueFromJsonObject(section, "high_bands_suppression",
    402                               &subsection)) {
    403      ReadParam(subsection, "enr_threshold",
    404                &cfg.suppressor.high_bands_suppression.enr_threshold);
    405      ReadParam(subsection, "max_gain_during_echo",
    406                &cfg.suppressor.high_bands_suppression.max_gain_during_echo);
    407      ReadParam(subsection, "anti_howling_activation_threshold",
    408                &cfg.suppressor.high_bands_suppression
    409                     .anti_howling_activation_threshold);
    410      ReadParam(subsection, "anti_howling_gain",
    411                &cfg.suppressor.high_bands_suppression.anti_howling_gain);
    412    }
    413 
    414    ReadParam(section, "floor_first_increase",
    415              &cfg.suppressor.floor_first_increase);
    416    ReadParam(section, "conservative_hf_suppression",
    417              &cfg.suppressor.conservative_hf_suppression);
    418  }
    419 
    420  if (GetValueFromJsonObject(aec3_root, "multi_channel", &section)) {
    421    ReadParam(section, "detect_stereo_content",
    422              &cfg.multi_channel.detect_stereo_content);
    423    ReadParam(section, "stereo_detection_threshold",
    424              &cfg.multi_channel.stereo_detection_threshold);
    425    ReadParam(section, "stereo_detection_timeout_threshold_seconds",
    426              &cfg.multi_channel.stereo_detection_timeout_threshold_seconds);
    427    ReadParam(section, "stereo_detection_hysteresis_seconds",
    428              &cfg.multi_channel.stereo_detection_hysteresis_seconds);
    429  }
    430 }
    431 
    432 std::string Aec3ConfigToJsonString(const EchoCanceller3Config& config) {
    433  StringBuilder ost;
    434  ost << "{";
    435  ost << "\"aec3\": {";
    436  ost << "\"buffering\": {";
    437  ost << "\"excess_render_detection_interval_blocks\": "
    438      << config.buffering.excess_render_detection_interval_blocks << ",";
    439  ost << "\"max_allowed_excess_render_blocks\": "
    440      << config.buffering.max_allowed_excess_render_blocks;
    441  ost << "},";
    442 
    443  ost << "\"delay\": {";
    444  ost << "\"default_delay\": " << config.delay.default_delay << ",";
    445  ost << "\"down_sampling_factor\": " << config.delay.down_sampling_factor
    446      << ",";
    447  ost << "\"num_filters\": " << config.delay.num_filters << ",";
    448  ost << "\"delay_headroom_samples\": " << config.delay.delay_headroom_samples
    449      << ",";
    450  ost << "\"hysteresis_limit_blocks\": " << config.delay.hysteresis_limit_blocks
    451      << ",";
    452  ost << "\"fixed_capture_delay_samples\": "
    453      << config.delay.fixed_capture_delay_samples << ",";
    454  ost << "\"delay_estimate_smoothing\": "
    455      << config.delay.delay_estimate_smoothing << ",";
    456  ost << "\"delay_estimate_smoothing_delay_found\": "
    457      << config.delay.delay_estimate_smoothing_delay_found << ",";
    458  ost << "\"delay_candidate_detection_threshold\": "
    459      << config.delay.delay_candidate_detection_threshold << ",";
    460 
    461  ost << "\"delay_selection_thresholds\": {";
    462  ost << "\"initial\": " << config.delay.delay_selection_thresholds.initial
    463      << ",";
    464  ost << "\"converged\": " << config.delay.delay_selection_thresholds.converged;
    465  ost << "},";
    466 
    467  ost << "\"use_external_delay_estimator\": "
    468      << (config.delay.use_external_delay_estimator ? "true" : "false") << ",";
    469  ost << "\"log_warning_on_delay_changes\": "
    470      << (config.delay.log_warning_on_delay_changes ? "true" : "false") << ",";
    471 
    472  ost << "\"render_alignment_mixing\": {";
    473  ost << "\"downmix\": "
    474      << (config.delay.render_alignment_mixing.downmix ? "true" : "false")
    475      << ",";
    476  ost << "\"adaptive_selection\": "
    477      << (config.delay.render_alignment_mixing.adaptive_selection ? "true"
    478                                                                  : "false")
    479      << ",";
    480  ost << "\"activity_power_threshold\": "
    481      << config.delay.render_alignment_mixing.activity_power_threshold << ",";
    482  ost << "\"prefer_first_two_channels\": "
    483      << (config.delay.render_alignment_mixing.prefer_first_two_channels
    484              ? "true"
    485              : "false");
    486  ost << "},";
    487 
    488  ost << "\"capture_alignment_mixing\": {";
    489  ost << "\"downmix\": "
    490      << (config.delay.capture_alignment_mixing.downmix ? "true" : "false")
    491      << ",";
    492  ost << "\"adaptive_selection\": "
    493      << (config.delay.capture_alignment_mixing.adaptive_selection ? "true"
    494                                                                   : "false")
    495      << ",";
    496  ost << "\"activity_power_threshold\": "
    497      << config.delay.capture_alignment_mixing.activity_power_threshold << ",";
    498  ost << "\"prefer_first_two_channels\": "
    499      << (config.delay.capture_alignment_mixing.prefer_first_two_channels
    500              ? "true"
    501              : "false");
    502  ost << "},";
    503  ost << "\"detect_pre_echo\": "
    504      << (config.delay.detect_pre_echo ? "true" : "false");
    505  ost << "},";
    506 
    507  ost << "\"filter\": {";
    508 
    509  ost << "\"refined\": [";
    510  ost << config.filter.refined.length_blocks << ",";
    511  ost << config.filter.refined.leakage_converged << ",";
    512  ost << config.filter.refined.leakage_diverged << ",";
    513  ost << config.filter.refined.error_floor << ",";
    514  ost << config.filter.refined.error_ceil << ",";
    515  ost << config.filter.refined.noise_gate;
    516  ost << "],";
    517 
    518  ost << "\"coarse\": [";
    519  ost << config.filter.coarse.length_blocks << ",";
    520  ost << config.filter.coarse.rate << ",";
    521  ost << config.filter.coarse.noise_gate;
    522  ost << "],";
    523 
    524  ost << "\"refined_initial\": [";
    525  ost << config.filter.refined_initial.length_blocks << ",";
    526  ost << config.filter.refined_initial.leakage_converged << ",";
    527  ost << config.filter.refined_initial.leakage_diverged << ",";
    528  ost << config.filter.refined_initial.error_floor << ",";
    529  ost << config.filter.refined_initial.error_ceil << ",";
    530  ost << config.filter.refined_initial.noise_gate;
    531  ost << "],";
    532 
    533  ost << "\"coarse_initial\": [";
    534  ost << config.filter.coarse_initial.length_blocks << ",";
    535  ost << config.filter.coarse_initial.rate << ",";
    536  ost << config.filter.coarse_initial.noise_gate;
    537  ost << "],";
    538 
    539  ost << "\"config_change_duration_blocks\": "
    540      << config.filter.config_change_duration_blocks << ",";
    541  ost << "\"initial_state_seconds\": " << config.filter.initial_state_seconds
    542      << ",";
    543  ost << "\"coarse_reset_hangover_blocks\": "
    544      << config.filter.coarse_reset_hangover_blocks << ",";
    545  ost << "\"conservative_initial_phase\": "
    546      << (config.filter.conservative_initial_phase ? "true" : "false") << ",";
    547  ost << "\"enable_coarse_filter_output_usage\": "
    548      << (config.filter.enable_coarse_filter_output_usage ? "true" : "false")
    549      << ",";
    550  ost << "\"use_linear_filter\": "
    551      << (config.filter.use_linear_filter ? "true" : "false") << ",";
    552  ost << "\"high_pass_filter_echo_reference\": "
    553      << (config.filter.high_pass_filter_echo_reference ? "true" : "false")
    554      << ",";
    555  ost << "\"export_linear_aec_output\": "
    556      << (config.filter.export_linear_aec_output ? "true" : "false");
    557 
    558  ost << "},";
    559 
    560  ost << "\"erle\": {";
    561  ost << "\"min\": " << config.erle.min << ",";
    562  ost << "\"max_l\": " << config.erle.max_l << ",";
    563  ost << "\"max_h\": " << config.erle.max_h << ",";
    564  ost << "\"onset_detection\": "
    565      << (config.erle.onset_detection ? "true" : "false") << ",";
    566  ost << "\"num_sections\": " << config.erle.num_sections << ",";
    567  ost << "\"clamp_quality_estimate_to_zero\": "
    568      << (config.erle.clamp_quality_estimate_to_zero ? "true" : "false") << ",";
    569  ost << "\"clamp_quality_estimate_to_one\": "
    570      << (config.erle.clamp_quality_estimate_to_one ? "true" : "false");
    571  ost << "},";
    572 
    573  ost << "\"ep_strength\": {";
    574  ost << "\"default_gain\": " << config.ep_strength.default_gain << ",";
    575  ost << "\"default_len\": " << config.ep_strength.default_len << ",";
    576  ost << "\"nearend_len\": " << config.ep_strength.nearend_len << ",";
    577  ost << "\"echo_can_saturate\": "
    578      << (config.ep_strength.echo_can_saturate ? "true" : "false") << ",";
    579  ost << "\"bounded_erl\": "
    580      << (config.ep_strength.bounded_erl ? "true" : "false") << ",";
    581  ost << "\"erle_onset_compensation_in_dominant_nearend\": "
    582      << (config.ep_strength.erle_onset_compensation_in_dominant_nearend
    583              ? "true"
    584              : "false")
    585      << ",";
    586  ost << "\"use_conservative_tail_frequency_response\": "
    587      << (config.ep_strength.use_conservative_tail_frequency_response
    588              ? "true"
    589              : "false");
    590  ost << "},";
    591 
    592  ost << "\"echo_audibility\": {";
    593  ost << "\"low_render_limit\": " << config.echo_audibility.low_render_limit
    594      << ",";
    595  ost << "\"normal_render_limit\": "
    596      << config.echo_audibility.normal_render_limit << ",";
    597  ost << "\"floor_power\": " << config.echo_audibility.floor_power << ",";
    598  ost << "\"audibility_threshold_lf\": "
    599      << config.echo_audibility.audibility_threshold_lf << ",";
    600  ost << "\"audibility_threshold_mf\": "
    601      << config.echo_audibility.audibility_threshold_mf << ",";
    602  ost << "\"audibility_threshold_hf\": "
    603      << config.echo_audibility.audibility_threshold_hf << ",";
    604  ost << "\"use_stationarity_properties\": "
    605      << (config.echo_audibility.use_stationarity_properties ? "true" : "false")
    606      << ",";
    607  ost << "\"use_stationarity_properties_at_init\": "
    608      << (config.echo_audibility.use_stationarity_properties_at_init ? "true"
    609                                                                     : "false");
    610  ost << "},";
    611 
    612  ost << "\"render_levels\": {";
    613  ost << "\"active_render_limit\": " << config.render_levels.active_render_limit
    614      << ",";
    615  ost << "\"poor_excitation_render_limit\": "
    616      << config.render_levels.poor_excitation_render_limit << ",";
    617  ost << "\"poor_excitation_render_limit_ds8\": "
    618      << config.render_levels.poor_excitation_render_limit_ds8 << ",";
    619  ost << "\"render_power_gain_db\": "
    620      << config.render_levels.render_power_gain_db;
    621  ost << "},";
    622 
    623  ost << "\"echo_removal_control\": {";
    624  ost << "\"has_clock_drift\": "
    625      << (config.echo_removal_control.has_clock_drift ? "true" : "false")
    626      << ",";
    627  ost << "\"linear_and_stable_echo_path\": "
    628      << (config.echo_removal_control.linear_and_stable_echo_path ? "true"
    629                                                                  : "false");
    630 
    631  ost << "},";
    632 
    633  ost << "\"echo_model\": {";
    634  ost << "\"noise_floor_hold\": " << config.echo_model.noise_floor_hold << ",";
    635  ost << "\"min_noise_floor_power\": "
    636      << config.echo_model.min_noise_floor_power << ",";
    637  ost << "\"stationary_gate_slope\": "
    638      << config.echo_model.stationary_gate_slope << ",";
    639  ost << "\"noise_gate_power\": " << config.echo_model.noise_gate_power << ",";
    640  ost << "\"noise_gate_slope\": " << config.echo_model.noise_gate_slope << ",";
    641  ost << "\"render_pre_window_size\": "
    642      << config.echo_model.render_pre_window_size << ",";
    643  ost << "\"render_post_window_size\": "
    644      << config.echo_model.render_post_window_size << ",";
    645  ost << "\"model_reverb_in_nonlinear_mode\": "
    646      << (config.echo_model.model_reverb_in_nonlinear_mode ? "true" : "false");
    647  ost << "},";
    648 
    649  ost << "\"comfort_noise\": {";
    650  ost << "\"noise_floor_dbfs\": " << config.comfort_noise.noise_floor_dbfs;
    651  ost << "},";
    652 
    653  ost << "\"suppressor\": {";
    654  ost << "\"nearend_average_blocks\": "
    655      << config.suppressor.nearend_average_blocks << ",";
    656  ost << "\"normal_tuning\": {";
    657  ost << "\"mask_lf\": [";
    658  ost << config.suppressor.normal_tuning.mask_lf.enr_transparent << ",";
    659  ost << config.suppressor.normal_tuning.mask_lf.enr_suppress << ",";
    660  ost << config.suppressor.normal_tuning.mask_lf.emr_transparent;
    661  ost << "],";
    662  ost << "\"mask_hf\": [";
    663  ost << config.suppressor.normal_tuning.mask_hf.enr_transparent << ",";
    664  ost << config.suppressor.normal_tuning.mask_hf.enr_suppress << ",";
    665  ost << config.suppressor.normal_tuning.mask_hf.emr_transparent;
    666  ost << "],";
    667  ost << "\"max_inc_factor\": "
    668      << config.suppressor.normal_tuning.max_inc_factor << ",";
    669  ost << "\"max_dec_factor_lf\": "
    670      << config.suppressor.normal_tuning.max_dec_factor_lf;
    671  ost << "},";
    672  ost << "\"nearend_tuning\": {";
    673  ost << "\"mask_lf\": [";
    674  ost << config.suppressor.nearend_tuning.mask_lf.enr_transparent << ",";
    675  ost << config.suppressor.nearend_tuning.mask_lf.enr_suppress << ",";
    676  ost << config.suppressor.nearend_tuning.mask_lf.emr_transparent;
    677  ost << "],";
    678  ost << "\"mask_hf\": [";
    679  ost << config.suppressor.nearend_tuning.mask_hf.enr_transparent << ",";
    680  ost << config.suppressor.nearend_tuning.mask_hf.enr_suppress << ",";
    681  ost << config.suppressor.nearend_tuning.mask_hf.emr_transparent;
    682  ost << "],";
    683  ost << "\"max_inc_factor\": "
    684      << config.suppressor.nearend_tuning.max_inc_factor << ",";
    685  ost << "\"max_dec_factor_lf\": "
    686      << config.suppressor.nearend_tuning.max_dec_factor_lf;
    687  ost << "},";
    688  ost << "\"lf_smoothing_during_initial_phase\": "
    689      << (config.suppressor.lf_smoothing_during_initial_phase ? "true"
    690                                                              : "false")
    691      << ",";
    692  ost << "\"last_permanent_lf_smoothing_band\": "
    693      << config.suppressor.last_permanent_lf_smoothing_band << ",";
    694  ost << "\"last_lf_smoothing_band\": "
    695      << config.suppressor.last_lf_smoothing_band << ",";
    696  ost << "\"last_lf_band\": " << config.suppressor.last_lf_band << ",";
    697  ost << "\"first_hf_band\": " << config.suppressor.first_hf_band << ",";
    698  {
    699    const auto& dnd = config.suppressor.dominant_nearend_detection;
    700    ost << "\"dominant_nearend_detection\": {";
    701    ost << "\"enr_threshold\": " << dnd.enr_threshold << ",";
    702    ost << "\"enr_exit_threshold\": " << dnd.enr_exit_threshold << ",";
    703    ost << "\"snr_threshold\": " << dnd.snr_threshold << ",";
    704    ost << "\"hold_duration\": " << dnd.hold_duration << ",";
    705    ost << "\"trigger_threshold\": " << dnd.trigger_threshold << ",";
    706    ost << "\"use_during_initial_phase\": " << dnd.use_during_initial_phase
    707        << ",";
    708    ost << "\"use_unbounded_echo_spectrum\": "
    709        << dnd.use_unbounded_echo_spectrum;
    710    ost << "},";
    711  }
    712  ost << "\"subband_nearend_detection\": {";
    713  ost << "\"nearend_average_blocks\": "
    714      << config.suppressor.subband_nearend_detection.nearend_average_blocks
    715      << ",";
    716  ost << "\"subband1\": [";
    717  ost << config.suppressor.subband_nearend_detection.subband1.low << ",";
    718  ost << config.suppressor.subband_nearend_detection.subband1.high;
    719  ost << "],";
    720  ost << "\"subband2\": [";
    721  ost << config.suppressor.subband_nearend_detection.subband2.low << ",";
    722  ost << config.suppressor.subband_nearend_detection.subband2.high;
    723  ost << "],";
    724  ost << "\"nearend_threshold\": "
    725      << config.suppressor.subband_nearend_detection.nearend_threshold << ",";
    726  ost << "\"snr_threshold\": "
    727      << config.suppressor.subband_nearend_detection.snr_threshold;
    728  ost << "},";
    729  ost << "\"use_subband_nearend_detection\": "
    730      << config.suppressor.use_subband_nearend_detection << ",";
    731  ost << "\"high_bands_suppression\": {";
    732  ost << "\"enr_threshold\": "
    733      << config.suppressor.high_bands_suppression.enr_threshold << ",";
    734  ost << "\"max_gain_during_echo\": "
    735      << config.suppressor.high_bands_suppression.max_gain_during_echo << ",";
    736  ost << "\"anti_howling_activation_threshold\": "
    737      << config.suppressor.high_bands_suppression
    738             .anti_howling_activation_threshold
    739      << ",";
    740  ost << "\"anti_howling_gain\": "
    741      << config.suppressor.high_bands_suppression.anti_howling_gain;
    742  ost << "},";
    743  ost << "\"floor_first_increase\": " << config.suppressor.floor_first_increase
    744      << ",";
    745  ost << "\"conservative_hf_suppression\": "
    746      << config.suppressor.conservative_hf_suppression;
    747  ost << "},";
    748 
    749  ost << "\"multi_channel\": {";
    750  ost << "\"detect_stereo_content\": "
    751      << (config.multi_channel.detect_stereo_content ? "true" : "false") << ",";
    752  ost << "\"stereo_detection_threshold\": "
    753      << config.multi_channel.stereo_detection_threshold << ",";
    754  ost << "\"stereo_detection_timeout_threshold_seconds\": "
    755      << config.multi_channel.stereo_detection_timeout_threshold_seconds << ",";
    756  ost << "\"stereo_detection_hysteresis_seconds\": "
    757      << config.multi_channel.stereo_detection_hysteresis_seconds;
    758  ost << "}";
    759 
    760  ost << "}";
    761  ost << "}";
    762 
    763  return ost.Release();
    764 }
    765 }  // namespace webrtc