blob: f2a7b54290c86a16ebe52326f326931b78ea72cb [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"
peah69221db2017-01-27 03:28:19 -080025
26namespace webrtc {
27
28namespace {
29
Per Åhgren47127762018-02-13 12:59:33 +010030constexpr int kSkewHistorySizeLog2 = 8;
31
peah69221db2017-01-27 03:28:19 -080032class RenderDelayControllerImpl final : public RenderDelayController {
33 public:
Gustaf Ullbergbd83b912017-10-18 12:32:42 +020034 RenderDelayControllerImpl(const EchoCanceller3Config& config,
Per Åhgrenc59a5762017-12-11 21:34:19 +010035 int non_causal_offset,
Gustaf Ullbergbd83b912017-10-18 12:32:42 +020036 int sample_rate_hz);
peah69221db2017-01-27 03:28:19 -080037 ~RenderDelayControllerImpl() override;
peahcf02cf12017-04-05 14:18:07 -070038 void Reset() override;
Per Åhgren47127762018-02-13 12:59:33 +010039 void LogRenderCall() override;
Per Åhgrena76ef9d2018-01-25 07:01:34 +010040 rtc::Optional<DelayEstimate> GetDelay(
41 const DownsampledRenderBuffer& render_buffer,
42 rtc::ArrayView<const float> capture) override;
peah69221db2017-01-27 03:28:19 -080043
44 private:
45 static int instance_count_;
46 std::unique_ptr<ApmDataDumper> data_dumper_;
Per Åhgrend84b3d12018-01-12 14:47:11 +010047 const int delay_headroom_blocks_;
48 const int hysteresis_limit_1_blocks_;
49 const int hysteresis_limit_2_blocks_;
Per Åhgrena76ef9d2018-01-25 07:01:34 +010050 rtc::Optional<DelayEstimate> delay_;
Per Åhgren8ba58612017-12-01 23:01:44 +010051 EchoPathDelayEstimator delay_estimator_;
Per Åhgrenc59a5762017-12-11 21:34:19 +010052 std::vector<float> delay_buf_;
53 int delay_buf_index_ = 0;
peahe985b3f2017-02-28 22:08:53 -080054 RenderDelayControllerMetrics metrics_;
Per Åhgren47127762018-02-13 12:59:33 +010055 SkewEstimator skew_estimator_;
56 rtc::Optional<DelayEstimate> delay_samples_;
57 rtc::Optional<int> skew_;
58 int delay_change_counter_ = 0;
59 size_t soft_reset_counter_ = 0;
peah69221db2017-01-27 03:28:19 -080060 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(RenderDelayControllerImpl);
61};
62
Per Åhgren47127762018-02-13 12:59:33 +010063DelayEstimate ComputeBufferDelay(
Per Åhgrena76ef9d2018-01-25 07:01:34 +010064 const rtc::Optional<DelayEstimate>& current_delay,
65 int delay_headroom_blocks,
66 int hysteresis_limit_1_blocks,
67 int hysteresis_limit_2_blocks,
Per Åhgren47127762018-02-13 12:59:33 +010068 int offset_blocks,
Per Åhgrena76ef9d2018-01-25 07:01:34 +010069 DelayEstimate estimated_delay) {
peah69221db2017-01-27 03:28:19 -080070 // The below division is not exact and the truncation is intended.
Per Åhgrena76ef9d2018-01-25 07:01:34 +010071 const int echo_path_delay_blocks = estimated_delay.delay >> kBlockSizeLog2;
peah69221db2017-01-27 03:28:19 -080072
73 // Compute the buffer delay increase required to achieve the desired latency.
Per Åhgren47127762018-02-13 12:59:33 +010074 size_t new_delay_blocks = std::max(
75 echo_path_delay_blocks + offset_blocks - delay_headroom_blocks, 0);
Per Åhgrena76ef9d2018-01-25 07:01:34 +010076
peah69221db2017-01-27 03:28:19 -080077 // Add hysteresis.
Per Åhgrenc59a5762017-12-11 21:34:19 +010078 if (current_delay) {
Per Åhgrena76ef9d2018-01-25 07:01:34 +010079 size_t current_delay_blocks = current_delay->delay;
80 if (new_delay_blocks > current_delay_blocks) {
81 if (new_delay_blocks <=
82 current_delay_blocks + hysteresis_limit_1_blocks) {
83 new_delay_blocks = current_delay_blocks;
Per Åhgrend84b3d12018-01-12 14:47:11 +010084 }
Per Åhgrena76ef9d2018-01-25 07:01:34 +010085 } else if (new_delay_blocks < current_delay_blocks) {
Per Åhgrend84b3d12018-01-12 14:47:11 +010086 size_t hysteresis_limit = std::max(
Per Åhgrena76ef9d2018-01-25 07:01:34 +010087 static_cast<int>(current_delay_blocks) - hysteresis_limit_2_blocks,
88 0);
89 if (new_delay_blocks >= hysteresis_limit) {
90 new_delay_blocks = current_delay_blocks;
Per Åhgrend84b3d12018-01-12 14:47:11 +010091 }
Per Åhgrenc59a5762017-12-11 21:34:19 +010092 }
peah69221db2017-01-27 03:28:19 -080093 }
94
Per Åhgren3ab308f2018-02-21 08:46:03 +010095 DelayEstimate new_delay = estimated_delay;
96 new_delay.delay = new_delay_blocks;
97 return new_delay;
peah69221db2017-01-27 03:28:19 -080098}
99
100int RenderDelayControllerImpl::instance_count_ = 0;
101
peah4fed3c02017-08-30 06:58:44 -0700102RenderDelayControllerImpl::RenderDelayControllerImpl(
Gustaf Ullbergbd83b912017-10-18 12:32:42 +0200103 const EchoCanceller3Config& config,
Per Åhgrenc59a5762017-12-11 21:34:19 +0100104 int non_causal_offset,
peah4fed3c02017-08-30 06:58:44 -0700105 int sample_rate_hz)
peah69221db2017-01-27 03:28:19 -0800106 : data_dumper_(
107 new ApmDataDumper(rtc::AtomicOps::Increment(&instance_count_))),
Per Åhgrend84b3d12018-01-12 14:47:11 +0100108 delay_headroom_blocks_(
109 static_cast<int>(config.delay.delay_headroom_blocks)),
110 hysteresis_limit_1_blocks_(
111 static_cast<int>(config.delay.hysteresis_limit_1_blocks)),
112 hysteresis_limit_2_blocks_(
113 static_cast<int>(config.delay.hysteresis_limit_2_blocks)),
Per Åhgren8ba58612017-12-01 23:01:44 +0100114 delay_estimator_(data_dumper_.get(), config),
Per Åhgren39f491e2018-02-22 00:39:23 +0100115 delay_buf_(kBlockSize * non_causal_offset, 0.f),
116 skew_estimator_(kSkewHistorySizeLog2) {
peah21920892017-02-08 05:08:56 -0800117 RTC_DCHECK(ValidFullBandRate(sample_rate_hz));
Per Åhgren38e2d952017-11-17 14:54:28 +0100118 delay_estimator_.LogDelayEstimationProperties(sample_rate_hz,
Per Åhgrenc59a5762017-12-11 21:34:19 +0100119 delay_buf_.size());
peah69221db2017-01-27 03:28:19 -0800120}
121
122RenderDelayControllerImpl::~RenderDelayControllerImpl() = default;
123
peahcf02cf12017-04-05 14:18:07 -0700124void RenderDelayControllerImpl::Reset() {
Per Åhgrenc59a5762017-12-11 21:34:19 +0100125 delay_ = rtc::nullopt;
Per Åhgren47127762018-02-13 12:59:33 +0100126 delay_samples_ = rtc::nullopt;
127 skew_ = rtc::nullopt;
Per Åhgrenc59a5762017-12-11 21:34:19 +0100128 std::fill(delay_buf_.begin(), delay_buf_.end(), 0.f);
Per Åhgren47127762018-02-13 12:59:33 +0100129 delay_estimator_.Reset(false);
130 skew_estimator_.Reset();
131 delay_change_counter_ = 0;
132 soft_reset_counter_ = 0;
133}
134
135void RenderDelayControllerImpl::LogRenderCall() {
136 skew_estimator_.LogRenderCall();
peahcf02cf12017-04-05 14:18:07 -0700137}
138
Per Åhgrena76ef9d2018-01-25 07:01:34 +0100139rtc::Optional<DelayEstimate> RenderDelayControllerImpl::GetDelay(
peahcf02cf12017-04-05 14:18:07 -0700140 const DownsampledRenderBuffer& render_buffer,
peah69221db2017-01-27 03:28:19 -0800141 rtc::ArrayView<const float> capture) {
142 RTC_DCHECK_EQ(kBlockSize, capture.size());
Per Åhgren930021d2017-09-15 07:32:53 +0200143
Per Åhgrenc59a5762017-12-11 21:34:19 +0100144 // Estimate the delay with a delayed capture.
145 RTC_DCHECK_LT(delay_buf_index_ + kBlockSize - 1, delay_buf_.size());
146 rtc::ArrayView<const float> capture_delayed(&delay_buf_[delay_buf_index_],
147 kBlockSize);
148 auto delay_samples =
149 delay_estimator_.EstimateDelay(render_buffer, capture_delayed);
150
Per Åhgren930021d2017-09-15 07:32:53 +0200151 std::copy(capture.begin(), capture.end(),
Per Åhgrenc59a5762017-12-11 21:34:19 +0100152 delay_buf_.begin() + delay_buf_index_);
153 delay_buf_index_ = (delay_buf_index_ + kBlockSize) % delay_buf_.size();
Per Åhgren930021d2017-09-15 07:32:53 +0200154
Per Åhgren47127762018-02-13 12:59:33 +0100155 // Compute the latest skew update.
156 rtc::Optional<int> skew = skew_estimator_.GetSkewFromCapture();
157
Per Åhgrenc59a5762017-12-11 21:34:19 +0100158 if (delay_samples) {
Per Åhgren47127762018-02-13 12:59:33 +0100159 if (!delay_samples_ || delay_samples->delay != delay_samples_->delay) {
160 delay_change_counter_ = 0;
161 }
Per Åhgren3ab308f2018-02-21 08:46:03 +0100162 if (delay_samples_) {
163 delay_samples_->blocks_since_last_change =
164 delay_samples_->delay == delay_samples->delay
165 ? delay_samples_->blocks_since_last_change + 1
166 : 0;
167 delay_samples_->blocks_since_last_update = 0;
168 delay_samples_->delay = delay_samples->delay;
169 delay_samples_->quality = delay_samples->quality;
170 } else {
171 delay_samples_ = delay_samples;
172 }
173 } else {
174 if (delay_samples_) {
175 ++delay_samples_->blocks_since_last_change;
176 ++delay_samples_->blocks_since_last_update;
177 }
Per Åhgren930021d2017-09-15 07:32:53 +0200178 }
peahe985b3f2017-02-28 22:08:53 -0800179
Per Åhgren47127762018-02-13 12:59:33 +0100180 if (delay_change_counter_ < 2 * kNumBlocksPerSecond) {
181 ++delay_change_counter_;
182 // If a new delay estimate is recently obtained, store the skew for that.
183 skew_ = skew;
184 } else {
185 // A reliable skew should have been obtained after 2 seconds.
186 RTC_DCHECK(skew_);
187 RTC_DCHECK(skew);
188 }
189
190 ++soft_reset_counter_;
191 int offset_blocks = 0;
192 if (skew_ && skew && delay_samples_ &&
193 delay_samples_->quality == DelayEstimate::Quality::kRefined) {
194 // Compute the skew offset and add a margin.
195 offset_blocks = *skew_ - *skew;
Per Åhgrenfdd44002018-02-13 14:01:46 +0100196 if (offset_blocks != 0 && soft_reset_counter_ > 10 * kNumBlocksPerSecond) {
Per Åhgren47127762018-02-13 12:59:33 +0100197 // Soft reset the delay estimator if there is a significant offset
198 // detected.
199 delay_estimator_.Reset(true);
200 soft_reset_counter_ = 0;
201 }
202 }
203
204 if (delay_samples_) {
205 // Compute the render delay buffer delay.
206 delay_ = ComputeBufferDelay(
207 delay_, delay_headroom_blocks_, hysteresis_limit_1_blocks_,
208 hysteresis_limit_2_blocks_, offset_blocks, *delay_samples_);
209 }
210
211 metrics_.Update(delay_samples_ ? rtc::Optional<size_t>(delay_samples_->delay)
212 : rtc::nullopt,
213 delay_ ? delay_->delay : 0);
214
Per Åhgrenc59a5762017-12-11 21:34:19 +0100215 data_dumper_->DumpRaw("aec3_render_delay_controller_delay",
Per Åhgrena76ef9d2018-01-25 07:01:34 +0100216 delay_samples ? delay_samples->delay : 0);
Per Åhgrenc59a5762017-12-11 21:34:19 +0100217 data_dumper_->DumpRaw("aec3_render_delay_controller_buffer_delay",
Per Åhgrena76ef9d2018-01-25 07:01:34 +0100218 delay_ ? delay_->delay : 0);
peah69221db2017-01-27 03:28:19 -0800219
Per Åhgren47127762018-02-13 12:59:33 +0100220 data_dumper_->DumpRaw("aec3_render_delay_controller_new_skew",
221 skew ? *skew : 0);
222 data_dumper_->DumpRaw("aec3_render_delay_controller_old_skew",
223 skew_ ? *skew_ : 0);
224 data_dumper_->DumpRaw("aec3_render_delay_controller_offset", offset_blocks);
225
peah69221db2017-01-27 03:28:19 -0800226 return delay_;
227}
228
peah69221db2017-01-27 03:28:19 -0800229} // namespace
230
peah4fed3c02017-08-30 06:58:44 -0700231RenderDelayController* RenderDelayController::Create(
Gustaf Ullbergbd83b912017-10-18 12:32:42 +0200232 const EchoCanceller3Config& config,
Per Åhgrenc59a5762017-12-11 21:34:19 +0100233 int non_causal_offset,
peah4fed3c02017-08-30 06:58:44 -0700234 int sample_rate_hz) {
Per Åhgrenc59a5762017-12-11 21:34:19 +0100235 return new RenderDelayControllerImpl(config, non_causal_offset,
236 sample_rate_hz);
peah69221db2017-01-27 03:28:19 -0800237}
238
239} // namespace webrtc