blob: 24f2c9176df71eb24929bf7e2558b4e835d4a81a [file] [log] [blame]
peahd0263542017-01-03 04:20:34 -08001/*
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 */
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020010#include "modules/audio_processing/aec3/block_processor.h"
peahd0263542017-01-03 04:20:34 -080011
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020012#include "api/optional.h"
13#include "modules/audio_processing/aec3/aec3_common.h"
14#include "modules/audio_processing/aec3/block_processor_metrics.h"
15#include "modules/audio_processing/aec3/echo_path_variability.h"
16#include "modules/audio_processing/logging/apm_data_dumper.h"
17#include "rtc_base/atomicops.h"
18#include "rtc_base/constructormagic.h"
Per Åhgrenfe9f2222017-09-26 23:33:26 +020019#include "rtc_base/logging.h"
peahd0263542017-01-03 04:20:34 -080020
21namespace webrtc {
22namespace {
23
peahcf02cf12017-04-05 14:18:07 -070024enum class BlockProcessorApiCall { kCapture, kRender };
25
peahd0263542017-01-03 04:20:34 -080026class BlockProcessorImpl final : public BlockProcessor {
27 public:
Per Åhgren8ba58612017-12-01 23:01:44 +010028 BlockProcessorImpl(const EchoCanceller3Config& config,
29 int sample_rate_hz,
peah69221db2017-01-27 03:28:19 -080030 std::unique_ptr<RenderDelayBuffer> render_buffer,
31 std::unique_ptr<RenderDelayController> delay_controller,
32 std::unique_ptr<EchoRemover> echo_remover);
33
peahd0263542017-01-03 04:20:34 -080034 ~BlockProcessorImpl() override;
35
peah69221db2017-01-27 03:28:19 -080036 void ProcessCapture(bool echo_path_gain_change,
37 bool capture_signal_saturation,
peahd0263542017-01-03 04:20:34 -080038 std::vector<std::vector<float>>* capture_block) override;
39
peahcf02cf12017-04-05 14:18:07 -070040 void BufferRender(const std::vector<std::vector<float>>& block) override;
peahd0263542017-01-03 04:20:34 -080041
peah69221db2017-01-27 03:28:19 -080042 void UpdateEchoLeakageStatus(bool leakage_detected) override;
peahd0263542017-01-03 04:20:34 -080043
Gustaf Ullberg332150d2017-11-22 14:17:39 +010044 void GetMetrics(EchoControl::Metrics* metrics) const override;
45
peahd0263542017-01-03 04:20:34 -080046 private:
peahd0263542017-01-03 04:20:34 -080047 static int instance_count_;
48 std::unique_ptr<ApmDataDumper> data_dumper_;
Per Åhgren8ba58612017-12-01 23:01:44 +010049 const EchoCanceller3Config config_;
50 bool capture_properly_started_ = false;
51 bool render_properly_started_ = false;
peah69221db2017-01-27 03:28:19 -080052 const size_t sample_rate_hz_;
53 std::unique_ptr<RenderDelayBuffer> render_buffer_;
54 std::unique_ptr<RenderDelayController> delay_controller_;
55 std::unique_ptr<EchoRemover> echo_remover_;
peahe985b3f2017-02-28 22:08:53 -080056 BlockProcessorMetrics metrics_;
Per Åhgren8ba58612017-12-01 23:01:44 +010057 RenderDelayBuffer::BufferingEvent render_event_;
Per Åhgrenc59a5762017-12-11 21:34:19 +010058 size_t capture_call_counter_ = 0;
Per Åhgrena76ef9d2018-01-25 07:01:34 +010059 rtc::Optional<DelayEstimate> estimated_delay_;
peahd0263542017-01-03 04:20:34 -080060 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(BlockProcessorImpl);
61};
62
63int BlockProcessorImpl::instance_count_ = 0;
64
peah69221db2017-01-27 03:28:19 -080065BlockProcessorImpl::BlockProcessorImpl(
Per Åhgren8ba58612017-12-01 23:01:44 +010066 const EchoCanceller3Config& config,
peah69221db2017-01-27 03:28:19 -080067 int sample_rate_hz,
68 std::unique_ptr<RenderDelayBuffer> render_buffer,
69 std::unique_ptr<RenderDelayController> delay_controller,
70 std::unique_ptr<EchoRemover> echo_remover)
71 : data_dumper_(
72 new ApmDataDumper(rtc::AtomicOps::Increment(&instance_count_))),
Per Åhgren8ba58612017-12-01 23:01:44 +010073 config_(config),
peah69221db2017-01-27 03:28:19 -080074 sample_rate_hz_(sample_rate_hz),
75 render_buffer_(std::move(render_buffer)),
76 delay_controller_(std::move(delay_controller)),
Per Åhgren8ba58612017-12-01 23:01:44 +010077 echo_remover_(std::move(echo_remover)),
78 render_event_(RenderDelayBuffer::BufferingEvent::kNone) {
peah21920892017-02-08 05:08:56 -080079 RTC_DCHECK(ValidFullBandRate(sample_rate_hz_));
80}
peahd0263542017-01-03 04:20:34 -080081
82BlockProcessorImpl::~BlockProcessorImpl() = default;
83
84void BlockProcessorImpl::ProcessCapture(
peah69221db2017-01-27 03:28:19 -080085 bool echo_path_gain_change,
86 bool capture_signal_saturation,
peahd0263542017-01-03 04:20:34 -080087 std::vector<std::vector<float>>* capture_block) {
88 RTC_DCHECK(capture_block);
89 RTC_DCHECK_EQ(NumBandsForRate(sample_rate_hz_), capture_block->size());
90 RTC_DCHECK_EQ(kBlockSize, (*capture_block)[0].size());
Per Åhgrenc59a5762017-12-11 21:34:19 +010091
92 capture_call_counter_++;
93
peahcf02cf12017-04-05 14:18:07 -070094 data_dumper_->DumpRaw("aec3_processblock_call_order",
95 static_cast<int>(BlockProcessorApiCall::kCapture));
96 data_dumper_->DumpWav("aec3_processblock_capture_input", kBlockSize,
97 &(*capture_block)[0][0],
98 LowestBandRate(sample_rate_hz_), 1);
peah69221db2017-01-27 03:28:19 -080099
Per Åhgren8ba58612017-12-01 23:01:44 +0100100 if (render_properly_started_) {
101 if (!capture_properly_started_) {
102 capture_properly_started_ = true;
103 render_buffer_->Reset();
104 }
105 } else {
106 // If no render data has yet arrived, do not process the capture signal.
peahcf02cf12017-04-05 14:18:07 -0700107 return;
peah69221db2017-01-27 03:28:19 -0800108 }
109
Per Åhgren8ba58612017-12-01 23:01:44 +0100110 EchoPathVariability echo_path_variability(
111 echo_path_gain_change, EchoPathVariability::DelayAdjustment::kNone,
112 false);
113
114 if (render_event_ == RenderDelayBuffer::BufferingEvent::kRenderOverrun &&
115 render_properly_started_) {
116 echo_path_variability.delay_change =
117 EchoPathVariability::DelayAdjustment::kBufferFlush;
118 delay_controller_->Reset();
Per Åhgrenc59a5762017-12-11 21:34:19 +0100119 RTC_LOG(LS_WARNING) << "Reset due to render buffer overrun at block "
120 << capture_call_counter_;
Per Åhgren8ba58612017-12-01 23:01:44 +0100121 }
122
123 // Update the render buffers with any newly arrived render blocks and prepare
124 // the render buffers for reading the render data corresponding to the current
125 // capture block.
Per Åhgrenc59a5762017-12-11 21:34:19 +0100126 render_event_ = render_buffer_->PrepareCaptureProcessing();
Per Åhgren8ba58612017-12-01 23:01:44 +0100127 RTC_DCHECK(RenderDelayBuffer::BufferingEvent::kRenderOverrun !=
128 render_event_);
129 if (render_event_ == RenderDelayBuffer::BufferingEvent::kRenderUnderrun) {
Per Åhgrena76ef9d2018-01-25 07:01:34 +0100130 if (estimated_delay_ &&
131 estimated_delay_->quality == DelayEstimate::Quality::kRefined) {
132 echo_path_variability.delay_change =
133 EchoPathVariability::DelayAdjustment::kDelayReset;
134 delay_controller_->Reset();
135 capture_properly_started_ = false;
136 render_properly_started_ = false;
Per Åhgrenc59a5762017-12-11 21:34:19 +0100137
Per Åhgrena76ef9d2018-01-25 07:01:34 +0100138 RTC_LOG(LS_WARNING) << "Reset due to render buffer underrrun at block "
139 << capture_call_counter_;
140 }
Per Åhgren8ba58612017-12-01 23:01:44 +0100141 } else if (render_event_ == RenderDelayBuffer::BufferingEvent::kApiCallSkew) {
142 // There have been too many render calls in a row. Reset to avoid noncausal
143 // echo.
144 echo_path_variability.delay_change =
145 EchoPathVariability::DelayAdjustment::kDelayReset;
146 delay_controller_->Reset();
Per Åhgren8ba58612017-12-01 23:01:44 +0100147 capture_properly_started_ = false;
148 render_properly_started_ = false;
Per Åhgrenc59a5762017-12-11 21:34:19 +0100149 RTC_LOG(LS_WARNING) << "Reset due to render buffer api skew at block "
150 << capture_call_counter_;
Per Åhgren8ba58612017-12-01 23:01:44 +0100151 }
152
peahcf02cf12017-04-05 14:18:07 -0700153 data_dumper_->DumpWav("aec3_processblock_capture_input2", kBlockSize,
154 &(*capture_block)[0][0],
155 LowestBandRate(sample_rate_hz_), 1);
156
peah4b572d02017-04-06 16:33:06 -0700157 // Compute and and apply the render delay required to achieve proper signal
158 // alignment.
Per Åhgrena76ef9d2018-01-25 07:01:34 +0100159 estimated_delay_ = delay_controller_->GetDelay(
peah4b572d02017-04-06 16:33:06 -0700160 render_buffer_->GetDownsampledRenderBuffer(), (*capture_block)[0]);
peah4b572d02017-04-06 16:33:06 -0700161
Per Åhgrena76ef9d2018-01-25 07:01:34 +0100162 if (estimated_delay_) {
163 if (render_buffer_->CausalDelay(estimated_delay_->delay)) {
164 bool delay_change = render_buffer_->SetDelay(estimated_delay_->delay);
165 if (delay_change) {
166 RTC_LOG(LS_WARNING) << "Delay changed to " << estimated_delay_->delay
167 << " at block " << capture_call_counter_;
Per Åhgrenc59a5762017-12-11 21:34:19 +0100168 echo_path_variability.delay_change =
169 EchoPathVariability::DelayAdjustment::kNewDetectedDelay;
Per Åhgrena76ef9d2018-01-25 07:01:34 +0100170 }
171 } else {
172 // A noncausal delay has been detected. This can only happen if there is
173 // clockdrift, an audio pipeline issue has occurred, an unreliable delay
174 // estimate is used or the specified minimum delay is too short.
175 if (estimated_delay_->quality == DelayEstimate::Quality::kRefined) {
Per Åhgrenc59a5762017-12-11 21:34:19 +0100176 echo_path_variability.delay_change =
177 EchoPathVariability::DelayAdjustment::kDelayReset;
178 delay_controller_->Reset();
179 render_buffer_->Reset();
180 capture_properly_started_ = false;
181 render_properly_started_ = false;
182 RTC_LOG(LS_WARNING) << "Reset due to noncausal delay at block "
183 << capture_call_counter_;
184 }
185 }
peah96b951c2017-08-22 10:26:07 -0700186 }
peah4b572d02017-04-06 16:33:06 -0700187
188 // Remove the echo from the capture signal.
189 echo_remover_->ProcessCapture(
Per Åhgrende22a172017-12-20 18:00:51 +0100190 echo_path_variability, capture_signal_saturation,
191 render_buffer_->GetRenderBuffer(), capture_block);
peah4b572d02017-04-06 16:33:06 -0700192
peahcf02cf12017-04-05 14:18:07 -0700193 // Update the metrics.
Per Åhgren8ba58612017-12-01 23:01:44 +0100194 metrics_.UpdateCapture(false);
peahcf02cf12017-04-05 14:18:07 -0700195
Per Åhgren8ba58612017-12-01 23:01:44 +0100196 render_event_ = RenderDelayBuffer::BufferingEvent::kNone;
peahd0263542017-01-03 04:20:34 -0800197}
198
peahcf02cf12017-04-05 14:18:07 -0700199void BlockProcessorImpl::BufferRender(
200 const std::vector<std::vector<float>>& block) {
201 RTC_DCHECK_EQ(NumBandsForRate(sample_rate_hz_), block.size());
202 RTC_DCHECK_EQ(kBlockSize, block[0].size());
203 data_dumper_->DumpRaw("aec3_processblock_call_order",
204 static_cast<int>(BlockProcessorApiCall::kRender));
205 data_dumper_->DumpWav("aec3_processblock_render_input", kBlockSize,
206 &block[0][0], LowestBandRate(sample_rate_hz_), 1);
peahcf02cf12017-04-05 14:18:07 -0700207 data_dumper_->DumpWav("aec3_processblock_render_input2", kBlockSize,
208 &block[0][0], LowestBandRate(sample_rate_hz_), 1);
209
Per Åhgren8ba58612017-12-01 23:01:44 +0100210 render_event_ = render_buffer_->Insert(block);
peahcf02cf12017-04-05 14:18:07 -0700211
Per Åhgren8ba58612017-12-01 23:01:44 +0100212 metrics_.UpdateRender(render_event_ !=
213 RenderDelayBuffer::BufferingEvent::kNone);
214
215 render_properly_started_ = true;
peahd0263542017-01-03 04:20:34 -0800216}
217
peah69221db2017-01-27 03:28:19 -0800218void BlockProcessorImpl::UpdateEchoLeakageStatus(bool leakage_detected) {
219 echo_remover_->UpdateEchoLeakageStatus(leakage_detected);
220}
peahd0263542017-01-03 04:20:34 -0800221
Gustaf Ullberg332150d2017-11-22 14:17:39 +0100222void BlockProcessorImpl::GetMetrics(EchoControl::Metrics* metrics) const {
223 echo_remover_->GetMetrics(metrics);
Per Åhgren83c4a022017-11-27 12:07:09 +0100224 const int block_size_ms = sample_rate_hz_ == 8000 ? 8 : 4;
Per Åhgrenc59a5762017-12-11 21:34:19 +0100225 rtc::Optional<size_t> delay = render_buffer_->Delay();
226 metrics->delay_ms = delay ? static_cast<int>(*delay) * block_size_ms : 0;
Gustaf Ullberg332150d2017-11-22 14:17:39 +0100227}
228
peahd0263542017-01-03 04:20:34 -0800229} // namespace
230
Gustaf Ullbergbd83b912017-10-18 12:32:42 +0200231BlockProcessor* BlockProcessor::Create(const EchoCanceller3Config& config,
232 int sample_rate_hz) {
Per Åhgren8ba58612017-12-01 23:01:44 +0100233 std::unique_ptr<RenderDelayBuffer> render_buffer(
234 RenderDelayBuffer::Create(config, NumBandsForRate(sample_rate_hz)));
peah69221db2017-01-27 03:28:19 -0800235 std::unique_ptr<RenderDelayController> delay_controller(
Per Åhgrenc59a5762017-12-11 21:34:19 +0100236 RenderDelayController::Create(
237 config, RenderDelayBuffer::DelayEstimatorOffset(config),
238 sample_rate_hz));
peah69221db2017-01-27 03:28:19 -0800239 std::unique_ptr<EchoRemover> echo_remover(
peah697a5902017-06-30 07:06:10 -0700240 EchoRemover::Create(config, sample_rate_hz));
241 return Create(config, sample_rate_hz, std::move(render_buffer),
peah69221db2017-01-27 03:28:19 -0800242 std::move(delay_controller), std::move(echo_remover));
243}
244
245BlockProcessor* BlockProcessor::Create(
Gustaf Ullbergbd83b912017-10-18 12:32:42 +0200246 const EchoCanceller3Config& config,
peah69221db2017-01-27 03:28:19 -0800247 int sample_rate_hz,
248 std::unique_ptr<RenderDelayBuffer> render_buffer) {
249 std::unique_ptr<RenderDelayController> delay_controller(
Per Åhgrenc59a5762017-12-11 21:34:19 +0100250 RenderDelayController::Create(
251 config, RenderDelayBuffer::DelayEstimatorOffset(config),
252 sample_rate_hz));
peah69221db2017-01-27 03:28:19 -0800253 std::unique_ptr<EchoRemover> echo_remover(
peah697a5902017-06-30 07:06:10 -0700254 EchoRemover::Create(config, sample_rate_hz));
255 return Create(config, sample_rate_hz, std::move(render_buffer),
peah69221db2017-01-27 03:28:19 -0800256 std::move(delay_controller), std::move(echo_remover));
257}
258
259BlockProcessor* BlockProcessor::Create(
Gustaf Ullbergbd83b912017-10-18 12:32:42 +0200260 const EchoCanceller3Config& config,
peah69221db2017-01-27 03:28:19 -0800261 int sample_rate_hz,
262 std::unique_ptr<RenderDelayBuffer> render_buffer,
263 std::unique_ptr<RenderDelayController> delay_controller,
264 std::unique_ptr<EchoRemover> echo_remover) {
Per Åhgren8ba58612017-12-01 23:01:44 +0100265 return new BlockProcessorImpl(
266 config, sample_rate_hz, std::move(render_buffer),
267 std::move(delay_controller), std::move(echo_remover));
peahd0263542017-01-03 04:20:34 -0800268}
269
270} // namespace webrtc