OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 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 | 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 | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
11 #include "webrtc/modules/audio_processing/residual_echo_detector.h" | 11 #include "webrtc/modules/audio_processing/residual_echo_detector.h" |
12 | 12 |
13 #include <algorithm> | 13 #include <algorithm> |
14 #include <numeric> | 14 #include <numeric> |
15 | 15 |
16 #include "webrtc/base/atomicops.h" | 16 #include "webrtc/base/atomicops.h" |
| 17 #include "webrtc/base/logging.h" |
17 #include "webrtc/modules/audio_processing/audio_buffer.h" | 18 #include "webrtc/modules/audio_processing/audio_buffer.h" |
18 #include "webrtc/modules/audio_processing/logging/apm_data_dumper.h" | 19 #include "webrtc/modules/audio_processing/logging/apm_data_dumper.h" |
19 #include "webrtc/system_wrappers/include/metrics.h" | 20 #include "webrtc/system_wrappers/include/metrics.h" |
20 | 21 |
21 namespace { | 22 namespace { |
22 | 23 |
23 float Power(rtc::ArrayView<const float> input) { | 24 float Power(rtc::ArrayView<const float> input) { |
24 if (input.size() == 0) { | 25 if (input.size() == 0) { |
25 return 0.f; | 26 return 0.f; |
26 } | 27 } |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
107 // Get the next capture value, update capture statistics and add the relevant | 108 // Get the next capture value, update capture statistics and add the relevant |
108 // values to the buffers. | 109 // values to the buffers. |
109 const float capture_power = Power(capture_audio); | 110 const float capture_power = Power(capture_audio); |
110 capture_statistics_.Update(capture_power); | 111 capture_statistics_.Update(capture_power); |
111 const float capture_mean = capture_statistics_.mean(); | 112 const float capture_mean = capture_statistics_.mean(); |
112 const float capture_std_deviation = capture_statistics_.std_deviation(); | 113 const float capture_std_deviation = capture_statistics_.std_deviation(); |
113 | 114 |
114 // Update the covariance values and determine the new echo likelihood. | 115 // Update the covariance values and determine the new echo likelihood. |
115 echo_likelihood_ = 0.f; | 116 echo_likelihood_ = 0.f; |
116 size_t read_index = next_insertion_index_; | 117 size_t read_index = next_insertion_index_; |
| 118 |
| 119 int best_delay = -1; |
117 for (size_t delay = 0; delay < covariances_.size(); ++delay) { | 120 for (size_t delay = 0; delay < covariances_.size(); ++delay) { |
118 RTC_DCHECK_LT(read_index, render_power_.size()); | 121 RTC_DCHECK_LT(read_index, render_power_.size()); |
119 covariances_[delay].Update(capture_power, capture_mean, | 122 covariances_[delay].Update(capture_power, capture_mean, |
120 capture_std_deviation, render_power_[read_index], | 123 capture_std_deviation, render_power_[read_index], |
121 render_power_mean_[read_index], | 124 render_power_mean_[read_index], |
122 render_power_std_dev_[read_index]); | 125 render_power_std_dev_[read_index]); |
123 echo_likelihood_ = std::max( | 126 read_index = read_index > 0 ? read_index - 1 : kLookbackFrames - 1; |
124 echo_likelihood_, covariances_[delay].normalized_cross_correlation()); | |
125 | 127 |
126 read_index = read_index > 0 ? read_index - 1 : kLookbackFrames - 1; | 128 if (covariances_[delay].normalized_cross_correlation() > echo_likelihood_) { |
| 129 echo_likelihood_ = covariances_[delay].normalized_cross_correlation(); |
| 130 best_delay = static_cast<int>(delay); |
| 131 } |
| 132 } |
| 133 // This is a temporary log message to help find the underlying cause for echo |
| 134 // likelihoods > 1.0. |
| 135 // TODO(ivoc): Remove once the issue is resolved. |
| 136 if (echo_likelihood_ > 1.1f) { |
| 137 // Make sure we don't spam the log. |
| 138 if (log_counter_ < 5 && best_delay != -1) { |
| 139 size_t read_index = kLookbackFrames + next_insertion_index_ - best_delay; |
| 140 if (read_index >= kLookbackFrames) { |
| 141 read_index -= kLookbackFrames; |
| 142 } |
| 143 RTC_DCHECK_LT(read_index, render_power_.size()); |
| 144 LOG_F(LS_ERROR) << "Echo detector internal state: {" |
| 145 << "Echo likelihood: " << echo_likelihood_ |
| 146 << ", Best Delay: " << best_delay << ", Covariance: " |
| 147 << covariances_[best_delay].covariance() |
| 148 << ", Last capture power: " << capture_power |
| 149 << ", Capture mean: " << capture_mean |
| 150 << ", Capture_standard deviation: " |
| 151 << capture_std_deviation |
| 152 << ", Last render power: " << render_power_[read_index] |
| 153 << ", Render mean: " << render_power_mean_[read_index] |
| 154 << ", Render standard deviation: " |
| 155 << render_power_std_dev_[read_index] |
| 156 << ", Reliability: " << reliability_ << "}"; |
| 157 log_counter_++; |
| 158 } |
127 } | 159 } |
128 RTC_DCHECK_LT(echo_likelihood_, 1.1f); | 160 RTC_DCHECK_LT(echo_likelihood_, 1.1f); |
| 161 |
129 reliability_ = (1.0f - kAlpha) * reliability_ + kAlpha * 1.0f; | 162 reliability_ = (1.0f - kAlpha) * reliability_ + kAlpha * 1.0f; |
130 echo_likelihood_ *= reliability_; | 163 echo_likelihood_ *= reliability_; |
131 // This is a temporary fix to prevent echo likelihood values > 1.0. | 164 // This is a temporary fix to prevent echo likelihood values > 1.0. |
132 // TODO(ivoc): Find the root cause of this issue and fix it. | 165 // TODO(ivoc): Find the root cause of this issue and fix it. |
133 echo_likelihood_ = std::min(echo_likelihood_, 1.0f); | 166 echo_likelihood_ = std::min(echo_likelihood_, 1.0f); |
134 int echo_percentage = static_cast<int>(echo_likelihood_ * 100); | 167 int echo_percentage = static_cast<int>(echo_likelihood_ * 100); |
135 RTC_HISTOGRAM_COUNTS("WebRTC.Audio.ResidualEchoDetector.EchoLikelihood", | 168 RTC_HISTOGRAM_COUNTS("WebRTC.Audio.ResidualEchoDetector.EchoLikelihood", |
136 echo_percentage, 0, 100, 100 /* number of bins */); | 169 echo_percentage, 0, 100, 100 /* number of bins */); |
137 | 170 |
138 // Update the buffer of recent likelihood values. | 171 // Update the buffer of recent likelihood values. |
(...skipping 23 matching lines...) Expand all Loading... |
162 | 195 |
163 void ResidualEchoDetector::PackRenderAudioBuffer( | 196 void ResidualEchoDetector::PackRenderAudioBuffer( |
164 AudioBuffer* audio, | 197 AudioBuffer* audio, |
165 std::vector<float>* packed_buffer) { | 198 std::vector<float>* packed_buffer) { |
166 packed_buffer->clear(); | 199 packed_buffer->clear(); |
167 packed_buffer->insert(packed_buffer->end(), audio->channels_f()[0], | 200 packed_buffer->insert(packed_buffer->end(), audio->channels_f()[0], |
168 audio->channels_f()[0] + audio->num_frames()); | 201 audio->channels_f()[0] + audio->num_frames()); |
169 } | 202 } |
170 | 203 |
171 } // namespace webrtc | 204 } // namespace webrtc |
OLD | NEW |