AEC3: Redesign delay headroom

This change reduces the risk of echo due to noise in the headroom
of the linear filter.

Changes:
- Use shorter delay headroom
- Delay headroom is specified in samples (not blocks)
- No hysteresis limit when delay is reduced

Bug: chromium:119942,webrtc:10341
Change-Id: I708e80e26d541dff8ca04b6da2d346a1d59cbfcb
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/126420
Commit-Queue: Gustaf Ullberg <gustaf@webrtc.org>
Reviewed-by: Sam Zackrisson <saza@webrtc.org>
Reviewed-by: Per Åhgren <peah@webrtc.org>
Reviewed-by: Jesus de Vicente Pena <devicentepena@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#27126}
This commit is contained in:
Gustaf Ullberg
2019-03-14 11:24:54 +01:00
committed by Commit Bot
parent 41f9f2cc57
commit 9249fbf3a6
11 changed files with 48 additions and 72 deletions

View File

@ -46,9 +46,8 @@ class RenderDelayControllerImpl final : public RenderDelayController {
private:
static int instance_count_;
std::unique_ptr<ApmDataDumper> data_dumper_;
const int delay_headroom_blocks_;
const int hysteresis_limit_1_blocks_;
const int hysteresis_limit_2_blocks_;
const int hysteresis_limit_blocks_;
const int delay_headroom_samples_;
absl::optional<DelayEstimate> delay_;
EchoPathDelayEstimator delay_estimator_;
RenderDelayControllerMetrics metrics_;
@ -61,32 +60,22 @@ class RenderDelayControllerImpl final : public RenderDelayController {
DelayEstimate ComputeBufferDelay(
const absl::optional<DelayEstimate>& current_delay,
int delay_headroom_blocks,
int hysteresis_limit_1_blocks,
int hysteresis_limit_2_blocks,
int hysteresis_limit_blocks,
int delay_headroom_samples,
DelayEstimate estimated_delay) {
// The below division is not exact and the truncation is intended.
const int echo_path_delay_blocks = estimated_delay.delay >> kBlockSizeLog2;
// Subtract delay headroom.
const int delay_with_headroom_samples = std::max(
static_cast<int>(estimated_delay.delay) - delay_headroom_samples, 0);
// Compute the buffer delay increase required to achieve the desired latency.
size_t new_delay_blocks =
std::max(echo_path_delay_blocks - delay_headroom_blocks, 0);
size_t new_delay_blocks = delay_with_headroom_samples >> kBlockSizeLog2;
// Add hysteresis.
if (current_delay) {
size_t current_delay_blocks = current_delay->delay;
if (new_delay_blocks > current_delay_blocks) {
if (new_delay_blocks <=
current_delay_blocks + hysteresis_limit_1_blocks) {
new_delay_blocks = current_delay_blocks;
}
} else if (new_delay_blocks < current_delay_blocks) {
size_t hysteresis_limit = std::max(
static_cast<int>(current_delay_blocks) - hysteresis_limit_2_blocks,
0);
if (new_delay_blocks >= hysteresis_limit) {
new_delay_blocks = current_delay_blocks;
}
if (new_delay_blocks > current_delay_blocks &&
new_delay_blocks <= current_delay_blocks + hysteresis_limit_blocks) {
new_delay_blocks = current_delay_blocks;
}
}
@ -102,12 +91,9 @@ RenderDelayControllerImpl::RenderDelayControllerImpl(
int sample_rate_hz)
: data_dumper_(
new ApmDataDumper(rtc::AtomicOps::Increment(&instance_count_))),
delay_headroom_blocks_(
static_cast<int>(config.delay.delay_headroom_blocks)),
hysteresis_limit_1_blocks_(
static_cast<int>(config.delay.hysteresis_limit_1_blocks)),
hysteresis_limit_2_blocks_(
static_cast<int>(config.delay.hysteresis_limit_2_blocks)),
hysteresis_limit_blocks_(
static_cast<int>(config.delay.hysteresis_limit_blocks)),
delay_headroom_samples_(config.delay.delay_headroom_samples),
delay_estimator_(data_dumper_.get(), config),
last_delay_estimate_quality_(DelayEstimate::Quality::kCoarse) {
RTC_DCHECK(ValidFullBandRate(sample_rate_hz));
@ -177,10 +163,9 @@ absl::optional<DelayEstimate> RenderDelayControllerImpl::GetDelay(
const bool use_hysteresis =
last_delay_estimate_quality_ == DelayEstimate::Quality::kRefined &&
delay_samples_->quality == DelayEstimate::Quality::kRefined;
delay_ = ComputeBufferDelay(delay_, delay_headroom_blocks_,
use_hysteresis ? hysteresis_limit_1_blocks_ : 0,
use_hysteresis ? hysteresis_limit_2_blocks_ : 0,
*delay_samples_);
delay_ = ComputeBufferDelay(delay_,
use_hysteresis ? hysteresis_limit_blocks_ : 0,
delay_headroom_samples_, *delay_samples_);
last_delay_estimate_quality_ = delay_samples_->quality;
}