• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright (c) 2017 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_path_delay_estimator.h"
11 
12 #include <array>
13 
14 #include "api/audio/echo_canceller3_config.h"
15 #include "modules/audio_processing/aec3/aec3_common.h"
16 #include "modules/audio_processing/aec3/downsampled_render_buffer.h"
17 #include "modules/audio_processing/logging/apm_data_dumper.h"
18 #include "rtc_base/checks.h"
19 
20 namespace webrtc {
21 
EchoPathDelayEstimator(ApmDataDumper * data_dumper,const EchoCanceller3Config & config,size_t num_capture_channels)22 EchoPathDelayEstimator::EchoPathDelayEstimator(
23     ApmDataDumper* data_dumper,
24     const EchoCanceller3Config& config,
25     size_t num_capture_channels)
26     : data_dumper_(data_dumper),
27       down_sampling_factor_(config.delay.down_sampling_factor),
28       sub_block_size_(down_sampling_factor_ != 0
29                           ? kBlockSize / down_sampling_factor_
30                           : kBlockSize),
31       capture_mixer_(num_capture_channels,
32                      config.delay.capture_alignment_mixing),
33       capture_decimator_(down_sampling_factor_),
34       matched_filter_(
35           data_dumper_,
36           DetectOptimization(),
37           sub_block_size_,
38           kMatchedFilterWindowSizeSubBlocks,
39           config.delay.num_filters,
40           kMatchedFilterAlignmentShiftSizeSubBlocks,
41           config.delay.down_sampling_factor == 8
42               ? config.render_levels.poor_excitation_render_limit_ds8
43               : config.render_levels.poor_excitation_render_limit,
44           config.delay.delay_estimate_smoothing,
45           config.delay.delay_candidate_detection_threshold),
46       matched_filter_lag_aggregator_(data_dumper_,
47                                      matched_filter_.GetMaxFilterLag(),
48                                      config.delay.delay_selection_thresholds) {
49   RTC_DCHECK(data_dumper);
50   RTC_DCHECK(down_sampling_factor_ > 0);
51 }
52 
53 EchoPathDelayEstimator::~EchoPathDelayEstimator() = default;
54 
Reset(bool reset_delay_confidence)55 void EchoPathDelayEstimator::Reset(bool reset_delay_confidence) {
56   Reset(true, reset_delay_confidence);
57 }
58 
EstimateDelay(const DownsampledRenderBuffer & render_buffer,const std::vector<std::vector<float>> & capture)59 absl::optional<DelayEstimate> EchoPathDelayEstimator::EstimateDelay(
60     const DownsampledRenderBuffer& render_buffer,
61     const std::vector<std::vector<float>>& capture) {
62   RTC_DCHECK_EQ(kBlockSize, capture[0].size());
63 
64   std::array<float, kBlockSize> downsampled_capture_data;
65   rtc::ArrayView<float> downsampled_capture(downsampled_capture_data.data(),
66                                             sub_block_size_);
67 
68   std::array<float, kBlockSize> downmixed_capture;
69   capture_mixer_.ProduceOutput(capture, downmixed_capture);
70   capture_decimator_.Decimate(downmixed_capture, downsampled_capture);
71   data_dumper_->DumpWav("aec3_capture_decimator_output",
72                         downsampled_capture.size(), downsampled_capture.data(),
73                         16000 / down_sampling_factor_, 1);
74   matched_filter_.Update(render_buffer, downsampled_capture);
75 
76   absl::optional<DelayEstimate> aggregated_matched_filter_lag =
77       matched_filter_lag_aggregator_.Aggregate(
78           matched_filter_.GetLagEstimates());
79 
80   // Run clockdrift detection.
81   if (aggregated_matched_filter_lag &&
82       (*aggregated_matched_filter_lag).quality ==
83           DelayEstimate::Quality::kRefined)
84     clockdrift_detector_.Update((*aggregated_matched_filter_lag).delay);
85 
86   // TODO(peah): Move this logging outside of this class once EchoCanceller3
87   // development is done.
88   data_dumper_->DumpRaw(
89       "aec3_echo_path_delay_estimator_delay",
90       aggregated_matched_filter_lag
91           ? static_cast<int>(aggregated_matched_filter_lag->delay *
92                              down_sampling_factor_)
93           : -1);
94 
95   // Return the detected delay in samples as the aggregated matched filter lag
96   // compensated by the down sampling factor for the signal being correlated.
97   if (aggregated_matched_filter_lag) {
98     aggregated_matched_filter_lag->delay *= down_sampling_factor_;
99   }
100 
101   if (old_aggregated_lag_ && aggregated_matched_filter_lag &&
102       old_aggregated_lag_->delay == aggregated_matched_filter_lag->delay) {
103     ++consistent_estimate_counter_;
104   } else {
105     consistent_estimate_counter_ = 0;
106   }
107   old_aggregated_lag_ = aggregated_matched_filter_lag;
108   constexpr size_t kNumBlocksPerSecondBy2 = kNumBlocksPerSecond / 2;
109   if (consistent_estimate_counter_ > kNumBlocksPerSecondBy2) {
110     Reset(false, false);
111   }
112 
113   return aggregated_matched_filter_lag;
114 }
115 
Reset(bool reset_lag_aggregator,bool reset_delay_confidence)116 void EchoPathDelayEstimator::Reset(bool reset_lag_aggregator,
117                                    bool reset_delay_confidence) {
118   if (reset_lag_aggregator) {
119     matched_filter_lag_aggregator_.Reset(reset_delay_confidence);
120   }
121   matched_filter_.Reset();
122   old_aggregated_lag_ = absl::nullopt;
123   consistent_estimate_counter_ = 0;
124 }
125 }  // namespace webrtc
126