Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(564)

Side by Side Diff: webrtc/modules/audio_processing/aec3/aec_state.cc

Issue 2678423005: Finalization of the first version of EchoCanceller 3 (Closed)
Patch Set: Fixed compilation error Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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
11 #include "webrtc/modules/audio_processing/aec3/aec_state.h"
12
13 #include <math.h>
14 #include <numeric>
15 #include <vector>
16
17 #include "webrtc/base/atomicops.h"
18 #include "webrtc/base/checks.h"
19 #include "webrtc/modules/audio_processing/logging/apm_data_dumper.h"
20
21 namespace webrtc {
22 namespace {
23
24 constexpr float kMaxFilterEstimateStrength = 1000.f;
25
26 // Compute the delay of the adaptive filter as the partition with a distinct
27 // peak.
28 void AnalyzeFilter(
29 const std::vector<std::array<float, kFftLengthBy2Plus1>>&
30 filter_frequency_response,
31 std::array<bool, kFftLengthBy2Plus1>* bands_with_reliable_filter,
32 std::array<float, kFftLengthBy2Plus1>* filter_estimate_strength,
33 rtc::Optional<size_t>* filter_delay) {
34 const auto& H2 = filter_frequency_response;
35
36 size_t reliable_delays_sum = 0;
37 size_t num_reliable_delays = 0;
38
39 constexpr size_t kUpperBin = kFftLengthBy2 - 5;
40 for (size_t k = 1; k < kUpperBin; ++k) {
41 int peak = 0;
42 for (size_t j = 0; j < H2.size(); ++j) {
43 if (H2[j][k] > H2[peak][k]) {
44 peak = j;
45 }
46 }
47
48 if (H2[peak][k] == 0.f) {
49 (*filter_estimate_strength)[k] = 0.f;
50 } else if (H2[H2.size() - 1][k] == 0.f) {
51 (*filter_estimate_strength)[k] = kMaxFilterEstimateStrength;
52 } else {
53 (*filter_estimate_strength)[k] = std::min(
54 kMaxFilterEstimateStrength, H2[peak][k] / H2[H2.size() - 1][k]);
55 }
56
57 constexpr float kMargin = 10.f;
58 if (kMargin * H2[H2.size() - 1][k] < H2[peak][k]) {
59 (*bands_with_reliable_filter)[k] = true;
60 reliable_delays_sum += peak;
61 ++num_reliable_delays;
62 } else {
63 (*bands_with_reliable_filter)[k] = false;
64 }
65 }
66 (*bands_with_reliable_filter)[0] = (*bands_with_reliable_filter)[1];
67 std::fill(bands_with_reliable_filter->begin() + kUpperBin,
68 bands_with_reliable_filter->end(),
69 (*bands_with_reliable_filter)[kUpperBin - 1]);
70 (*filter_estimate_strength)[0] = (*filter_estimate_strength)[1];
71 std::fill(filter_estimate_strength->begin() + kUpperBin,
72 filter_estimate_strength->end(),
73 (*filter_estimate_strength)[kUpperBin - 1]);
74
75 *filter_delay =
76 num_reliable_delays > 20
77 ? rtc::Optional<size_t>(reliable_delays_sum / num_reliable_delays)
78 : rtc::Optional<size_t>();
79 }
80
81 constexpr int kActiveRenderCounterInitial = 50;
82 constexpr int kActiveRenderCounterMax = 200;
83 constexpr int kEchoPathChangeCounterInitial = 50;
84 constexpr int kEchoPathChangeCounterMax = 200;
85
86 } // namespace
87
88 int AecState::instance_count_ = 0;
89
90 AecState::AecState()
91 : data_dumper_(
92 new ApmDataDumper(rtc::AtomicOps::Increment(&instance_count_))),
93 echo_path_change_counter_(kEchoPathChangeCounterInitial),
94 active_render_counter_(kActiveRenderCounterInitial) {
95 bands_with_reliable_filter_.fill(false);
96 filter_estimate_strength_.fill(0.f);
97 }
98
99 AecState::~AecState() = default;
100
101 void AecState::Update(const std::vector<std::array<float, kFftLengthBy2Plus1>>&
102 filter_frequency_response,
103 const rtc::Optional<size_t>& external_delay_samples,
104 const FftBuffer& X_buffer,
105 const std::array<float, kFftLengthBy2Plus1>& E2_main,
106 const std::array<float, kFftLengthBy2Plus1>& E2_shadow,
107 const std::array<float, kFftLengthBy2Plus1>& Y2,
108 rtc::ArrayView<const float> x,
109 const EchoPathVariability& echo_path_variability,
110 bool echo_leakage_detected) {
111 filter_length_ = filter_frequency_response.size();
112 AnalyzeFilter(filter_frequency_response, &bands_with_reliable_filter_,
113 &filter_estimate_strength_, &filter_delay_);
114 // Compute the externally provided delay in partitions. The truncation is
115 // intended here.
116 external_delay_ =
117 external_delay_samples
118 ? rtc::Optional<size_t>(*external_delay_samples / kBlockSize)
119 : rtc::Optional<size_t>();
120
121 const float x_energy = std::inner_product(x.begin(), x.end(), x.begin(), 0.f);
122
123 echo_path_change_counter_ = echo_path_variability.AudioPathChanged()
124 ? kEchoPathChangeCounterMax
125 : echo_path_change_counter_ - 1;
126 active_render_counter_ = x_energy > 10000.f * kFftLengthBy2
127 ? kActiveRenderCounterMax
128 : active_render_counter_ - 1;
129
130 usable_linear_estimate_ = filter_delay_ && echo_path_change_counter_ <= 0;
131
132 echo_leakage_detected_ = echo_leakage_detected;
133
134 model_based_aec_feasible_ = usable_linear_estimate_ || external_delay_;
135
136 if (usable_linear_estimate_) {
137 const auto& X2 = X_buffer.Spectrum(*filter_delay_);
138
139 // TODO(peah): Expose these as stats.
140 erle_estimator_.Update(X2, Y2, E2_main);
141 erl_estimator_.Update(X2, Y2);
142
143 // TODO(peah): Add working functionality for headset detection. Until the
144 // functionality for that is working the headset detector is hardcoded to detect
145 // no headset.
146 #if 0
147 const auto& erl = erl_estimator_.Erl();
148 const int low_erl_band_count = std::count_if(
149 erl.begin(), erl.end(), [](float a) { return a <= 0.1f; });
150
151 const int noisy_band_count = std::count_if(
152 filter_estimate_strength_.begin(), filter_estimate_strength_.end(),
153 [](float a) { return a <= 10.f; });
154 headset_detected_ = low_erl_band_count > 20 && noisy_band_count > 20;
155 #endif
156 headset_detected_ = false;
157 } else {
158 headset_detected_ = false;
159 }
160 }
161
162 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698