tor-browser

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

echo_canceller3.cc (43108B)


      1 /*
      2 *  Copyright (c) 2016 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/aec3/echo_canceller3.h"
     11 
     12 #include <algorithm>
     13 #include <atomic>
     14 #include <cstddef>
     15 #include <memory>
     16 #include <optional>
     17 #include <string>
     18 #include <utility>
     19 #include <vector>
     20 
     21 #include "absl/strings/string_view.h"
     22 #include "api/array_view.h"
     23 #include "api/audio/echo_canceller3_config.h"
     24 #include "api/audio/echo_control.h"
     25 #include "api/environment/environment.h"
     26 #include "api/field_trials_view.h"
     27 #include "modules/audio_processing/aec3/aec3_common.h"
     28 #include "modules/audio_processing/aec3/block.h"
     29 #include "modules/audio_processing/aec3/block_delay_buffer.h"
     30 #include "modules/audio_processing/aec3/block_framer.h"
     31 #include "modules/audio_processing/aec3/block_processor.h"
     32 #include "modules/audio_processing/aec3/frame_blocker.h"
     33 #include "modules/audio_processing/high_pass_filter.h"
     34 #include "modules/audio_processing/logging/apm_data_dumper.h"
     35 #include "rtc_base/checks.h"
     36 #include "rtc_base/experiments/field_trial_parser.h"
     37 #include "rtc_base/logging.h"
     38 #include "rtc_base/race_checker.h"
     39 #include "rtc_base/swap_queue.h"
     40 
     41 namespace webrtc {
     42 
     43 namespace {
     44 
     45 enum class EchoCanceller3ApiCall { kCapture, kRender };
     46 
     47 bool DetectSaturation(ArrayView<const float> y) {
     48  for (size_t k = 0; k < y.size(); ++k) {
     49    if (y[k] >= 32700.0f || y[k] <= -32700.0f) {
     50      return true;
     51    }
     52  }
     53  return false;
     54 }
     55 
     56 // Retrieves a value from a field trial if it is available. If no value is
     57 // present, the default value is returned. If the retrieved value is beyond the
     58 // specified limits, the default value is returned instead.
     59 void RetrieveFieldTrialValue(const FieldTrialsView& field_trials,
     60                             absl::string_view trial_name,
     61                             float min,
     62                             float max,
     63                             float* value_to_update) {
     64  const std::string field_trial_str = field_trials.Lookup(trial_name);
     65 
     66  FieldTrialParameter<double> field_trial_param(/*key=*/"", *value_to_update);
     67 
     68  ParseFieldTrial({&field_trial_param}, field_trial_str);
     69  float field_trial_value = static_cast<float>(field_trial_param.Get());
     70 
     71  if (field_trial_value >= min && field_trial_value <= max &&
     72      field_trial_value != *value_to_update) {
     73    RTC_LOG(LS_INFO) << "Key " << trial_name
     74                     << " changing AEC3 parameter value from "
     75                     << *value_to_update << " to " << field_trial_value;
     76    *value_to_update = field_trial_value;
     77  }
     78 }
     79 
     80 void RetrieveFieldTrialValue(const FieldTrialsView& field_trials,
     81                             absl::string_view trial_name,
     82                             int min,
     83                             int max,
     84                             int* value_to_update) {
     85  const std::string field_trial_str = field_trials.Lookup(trial_name);
     86 
     87  FieldTrialParameter<int> field_trial_param(/*key=*/"", *value_to_update);
     88 
     89  ParseFieldTrial({&field_trial_param}, field_trial_str);
     90  float field_trial_value = field_trial_param.Get();
     91 
     92  if (field_trial_value >= min && field_trial_value <= max &&
     93      field_trial_value != *value_to_update) {
     94    RTC_LOG(LS_INFO) << "Key " << trial_name
     95                     << " changing AEC3 parameter value from "
     96                     << *value_to_update << " to " << field_trial_value;
     97    *value_to_update = field_trial_value;
     98  }
     99 }
    100 
    101 void FillSubFrameView(
    102    AudioBuffer* frame,
    103    size_t sub_frame_index,
    104    std::vector<std::vector<ArrayView<float>>>* sub_frame_view) {
    105  RTC_DCHECK_GE(1, sub_frame_index);
    106  RTC_DCHECK_LE(0, sub_frame_index);
    107  RTC_DCHECK_EQ(frame->num_bands(), sub_frame_view->size());
    108  RTC_DCHECK_EQ(frame->num_channels(), (*sub_frame_view)[0].size());
    109  for (size_t band = 0; band < sub_frame_view->size(); ++band) {
    110    for (size_t channel = 0; channel < (*sub_frame_view)[0].size(); ++channel) {
    111      (*sub_frame_view)[band][channel] = ArrayView<float>(
    112          &frame->split_bands(channel)[band][sub_frame_index * kSubFrameLength],
    113          kSubFrameLength);
    114    }
    115  }
    116 }
    117 
    118 void FillSubFrameView(
    119    bool proper_downmix_needed,
    120    std::vector<std::vector<std::vector<float>>>* frame,
    121    size_t sub_frame_index,
    122    std::vector<std::vector<ArrayView<float>>>* sub_frame_view) {
    123  RTC_DCHECK_GE(1, sub_frame_index);
    124  RTC_DCHECK_EQ(frame->size(), sub_frame_view->size());
    125  const size_t frame_num_channels = (*frame)[0].size();
    126  const size_t sub_frame_num_channels = (*sub_frame_view)[0].size();
    127  if (frame_num_channels > sub_frame_num_channels) {
    128    RTC_DCHECK_EQ(sub_frame_num_channels, 1u);
    129    if (proper_downmix_needed) {
    130      // When a proper downmix is needed (which is the case when proper stereo
    131      // is present in the echo reference signal but the echo canceller does the
    132      // processing in mono) downmix the echo reference by averaging the channel
    133      // content (otherwise downmixing is done by selecting channel 0).
    134      for (size_t band = 0; band < frame->size(); ++band) {
    135        for (size_t ch = 1; ch < frame_num_channels; ++ch) {
    136          for (size_t k = 0; k < kSubFrameLength; ++k) {
    137            (*frame)[band][/*channel=*/0]
    138                    [sub_frame_index * kSubFrameLength + k] +=
    139                (*frame)[band][ch][sub_frame_index * kSubFrameLength + k];
    140          }
    141        }
    142        const float one_by_num_channels = 1.0f / frame_num_channels;
    143        for (size_t k = 0; k < kSubFrameLength; ++k) {
    144          (*frame)[band][/*channel=*/0][sub_frame_index * kSubFrameLength +
    145                                        k] *= one_by_num_channels;
    146        }
    147      }
    148    }
    149    for (size_t band = 0; band < frame->size(); ++band) {
    150      (*sub_frame_view)[band][/*channel=*/0] = ArrayView<float>(
    151          &(*frame)[band][/*channel=*/0][sub_frame_index * kSubFrameLength],
    152          kSubFrameLength);
    153    }
    154  } else {
    155    RTC_DCHECK_EQ(frame_num_channels, sub_frame_num_channels);
    156    for (size_t band = 0; band < frame->size(); ++band) {
    157      for (size_t channel = 0; channel < (*frame)[band].size(); ++channel) {
    158        (*sub_frame_view)[band][channel] = ArrayView<float>(
    159            &(*frame)[band][channel][sub_frame_index * kSubFrameLength],
    160            kSubFrameLength);
    161      }
    162    }
    163  }
    164 }
    165 
    166 void ProcessCaptureFrameContent(
    167    AudioBuffer* linear_output,
    168    AudioBuffer* capture,
    169    bool level_change,
    170    bool aec_reference_is_downmixed_stereo,
    171    bool saturated_microphone_signal,
    172    size_t sub_frame_index,
    173    FrameBlocker* capture_blocker,
    174    BlockFramer* linear_output_framer,
    175    BlockFramer* output_framer,
    176    BlockProcessor* block_processor,
    177    Block* linear_output_block,
    178    std::vector<std::vector<ArrayView<float>>>* linear_output_sub_frame_view,
    179    Block* capture_block,
    180    std::vector<std::vector<ArrayView<float>>>* capture_sub_frame_view) {
    181  FillSubFrameView(capture, sub_frame_index, capture_sub_frame_view);
    182 
    183  if (linear_output) {
    184    RTC_DCHECK(linear_output_framer);
    185    RTC_DCHECK(linear_output_block);
    186    RTC_DCHECK(linear_output_sub_frame_view);
    187    FillSubFrameView(linear_output, sub_frame_index,
    188                     linear_output_sub_frame_view);
    189  }
    190 
    191  capture_blocker->InsertSubFrameAndExtractBlock(*capture_sub_frame_view,
    192                                                 capture_block);
    193  block_processor->ProcessCapture(
    194      /*echo_path_gain_change=*/level_change ||
    195          aec_reference_is_downmixed_stereo,
    196      saturated_microphone_signal, linear_output_block, capture_block);
    197  output_framer->InsertBlockAndExtractSubFrame(*capture_block,
    198                                               capture_sub_frame_view);
    199 
    200  if (linear_output) {
    201    RTC_DCHECK(linear_output_framer);
    202    linear_output_framer->InsertBlockAndExtractSubFrame(
    203        *linear_output_block, linear_output_sub_frame_view);
    204  }
    205 }
    206 
    207 void ProcessRemainingCaptureFrameContent(bool level_change,
    208                                         bool aec_reference_is_downmixed_stereo,
    209                                         bool saturated_microphone_signal,
    210                                         FrameBlocker* capture_blocker,
    211                                         BlockFramer* linear_output_framer,
    212                                         BlockFramer* output_framer,
    213                                         BlockProcessor* block_processor,
    214                                         Block* linear_output_block,
    215                                         Block* block) {
    216  if (!capture_blocker->IsBlockAvailable()) {
    217    return;
    218  }
    219 
    220  capture_blocker->ExtractBlock(block);
    221  block_processor->ProcessCapture(
    222      /*echo_path_gain_change=*/level_change ||
    223          aec_reference_is_downmixed_stereo,
    224      saturated_microphone_signal, linear_output_block, block);
    225  output_framer->InsertBlock(*block);
    226 
    227  if (linear_output_framer) {
    228    RTC_DCHECK(linear_output_block);
    229    linear_output_framer->InsertBlock(*linear_output_block);
    230  }
    231 }
    232 
    233 void BufferRenderFrameContent(
    234    bool proper_downmix_needed,
    235    std::vector<std::vector<std::vector<float>>>* render_frame,
    236    size_t sub_frame_index,
    237    FrameBlocker* render_blocker,
    238    BlockProcessor* block_processor,
    239    Block* block,
    240    std::vector<std::vector<ArrayView<float>>>* sub_frame_view) {
    241  FillSubFrameView(proper_downmix_needed, render_frame, sub_frame_index,
    242                   sub_frame_view);
    243  render_blocker->InsertSubFrameAndExtractBlock(*sub_frame_view, block);
    244  block_processor->BufferRender(*block);
    245 }
    246 
    247 void BufferRemainingRenderFrameContent(FrameBlocker* render_blocker,
    248                                       BlockProcessor* block_processor,
    249                                       Block* block) {
    250  if (!render_blocker->IsBlockAvailable()) {
    251    return;
    252  }
    253  render_blocker->ExtractBlock(block);
    254  block_processor->BufferRender(*block);
    255 }
    256 
    257 void CopyBufferIntoFrame(const AudioBuffer& buffer,
    258                         size_t num_bands,
    259                         size_t num_channels,
    260                         std::vector<std::vector<std::vector<float>>>* frame) {
    261  RTC_DCHECK_EQ(num_bands, frame->size());
    262  RTC_DCHECK_EQ(num_channels, (*frame)[0].size());
    263  RTC_DCHECK_EQ(AudioBuffer::kSplitBandSize, (*frame)[0][0].size());
    264  for (size_t band = 0; band < num_bands; ++band) {
    265    for (size_t channel = 0; channel < num_channels; ++channel) {
    266      ArrayView<const float> buffer_view(
    267          &buffer.split_bands_const(channel)[band][0],
    268          AudioBuffer::kSplitBandSize);
    269      std::copy(buffer_view.begin(), buffer_view.end(),
    270                (*frame)[band][channel].begin());
    271    }
    272  }
    273 }
    274 
    275 }  // namespace
    276 
    277 // TODO(webrtc:5298): Move this to a separate file.
    278 EchoCanceller3Config AdjustConfig(const EchoCanceller3Config& config,
    279                                  const FieldTrialsView& field_trials) {
    280  EchoCanceller3Config adjusted_cfg = config;
    281 
    282  if (field_trials.IsEnabled("WebRTC-Aec3StereoContentDetectionKillSwitch")) {
    283    adjusted_cfg.multi_channel.detect_stereo_content = false;
    284  }
    285 
    286  if (field_trials.IsEnabled("WebRTC-Aec3AntiHowlingMinimizationKillSwitch")) {
    287    adjusted_cfg.suppressor.high_bands_suppression
    288        .anti_howling_activation_threshold = 25.f;
    289    adjusted_cfg.suppressor.high_bands_suppression.anti_howling_gain = 0.01f;
    290  }
    291 
    292  if (field_trials.IsEnabled("WebRTC-Aec3UseShortConfigChangeDuration")) {
    293    adjusted_cfg.filter.config_change_duration_blocks = 10;
    294  }
    295 
    296  if (field_trials.IsEnabled("WebRTC-Aec3UseZeroInitialStateDuration")) {
    297    adjusted_cfg.filter.initial_state_seconds = 0.f;
    298  } else if (field_trials.IsEnabled(
    299                 "WebRTC-Aec3UseDot1SecondsInitialStateDuration")) {
    300    adjusted_cfg.filter.initial_state_seconds = .1f;
    301  } else if (field_trials.IsEnabled(
    302                 "WebRTC-Aec3UseDot2SecondsInitialStateDuration")) {
    303    adjusted_cfg.filter.initial_state_seconds = .2f;
    304  } else if (field_trials.IsEnabled(
    305                 "WebRTC-Aec3UseDot3SecondsInitialStateDuration")) {
    306    adjusted_cfg.filter.initial_state_seconds = .3f;
    307  } else if (field_trials.IsEnabled(
    308                 "WebRTC-Aec3UseDot6SecondsInitialStateDuration")) {
    309    adjusted_cfg.filter.initial_state_seconds = .6f;
    310  } else if (field_trials.IsEnabled(
    311                 "WebRTC-Aec3UseDot9SecondsInitialStateDuration")) {
    312    adjusted_cfg.filter.initial_state_seconds = .9f;
    313  } else if (field_trials.IsEnabled(
    314                 "WebRTC-Aec3Use1Dot2SecondsInitialStateDuration")) {
    315    adjusted_cfg.filter.initial_state_seconds = 1.2f;
    316  } else if (field_trials.IsEnabled(
    317                 "WebRTC-Aec3Use1Dot6SecondsInitialStateDuration")) {
    318    adjusted_cfg.filter.initial_state_seconds = 1.6f;
    319  } else if (field_trials.IsEnabled(
    320                 "WebRTC-Aec3Use2Dot0SecondsInitialStateDuration")) {
    321    adjusted_cfg.filter.initial_state_seconds = 2.0f;
    322  }
    323 
    324  if (field_trials.IsEnabled("WebRTC-Aec3HighPassFilterEchoReference")) {
    325    adjusted_cfg.filter.high_pass_filter_echo_reference = true;
    326  }
    327 
    328  if (field_trials.IsEnabled("WebRTC-Aec3EchoSaturationDetectionKillSwitch")) {
    329    adjusted_cfg.ep_strength.echo_can_saturate = false;
    330  }
    331 
    332  const std::string use_nearend_reverb_len_tunings =
    333      field_trials.Lookup("WebRTC-Aec3UseNearendReverbLen");
    334  FieldTrialParameter<double> nearend_reverb_default_len(
    335      "default_len", adjusted_cfg.ep_strength.default_len);
    336  FieldTrialParameter<double> nearend_reverb_nearend_len(
    337      "nearend_len", adjusted_cfg.ep_strength.nearend_len);
    338 
    339  ParseFieldTrial({&nearend_reverb_default_len, &nearend_reverb_nearend_len},
    340                  use_nearend_reverb_len_tunings);
    341  float default_len = static_cast<float>(nearend_reverb_default_len.Get());
    342  float nearend_len = static_cast<float>(nearend_reverb_nearend_len.Get());
    343  if (default_len > -1 && default_len < 1 && nearend_len > -1 &&
    344      nearend_len < 1) {
    345    adjusted_cfg.ep_strength.default_len =
    346        static_cast<float>(nearend_reverb_default_len.Get());
    347    adjusted_cfg.ep_strength.nearend_len =
    348        static_cast<float>(nearend_reverb_nearend_len.Get());
    349  }
    350 
    351  if (field_trials.IsEnabled("WebRTC-Aec3ConservativeTailFreqResponse")) {
    352    adjusted_cfg.ep_strength.use_conservative_tail_frequency_response = true;
    353  }
    354 
    355  if (field_trials.IsDisabled("WebRTC-Aec3ConservativeTailFreqResponse")) {
    356    adjusted_cfg.ep_strength.use_conservative_tail_frequency_response = false;
    357  }
    358 
    359  if (field_trials.IsEnabled("WebRTC-Aec3ShortHeadroomKillSwitch")) {
    360    // Two blocks headroom.
    361    adjusted_cfg.delay.delay_headroom_samples = kBlockSize * 2;
    362  }
    363 
    364  if (field_trials.IsEnabled("WebRTC-Aec3ClampInstQualityToZeroKillSwitch")) {
    365    adjusted_cfg.erle.clamp_quality_estimate_to_zero = false;
    366  }
    367 
    368  if (field_trials.IsEnabled("WebRTC-Aec3ClampInstQualityToOneKillSwitch")) {
    369    adjusted_cfg.erle.clamp_quality_estimate_to_one = false;
    370  }
    371 
    372  if (field_trials.IsEnabled("WebRTC-Aec3OnsetDetectionKillSwitch")) {
    373    adjusted_cfg.erle.onset_detection = false;
    374  }
    375 
    376  if (field_trials.IsEnabled(
    377          "WebRTC-Aec3EnforceRenderDelayEstimationDownmixing")) {
    378    adjusted_cfg.delay.render_alignment_mixing.downmix = true;
    379    adjusted_cfg.delay.render_alignment_mixing.adaptive_selection = false;
    380  }
    381 
    382  if (field_trials.IsEnabled(
    383          "WebRTC-Aec3EnforceCaptureDelayEstimationDownmixing")) {
    384    adjusted_cfg.delay.capture_alignment_mixing.downmix = true;
    385    adjusted_cfg.delay.capture_alignment_mixing.adaptive_selection = false;
    386  }
    387 
    388  if (field_trials.IsEnabled(
    389          "WebRTC-Aec3EnforceCaptureDelayEstimationLeftRightPrioritization")) {
    390    adjusted_cfg.delay.capture_alignment_mixing.prefer_first_two_channels =
    391        true;
    392  }
    393 
    394  if (field_trials.IsEnabled(
    395          "WebRTC-"
    396          "Aec3RenderDelayEstimationLeftRightPrioritizationKillSwitch")) {
    397    adjusted_cfg.delay.capture_alignment_mixing.prefer_first_two_channels =
    398        false;
    399  }
    400 
    401  if (field_trials.IsEnabled("WebRTC-Aec3SensitiveDominantNearendActivation")) {
    402    adjusted_cfg.suppressor.dominant_nearend_detection.enr_threshold = 0.5f;
    403  } else if (field_trials.IsEnabled(
    404                 "WebRTC-Aec3VerySensitiveDominantNearendActivation")) {
    405    adjusted_cfg.suppressor.dominant_nearend_detection.enr_threshold = 0.75f;
    406  }
    407 
    408  if (field_trials.IsEnabled("WebRTC-Aec3TransparentAntiHowlingGain")) {
    409    adjusted_cfg.suppressor.high_bands_suppression.anti_howling_gain = 1.f;
    410  }
    411 
    412  if (field_trials.IsEnabled(
    413          "WebRTC-Aec3EnforceMoreTransparentNormalSuppressorTuning")) {
    414    adjusted_cfg.suppressor.normal_tuning.mask_lf.enr_transparent = 0.4f;
    415    adjusted_cfg.suppressor.normal_tuning.mask_lf.enr_suppress = 0.5f;
    416  }
    417 
    418  if (field_trials.IsEnabled(
    419          "WebRTC-Aec3EnforceMoreTransparentNearendSuppressorTuning")) {
    420    adjusted_cfg.suppressor.nearend_tuning.mask_lf.enr_transparent = 1.29f;
    421    adjusted_cfg.suppressor.nearend_tuning.mask_lf.enr_suppress = 1.3f;
    422  }
    423 
    424  if (field_trials.IsEnabled(
    425          "WebRTC-Aec3EnforceMoreTransparentNormalSuppressorHfTuning")) {
    426    adjusted_cfg.suppressor.normal_tuning.mask_hf.enr_transparent = 0.3f;
    427    adjusted_cfg.suppressor.normal_tuning.mask_hf.enr_suppress = 0.4f;
    428  }
    429 
    430  if (field_trials.IsEnabled(
    431          "WebRTC-Aec3EnforceMoreTransparentNearendSuppressorHfTuning")) {
    432    adjusted_cfg.suppressor.nearend_tuning.mask_hf.enr_transparent = 1.09f;
    433    adjusted_cfg.suppressor.nearend_tuning.mask_hf.enr_suppress = 1.1f;
    434  }
    435 
    436  if (field_trials.IsEnabled(
    437          "WebRTC-Aec3EnforceRapidlyAdjustingNormalSuppressorTunings")) {
    438    adjusted_cfg.suppressor.normal_tuning.max_inc_factor = 2.5f;
    439  }
    440 
    441  if (field_trials.IsEnabled(
    442          "WebRTC-Aec3EnforceRapidlyAdjustingNearendSuppressorTunings")) {
    443    adjusted_cfg.suppressor.nearend_tuning.max_inc_factor = 2.5f;
    444  }
    445 
    446  if (field_trials.IsEnabled(
    447          "WebRTC-Aec3EnforceSlowlyAdjustingNormalSuppressorTunings")) {
    448    adjusted_cfg.suppressor.normal_tuning.max_dec_factor_lf = .2f;
    449  }
    450 
    451  if (field_trials.IsEnabled(
    452          "WebRTC-Aec3EnforceSlowlyAdjustingNearendSuppressorTunings")) {
    453    adjusted_cfg.suppressor.nearend_tuning.max_dec_factor_lf = .2f;
    454  }
    455 
    456  if (field_trials.IsEnabled("WebRTC-Aec3EnforceConservativeHfSuppression")) {
    457    adjusted_cfg.suppressor.conservative_hf_suppression = true;
    458  }
    459 
    460  if (field_trials.IsEnabled("WebRTC-Aec3EnforceStationarityProperties")) {
    461    adjusted_cfg.echo_audibility.use_stationarity_properties = true;
    462  }
    463 
    464  if (field_trials.IsEnabled(
    465          "WebRTC-Aec3EnforceStationarityPropertiesAtInit")) {
    466    adjusted_cfg.echo_audibility.use_stationarity_properties_at_init = true;
    467  }
    468 
    469  if (field_trials.IsEnabled("WebRTC-Aec3EnforceLowActiveRenderLimit")) {
    470    adjusted_cfg.render_levels.active_render_limit = 50.f;
    471  } else if (field_trials.IsEnabled(
    472                 "WebRTC-Aec3EnforceVeryLowActiveRenderLimit")) {
    473    adjusted_cfg.render_levels.active_render_limit = 30.f;
    474  }
    475 
    476  if (field_trials.IsEnabled("WebRTC-Aec3NonlinearModeReverbKillSwitch")) {
    477    adjusted_cfg.echo_model.model_reverb_in_nonlinear_mode = false;
    478  }
    479 
    480  // Field-trial based override for the whole suppressor tuning.
    481  const std::string suppressor_tuning_override_trial_name =
    482      field_trials.Lookup("WebRTC-Aec3SuppressorTuningOverride");
    483 
    484  FieldTrialParameter<double> nearend_tuning_mask_lf_enr_transparent(
    485      "nearend_tuning_mask_lf_enr_transparent",
    486      adjusted_cfg.suppressor.nearend_tuning.mask_lf.enr_transparent);
    487  FieldTrialParameter<double> nearend_tuning_mask_lf_enr_suppress(
    488      "nearend_tuning_mask_lf_enr_suppress",
    489      adjusted_cfg.suppressor.nearend_tuning.mask_lf.enr_suppress);
    490  FieldTrialParameter<double> nearend_tuning_mask_hf_enr_transparent(
    491      "nearend_tuning_mask_hf_enr_transparent",
    492      adjusted_cfg.suppressor.nearend_tuning.mask_hf.enr_transparent);
    493  FieldTrialParameter<double> nearend_tuning_mask_hf_enr_suppress(
    494      "nearend_tuning_mask_hf_enr_suppress",
    495      adjusted_cfg.suppressor.nearend_tuning.mask_hf.enr_suppress);
    496  FieldTrialParameter<double> nearend_tuning_max_inc_factor(
    497      "nearend_tuning_max_inc_factor",
    498      adjusted_cfg.suppressor.nearend_tuning.max_inc_factor);
    499  FieldTrialParameter<double> nearend_tuning_max_dec_factor_lf(
    500      "nearend_tuning_max_dec_factor_lf",
    501      adjusted_cfg.suppressor.nearend_tuning.max_dec_factor_lf);
    502  FieldTrialParameter<double> normal_tuning_mask_lf_enr_transparent(
    503      "normal_tuning_mask_lf_enr_transparent",
    504      adjusted_cfg.suppressor.normal_tuning.mask_lf.enr_transparent);
    505  FieldTrialParameter<double> normal_tuning_mask_lf_enr_suppress(
    506      "normal_tuning_mask_lf_enr_suppress",
    507      adjusted_cfg.suppressor.normal_tuning.mask_lf.enr_suppress);
    508  FieldTrialParameter<double> normal_tuning_mask_hf_enr_transparent(
    509      "normal_tuning_mask_hf_enr_transparent",
    510      adjusted_cfg.suppressor.normal_tuning.mask_hf.enr_transparent);
    511  FieldTrialParameter<double> normal_tuning_mask_hf_enr_suppress(
    512      "normal_tuning_mask_hf_enr_suppress",
    513      adjusted_cfg.suppressor.normal_tuning.mask_hf.enr_suppress);
    514  FieldTrialParameter<double> normal_tuning_max_inc_factor(
    515      "normal_tuning_max_inc_factor",
    516      adjusted_cfg.suppressor.normal_tuning.max_inc_factor);
    517  FieldTrialParameter<double> normal_tuning_max_dec_factor_lf(
    518      "normal_tuning_max_dec_factor_lf",
    519      adjusted_cfg.suppressor.normal_tuning.max_dec_factor_lf);
    520  FieldTrialParameter<double> dominant_nearend_detection_enr_threshold(
    521      "dominant_nearend_detection_enr_threshold",
    522      adjusted_cfg.suppressor.dominant_nearend_detection.enr_threshold);
    523  FieldTrialParameter<double> dominant_nearend_detection_enr_exit_threshold(
    524      "dominant_nearend_detection_enr_exit_threshold",
    525      adjusted_cfg.suppressor.dominant_nearend_detection.enr_exit_threshold);
    526  FieldTrialParameter<double> dominant_nearend_detection_snr_threshold(
    527      "dominant_nearend_detection_snr_threshold",
    528      adjusted_cfg.suppressor.dominant_nearend_detection.snr_threshold);
    529  FieldTrialParameter<int> dominant_nearend_detection_hold_duration(
    530      "dominant_nearend_detection_hold_duration",
    531      adjusted_cfg.suppressor.dominant_nearend_detection.hold_duration);
    532  FieldTrialParameter<int> dominant_nearend_detection_trigger_threshold(
    533      "dominant_nearend_detection_trigger_threshold",
    534      adjusted_cfg.suppressor.dominant_nearend_detection.trigger_threshold);
    535 
    536  ParseFieldTrial(
    537      {&nearend_tuning_mask_lf_enr_transparent,
    538       &nearend_tuning_mask_lf_enr_suppress,
    539       &nearend_tuning_mask_hf_enr_transparent,
    540       &nearend_tuning_mask_hf_enr_suppress, &nearend_tuning_max_inc_factor,
    541       &nearend_tuning_max_dec_factor_lf,
    542       &normal_tuning_mask_lf_enr_transparent,
    543       &normal_tuning_mask_lf_enr_suppress,
    544       &normal_tuning_mask_hf_enr_transparent,
    545       &normal_tuning_mask_hf_enr_suppress, &normal_tuning_max_inc_factor,
    546       &normal_tuning_max_dec_factor_lf,
    547       &dominant_nearend_detection_enr_threshold,
    548       &dominant_nearend_detection_enr_exit_threshold,
    549       &dominant_nearend_detection_snr_threshold,
    550       &dominant_nearend_detection_hold_duration,
    551       &dominant_nearend_detection_trigger_threshold},
    552      suppressor_tuning_override_trial_name);
    553 
    554  adjusted_cfg.suppressor.nearend_tuning.mask_lf.enr_transparent =
    555      static_cast<float>(nearend_tuning_mask_lf_enr_transparent.Get());
    556  adjusted_cfg.suppressor.nearend_tuning.mask_lf.enr_suppress =
    557      static_cast<float>(nearend_tuning_mask_lf_enr_suppress.Get());
    558  adjusted_cfg.suppressor.nearend_tuning.mask_hf.enr_transparent =
    559      static_cast<float>(nearend_tuning_mask_hf_enr_transparent.Get());
    560  adjusted_cfg.suppressor.nearend_tuning.mask_hf.enr_suppress =
    561      static_cast<float>(nearend_tuning_mask_hf_enr_suppress.Get());
    562  adjusted_cfg.suppressor.nearend_tuning.max_inc_factor =
    563      static_cast<float>(nearend_tuning_max_inc_factor.Get());
    564  adjusted_cfg.suppressor.nearend_tuning.max_dec_factor_lf =
    565      static_cast<float>(nearend_tuning_max_dec_factor_lf.Get());
    566  adjusted_cfg.suppressor.normal_tuning.mask_lf.enr_transparent =
    567      static_cast<float>(normal_tuning_mask_lf_enr_transparent.Get());
    568  adjusted_cfg.suppressor.normal_tuning.mask_lf.enr_suppress =
    569      static_cast<float>(normal_tuning_mask_lf_enr_suppress.Get());
    570  adjusted_cfg.suppressor.normal_tuning.mask_hf.enr_transparent =
    571      static_cast<float>(normal_tuning_mask_hf_enr_transparent.Get());
    572  adjusted_cfg.suppressor.normal_tuning.mask_hf.enr_suppress =
    573      static_cast<float>(normal_tuning_mask_hf_enr_suppress.Get());
    574  adjusted_cfg.suppressor.normal_tuning.max_inc_factor =
    575      static_cast<float>(normal_tuning_max_inc_factor.Get());
    576  adjusted_cfg.suppressor.normal_tuning.max_dec_factor_lf =
    577      static_cast<float>(normal_tuning_max_dec_factor_lf.Get());
    578  adjusted_cfg.suppressor.dominant_nearend_detection.enr_threshold =
    579      static_cast<float>(dominant_nearend_detection_enr_threshold.Get());
    580  adjusted_cfg.suppressor.dominant_nearend_detection.enr_exit_threshold =
    581      static_cast<float>(dominant_nearend_detection_enr_exit_threshold.Get());
    582  adjusted_cfg.suppressor.dominant_nearend_detection.snr_threshold =
    583      static_cast<float>(dominant_nearend_detection_snr_threshold.Get());
    584  adjusted_cfg.suppressor.dominant_nearend_detection.hold_duration =
    585      dominant_nearend_detection_hold_duration.Get();
    586  adjusted_cfg.suppressor.dominant_nearend_detection.trigger_threshold =
    587      dominant_nearend_detection_trigger_threshold.Get();
    588 
    589  // Field trial-based overrides of individual suppressor parameters.
    590  RetrieveFieldTrialValue(
    591      field_trials, "WebRTC-Aec3SuppressorNearendLfMaskTransparentOverride",
    592      0.f, 10.f,
    593      &adjusted_cfg.suppressor.nearend_tuning.mask_lf.enr_transparent);
    594  RetrieveFieldTrialValue(
    595      field_trials, "WebRTC-Aec3SuppressorNearendLfMaskSuppressOverride", 0.f,
    596      10.f, &adjusted_cfg.suppressor.nearend_tuning.mask_lf.enr_suppress);
    597  RetrieveFieldTrialValue(
    598      field_trials, "WebRTC-Aec3SuppressorNearendHfMaskTransparentOverride",
    599      0.f, 10.f,
    600      &adjusted_cfg.suppressor.nearend_tuning.mask_hf.enr_transparent);
    601  RetrieveFieldTrialValue(
    602      field_trials, "WebRTC-Aec3SuppressorNearendHfMaskSuppressOverride", 0.f,
    603      10.f, &adjusted_cfg.suppressor.nearend_tuning.mask_hf.enr_suppress);
    604  RetrieveFieldTrialValue(
    605      field_trials, "WebRTC-Aec3SuppressorNearendMaxIncFactorOverride", 0.f,
    606      10.f, &adjusted_cfg.suppressor.nearend_tuning.max_inc_factor);
    607  RetrieveFieldTrialValue(
    608      field_trials, "WebRTC-Aec3SuppressorNearendMaxDecFactorLfOverride", 0.f,
    609      10.f, &adjusted_cfg.suppressor.nearend_tuning.max_dec_factor_lf);
    610 
    611  RetrieveFieldTrialValue(
    612      field_trials, "WebRTC-Aec3SuppressorNormalLfMaskTransparentOverride", 0.f,
    613      10.f, &adjusted_cfg.suppressor.normal_tuning.mask_lf.enr_transparent);
    614  RetrieveFieldTrialValue(
    615      field_trials, "WebRTC-Aec3SuppressorNormalLfMaskSuppressOverride", 0.f,
    616      10.f, &adjusted_cfg.suppressor.normal_tuning.mask_lf.enr_suppress);
    617  RetrieveFieldTrialValue(
    618      field_trials, "WebRTC-Aec3SuppressorNormalHfMaskTransparentOverride", 0.f,
    619      10.f, &adjusted_cfg.suppressor.normal_tuning.mask_hf.enr_transparent);
    620  RetrieveFieldTrialValue(
    621      field_trials, "WebRTC-Aec3SuppressorNormalHfMaskSuppressOverride", 0.f,
    622      10.f, &adjusted_cfg.suppressor.normal_tuning.mask_hf.enr_suppress);
    623  RetrieveFieldTrialValue(
    624      field_trials, "WebRTC-Aec3SuppressorNormalMaxIncFactorOverride", 0.f,
    625      10.f, &adjusted_cfg.suppressor.normal_tuning.max_inc_factor);
    626  RetrieveFieldTrialValue(
    627      field_trials, "WebRTC-Aec3SuppressorNormalMaxDecFactorLfOverride", 0.f,
    628      10.f, &adjusted_cfg.suppressor.normal_tuning.max_dec_factor_lf);
    629 
    630  RetrieveFieldTrialValue(
    631      field_trials, "WebRTC-Aec3SuppressorDominantNearendEnrThresholdOverride",
    632      0.f, 100.f,
    633      &adjusted_cfg.suppressor.dominant_nearend_detection.enr_threshold);
    634  RetrieveFieldTrialValue(
    635      field_trials,
    636      "WebRTC-Aec3SuppressorDominantNearendEnrExitThresholdOverride", 0.f,
    637      100.f,
    638      &adjusted_cfg.suppressor.dominant_nearend_detection.enr_exit_threshold);
    639  RetrieveFieldTrialValue(
    640      field_trials, "WebRTC-Aec3SuppressorDominantNearendSnrThresholdOverride",
    641      0.f, 100.f,
    642      &adjusted_cfg.suppressor.dominant_nearend_detection.snr_threshold);
    643  RetrieveFieldTrialValue(
    644      field_trials, "WebRTC-Aec3SuppressorDominantNearendHoldDurationOverride",
    645      0, 1000,
    646      &adjusted_cfg.suppressor.dominant_nearend_detection.hold_duration);
    647  RetrieveFieldTrialValue(
    648      field_trials,
    649      "WebRTC-Aec3SuppressorDominantNearendTriggerThresholdOverride", 0, 1000,
    650      &adjusted_cfg.suppressor.dominant_nearend_detection.trigger_threshold);
    651 
    652  RetrieveFieldTrialValue(
    653      field_trials, "WebRTC-Aec3SuppressorAntiHowlingGainOverride", 0.f, 10.f,
    654      &adjusted_cfg.suppressor.high_bands_suppression.anti_howling_gain);
    655 
    656  // Field trial-based overrides of individual delay estimator parameters.
    657  RetrieveFieldTrialValue(field_trials,
    658                          "WebRTC-Aec3DelayEstimateSmoothingOverride", 0.f, 1.f,
    659                          &adjusted_cfg.delay.delay_estimate_smoothing);
    660  RetrieveFieldTrialValue(
    661      field_trials, "WebRTC-Aec3DelayEstimateSmoothingDelayFoundOverride", 0.f,
    662      1.f, &adjusted_cfg.delay.delay_estimate_smoothing_delay_found);
    663 
    664  int max_allowed_excess_render_blocks_override =
    665      adjusted_cfg.buffering.max_allowed_excess_render_blocks;
    666  RetrieveFieldTrialValue(
    667      field_trials, "WebRTC-Aec3BufferingMaxAllowedExcessRenderBlocksOverride",
    668      0, 20, &max_allowed_excess_render_blocks_override);
    669  adjusted_cfg.buffering.max_allowed_excess_render_blocks =
    670      max_allowed_excess_render_blocks_override;
    671  return adjusted_cfg;
    672 }
    673 
    674 class EchoCanceller3::RenderWriter {
    675 public:
    676  RenderWriter(ApmDataDumper* data_dumper,
    677               const EchoCanceller3Config& config,
    678               SwapQueue<std::vector<std::vector<std::vector<float>>>,
    679                         Aec3RenderQueueItemVerifier>* render_transfer_queue,
    680               size_t num_bands,
    681               size_t num_channels);
    682 
    683  RenderWriter() = delete;
    684  RenderWriter(const RenderWriter&) = delete;
    685  RenderWriter& operator=(const RenderWriter&) = delete;
    686 
    687  ~RenderWriter();
    688  void Insert(const AudioBuffer& input);
    689 
    690 private:
    691  ApmDataDumper* data_dumper_;
    692  const size_t num_bands_;
    693  const size_t num_channels_;
    694  std::unique_ptr<HighPassFilter> high_pass_filter_;
    695  std::vector<std::vector<std::vector<float>>> render_queue_input_frame_;
    696  SwapQueue<std::vector<std::vector<std::vector<float>>>,
    697            Aec3RenderQueueItemVerifier>* render_transfer_queue_;
    698 };
    699 
    700 EchoCanceller3::RenderWriter::RenderWriter(
    701    ApmDataDumper* data_dumper,
    702    const EchoCanceller3Config& config,
    703    SwapQueue<std::vector<std::vector<std::vector<float>>>,
    704              Aec3RenderQueueItemVerifier>* render_transfer_queue,
    705    size_t num_bands,
    706    size_t num_channels)
    707    : data_dumper_(data_dumper),
    708      num_bands_(num_bands),
    709      num_channels_(num_channels),
    710      render_queue_input_frame_(
    711          num_bands_,
    712          std::vector<std::vector<float>>(
    713              num_channels_,
    714              std::vector<float>(AudioBuffer::kSplitBandSize, 0.f))),
    715      render_transfer_queue_(render_transfer_queue) {
    716  RTC_DCHECK(data_dumper);
    717  if (config.filter.high_pass_filter_echo_reference) {
    718    high_pass_filter_ = std::make_unique<HighPassFilter>(16000, num_channels);
    719  }
    720 }
    721 
    722 EchoCanceller3::RenderWriter::~RenderWriter() = default;
    723 
    724 void EchoCanceller3::RenderWriter::Insert(const AudioBuffer& input) {
    725  RTC_DCHECK_EQ(AudioBuffer::kSplitBandSize, input.num_frames_per_band());
    726  RTC_DCHECK_EQ(num_bands_, input.num_bands());
    727  RTC_DCHECK_EQ(num_channels_, input.num_channels());
    728 
    729  // TODO(bugs.webrtc.org/8759) Temporary work-around.
    730  if (num_bands_ != input.num_bands())
    731    return;
    732 
    733  data_dumper_->DumpWav("aec3_render_input", AudioBuffer::kSplitBandSize,
    734                        &input.split_bands_const(0)[0][0], 16000, 1);
    735 
    736  CopyBufferIntoFrame(input, num_bands_, num_channels_,
    737                      &render_queue_input_frame_);
    738  if (high_pass_filter_) {
    739    high_pass_filter_->Process(&render_queue_input_frame_[0]);
    740  }
    741 
    742  static_cast<void>(render_transfer_queue_->Insert(&render_queue_input_frame_));
    743 }
    744 
    745 std::atomic<int> EchoCanceller3::instance_count_(0);
    746 
    747 EchoCanceller3::EchoCanceller3(
    748    const Environment& env,
    749    const EchoCanceller3Config& config,
    750    const std::optional<EchoCanceller3Config>& multichannel_config,
    751    NeuralResidualEchoEstimator* neural_residual_echo_estimator,
    752    int sample_rate_hz,
    753    size_t num_render_channels,
    754    size_t num_capture_channels)
    755    : env_(env),
    756      data_dumper_(new ApmDataDumper(instance_count_.fetch_add(1) + 1)),
    757      config_(AdjustConfig(config, env.field_trials())),
    758      sample_rate_hz_(sample_rate_hz),
    759      num_bands_(NumBandsForRate(sample_rate_hz_)),
    760      num_render_input_channels_(num_render_channels),
    761      num_capture_channels_(num_capture_channels),
    762      config_selector_(config_,
    763                       multichannel_config,
    764                       num_render_input_channels_),
    765      multichannel_content_detector_(
    766          config_selector_.active_config().multi_channel.detect_stereo_content,
    767          num_render_input_channels_,
    768          config_selector_.active_config()
    769              .multi_channel.stereo_detection_threshold,
    770          config_selector_.active_config()
    771              .multi_channel.stereo_detection_timeout_threshold_seconds,
    772          config_selector_.active_config()
    773              .multi_channel.stereo_detection_hysteresis_seconds),
    774      neural_residual_echo_estimator_(neural_residual_echo_estimator),
    775      output_framer_(num_bands_, num_capture_channels_),
    776      capture_blocker_(num_bands_, num_capture_channels_),
    777      render_transfer_queue_(
    778          kRenderTransferQueueSizeFrames,
    779          std::vector<std::vector<std::vector<float>>>(
    780              num_bands_,
    781              std::vector<std::vector<float>>(
    782                  num_render_input_channels_,
    783                  std::vector<float>(AudioBuffer::kSplitBandSize, 0.f))),
    784          Aec3RenderQueueItemVerifier(num_bands_,
    785                                      num_render_input_channels_,
    786                                      AudioBuffer::kSplitBandSize)),
    787      render_queue_output_frame_(
    788          num_bands_,
    789          std::vector<std::vector<float>>(
    790              num_render_input_channels_,
    791              std::vector<float>(AudioBuffer::kSplitBandSize, 0.f))),
    792      render_block_(num_bands_, num_render_input_channels_),
    793      capture_block_(num_bands_, num_capture_channels_),
    794      capture_sub_frame_view_(
    795          num_bands_,
    796          std::vector<ArrayView<float>>(num_capture_channels_)) {
    797  RTC_DCHECK(ValidFullBandRate(sample_rate_hz_));
    798 
    799  if (config_selector_.active_config().delay.fixed_capture_delay_samples > 0) {
    800    block_delay_buffer_.reset(new BlockDelayBuffer(
    801        num_capture_channels_, num_bands_, AudioBuffer::kSplitBandSize,
    802        config_.delay.fixed_capture_delay_samples));
    803  }
    804 
    805  render_writer_.reset(new RenderWriter(
    806      data_dumper_.get(), config_selector_.active_config(),
    807      &render_transfer_queue_, num_bands_, num_render_input_channels_));
    808 
    809  RTC_DCHECK_EQ(num_bands_, std::max(sample_rate_hz_, 16000) / 16000);
    810  RTC_DCHECK_GE(kMaxNumBands, num_bands_);
    811 
    812  if (config_selector_.active_config().filter.export_linear_aec_output) {
    813    linear_output_framer_.reset(
    814        new BlockFramer(/*num_bands=*/1, num_capture_channels_));
    815    linear_output_block_ =
    816        std::make_unique<Block>(/*num_bands=*/1, num_capture_channels_);
    817    linear_output_sub_frame_view_ = std::vector<std::vector<ArrayView<float>>>(
    818        1, std::vector<ArrayView<float>>(num_capture_channels_));
    819  }
    820 
    821  Initialize();
    822 
    823  RTC_LOG(LS_INFO) << "AEC3 created with sample rate: " << sample_rate_hz_
    824                   << " Hz, num render channels: " << num_render_input_channels_
    825                   << ", num capture channels: " << num_capture_channels_;
    826 }
    827 
    828 EchoCanceller3::~EchoCanceller3() = default;
    829 
    830 void EchoCanceller3::Initialize() {
    831  RTC_DCHECK_RUNS_SERIALIZED(&capture_race_checker_);
    832 
    833  num_render_channels_to_aec_ =
    834      multichannel_content_detector_.IsProperMultiChannelContentDetected()
    835          ? num_render_input_channels_
    836          : 1;
    837 
    838  config_selector_.Update(
    839      multichannel_content_detector_.IsProperMultiChannelContentDetected());
    840 
    841  render_block_.SetNumChannels(num_render_channels_to_aec_);
    842 
    843  render_blocker_.reset(
    844      new FrameBlocker(num_bands_, num_render_channels_to_aec_));
    845 
    846  block_processor_ = BlockProcessor::Create(
    847      env_, config_selector_.active_config(), sample_rate_hz_,
    848      num_render_channels_to_aec_, num_capture_channels_,
    849      neural_residual_echo_estimator_);
    850 
    851  render_sub_frame_view_ = std::vector<std::vector<ArrayView<float>>>(
    852      num_bands_, std::vector<ArrayView<float>>(num_render_channels_to_aec_));
    853 }
    854 
    855 void EchoCanceller3::AnalyzeRender(const AudioBuffer& render) {
    856  RTC_DCHECK_RUNS_SERIALIZED(&render_race_checker_);
    857 
    858  RTC_DCHECK_EQ(render.num_channels(), num_render_input_channels_);
    859  data_dumper_->DumpRaw("aec3_call_order",
    860                        static_cast<int>(EchoCanceller3ApiCall::kRender));
    861 
    862  return render_writer_->Insert(render);
    863 }
    864 
    865 void EchoCanceller3::AnalyzeCapture(const AudioBuffer& capture) {
    866  RTC_DCHECK_RUNS_SERIALIZED(&capture_race_checker_);
    867  data_dumper_->DumpWav("aec3_capture_analyze_input", capture.num_frames(),
    868                        capture.channels_const()[0], sample_rate_hz_, 1);
    869  saturated_microphone_signal_ = false;
    870  for (size_t channel = 0; channel < capture.num_channels(); ++channel) {
    871    saturated_microphone_signal_ |= DetectSaturation(ArrayView<const float>(
    872        capture.channels_const()[channel], capture.num_frames()));
    873    if (saturated_microphone_signal_) {
    874      break;
    875    }
    876  }
    877 }
    878 
    879 void EchoCanceller3::ProcessCapture(AudioBuffer* capture, bool level_change) {
    880  ProcessCapture(capture, nullptr, level_change);
    881 }
    882 
    883 void EchoCanceller3::ProcessCapture(AudioBuffer* capture,
    884                                    AudioBuffer* linear_output,
    885                                    bool level_change) {
    886  RTC_DCHECK_RUNS_SERIALIZED(&capture_race_checker_);
    887  RTC_DCHECK(capture);
    888  RTC_DCHECK_EQ(num_bands_, capture->num_bands());
    889  RTC_DCHECK_EQ(AudioBuffer::kSplitBandSize, capture->num_frames_per_band());
    890  RTC_DCHECK_EQ(capture->num_channels(), num_capture_channels_);
    891  data_dumper_->DumpRaw("aec3_call_order",
    892                        static_cast<int>(EchoCanceller3ApiCall::kCapture));
    893 
    894  if (linear_output && !linear_output_framer_) {
    895    RTC_LOG(LS_ERROR) << "Trying to retrieve the linear AEC output without "
    896                         "properly configuring AEC3.";
    897    RTC_DCHECK_NOTREACHED();
    898  }
    899 
    900  // Report capture call in the metrics and periodically update API call
    901  // metrics.
    902  api_call_metrics_.ReportCaptureCall();
    903 
    904  // Optionally delay the capture signal.
    905  if (config_selector_.active_config().delay.fixed_capture_delay_samples > 0) {
    906    RTC_DCHECK(block_delay_buffer_);
    907    block_delay_buffer_->DelaySignal(capture);
    908  }
    909 
    910  ArrayView<float> capture_lower_band = ArrayView<float>(
    911      &capture->split_bands(0)[0][0], AudioBuffer::kSplitBandSize);
    912 
    913  data_dumper_->DumpWav("aec3_capture_input", capture_lower_band, 16000, 1);
    914 
    915  EmptyRenderQueue();
    916 
    917  ProcessCaptureFrameContent(
    918      linear_output, capture, level_change,
    919      multichannel_content_detector_.IsTemporaryMultiChannelContentDetected(),
    920      saturated_microphone_signal_, 0, &capture_blocker_,
    921      linear_output_framer_.get(), &output_framer_, block_processor_.get(),
    922      linear_output_block_.get(), &linear_output_sub_frame_view_,
    923      &capture_block_, &capture_sub_frame_view_);
    924 
    925  ProcessCaptureFrameContent(
    926      linear_output, capture, level_change,
    927      multichannel_content_detector_.IsTemporaryMultiChannelContentDetected(),
    928      saturated_microphone_signal_, 1, &capture_blocker_,
    929      linear_output_framer_.get(), &output_framer_, block_processor_.get(),
    930      linear_output_block_.get(), &linear_output_sub_frame_view_,
    931      &capture_block_, &capture_sub_frame_view_);
    932 
    933  ProcessRemainingCaptureFrameContent(
    934      level_change,
    935      multichannel_content_detector_.IsTemporaryMultiChannelContentDetected(),
    936      saturated_microphone_signal_, &capture_blocker_,
    937      linear_output_framer_.get(), &output_framer_, block_processor_.get(),
    938      linear_output_block_.get(), &capture_block_);
    939 
    940  data_dumper_->DumpWav("aec3_capture_output", AudioBuffer::kSplitBandSize,
    941                        &capture->split_bands(0)[0][0], 16000, 1);
    942 }
    943 
    944 EchoControl::Metrics EchoCanceller3::GetMetrics() const {
    945  RTC_DCHECK_RUNS_SERIALIZED(&capture_race_checker_);
    946  Metrics metrics;
    947  block_processor_->GetMetrics(&metrics);
    948  return metrics;
    949 }
    950 
    951 void EchoCanceller3::SetAudioBufferDelay(int delay_ms) {
    952  RTC_DCHECK_RUNS_SERIALIZED(&capture_race_checker_);
    953  block_processor_->SetAudioBufferDelay(delay_ms);
    954 }
    955 
    956 void EchoCanceller3::SetCaptureOutputUsage(bool capture_output_used) {
    957  RTC_DCHECK_RUNS_SERIALIZED(&capture_race_checker_);
    958  block_processor_->SetCaptureOutputUsage(capture_output_used);
    959 }
    960 
    961 bool EchoCanceller3::ActiveProcessing() const {
    962  return true;
    963 }
    964 
    965 void EchoCanceller3::SetBlockProcessorForTesting(
    966    std::unique_ptr<BlockProcessor> block_processor) {
    967  RTC_DCHECK_RUNS_SERIALIZED(&capture_race_checker_);
    968  RTC_DCHECK(block_processor);
    969  block_processor_ = std::move(block_processor);
    970 }
    971 
    972 void EchoCanceller3::EmptyRenderQueue() {
    973  RTC_DCHECK_RUNS_SERIALIZED(&capture_race_checker_);
    974  bool frame_to_buffer =
    975      render_transfer_queue_.Remove(&render_queue_output_frame_);
    976  while (frame_to_buffer) {
    977    // Report render call in the metrics.
    978    api_call_metrics_.ReportRenderCall();
    979 
    980    if (multichannel_content_detector_.UpdateDetection(
    981            render_queue_output_frame_)) {
    982      // Reinitialize the AEC when proper stereo is detected.
    983      Initialize();
    984    }
    985 
    986    // Buffer frame content.
    987    BufferRenderFrameContent(
    988        /*proper_downmix_needed=*/multichannel_content_detector_
    989            .IsTemporaryMultiChannelContentDetected(),
    990        &render_queue_output_frame_, 0, render_blocker_.get(),
    991        block_processor_.get(), &render_block_, &render_sub_frame_view_);
    992 
    993    BufferRenderFrameContent(
    994        /*proper_downmix_needed=*/multichannel_content_detector_
    995            .IsTemporaryMultiChannelContentDetected(),
    996        &render_queue_output_frame_, 1, render_blocker_.get(),
    997        block_processor_.get(), &render_block_, &render_sub_frame_view_);
    998 
    999    BufferRemainingRenderFrameContent(render_blocker_.get(),
   1000                                      block_processor_.get(), &render_block_);
   1001 
   1002    frame_to_buffer =
   1003        render_transfer_queue_.Remove(&render_queue_output_frame_);
   1004  }
   1005 }
   1006 }  // namespace webrtc