Robustify the faster alignment in AEC3 to avoid resets

The faster AEC3 alignment introduced recently may in
cases cause the alignment (and the AEC3) to repeatedly
reset. This CL avoids these resets by handling buffer
issues (which are triggering the resets) separately
during the initial coarse alignment phase.



Change-Id: Idf5e2ffda2591906da8060d03ec8ca73cdaedf53
Bug: webrtc:8798,chromium:805815
Reviewed-on: https://webrtc-review.googlesource.com/43480
Commit-Queue: Per Åhgren <peah@webrtc.org>
Reviewed-by: Gustaf Ullberg <gustaf@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#21758}
This commit is contained in:
Per Åhgren 2018-01-25 07:01:34 +01:00 committed by Commit Bot
parent b9b07eaf28
commit a76ef9d0b4
17 changed files with 148 additions and 109 deletions

View File

@ -55,6 +55,7 @@ rtc_static_library("audio_processing") {
"aec3/comfort_noise_generator.h",
"aec3/decimator.cc",
"aec3/decimator.h",
"aec3/delay_estimate.h",
"aec3/downsampled_render_buffer.cc",
"aec3/downsampled_render_buffer.h",
"aec3/echo_canceller3.cc",

View File

@ -56,6 +56,7 @@ class BlockProcessorImpl final : public BlockProcessor {
BlockProcessorMetrics metrics_;
RenderDelayBuffer::BufferingEvent render_event_;
size_t capture_call_counter_ = 0;
rtc::Optional<DelayEstimate> estimated_delay_;
RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(BlockProcessorImpl);
};
@ -126,14 +127,17 @@ void BlockProcessorImpl::ProcessCapture(
RTC_DCHECK(RenderDelayBuffer::BufferingEvent::kRenderOverrun !=
render_event_);
if (render_event_ == RenderDelayBuffer::BufferingEvent::kRenderUnderrun) {
echo_path_variability.delay_change =
EchoPathVariability::DelayAdjustment::kDelayReset;
delay_controller_->Reset();
capture_properly_started_ = false;
render_properly_started_ = false;
if (estimated_delay_ &&
estimated_delay_->quality == DelayEstimate::Quality::kRefined) {
echo_path_variability.delay_change =
EchoPathVariability::DelayAdjustment::kDelayReset;
delay_controller_->Reset();
capture_properly_started_ = false;
render_properly_started_ = false;
RTC_LOG(LS_WARNING) << "Reset due to render buffer underrrun at block "
<< capture_call_counter_;
RTC_LOG(LS_WARNING) << "Reset due to render buffer underrrun at block "
<< capture_call_counter_;
}
} else if (render_event_ == RenderDelayBuffer::BufferingEvent::kApiCallSkew) {
// There have been too many render calls in a row. Reset to avoid noncausal
// echo.
@ -152,22 +156,23 @@ void BlockProcessorImpl::ProcessCapture(
// Compute and and apply the render delay required to achieve proper signal
// alignment.
rtc::Optional<size_t> estimated_delay = delay_controller_->GetDelay(
estimated_delay_ = delay_controller_->GetDelay(
render_buffer_->GetDownsampledRenderBuffer(), (*capture_block)[0]);
if (estimated_delay) {
bool delay_change = render_buffer_->SetDelay(*estimated_delay);
if (delay_change) {
RTC_LOG(LS_WARNING) << "Delay changed to " << *estimated_delay
<< " at block " << capture_call_counter_;
if (render_buffer_->CausalDelay()) {
if (estimated_delay_) {
if (render_buffer_->CausalDelay(estimated_delay_->delay)) {
bool delay_change = render_buffer_->SetDelay(estimated_delay_->delay);
if (delay_change) {
RTC_LOG(LS_WARNING) << "Delay changed to " << estimated_delay_->delay
<< " at block " << capture_call_counter_;
echo_path_variability.delay_change =
EchoPathVariability::DelayAdjustment::kNewDetectedDelay;
} else {
// A noncausal delay has been detected. This can only happen if there is
// clockdrift, an audio pipeline issue has occurred or the specified
// minimum delay is too short. Perform a full reset.
}
} else {
// A noncausal delay has been detected. This can only happen if there is
// clockdrift, an audio pipeline issue has occurred, an unreliable delay
// estimate is used or the specified minimum delay is too short.
if (estimated_delay_->quality == DelayEstimate::Quality::kRefined) {
echo_path_variability.delay_change =
EchoPathVariability::DelayAdjustment::kDelayReset;
delay_controller_->Reset();

View File

@ -165,8 +165,7 @@ TEST(BlockProcessor, DISABLED_SubmoduleIntegration) {
.Times(kNumBlocks)
.WillRepeatedly(Return(0));
EXPECT_CALL(*render_delay_controller_mock, GetDelay(_, _))
.Times(kNumBlocks)
.WillRepeatedly(Return(9));
.Times(kNumBlocks);
EXPECT_CALL(*echo_remover_mock, ProcessCapture(_, _, _, _))
.Times(kNumBlocks);
EXPECT_CALL(*echo_remover_mock, UpdateEchoLeakageStatus(_))

View File

@ -0,0 +1,29 @@
/*
* Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef MODULES_AUDIO_PROCESSING_AEC3_DELAY_ESTIMATE_H_
#define MODULES_AUDIO_PROCESSING_AEC3_DELAY_ESTIMATE_H_
namespace webrtc {
// Stores delay_estimates.
struct DelayEstimate {
enum class Quality { kCoarse, kRefined };
DelayEstimate(Quality quality, size_t delay)
: quality(quality), delay(delay) {}
Quality quality;
size_t delay;
};
} // namespace webrtc
#endif // MODULES_AUDIO_PROCESSING_AEC3_DELAY_ESTIMATE_H_

View File

@ -48,7 +48,7 @@ void EchoPathDelayEstimator::Reset() {
matched_filter_.Reset();
}
rtc::Optional<size_t> EchoPathDelayEstimator::EstimateDelay(
rtc::Optional<DelayEstimate> EchoPathDelayEstimator::EstimateDelay(
const DownsampledRenderBuffer& render_buffer,
rtc::ArrayView<const float> capture) {
RTC_DCHECK_EQ(kBlockSize, capture.size());
@ -64,24 +64,25 @@ rtc::Optional<size_t> EchoPathDelayEstimator::EstimateDelay(
16000 / down_sampling_factor_, 1);
matched_filter_.Update(render_buffer, downsampled_capture);
rtc::Optional<size_t> aggregated_matched_filter_lag =
rtc::Optional<DelayEstimate> aggregated_matched_filter_lag =
matched_filter_lag_aggregator_.Aggregate(
matched_filter_.GetLagEstimates());
// TODO(peah): Move this logging outside of this class once EchoCanceller3
// development is done.
data_dumper_->DumpRaw("aec3_echo_path_delay_estimator_delay",
aggregated_matched_filter_lag
? static_cast<int>(*aggregated_matched_filter_lag *
down_sampling_factor_)
: -1);
data_dumper_->DumpRaw(
"aec3_echo_path_delay_estimator_delay",
aggregated_matched_filter_lag
? static_cast<int>(aggregated_matched_filter_lag->delay *
down_sampling_factor_)
: -1);
// Return the detected delay in samples as the aggregated matched filter lag
// compensated by the down sampling factor for the signal being correlated.
return aggregated_matched_filter_lag
? rtc::Optional<size_t>(*aggregated_matched_filter_lag *
down_sampling_factor_)
: rtc::nullopt;
if (aggregated_matched_filter_lag) {
aggregated_matched_filter_lag->delay *= down_sampling_factor_;
}
return aggregated_matched_filter_lag;
}
} // namespace webrtc

View File

@ -15,6 +15,7 @@
#include "api/optional.h"
#include "modules/audio_processing/aec3/decimator.h"
#include "modules/audio_processing/aec3/delay_estimate.h"
#include "modules/audio_processing/aec3/downsampled_render_buffer.h"
#include "modules/audio_processing/aec3/matched_filter.h"
#include "modules/audio_processing/aec3/matched_filter_lag_aggregator.h"
@ -36,7 +37,7 @@ class EchoPathDelayEstimator {
void Reset();
// Produce a delay estimate if such is avaliable.
rtc::Optional<size_t> EstimateDelay(
rtc::Optional<DelayEstimate> EstimateDelay(
const DownsampledRenderBuffer& render_buffer,
rtc::ArrayView<const float> capture);

View File

@ -72,7 +72,7 @@ TEST(EchoPathDelayEstimator, DelayEstimation) {
delay_samples + 2 * config.delay.api_call_jitter_blocks * 64);
EchoPathDelayEstimator estimator(&data_dumper, config);
rtc::Optional<size_t> estimated_delay_samples;
rtc::Optional<DelayEstimate> estimated_delay_samples;
for (size_t k = 0; k < (500 + (delay_samples) / kBlockSize); ++k) {
RandomizeSampleVector(&random_generator, render[0]);
signal_delay_buffer.Delay(render[0], capture);
@ -92,7 +92,7 @@ TEST(EchoPathDelayEstimator, DelayEstimation) {
// Due to the internal down-sampling done inside the delay estimator
// the estimated delay cannot be expected to be exact to the true delay.
EXPECT_NEAR(delay_samples,
*estimated_delay_samples -
estimated_delay_samples->delay -
(config.delay.api_call_jitter_blocks + 1) * 64,
config.delay.down_sampling_factor);
} else {

View File

@ -30,7 +30,7 @@ void MatchedFilterLagAggregator::Reset() {
significant_candidate_found_ = false;
}
rtc::Optional<size_t> MatchedFilterLagAggregator::Aggregate(
rtc::Optional<DelayEstimate> MatchedFilterLagAggregator::Aggregate(
rtc::ArrayView<const MatchedFilter::LagEstimate> lag_estimates) {
// Choose the strongest lag estimate as the best one.
float best_accuracy = 0.f;
@ -69,9 +69,9 @@ rtc::Optional<size_t> MatchedFilterLagAggregator::Aggregate(
if (histogram_[candidate] > 25) {
significant_candidate_found_ = true;
return candidate;
return DelayEstimate(DelayEstimate::Quality::kRefined, candidate);
} else if (!significant_candidate_found_) {
return candidate;
return DelayEstimate(DelayEstimate::Quality::kCoarse, candidate);
}
}
return rtc::nullopt;

View File

@ -14,6 +14,7 @@
#include <vector>
#include "api/optional.h"
#include "modules/audio_processing/aec3/delay_estimate.h"
#include "modules/audio_processing/aec3/matched_filter.h"
#include "rtc_base/constructormagic.h"
@ -32,7 +33,7 @@ class MatchedFilterLagAggregator {
void Reset();
// Aggregates the provided lag estimates.
rtc::Optional<size_t> Aggregate(
rtc::Optional<DelayEstimate> Aggregate(
rtc::ArrayView<const MatchedFilter::LagEstimate> lag_estimates);
private:

View File

@ -40,9 +40,10 @@ TEST(MatchedFilterLagAggregator, MostAccurateLagChosen) {
EXPECT_TRUE(aggregator.Aggregate(lag_estimates));
}
rtc::Optional<size_t> aggregated_lag = aggregator.Aggregate(lag_estimates);
rtc::Optional<DelayEstimate> aggregated_lag =
aggregator.Aggregate(lag_estimates);
EXPECT_TRUE(aggregated_lag);
EXPECT_EQ(kLag1, *aggregated_lag);
EXPECT_EQ(kLag1, aggregated_lag->delay);
lag_estimates[0] = MatchedFilter::LagEstimate(0.5f, true, kLag1, true);
lag_estimates[1] = MatchedFilter::LagEstimate(1.f, true, kLag2, true);
@ -50,13 +51,13 @@ TEST(MatchedFilterLagAggregator, MostAccurateLagChosen) {
for (size_t k = 0; k < kNumLagsBeforeDetection; ++k) {
aggregated_lag = aggregator.Aggregate(lag_estimates);
EXPECT_TRUE(aggregated_lag);
EXPECT_EQ(kLag1, *aggregated_lag);
EXPECT_EQ(kLag1, aggregated_lag->delay);
}
aggregated_lag = aggregator.Aggregate(lag_estimates);
aggregated_lag = aggregator.Aggregate(lag_estimates);
EXPECT_TRUE(aggregated_lag);
EXPECT_EQ(kLag2, *aggregated_lag);
EXPECT_EQ(kLag2, aggregated_lag->delay);
}
// Verifies that varying lag estimates causes lag estimates to not be deemed
@ -67,7 +68,7 @@ TEST(MatchedFilterLagAggregator,
std::vector<MatchedFilter::LagEstimate> lag_estimates(1);
MatchedFilterLagAggregator aggregator(&data_dumper, 100);
rtc::Optional<size_t> aggregated_lag;
rtc::Optional<DelayEstimate> aggregated_lag;
for (size_t k = 0; k < kNumLagsBeforeDetection; ++k) {
lag_estimates[0] = MatchedFilter::LagEstimate(1.f, true, 10, true);
aggregated_lag = aggregator.Aggregate(lag_estimates);
@ -97,9 +98,10 @@ TEST(MatchedFilterLagAggregator,
MatchedFilterLagAggregator aggregator(&data_dumper, kLag);
for (size_t k = 0; k < kNumLagsBeforeDetection * 10; ++k) {
lag_estimates[0] = MatchedFilter::LagEstimate(1.f, true, kLag, false);
rtc::Optional<size_t> aggregated_lag = aggregator.Aggregate(lag_estimates);
rtc::Optional<DelayEstimate> aggregated_lag =
aggregator.Aggregate(lag_estimates);
EXPECT_FALSE(aggregated_lag);
EXPECT_EQ(kLag, *aggregated_lag);
EXPECT_EQ(kLag, aggregated_lag->delay);
}
}
@ -112,19 +114,19 @@ TEST(MatchedFilterLagAggregator, DISABLED_PersistentAggregatedLag) {
ApmDataDumper data_dumper(0);
std::vector<MatchedFilter::LagEstimate> lag_estimates(1);
MatchedFilterLagAggregator aggregator(&data_dumper, std::max(kLag1, kLag2));
rtc::Optional<size_t> aggregated_lag;
rtc::Optional<DelayEstimate> aggregated_lag;
for (size_t k = 0; k < kNumLagsBeforeDetection; ++k) {
lag_estimates[0] = MatchedFilter::LagEstimate(1.f, true, kLag1, true);
aggregated_lag = aggregator.Aggregate(lag_estimates);
}
EXPECT_TRUE(aggregated_lag);
EXPECT_EQ(kLag1, *aggregated_lag);
EXPECT_EQ(kLag1, aggregated_lag->delay);
for (size_t k = 0; k < kNumLagsBeforeDetection * 40; ++k) {
lag_estimates[0] = MatchedFilter::LagEstimate(1.f, false, kLag2, true);
aggregated_lag = aggregator.Aggregate(lag_estimates);
EXPECT_TRUE(aggregated_lag);
EXPECT_EQ(kLag1, *aggregated_lag);
EXPECT_EQ(kLag1, aggregated_lag->delay);
}
}

View File

@ -52,7 +52,7 @@ class MockRenderDelayBuffer : public RenderDelayBuffer {
MOCK_METHOD0(GetRenderBuffer, RenderBuffer*());
MOCK_CONST_METHOD0(GetDownsampledRenderBuffer,
const DownsampledRenderBuffer&());
MOCK_CONST_METHOD0(CausalDelay, bool());
MOCK_CONST_METHOD1(CausalDelay, bool(size_t delay));
private:
RenderBuffer* FakeGetRenderBuffer() { return &render_buffer_; }

View File

@ -25,11 +25,10 @@ class MockRenderDelayController : public RenderDelayController {
virtual ~MockRenderDelayController() = default;
MOCK_METHOD0(Reset, void());
MOCK_METHOD1(SetDelay, void(size_t render_delay));
MOCK_METHOD2(
GetDelay,
rtc::Optional<size_t>(const DownsampledRenderBuffer& render_buffer,
rtc::ArrayView<const float> capture));
rtc::Optional<DelayEstimate>(const DownsampledRenderBuffer& render_buffer,
rtc::ArrayView<const float> capture));
};
} // namespace test

View File

@ -47,7 +47,7 @@ class RenderDelayBufferImpl final : public RenderDelayBuffer {
return low_rate_;
}
bool CausalDelay() const override;
bool CausalDelay(size_t delay) const override;
private:
static int instance_count_;
@ -304,10 +304,14 @@ bool RenderDelayBufferImpl::SetDelay(size_t delay) {
}
// Returns whether the specified delay is causal.
bool RenderDelayBufferImpl::CausalDelay() const {
return !internal_delay_ ||
*internal_delay_ >=
static_cast<int>(config_.delay.min_echo_path_delay_blocks);
bool RenderDelayBufferImpl::CausalDelay(size_t delay) const {
// Compute the internal delay and limit the delay to the allowed range.
int internal_delay = MaxExternalDelayToInternalDelay(delay);
internal_delay =
std::min(MaxDelay(), static_cast<size_t>(std::max(internal_delay, 0)));
return internal_delay >=
static_cast<int>(config_.delay.min_echo_path_delay_blocks);
}
// Maps the externally computed delay to the delay used internally.

View File

@ -68,7 +68,7 @@ class RenderDelayBuffer {
virtual const DownsampledRenderBuffer& GetDownsampledRenderBuffer() const = 0;
// Returns whether the current delay is noncausal.
virtual bool CausalDelay() const = 0;
virtual bool CausalDelay(size_t delay) const = 0;
// Returns the maximum non calusal offset that can occur in the delay buffer.
static int DelayEstimatorOffset(const EchoCanceller3Config& config);

View File

@ -32,9 +32,9 @@ class RenderDelayControllerImpl final : public RenderDelayController {
int sample_rate_hz);
~RenderDelayControllerImpl() override;
void Reset() override;
void SetDelay(size_t render_delay) override;
rtc::Optional<size_t> GetDelay(const DownsampledRenderBuffer& render_buffer,
rtc::ArrayView<const float> capture) override;
rtc::Optional<DelayEstimate> GetDelay(
const DownsampledRenderBuffer& render_buffer,
rtc::ArrayView<const float> capture) override;
private:
static int instance_count_;
@ -42,7 +42,7 @@ class RenderDelayControllerImpl final : public RenderDelayController {
const int delay_headroom_blocks_;
const int hysteresis_limit_1_blocks_;
const int hysteresis_limit_2_blocks_;
rtc::Optional<size_t> delay_;
rtc::Optional<DelayEstimate> delay_;
EchoPathDelayEstimator delay_estimator_;
std::vector<float> delay_buf_;
int delay_buf_index_ = 0;
@ -50,34 +50,40 @@ class RenderDelayControllerImpl final : public RenderDelayController {
RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(RenderDelayControllerImpl);
};
size_t ComputeNewBufferDelay(const rtc::Optional<size_t>& current_delay,
int delay_headroom_blocks,
int hysteresis_limit_1_blocks,
int hysteresis_limit_2_blocks,
size_t delay_samples) {
DelayEstimate ComputeNewBufferDelay(
const rtc::Optional<DelayEstimate>& current_delay,
int delay_headroom_blocks,
int hysteresis_limit_1_blocks,
int hysteresis_limit_2_blocks,
DelayEstimate estimated_delay) {
// The below division is not exact and the truncation is intended.
const int echo_path_delay_blocks = delay_samples >> kBlockSizeLog2;
const int echo_path_delay_blocks = estimated_delay.delay >> kBlockSizeLog2;
// Compute the buffer delay increase required to achieve the desired latency.
size_t new_delay =
size_t new_delay_blocks =
std::max(echo_path_delay_blocks - delay_headroom_blocks, 0);
DelayEstimate new_delay(estimated_delay.quality, new_delay_blocks);
// Add hysteresis.
if (current_delay) {
if (new_delay > *current_delay) {
if (new_delay <= *current_delay + hysteresis_limit_1_blocks) {
new_delay = *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 < *current_delay) {
} else if (new_delay_blocks < current_delay_blocks) {
size_t hysteresis_limit = std::max(
static_cast<int>(*current_delay) - hysteresis_limit_2_blocks, 0);
if (new_delay >= hysteresis_limit) {
new_delay = *current_delay;
static_cast<int>(current_delay_blocks) - hysteresis_limit_2_blocks,
0);
if (new_delay_blocks >= hysteresis_limit) {
new_delay_blocks = current_delay_blocks;
}
}
}
return new_delay;
return DelayEstimate(estimated_delay.quality, new_delay_blocks);
}
int RenderDelayControllerImpl::instance_count_ = 0;
@ -109,16 +115,7 @@ void RenderDelayControllerImpl::Reset() {
delay_estimator_.Reset();
}
void RenderDelayControllerImpl::SetDelay(size_t render_delay) {
if (delay_ != render_delay) {
// If a the delay set does not match the actual delay, reset the delay
// controller.
Reset();
delay_ = render_delay;
}
}
rtc::Optional<size_t> RenderDelayControllerImpl::GetDelay(
rtc::Optional<DelayEstimate> RenderDelayControllerImpl::GetDelay(
const DownsampledRenderBuffer& render_buffer,
rtc::ArrayView<const float> capture) {
RTC_DCHECK_EQ(kBlockSize, capture.size());
@ -136,19 +133,21 @@ rtc::Optional<size_t> RenderDelayControllerImpl::GetDelay(
if (delay_samples) {
// Compute and set new render delay buffer delay.
delay_ = ComputeNewBufferDelay(
delay_, delay_headroom_blocks_, hysteresis_limit_1_blocks_,
hysteresis_limit_2_blocks_, static_cast<int>(*delay_samples));
metrics_.Update(static_cast<int>(*delay_samples), delay_ ? *delay_ : 0);
delay_ = ComputeNewBufferDelay(delay_, delay_headroom_blocks_,
hysteresis_limit_1_blocks_,
hysteresis_limit_2_blocks_, *delay_samples);
metrics_.Update(static_cast<int>(delay_samples->delay),
delay_ ? delay_->delay : 0);
} else {
metrics_.Update(rtc::nullopt, delay_ ? *delay_ : 0);
metrics_.Update(rtc::nullopt, delay_ ? delay_->delay : 0);
}
data_dumper_->DumpRaw("aec3_render_delay_controller_delay",
delay_samples ? *delay_samples : 0);
delay_samples ? delay_samples->delay : 0);
data_dumper_->DumpRaw("aec3_render_delay_controller_buffer_delay",
delay_ ? *delay_ : 0);
delay_ ? delay_->delay : 0);
return delay_;
}

View File

@ -13,6 +13,7 @@
#include "api/array_view.h"
#include "api/optional.h"
#include "modules/audio_processing/aec3/delay_estimate.h"
#include "modules/audio_processing/aec3/downsampled_render_buffer.h"
#include "modules/audio_processing/aec3/render_delay_buffer.h"
#include "modules/audio_processing/include/audio_processing.h"
@ -31,11 +32,8 @@ class RenderDelayController {
// Resets the delay controller.
virtual void Reset() = 0;
// Receives the externally used delay.
virtual void SetDelay(size_t render_delay) = 0;
// Aligns the render buffer content with the capture signal.
virtual rtc::Optional<size_t> GetDelay(
virtual rtc::Optional<DelayEstimate> GetDelay(
const DownsampledRenderBuffer& render_buffer,
rtc::ArrayView<const float> capture) = 0;
};

View File

@ -61,9 +61,9 @@ TEST(RenderDelayController, NoRenderSignal) {
RenderDelayController::Create(
config, RenderDelayBuffer::DelayEstimatorOffset(config), rate));
for (size_t k = 0; k < 100; ++k) {
EXPECT_EQ(config.delay.min_echo_path_delay_blocks,
delay_controller->GetDelay(
delay_buffer->GetDownsampledRenderBuffer(), block));
auto delay = delay_controller->GetDelay(
delay_buffer->GetDownsampledRenderBuffer(), block);
EXPECT_EQ(config.delay.min_echo_path_delay_blocks, delay->delay);
}
}
}
@ -73,7 +73,7 @@ TEST(RenderDelayController, NoRenderSignal) {
// Verifies the basic API call sequence.
TEST(RenderDelayController, BasicApiCalls) {
std::vector<float> capture_block(kBlockSize, 0.f);
rtc::Optional<size_t> delay_blocks = 0;
rtc::Optional<DelayEstimate> delay_blocks;
for (size_t num_matched_filters = 4; num_matched_filters == 10;
num_matched_filters++) {
for (auto down_sampling_factor : kDownSamplingFactors) {
@ -97,7 +97,7 @@ TEST(RenderDelayController, BasicApiCalls) {
render_delay_buffer->GetDownsampledRenderBuffer(), capture_block);
}
EXPECT_TRUE(delay_blocks);
EXPECT_EQ(config.delay.min_echo_path_delay_blocks, delay_blocks);
EXPECT_EQ(config.delay.min_echo_path_delay_blocks, delay_blocks->delay);
}
}
}
@ -120,7 +120,7 @@ TEST(RenderDelayController, Alignment) {
NumBandsForRate(rate), std::vector<float>(kBlockSize, 0.f));
for (size_t delay_samples : {15, 50, 150, 200, 800, 4000}) {
rtc::Optional<size_t> delay_blocks;
rtc::Optional<DelayEstimate> delay_blocks;
SCOPED_TRACE(ProduceDebugText(rate, delay_samples));
std::unique_ptr<RenderDelayBuffer> render_delay_buffer(
RenderDelayBuffer::Create(config, NumBandsForRate(rate)));
@ -145,7 +145,7 @@ TEST(RenderDelayController, Alignment) {
std::max(0, static_cast<int>(delay_samples / kBlockSize) -
kDelayHeadroomBlocks);
EXPECT_EQ(expected_delay_blocks, delay_blocks);
EXPECT_EQ(expected_delay_blocks, delay_blocks->delay);
}
}
}
@ -169,7 +169,7 @@ TEST(RenderDelayController, NonCausalAlignment) {
NumBandsForRate(rate), std::vector<float>(kBlockSize, 0.f));
for (int delay_samples : {-15, -50, -150, -200}) {
rtc::Optional<size_t> delay_blocks;
rtc::Optional<DelayEstimate> delay_blocks;
SCOPED_TRACE(ProduceDebugText(rate, -delay_samples));
std::unique_ptr<RenderDelayBuffer> render_delay_buffer(
RenderDelayBuffer::Create(config, NumBandsForRate(rate)));
@ -211,7 +211,7 @@ TEST(RenderDelayController, AlignmentWithJitter) {
std::vector<std::vector<float>> render_block(
NumBandsForRate(rate), std::vector<float>(kBlockSize, 0.f));
for (size_t delay_samples : {15, 50, 300, 800}) {
rtc::Optional<size_t> delay_blocks;
rtc::Optional<DelayEstimate> delay_blocks;
SCOPED_TRACE(ProduceDebugText(rate, delay_samples));
std::unique_ptr<RenderDelayBuffer> render_delay_buffer(
RenderDelayBuffer::Create(config, NumBandsForRate(rate)));
@ -250,7 +250,7 @@ TEST(RenderDelayController, AlignmentWithJitter) {
}
ASSERT_TRUE(delay_blocks);
EXPECT_EQ(expected_delay_blocks, *delay_blocks);
EXPECT_EQ(expected_delay_blocks, delay_blocks->delay);
}
}
}