blob: f336c392b4ee7039623668221d84c805fb6a9588 [file] [log] [blame]
peah69221db2017-01-27 03:28:19 -08001/*
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 */
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020010#include "modules/audio_processing/aec3/render_delay_controller.h"
peah69221db2017-01-27 03:28:19 -080011
12#include <algorithm>
13#include <memory>
Per Åhgren47127762018-02-13 12:59:33 +010014#include <numeric>
peah69221db2017-01-27 03:28:19 -080015#include <string>
16#include <vector>
17
Gustaf Ullberg3646f972018-02-14 15:19:04 +010018#include "api/audio/echo_canceller3_config.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020019#include "modules/audio_processing/aec3/aec3_common.h"
20#include "modules/audio_processing/aec3/echo_path_delay_estimator.h"
21#include "modules/audio_processing/aec3/render_delay_controller_metrics.h"
Per Åhgren39f491e2018-02-22 00:39:23 +010022#include "modules/audio_processing/aec3/skew_estimator.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020023#include "rtc_base/atomicops.h"
24#include "rtc_base/constructormagic.h"
Per Åhgrend8243fa2018-02-22 17:51:39 +010025#include "rtc_base/logging.h"
Per Åhgren2d9a3b12018-05-17 17:24:29 +020026#include "system_wrappers/include/field_trial.h"
peah69221db2017-01-27 03:28:19 -080027
28namespace webrtc {
29
30namespace {
31
Per Åhgren2d9a3b12018-05-17 17:24:29 +020032int GetSkewHysteresis(const EchoCanceller3Config& config) {
33 if (field_trial::IsEnabled("WebRTC-Aec3EnforceSkewHysteresis1")) {
34 return 1;
35 }
36 if (field_trial::IsEnabled("WebRTC-Aec3EnforceSkewHysteresis2")) {
37 return 2;
38 }
39
40 return static_cast<int>(config.delay.skew_hysteresis_blocks);
41}
42
Gustaf Ullbergd7b0c462018-10-04 12:59:24 +020043bool UseOffsetBlocks() {
44 return field_trial::IsEnabled("WebRTC-Aec3UseOffsetBlocks");
45}
46
Per Åhgren47127762018-02-13 12:59:33 +010047constexpr int kSkewHistorySizeLog2 = 8;
48
peah69221db2017-01-27 03:28:19 -080049class RenderDelayControllerImpl final : public RenderDelayController {
50 public:
Gustaf Ullbergbd83b912017-10-18 12:32:42 +020051 RenderDelayControllerImpl(const EchoCanceller3Config& config,
Per Åhgrenc59a5762017-12-11 21:34:19 +010052 int non_causal_offset,
Gustaf Ullbergbd83b912017-10-18 12:32:42 +020053 int sample_rate_hz);
peah69221db2017-01-27 03:28:19 -080054 ~RenderDelayControllerImpl() override;
peahcf02cf12017-04-05 14:18:07 -070055 void Reset() override;
Per Åhgren47127762018-02-13 12:59:33 +010056 void LogRenderCall() override;
Danil Chapovalovdb9f7ab2018-06-19 10:50:11 +020057 absl::optional<DelayEstimate> GetDelay(
Per Åhgrena76ef9d2018-01-25 07:01:34 +010058 const DownsampledRenderBuffer& render_buffer,
Per Åhgren5c532d32018-03-22 00:29:25 +010059 size_t render_delay_buffer_delay,
Danil Chapovalovdb9f7ab2018-06-19 10:50:11 +020060 const absl::optional<int>& echo_remover_delay,
Per Åhgrena76ef9d2018-01-25 07:01:34 +010061 rtc::ArrayView<const float> capture) override;
peah69221db2017-01-27 03:28:19 -080062
63 private:
64 static int instance_count_;
65 std::unique_ptr<ApmDataDumper> data_dumper_;
Per Åhgrend84b3d12018-01-12 14:47:11 +010066 const int delay_headroom_blocks_;
67 const int hysteresis_limit_1_blocks_;
68 const int hysteresis_limit_2_blocks_;
Per Åhgren8447e912018-02-28 13:28:34 +010069 const int skew_hysteresis_blocks_;
Gustaf Ullbergd7b0c462018-10-04 12:59:24 +020070 const bool use_offset_blocks_;
Danil Chapovalovdb9f7ab2018-06-19 10:50:11 +020071 absl::optional<DelayEstimate> delay_;
Per Åhgren8ba58612017-12-01 23:01:44 +010072 EchoPathDelayEstimator delay_estimator_;
Per Åhgrenc59a5762017-12-11 21:34:19 +010073 std::vector<float> delay_buf_;
74 int delay_buf_index_ = 0;
peahe985b3f2017-02-28 22:08:53 -080075 RenderDelayControllerMetrics metrics_;
Per Åhgren47127762018-02-13 12:59:33 +010076 SkewEstimator skew_estimator_;
Danil Chapovalovdb9f7ab2018-06-19 10:50:11 +020077 absl::optional<DelayEstimate> delay_samples_;
78 absl::optional<int> skew_;
Per Åhgrend8243fa2018-02-22 17:51:39 +010079 int previous_offset_blocks_ = 0;
80 int skew_shift_reporting_counter_ = 0;
81 size_t capture_call_counter_ = 0;
Per Åhgren47127762018-02-13 12:59:33 +010082 int delay_change_counter_ = 0;
83 size_t soft_reset_counter_ = 0;
peah69221db2017-01-27 03:28:19 -080084 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(RenderDelayControllerImpl);
85};
86
Per Åhgren47127762018-02-13 12:59:33 +010087DelayEstimate ComputeBufferDelay(
Danil Chapovalovdb9f7ab2018-06-19 10:50:11 +020088 const absl::optional<DelayEstimate>& current_delay,
Per Åhgrena76ef9d2018-01-25 07:01:34 +010089 int delay_headroom_blocks,
90 int hysteresis_limit_1_blocks,
91 int hysteresis_limit_2_blocks,
Per Åhgren47127762018-02-13 12:59:33 +010092 int offset_blocks,
Per Åhgrena76ef9d2018-01-25 07:01:34 +010093 DelayEstimate estimated_delay) {
peah69221db2017-01-27 03:28:19 -080094 // The below division is not exact and the truncation is intended.
Per Åhgrena76ef9d2018-01-25 07:01:34 +010095 const int echo_path_delay_blocks = estimated_delay.delay >> kBlockSizeLog2;
peah69221db2017-01-27 03:28:19 -080096
97 // Compute the buffer delay increase required to achieve the desired latency.
Per Åhgren47127762018-02-13 12:59:33 +010098 size_t new_delay_blocks = std::max(
99 echo_path_delay_blocks + offset_blocks - delay_headroom_blocks, 0);
Per Åhgrena76ef9d2018-01-25 07:01:34 +0100100
peah69221db2017-01-27 03:28:19 -0800101 // Add hysteresis.
Per Åhgrenc59a5762017-12-11 21:34:19 +0100102 if (current_delay) {
Per Åhgrena76ef9d2018-01-25 07:01:34 +0100103 size_t current_delay_blocks = current_delay->delay;
104 if (new_delay_blocks > current_delay_blocks) {
105 if (new_delay_blocks <=
106 current_delay_blocks + hysteresis_limit_1_blocks) {
107 new_delay_blocks = current_delay_blocks;
Per Åhgrend84b3d12018-01-12 14:47:11 +0100108 }
Per Åhgrena76ef9d2018-01-25 07:01:34 +0100109 } else if (new_delay_blocks < current_delay_blocks) {
Per Åhgrend84b3d12018-01-12 14:47:11 +0100110 size_t hysteresis_limit = std::max(
Per Åhgrena76ef9d2018-01-25 07:01:34 +0100111 static_cast<int>(current_delay_blocks) - hysteresis_limit_2_blocks,
112 0);
113 if (new_delay_blocks >= hysteresis_limit) {
114 new_delay_blocks = current_delay_blocks;
Per Åhgrend84b3d12018-01-12 14:47:11 +0100115 }
Per Åhgrenc59a5762017-12-11 21:34:19 +0100116 }
peah69221db2017-01-27 03:28:19 -0800117 }
118
Per Åhgren3ab308f2018-02-21 08:46:03 +0100119 DelayEstimate new_delay = estimated_delay;
120 new_delay.delay = new_delay_blocks;
121 return new_delay;
peah69221db2017-01-27 03:28:19 -0800122}
123
124int RenderDelayControllerImpl::instance_count_ = 0;
125
peah4fed3c02017-08-30 06:58:44 -0700126RenderDelayControllerImpl::RenderDelayControllerImpl(
Gustaf Ullbergbd83b912017-10-18 12:32:42 +0200127 const EchoCanceller3Config& config,
Per Åhgrenc59a5762017-12-11 21:34:19 +0100128 int non_causal_offset,
peah4fed3c02017-08-30 06:58:44 -0700129 int sample_rate_hz)
peah69221db2017-01-27 03:28:19 -0800130 : data_dumper_(
131 new ApmDataDumper(rtc::AtomicOps::Increment(&instance_count_))),
Per Åhgrend84b3d12018-01-12 14:47:11 +0100132 delay_headroom_blocks_(
133 static_cast<int>(config.delay.delay_headroom_blocks)),
134 hysteresis_limit_1_blocks_(
135 static_cast<int>(config.delay.hysteresis_limit_1_blocks)),
136 hysteresis_limit_2_blocks_(
137 static_cast<int>(config.delay.hysteresis_limit_2_blocks)),
Per Åhgren2d9a3b12018-05-17 17:24:29 +0200138 skew_hysteresis_blocks_(GetSkewHysteresis(config)),
Gustaf Ullbergd7b0c462018-10-04 12:59:24 +0200139 use_offset_blocks_(UseOffsetBlocks()),
Per Åhgren8ba58612017-12-01 23:01:44 +0100140 delay_estimator_(data_dumper_.get(), config),
Per Åhgren39f491e2018-02-22 00:39:23 +0100141 delay_buf_(kBlockSize * non_causal_offset, 0.f),
142 skew_estimator_(kSkewHistorySizeLog2) {
peah21920892017-02-08 05:08:56 -0800143 RTC_DCHECK(ValidFullBandRate(sample_rate_hz));
Per Åhgren38e2d952017-11-17 14:54:28 +0100144 delay_estimator_.LogDelayEstimationProperties(sample_rate_hz,
Per Åhgrenc59a5762017-12-11 21:34:19 +0100145 delay_buf_.size());
peah69221db2017-01-27 03:28:19 -0800146}
147
148RenderDelayControllerImpl::~RenderDelayControllerImpl() = default;
149
peahcf02cf12017-04-05 14:18:07 -0700150void RenderDelayControllerImpl::Reset() {
Danil Chapovalovdb9f7ab2018-06-19 10:50:11 +0200151 delay_ = absl::nullopt;
152 delay_samples_ = absl::nullopt;
153 skew_ = absl::nullopt;
Per Åhgrend8243fa2018-02-22 17:51:39 +0100154 previous_offset_blocks_ = 0;
Per Åhgrenc59a5762017-12-11 21:34:19 +0100155 std::fill(delay_buf_.begin(), delay_buf_.end(), 0.f);
Per Åhgren47127762018-02-13 12:59:33 +0100156 delay_estimator_.Reset(false);
157 skew_estimator_.Reset();
158 delay_change_counter_ = 0;
159 soft_reset_counter_ = 0;
160}
161
162void RenderDelayControllerImpl::LogRenderCall() {
163 skew_estimator_.LogRenderCall();
peahcf02cf12017-04-05 14:18:07 -0700164}
165
Danil Chapovalovdb9f7ab2018-06-19 10:50:11 +0200166absl::optional<DelayEstimate> RenderDelayControllerImpl::GetDelay(
peahcf02cf12017-04-05 14:18:07 -0700167 const DownsampledRenderBuffer& render_buffer,
Per Åhgren5c532d32018-03-22 00:29:25 +0100168 size_t render_delay_buffer_delay,
Danil Chapovalovdb9f7ab2018-06-19 10:50:11 +0200169 const absl::optional<int>& echo_remover_delay,
peah69221db2017-01-27 03:28:19 -0800170 rtc::ArrayView<const float> capture) {
171 RTC_DCHECK_EQ(kBlockSize, capture.size());
Per Åhgrend8243fa2018-02-22 17:51:39 +0100172 ++capture_call_counter_;
Per Åhgren930021d2017-09-15 07:32:53 +0200173
Per Åhgrenc59a5762017-12-11 21:34:19 +0100174 // Estimate the delay with a delayed capture.
175 RTC_DCHECK_LT(delay_buf_index_ + kBlockSize - 1, delay_buf_.size());
176 rtc::ArrayView<const float> capture_delayed(&delay_buf_[delay_buf_index_],
177 kBlockSize);
178 auto delay_samples =
179 delay_estimator_.EstimateDelay(render_buffer, capture_delayed);
180
Per Åhgren5c532d32018-03-22 00:29:25 +0100181 // Overrule the delay estimator delay if the echo remover reports a delay.
182 if (echo_remover_delay) {
183 int total_echo_remover_delay_samples =
184 (render_delay_buffer_delay + *echo_remover_delay) * kBlockSize;
185 delay_samples = DelayEstimate(DelayEstimate::Quality::kRefined,
186 total_echo_remover_delay_samples);
187 }
188
Per Åhgren930021d2017-09-15 07:32:53 +0200189 std::copy(capture.begin(), capture.end(),
Per Åhgrenc59a5762017-12-11 21:34:19 +0100190 delay_buf_.begin() + delay_buf_index_);
191 delay_buf_index_ = (delay_buf_index_ + kBlockSize) % delay_buf_.size();
Per Åhgren930021d2017-09-15 07:32:53 +0200192
Per Åhgren47127762018-02-13 12:59:33 +0100193 // Compute the latest skew update.
Danil Chapovalovdb9f7ab2018-06-19 10:50:11 +0200194 absl::optional<int> skew = skew_estimator_.GetSkewFromCapture();
Per Åhgren47127762018-02-13 12:59:33 +0100195
Per Åhgrenc59a5762017-12-11 21:34:19 +0100196 if (delay_samples) {
Per Åhgren5c532d32018-03-22 00:29:25 +0100197 // TODO(peah): Refactor the rest of the code to assume a kRefined estimate
198 // quality.
199 RTC_DCHECK(DelayEstimate::Quality::kRefined == delay_samples->quality);
Per Åhgren47127762018-02-13 12:59:33 +0100200 if (!delay_samples_ || delay_samples->delay != delay_samples_->delay) {
201 delay_change_counter_ = 0;
202 }
Per Åhgren3ab308f2018-02-21 08:46:03 +0100203 if (delay_samples_) {
204 delay_samples_->blocks_since_last_change =
205 delay_samples_->delay == delay_samples->delay
206 ? delay_samples_->blocks_since_last_change + 1
207 : 0;
208 delay_samples_->blocks_since_last_update = 0;
209 delay_samples_->delay = delay_samples->delay;
210 delay_samples_->quality = delay_samples->quality;
211 } else {
212 delay_samples_ = delay_samples;
213 }
214 } else {
215 if (delay_samples_) {
216 ++delay_samples_->blocks_since_last_change;
217 ++delay_samples_->blocks_since_last_update;
218 }
Per Åhgren930021d2017-09-15 07:32:53 +0200219 }
peahe985b3f2017-02-28 22:08:53 -0800220
Per Åhgren47127762018-02-13 12:59:33 +0100221 if (delay_change_counter_ < 2 * kNumBlocksPerSecond) {
222 ++delay_change_counter_;
223 // If a new delay estimate is recently obtained, store the skew for that.
224 skew_ = skew;
225 } else {
226 // A reliable skew should have been obtained after 2 seconds.
227 RTC_DCHECK(skew_);
228 RTC_DCHECK(skew);
229 }
230
231 ++soft_reset_counter_;
232 int offset_blocks = 0;
233 if (skew_ && skew && delay_samples_ &&
234 delay_samples_->quality == DelayEstimate::Quality::kRefined) {
235 // Compute the skew offset and add a margin.
236 offset_blocks = *skew_ - *skew;
Per Åhgren8447e912018-02-28 13:28:34 +0100237 if (abs(offset_blocks) <= skew_hysteresis_blocks_) {
238 offset_blocks = 0;
239 } else if (soft_reset_counter_ > 10 * kNumBlocksPerSecond) {
Per Åhgren47127762018-02-13 12:59:33 +0100240 // Soft reset the delay estimator if there is a significant offset
241 // detected.
242 delay_estimator_.Reset(true);
243 soft_reset_counter_ = 0;
244 }
245 }
Gustaf Ullbergd7b0c462018-10-04 12:59:24 +0200246 if (!use_offset_blocks_)
247 offset_blocks = 0;
Per Åhgren47127762018-02-13 12:59:33 +0100248
Per Åhgrend8243fa2018-02-22 17:51:39 +0100249 // Log any changes in the skew.
250 skew_shift_reporting_counter_ =
251 std::max(0, skew_shift_reporting_counter_ - 1);
Danil Chapovalovdb9f7ab2018-06-19 10:50:11 +0200252 absl::optional<int> skew_shift =
Per Åhgrend8243fa2018-02-22 17:51:39 +0100253 skew_shift_reporting_counter_ == 0 &&
254 previous_offset_blocks_ != offset_blocks
Danil Chapovalovdb9f7ab2018-06-19 10:50:11 +0200255 ? absl::optional<int>(offset_blocks - previous_offset_blocks_)
256 : absl::nullopt;
Per Åhgrend8243fa2018-02-22 17:51:39 +0100257 previous_offset_blocks_ = offset_blocks;
258 if (skew_shift) {
259 RTC_LOG(LS_WARNING) << "API call skew shift of " << *skew_shift
260 << " blocks detected at capture block "
261 << capture_call_counter_;
262 skew_shift_reporting_counter_ = 3 * kNumBlocksPerSecond;
263 }
264
Per Åhgren47127762018-02-13 12:59:33 +0100265 if (delay_samples_) {
266 // Compute the render delay buffer delay.
267 delay_ = ComputeBufferDelay(
268 delay_, delay_headroom_blocks_, hysteresis_limit_1_blocks_,
269 hysteresis_limit_2_blocks_, offset_blocks, *delay_samples_);
270 }
271
Danil Chapovalovdb9f7ab2018-06-19 10:50:11 +0200272 metrics_.Update(delay_samples_ ? absl::optional<size_t>(delay_samples_->delay)
273 : absl::nullopt,
Per Åhgrend8243fa2018-02-22 17:51:39 +0100274 delay_ ? delay_->delay : 0, skew_shift);
Per Åhgren47127762018-02-13 12:59:33 +0100275
Per Åhgrenc59a5762017-12-11 21:34:19 +0100276 data_dumper_->DumpRaw("aec3_render_delay_controller_delay",
Per Åhgrena76ef9d2018-01-25 07:01:34 +0100277 delay_samples ? delay_samples->delay : 0);
Per Åhgrenc59a5762017-12-11 21:34:19 +0100278 data_dumper_->DumpRaw("aec3_render_delay_controller_buffer_delay",
Per Åhgrena76ef9d2018-01-25 07:01:34 +0100279 delay_ ? delay_->delay : 0);
peah69221db2017-01-27 03:28:19 -0800280
Per Åhgren47127762018-02-13 12:59:33 +0100281 data_dumper_->DumpRaw("aec3_render_delay_controller_new_skew",
282 skew ? *skew : 0);
283 data_dumper_->DumpRaw("aec3_render_delay_controller_old_skew",
284 skew_ ? *skew_ : 0);
285 data_dumper_->DumpRaw("aec3_render_delay_controller_offset", offset_blocks);
286
peah69221db2017-01-27 03:28:19 -0800287 return delay_;
288}
289
peah69221db2017-01-27 03:28:19 -0800290} // namespace
291
peah4fed3c02017-08-30 06:58:44 -0700292RenderDelayController* RenderDelayController::Create(
Gustaf Ullbergbd83b912017-10-18 12:32:42 +0200293 const EchoCanceller3Config& config,
Per Åhgrenc59a5762017-12-11 21:34:19 +0100294 int non_causal_offset,
peah4fed3c02017-08-30 06:58:44 -0700295 int sample_rate_hz) {
Per Åhgrenc59a5762017-12-11 21:34:19 +0100296 return new RenderDelayControllerImpl(config, non_causal_offset,
297 sample_rate_hz);
peah69221db2017-01-27 03:28:19 -0800298}
299
300} // namespace webrtc