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