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

Side by Side Diff: webrtc/modules/audio_processing/residual_echo_detector.cc

Issue 2419563003: Add algorithm for Residual Echo Detector. (Closed)
Patch Set: Merged residual_echo_detector and echo_detector. Created 4 years, 1 month 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
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>
14 #include <numeric>
15
13 #include "webrtc/modules/audio_processing/audio_buffer.h" 16 #include "webrtc/modules/audio_processing/audio_buffer.h"
14 17
18 namespace {
19
20 float Power(rtc::ArrayView<const float> input) {
21 return std::inner_product(input.begin(), input.end(), input.begin(), 0.f);
22 }
23
24 constexpr size_t kLookbackFrames = 650;
25 // TODO(ivoc): Verify the size of this buffer.
26 constexpr size_t kRenderBufferSize = 30;
27
28 } // namespace
29
15 namespace webrtc { 30 namespace webrtc {
16 31
17 ResidualEchoDetector::ResidualEchoDetector() = default; 32 ResidualEchoDetector::ResidualEchoDetector()
33 : render_buffer_(kRenderBufferSize),
34 render_power_(kLookbackFrames),
35 render_power_mean_(kLookbackFrames),
36 render_power_std_dev_(kLookbackFrames),
37 covariances_(kLookbackFrames){};
18 38
19 ResidualEchoDetector::~ResidualEchoDetector() = default; 39 ResidualEchoDetector::~ResidualEchoDetector() = default;
20 40
21 void ResidualEchoDetector::AnalyzeRenderAudio( 41 void ResidualEchoDetector::AnalyzeRenderAudio(
22 rtc::ArrayView<const float> render_audio) const { 42 rtc::ArrayView<const float> render_audio) {
23 // TODO(ivoc): Add implementation. 43 if (render_buffer_.Size() == 0) {
44 frames_since_zero_buffer_size_ = 0;
45 } else if (frames_since_zero_buffer_size_ >= kRenderBufferSize) {
46 // This can happen in a few cases: at the start of a call, due to a glitch
47 // or due to clock drift. The excess capture value will be ignored.
48 // TODO(ivoc): Include how often this happens in APM stats.
49 render_buffer_.Pop();
50 frames_since_zero_buffer_size_ = 0;
51 }
52 ++frames_since_zero_buffer_size_;
53 float power = Power(render_audio);
54 render_buffer_.Push(power);
24 } 55 }
25 56
26 void ResidualEchoDetector::AnalyzeCaptureAudio( 57 void ResidualEchoDetector::AnalyzeCaptureAudio(
27 rtc::ArrayView<const float> render_audio) { 58 rtc::ArrayView<const float> capture_audio) {
28 // TODO(ivoc): Add implementation. 59 if (first_process_call_) {
60 // On the first process call (so the start of a call), we must flush the
61 // render buffer, otherwise the render data will be delayed.
62 render_buffer_.Clear();
63 first_process_call_ = false;
64 }
65
66 // Get the next render value.
67 const rtc::Optional<float> buffered_render_power = render_buffer_.Pop();
68 if (!buffered_render_power) {
69 // This can happen in a few cases: at the start of a call, due to a glitch
70 // or due to clock drift. The excess capture value will be ignored.
71 // TODO(ivoc): Include how often this happens in APM stats.
72 return;
73 }
74 // Update the render statistics, and store the statistics in circular buffers.
75 render_statistics_.Update(*buffered_render_power);
76 RTC_DCHECK_LT(next_insertion_index_, kLookbackFrames);
77 render_power_[next_insertion_index_] = *buffered_render_power;
78 render_power_mean_[next_insertion_index_] = render_statistics_.mean();
79 render_power_std_dev_[next_insertion_index_] =
80 render_statistics_.std_deviation();
81
82 // Get the next capture value, update capture statistics and add the relevant
83 // values to the buffers.
84 const float capture_power = Power(capture_audio);
85 capture_statistics_.Update(capture_power);
86 const float capture_mean = capture_statistics_.mean();
87 const float capture_std_deviation = capture_statistics_.std_deviation();
88
89 // Update the covariance values and determine the new echo likelihood.
90 echo_likelihood_ = 0.f;
91 for (size_t delay = 0; delay < covariances_.size(); ++delay) {
92 const size_t read_index =
93 (kLookbackFrames + next_insertion_index_ - delay) % kLookbackFrames;
94 RTC_DCHECK_LT(read_index, render_power_.size());
95 covariances_[delay].Update(capture_power, capture_mean,
96 capture_std_deviation, render_power_[read_index],
97 render_power_mean_[read_index],
98 render_power_std_dev_[read_index]);
99 echo_likelihood_ = std::max(
100 echo_likelihood_, covariances_[delay].normalized_cross_correlation());
101 }
102
103 // Update the next insertion index.
104 ++next_insertion_index_;
105 next_insertion_index_ %= kLookbackFrames;
29 } 106 }
30 107
31 void ResidualEchoDetector::Initialize() { 108 void ResidualEchoDetector::Initialize() {
32 // TODO(ivoc): Add implementation. 109 render_buffer_.Clear();
110 std::fill(render_power_.begin(), render_power_.end(), 0.f);
111 std::fill(render_power_mean_.begin(), render_power_mean_.end(), 0.f);
112 std::fill(render_power_std_dev_.begin(), render_power_std_dev_.end(), 0.f);
113 render_statistics_.Clear();
114 capture_statistics_.Clear();
115 for (auto& cov : covariances_) {
116 cov.Clear();
117 }
118 echo_likelihood_ = 0.f;
119 next_insertion_index_ = 0;
33 } 120 }
34 121
35 void ResidualEchoDetector::PackRenderAudioBuffer( 122 void ResidualEchoDetector::PackRenderAudioBuffer(
36 AudioBuffer* audio, 123 AudioBuffer* audio,
37 std::vector<float>* packed_buffer) { 124 std::vector<float>* packed_buffer) {
38 RTC_DCHECK_GE(160u, audio->num_frames_per_band()); 125 RTC_DCHECK_GE(160u, audio->num_frames_per_band());
39 126
40 packed_buffer->clear(); 127 packed_buffer->clear();
41 packed_buffer->insert(packed_buffer->end(), 128 packed_buffer->insert(packed_buffer->end(),
42 audio->split_bands_const_f(0)[kBand0To8kHz], 129 audio->split_bands_const_f(0)[kBand0To8kHz],
43 (audio->split_bands_const_f(0)[kBand0To8kHz] + 130 (audio->split_bands_const_f(0)[kBand0To8kHz] +
44 audio->num_frames_per_band())); 131 audio->num_frames_per_band()));
45 } 132 }
46 133
47 float ResidualEchoDetector::get_echo_likelihood() const {
48 // TODO(ivoc): Add implementation.
49 return 0.0f;
50 }
51
52 } // namespace webrtc 134 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698