mirror of
https://github.com/mollyim/webrtc.git
synced 2025-05-13 22:00:47 +01:00
AEC3: Parametrize the delay estimator to leverage strong echo paths
This CL introduces a new behavior for leveraging early information about the delay that is acquired before the standard delay estimate has been established. To simplify the process of setting the parameters for that, the CL also surfaces the delay estimator parameters to the config struct. Bug: webrtc:9720,chromium: 880686 Change-Id: If886813f70cd805bd37752c63913d28398f1c6fe Reviewed-on: https://webrtc-review.googlesource.com/97860 Commit-Queue: Per Åhgren <peah@webrtc.org> Reviewed-by: Jesus de Vicente Pena <devicentepena@webrtc.org> Reviewed-by: Gustaf Ullberg <gustaf@webrtc.org> Cr-Commit-Position: refs/heads/master@{#24614}
This commit is contained in:
parent
88e3e3f570
commit
6a4fd19bbd
9 changed files with 134 additions and 47 deletions
|
@ -32,6 +32,12 @@ struct EchoCanceller3Config {
|
|||
size_t hysteresis_limit_2_blocks = 1;
|
||||
size_t skew_hysteresis_blocks = 3;
|
||||
size_t fixed_capture_delay_samples = 0;
|
||||
float delay_estimate_smoothing = 0.7f;
|
||||
float delay_candidate_detection_threshold = 0.2f;
|
||||
struct DelaySelectionThresholds {
|
||||
int initial;
|
||||
int converged;
|
||||
} delay_selection_thresholds = {25, 25};
|
||||
} delay;
|
||||
|
||||
struct Filter {
|
||||
|
|
|
@ -47,9 +47,12 @@ EchoPathDelayEstimator::EchoPathDelayEstimator(
|
|||
kMatchedFilterAlignmentShiftSizeSubBlocks,
|
||||
GetDownSamplingFactor(config) == 8
|
||||
? config.render_levels.poor_excitation_render_limit_ds8
|
||||
: config.render_levels.poor_excitation_render_limit),
|
||||
: config.render_levels.poor_excitation_render_limit,
|
||||
config.delay.delay_estimate_smoothing,
|
||||
config.delay.delay_candidate_detection_threshold),
|
||||
matched_filter_lag_aggregator_(data_dumper_,
|
||||
matched_filter_.GetMaxFilterLag()) {
|
||||
matched_filter_.GetMaxFilterLag(),
|
||||
config.delay.delay_selection_thresholds) {
|
||||
RTC_DCHECK(data_dumper);
|
||||
RTC_DCHECK(down_sampling_factor_ > 0);
|
||||
}
|
||||
|
|
|
@ -32,6 +32,7 @@ namespace aec3 {
|
|||
|
||||
void MatchedFilterCore_NEON(size_t x_start_index,
|
||||
float x2_sum_threshold,
|
||||
float smoothing,
|
||||
rtc::ArrayView<const float> x,
|
||||
rtc::ArrayView<const float> y,
|
||||
rtc::ArrayView<float> h,
|
||||
|
@ -102,10 +103,10 @@ void MatchedFilterCore_NEON(size_t x_start_index,
|
|||
// Update the matched filter estimate in an NLMS manner.
|
||||
if (x2_sum > x2_sum_threshold && !saturation) {
|
||||
RTC_DCHECK_LT(0.f, x2_sum);
|
||||
const float alpha = 0.7f * e / x2_sum;
|
||||
const float alpha = smoothing * e / x2_sum;
|
||||
const float32x4_t alpha_128 = vmovq_n_f32(alpha);
|
||||
|
||||
// filter = filter + 0.7 * (y - filter * x) / x * x.
|
||||
// filter = filter + smoothing * (y - filter * x) * x / x * x.
|
||||
float* h_p = &h[0];
|
||||
x_p = &x[x_start_index];
|
||||
|
||||
|
@ -145,6 +146,7 @@ void MatchedFilterCore_NEON(size_t x_start_index,
|
|||
|
||||
void MatchedFilterCore_SSE2(size_t x_start_index,
|
||||
float x2_sum_threshold,
|
||||
float smoothing,
|
||||
rtc::ArrayView<const float> x,
|
||||
rtc::ArrayView<const float> y,
|
||||
rtc::ArrayView<float> h,
|
||||
|
@ -217,10 +219,10 @@ void MatchedFilterCore_SSE2(size_t x_start_index,
|
|||
// Update the matched filter estimate in an NLMS manner.
|
||||
if (x2_sum > x2_sum_threshold && !saturation) {
|
||||
RTC_DCHECK_LT(0.f, x2_sum);
|
||||
const float alpha = 0.7f * e / x2_sum;
|
||||
const float alpha = smoothing * e / x2_sum;
|
||||
const __m128 alpha_128 = _mm_set1_ps(alpha);
|
||||
|
||||
// filter = filter + 0.7 * (y - filter * x) / x * x.
|
||||
// filter = filter + smoothing * (y - filter * x) * x / x * x.
|
||||
float* h_p = &h[0];
|
||||
x_p = &x[x_start_index];
|
||||
|
||||
|
@ -259,6 +261,7 @@ void MatchedFilterCore_SSE2(size_t x_start_index,
|
|||
|
||||
void MatchedFilterCore(size_t x_start_index,
|
||||
float x2_sum_threshold,
|
||||
float smoothing,
|
||||
rtc::ArrayView<const float> x,
|
||||
rtc::ArrayView<const float> y,
|
||||
rtc::ArrayView<float> h,
|
||||
|
@ -288,9 +291,9 @@ void MatchedFilterCore(size_t x_start_index,
|
|||
// Update the matched filter estimate in an NLMS manner.
|
||||
if (x2_sum > x2_sum_threshold && !saturation) {
|
||||
RTC_DCHECK_LT(0.f, x2_sum);
|
||||
const float alpha = 0.7f * e / x2_sum;
|
||||
const float alpha = smoothing * e / x2_sum;
|
||||
|
||||
// filter = filter + 0.7 * (y - filter * x) / x * x.
|
||||
// filter = filter + smoothing * (y - filter * x) * x / x * x.
|
||||
size_t x_index = x_start_index;
|
||||
for (size_t k = 0; k < h.size(); ++k) {
|
||||
h[k] += alpha * x[x_index];
|
||||
|
@ -311,7 +314,9 @@ MatchedFilter::MatchedFilter(ApmDataDumper* data_dumper,
|
|||
size_t window_size_sub_blocks,
|
||||
int num_matched_filters,
|
||||
size_t alignment_shift_sub_blocks,
|
||||
float excitation_limit)
|
||||
float excitation_limit,
|
||||
float smoothing,
|
||||
float matching_filter_threshold)
|
||||
: data_dumper_(data_dumper),
|
||||
optimization_(optimization),
|
||||
sub_block_size_(sub_block_size),
|
||||
|
@ -321,7 +326,9 @@ MatchedFilter::MatchedFilter(ApmDataDumper* data_dumper,
|
|||
std::vector<float>(window_size_sub_blocks * sub_block_size_, 0.f)),
|
||||
lag_estimates_(num_matched_filters),
|
||||
filters_offsets_(num_matched_filters, 0),
|
||||
excitation_limit_(excitation_limit) {
|
||||
excitation_limit_(excitation_limit),
|
||||
smoothing_(smoothing),
|
||||
matching_filter_threshold_(matching_filter_threshold) {
|
||||
RTC_DCHECK(data_dumper);
|
||||
RTC_DCHECK_LT(0, window_size_sub_blocks);
|
||||
RTC_DCHECK((kBlockSize % sub_block_size) == 0);
|
||||
|
@ -362,19 +369,19 @@ void MatchedFilter::Update(const DownsampledRenderBuffer& render_buffer,
|
|||
#if defined(WEBRTC_ARCH_X86_FAMILY)
|
||||
case Aec3Optimization::kSse2:
|
||||
aec3::MatchedFilterCore_SSE2(x_start_index, x2_sum_threshold,
|
||||
render_buffer.buffer, y, filters_[n],
|
||||
&filters_updated, &error_sum);
|
||||
smoothing_, render_buffer.buffer, y,
|
||||
filters_[n], &filters_updated, &error_sum);
|
||||
break;
|
||||
#endif
|
||||
#if defined(WEBRTC_HAS_NEON)
|
||||
case Aec3Optimization::kNeon:
|
||||
aec3::MatchedFilterCore_NEON(x_start_index, x2_sum_threshold,
|
||||
render_buffer.buffer, y, filters_[n],
|
||||
&filters_updated, &error_sum);
|
||||
smoothing_, render_buffer.buffer, y,
|
||||
filters_[n], &filters_updated, &error_sum);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
aec3::MatchedFilterCore(x_start_index, x2_sum_threshold,
|
||||
aec3::MatchedFilterCore(x_start_index, x2_sum_threshold, smoothing_,
|
||||
render_buffer.buffer, y, filters_[n],
|
||||
&filters_updated, &error_sum);
|
||||
}
|
||||
|
@ -393,11 +400,10 @@ void MatchedFilter::Update(const DownsampledRenderBuffer& render_buffer,
|
|||
[](float a, float b) -> bool { return a * a < b * b; }));
|
||||
|
||||
// Update the lag estimates for the matched filter.
|
||||
const float kMatchingFilterThreshold = 0.2f;
|
||||
lag_estimates_[n] = LagEstimate(
|
||||
error_sum_anchor - error_sum,
|
||||
(lag_estimate > 2 && lag_estimate < (filters_[n].size() - 10) &&
|
||||
error_sum < kMatchingFilterThreshold * error_sum_anchor),
|
||||
error_sum < matching_filter_threshold_ * error_sum_anchor),
|
||||
lag_estimate + alignment_shift, filters_updated);
|
||||
|
||||
RTC_DCHECK_GE(10, filters_.size());
|
||||
|
|
|
@ -30,6 +30,7 @@ namespace aec3 {
|
|||
// Filter core for the matched filter that is optimized for NEON.
|
||||
void MatchedFilterCore_NEON(size_t x_start_index,
|
||||
float x2_sum_threshold,
|
||||
float smoothing,
|
||||
rtc::ArrayView<const float> x,
|
||||
rtc::ArrayView<const float> y,
|
||||
rtc::ArrayView<float> h,
|
||||
|
@ -43,6 +44,7 @@ void MatchedFilterCore_NEON(size_t x_start_index,
|
|||
// Filter core for the matched filter that is optimized for SSE2.
|
||||
void MatchedFilterCore_SSE2(size_t x_start_index,
|
||||
float x2_sum_threshold,
|
||||
float smoothing,
|
||||
rtc::ArrayView<const float> x,
|
||||
rtc::ArrayView<const float> y,
|
||||
rtc::ArrayView<float> h,
|
||||
|
@ -54,6 +56,7 @@ void MatchedFilterCore_SSE2(size_t x_start_index,
|
|||
// Filter core for the matched filter.
|
||||
void MatchedFilterCore(size_t x_start_index,
|
||||
float x2_sum_threshold,
|
||||
float smoothing,
|
||||
rtc::ArrayView<const float> x,
|
||||
rtc::ArrayView<const float> y,
|
||||
rtc::ArrayView<float> h,
|
||||
|
@ -87,7 +90,9 @@ class MatchedFilter {
|
|||
size_t window_size_sub_blocks,
|
||||
int num_matched_filters,
|
||||
size_t alignment_shift_sub_blocks,
|
||||
float excitation_limit);
|
||||
float excitation_limit,
|
||||
float smoothing,
|
||||
float matching_filter_threshold);
|
||||
|
||||
~MatchedFilter();
|
||||
|
||||
|
@ -122,6 +127,8 @@ class MatchedFilter {
|
|||
std::vector<LagEstimate> lag_estimates_;
|
||||
std::vector<size_t> filters_offsets_;
|
||||
const float excitation_limit_;
|
||||
const float smoothing_;
|
||||
const float matching_filter_threshold_;
|
||||
|
||||
RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(MatchedFilter);
|
||||
};
|
||||
|
|
|
@ -15,9 +15,13 @@ namespace webrtc {
|
|||
|
||||
MatchedFilterLagAggregator::MatchedFilterLagAggregator(
|
||||
ApmDataDumper* data_dumper,
|
||||
size_t max_filter_lag)
|
||||
: data_dumper_(data_dumper), histogram_(max_filter_lag + 1, 0) {
|
||||
size_t max_filter_lag,
|
||||
const EchoCanceller3Config::Delay::DelaySelectionThresholds& thresholds)
|
||||
: data_dumper_(data_dumper),
|
||||
histogram_(max_filter_lag + 1, 0),
|
||||
thresholds_(thresholds) {
|
||||
RTC_DCHECK(data_dumper);
|
||||
RTC_DCHECK_LE(thresholds_.initial, thresholds_.converged);
|
||||
histogram_data_.fill(0);
|
||||
}
|
||||
|
||||
|
@ -67,8 +71,12 @@ absl::optional<DelayEstimate> MatchedFilterLagAggregator::Aggregate(
|
|||
std::distance(histogram_.begin(),
|
||||
std::max_element(histogram_.begin(), histogram_.end()));
|
||||
|
||||
if (histogram_[candidate] > 25) {
|
||||
significant_candidate_found_ = true;
|
||||
significant_candidate_found_ =
|
||||
significant_candidate_found_ ||
|
||||
histogram_[candidate] > thresholds_.converged;
|
||||
if (histogram_[candidate] > thresholds_.converged ||
|
||||
(histogram_[candidate] > thresholds_.initial &&
|
||||
!significant_candidate_found_)) {
|
||||
return DelayEstimate(DelayEstimate::Quality::kRefined, candidate);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include <vector>
|
||||
|
||||
#include "absl/types/optional.h"
|
||||
#include "api/audio/echo_canceller3_config.h"
|
||||
#include "modules/audio_processing/aec3/delay_estimate.h"
|
||||
#include "modules/audio_processing/aec3/matched_filter.h"
|
||||
#include "rtc_base/constructormagic.h"
|
||||
|
@ -26,7 +27,10 @@ class ApmDataDumper;
|
|||
// reliable combined lag estimate.
|
||||
class MatchedFilterLagAggregator {
|
||||
public:
|
||||
MatchedFilterLagAggregator(ApmDataDumper* data_dumper, size_t max_filter_lag);
|
||||
MatchedFilterLagAggregator(
|
||||
ApmDataDumper* data_dumper,
|
||||
size_t max_filter_lag,
|
||||
const EchoCanceller3Config::Delay::DelaySelectionThresholds& thresholds);
|
||||
~MatchedFilterLagAggregator();
|
||||
|
||||
// Resets the aggregator.
|
||||
|
@ -42,6 +46,7 @@ class MatchedFilterLagAggregator {
|
|||
std::array<int, 250> histogram_data_;
|
||||
int histogram_data_index_ = 0;
|
||||
bool significant_candidate_found_ = false;
|
||||
const EchoCanceller3Config::Delay::DelaySelectionThresholds thresholds_;
|
||||
|
||||
RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(MatchedFilterLagAggregator);
|
||||
};
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include <vector>
|
||||
|
||||
#include "api/array_view.h"
|
||||
#include "api/audio/echo_canceller3_config.h"
|
||||
#include "modules/audio_processing/aec3/aec3_common.h"
|
||||
#include "modules/audio_processing/logging/apm_data_dumper.h"
|
||||
#include "test/gtest.h"
|
||||
|
@ -31,8 +32,11 @@ TEST(MatchedFilterLagAggregator, MostAccurateLagChosen) {
|
|||
constexpr size_t kLag1 = 5;
|
||||
constexpr size_t kLag2 = 10;
|
||||
ApmDataDumper data_dumper(0);
|
||||
EchoCanceller3Config config;
|
||||
std::vector<MatchedFilter::LagEstimate> lag_estimates(2);
|
||||
MatchedFilterLagAggregator aggregator(&data_dumper, std::max(kLag1, kLag2));
|
||||
MatchedFilterLagAggregator aggregator(
|
||||
&data_dumper, std::max(kLag1, kLag2),
|
||||
config.delay.delay_selection_thresholds);
|
||||
lag_estimates[0] = MatchedFilter::LagEstimate(1.f, true, kLag1, true);
|
||||
lag_estimates[1] = MatchedFilter::LagEstimate(0.5f, true, kLag2, true);
|
||||
|
||||
|
@ -65,8 +69,10 @@ TEST(MatchedFilterLagAggregator, MostAccurateLagChosen) {
|
|||
TEST(MatchedFilterLagAggregator,
|
||||
LagEstimateInvarianceRequiredForAggregatedLag) {
|
||||
ApmDataDumper data_dumper(0);
|
||||
EchoCanceller3Config config;
|
||||
std::vector<MatchedFilter::LagEstimate> lag_estimates(1);
|
||||
MatchedFilterLagAggregator aggregator(&data_dumper, 100);
|
||||
MatchedFilterLagAggregator aggregator(
|
||||
&data_dumper, 100, config.delay.delay_selection_thresholds);
|
||||
|
||||
absl::optional<DelayEstimate> aggregated_lag;
|
||||
for (size_t k = 0; k < kNumLagsBeforeDetection; ++k) {
|
||||
|
@ -94,8 +100,10 @@ TEST(MatchedFilterLagAggregator,
|
|||
DISABLED_LagEstimateUpdatesRequiredForAggregatedLag) {
|
||||
constexpr size_t kLag = 5;
|
||||
ApmDataDumper data_dumper(0);
|
||||
EchoCanceller3Config config;
|
||||
std::vector<MatchedFilter::LagEstimate> lag_estimates(1);
|
||||
MatchedFilterLagAggregator aggregator(&data_dumper, kLag);
|
||||
MatchedFilterLagAggregator aggregator(
|
||||
&data_dumper, kLag, config.delay.delay_selection_thresholds);
|
||||
for (size_t k = 0; k < kNumLagsBeforeDetection * 10; ++k) {
|
||||
lag_estimates[0] = MatchedFilter::LagEstimate(1.f, true, kLag, false);
|
||||
absl::optional<DelayEstimate> aggregated_lag =
|
||||
|
@ -112,8 +120,11 @@ TEST(MatchedFilterLagAggregator, DISABLED_PersistentAggregatedLag) {
|
|||
constexpr size_t kLag1 = 5;
|
||||
constexpr size_t kLag2 = 10;
|
||||
ApmDataDumper data_dumper(0);
|
||||
EchoCanceller3Config config;
|
||||
std::vector<MatchedFilter::LagEstimate> lag_estimates(1);
|
||||
MatchedFilterLagAggregator aggregator(&data_dumper, std::max(kLag1, kLag2));
|
||||
MatchedFilterLagAggregator aggregator(
|
||||
&data_dumper, std::max(kLag1, kLag2),
|
||||
config.delay.delay_selection_thresholds);
|
||||
absl::optional<DelayEstimate> aggregated_lag;
|
||||
for (size_t k = 0; k < kNumLagsBeforeDetection; ++k) {
|
||||
lag_estimates[0] = MatchedFilter::LagEstimate(1.f, true, kLag1, true);
|
||||
|
@ -134,7 +145,10 @@ TEST(MatchedFilterLagAggregator, DISABLED_PersistentAggregatedLag) {
|
|||
|
||||
// Verifies the check for non-null data dumper.
|
||||
TEST(MatchedFilterLagAggregator, NullDataDumper) {
|
||||
EXPECT_DEATH(MatchedFilterLagAggregator(nullptr, 10), "");
|
||||
EchoCanceller3Config config;
|
||||
EXPECT_DEATH(MatchedFilterLagAggregator(
|
||||
nullptr, 10, config.delay.delay_selection_thresholds),
|
||||
"");
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -52,6 +52,7 @@ constexpr size_t kAlignmentShiftSubBlocks = kWindowSizeSubBlocks * 3 / 4;
|
|||
// counterparts.
|
||||
TEST(MatchedFilter, TestNeonOptimizations) {
|
||||
Random random_generator(42U);
|
||||
constexpr float kSmoothing = 0.7f;
|
||||
for (auto down_sampling_factor : kDownSamplingFactors) {
|
||||
const size_t sub_block_size = kBlockSize / down_sampling_factor;
|
||||
|
||||
|
@ -69,10 +70,10 @@ TEST(MatchedFilter, TestNeonOptimizations) {
|
|||
bool filters_updated_NEON = false;
|
||||
float error_sum_NEON = 0.f;
|
||||
|
||||
MatchedFilterCore_NEON(x_index, h.size() * 150.f * 150.f, x, y, h_NEON,
|
||||
&filters_updated_NEON, &error_sum_NEON);
|
||||
MatchedFilterCore_NEON(x_index, h.size() * 150.f * 150.f, kSmoothing, x,
|
||||
y, h_NEON, &filters_updated_NEON, &error_sum_NEON);
|
||||
|
||||
MatchedFilterCore(x_index, h.size() * 150.f * 150.f, x, y, h,
|
||||
MatchedFilterCore(x_index, h.size() * 150.f * 150.f, kSmoothing, x, y, h,
|
||||
&filters_updated, &error_sum);
|
||||
|
||||
EXPECT_EQ(filters_updated, filters_updated_NEON);
|
||||
|
@ -95,6 +96,7 @@ TEST(MatchedFilter, TestSse2Optimizations) {
|
|||
bool use_sse2 = (WebRtc_GetCPUInfo(kSSE2) != 0);
|
||||
if (use_sse2) {
|
||||
Random random_generator(42U);
|
||||
constexpr float kSmoothing = 0.7f;
|
||||
for (auto down_sampling_factor : kDownSamplingFactors) {
|
||||
const size_t sub_block_size = kBlockSize / down_sampling_factor;
|
||||
std::vector<float> x(2000);
|
||||
|
@ -111,11 +113,12 @@ TEST(MatchedFilter, TestSse2Optimizations) {
|
|||
bool filters_updated_SSE2 = false;
|
||||
float error_sum_SSE2 = 0.f;
|
||||
|
||||
MatchedFilterCore_SSE2(x_index, h.size() * 150.f * 150.f, x, y, h_SSE2,
|
||||
&filters_updated_SSE2, &error_sum_SSE2);
|
||||
MatchedFilterCore_SSE2(x_index, h.size() * 150.f * 150.f, kSmoothing, x,
|
||||
y, h_SSE2, &filters_updated_SSE2,
|
||||
&error_sum_SSE2);
|
||||
|
||||
MatchedFilterCore(x_index, h.size() * 150.f * 150.f, x, y, h,
|
||||
&filters_updated, &error_sum);
|
||||
MatchedFilterCore(x_index, h.size() * 150.f * 150.f, kSmoothing, x, y,
|
||||
h, &filters_updated, &error_sum);
|
||||
|
||||
EXPECT_EQ(filters_updated, filters_updated_SSE2);
|
||||
EXPECT_NEAR(error_sum, error_sum_SSE2, error_sum / 100000.f);
|
||||
|
@ -157,7 +160,9 @@ TEST(MatchedFilter, LagEstimation) {
|
|||
delay_samples);
|
||||
MatchedFilter filter(&data_dumper, DetectOptimization(), sub_block_size,
|
||||
kWindowSizeSubBlocks, kNumMatchedFilters,
|
||||
kAlignmentShiftSubBlocks, 150);
|
||||
kAlignmentShiftSubBlocks, 150,
|
||||
config.delay.delay_estimate_smoothing,
|
||||
config.delay.delay_candidate_detection_threshold);
|
||||
|
||||
std::unique_ptr<RenderDelayBuffer> render_delay_buffer(
|
||||
RenderDelayBuffer::Create(config, 3));
|
||||
|
@ -259,7 +264,9 @@ TEST(MatchedFilter, LagNotReliableForUncorrelatedRenderAndCapture) {
|
|||
RenderDelayBuffer::Create(config, 3));
|
||||
MatchedFilter filter(&data_dumper, DetectOptimization(), sub_block_size,
|
||||
kWindowSizeSubBlocks, kNumMatchedFilters,
|
||||
kAlignmentShiftSubBlocks, 150);
|
||||
kAlignmentShiftSubBlocks, 150,
|
||||
config.delay.delay_estimate_smoothing,
|
||||
config.delay.delay_candidate_detection_threshold);
|
||||
|
||||
// Analyze the correlation between render and capture.
|
||||
for (size_t k = 0; k < 100; ++k) {
|
||||
|
@ -292,11 +299,14 @@ TEST(MatchedFilter, LagNotUpdatedForLowLevelRender) {
|
|||
std::array<float, kBlockSize> capture;
|
||||
capture.fill(0.f);
|
||||
ApmDataDumper data_dumper(0);
|
||||
EchoCanceller3Config config;
|
||||
MatchedFilter filter(&data_dumper, DetectOptimization(), sub_block_size,
|
||||
kWindowSizeSubBlocks, kNumMatchedFilters,
|
||||
kAlignmentShiftSubBlocks, 150);
|
||||
kAlignmentShiftSubBlocks, 150,
|
||||
config.delay.delay_estimate_smoothing,
|
||||
config.delay.delay_candidate_detection_threshold);
|
||||
std::unique_ptr<RenderDelayBuffer> render_delay_buffer(
|
||||
RenderDelayBuffer::Create(EchoCanceller3Config(), 3));
|
||||
RenderDelayBuffer::Create(config, 3));
|
||||
Decimator capture_decimator(down_sampling_factor);
|
||||
|
||||
// Analyze the correlation between render and capture.
|
||||
|
@ -331,12 +341,15 @@ TEST(MatchedFilter, LagNotUpdatedForLowLevelRender) {
|
|||
// number of alignment shifts.
|
||||
TEST(MatchedFilter, NumberOfLagEstimates) {
|
||||
ApmDataDumper data_dumper(0);
|
||||
EchoCanceller3Config config;
|
||||
for (auto down_sampling_factor : kDownSamplingFactors) {
|
||||
const size_t sub_block_size = kBlockSize / down_sampling_factor;
|
||||
for (size_t num_matched_filters = 0; num_matched_filters < 10;
|
||||
++num_matched_filters) {
|
||||
MatchedFilter filter(&data_dumper, DetectOptimization(), sub_block_size,
|
||||
32, num_matched_filters, 1, 150);
|
||||
32, num_matched_filters, 1, 150,
|
||||
config.delay.delay_estimate_smoothing,
|
||||
config.delay.delay_candidate_detection_threshold);
|
||||
EXPECT_EQ(num_matched_filters, filter.GetLagEstimates().size());
|
||||
}
|
||||
}
|
||||
|
@ -347,13 +360,19 @@ TEST(MatchedFilter, NumberOfLagEstimates) {
|
|||
// Verifies the check for non-zero windows size.
|
||||
TEST(MatchedFilter, ZeroWindowSize) {
|
||||
ApmDataDumper data_dumper(0);
|
||||
EXPECT_DEATH(
|
||||
MatchedFilter(&data_dumper, DetectOptimization(), 16, 0, 1, 1, 150), "");
|
||||
EchoCanceller3Config config;
|
||||
EXPECT_DEATH(MatchedFilter(&data_dumper, DetectOptimization(), 16, 0, 1, 1,
|
||||
150, config.delay.delay_estimate_smoothing,
|
||||
config.delay.delay_candidate_detection_threshold),
|
||||
"");
|
||||
}
|
||||
|
||||
// Verifies the check for non-null data dumper.
|
||||
TEST(MatchedFilter, NullDataDumper) {
|
||||
EXPECT_DEATH(MatchedFilter(nullptr, DetectOptimization(), 16, 1, 1, 1, 150),
|
||||
EchoCanceller3Config config;
|
||||
EXPECT_DEATH(MatchedFilter(nullptr, DetectOptimization(), 16, 1, 1, 1, 150,
|
||||
config.delay.delay_estimate_smoothing,
|
||||
config.delay.delay_candidate_detection_threshold),
|
||||
"");
|
||||
}
|
||||
|
||||
|
@ -361,8 +380,11 @@ TEST(MatchedFilter, NullDataDumper) {
|
|||
// TODO(peah): Activate the unittest once the required code has been landed.
|
||||
TEST(MatchedFilter, DISABLED_BlockSizeMultipleOf4) {
|
||||
ApmDataDumper data_dumper(0);
|
||||
EXPECT_DEATH(
|
||||
MatchedFilter(&data_dumper, DetectOptimization(), 15, 1, 1, 1, 150), "");
|
||||
EchoCanceller3Config config;
|
||||
EXPECT_DEATH(MatchedFilter(&data_dumper, DetectOptimization(), 15, 1, 1, 1,
|
||||
150, config.delay.delay_estimate_smoothing,
|
||||
config.delay.delay_candidate_detection_threshold),
|
||||
"");
|
||||
}
|
||||
|
||||
// Verifies the check for that there is an integer number of sub blocks that add
|
||||
|
@ -370,8 +392,11 @@ TEST(MatchedFilter, DISABLED_BlockSizeMultipleOf4) {
|
|||
// TODO(peah): Activate the unittest once the required code has been landed.
|
||||
TEST(MatchedFilter, DISABLED_SubBlockSizeAddsUpToBlockSize) {
|
||||
ApmDataDumper data_dumper(0);
|
||||
EXPECT_DEATH(
|
||||
MatchedFilter(&data_dumper, DetectOptimization(), 12, 1, 1, 1, 150), "");
|
||||
EchoCanceller3Config config;
|
||||
EXPECT_DEATH(MatchedFilter(&data_dumper, DetectOptimization(), 12, 1, 1, 1,
|
||||
150, config.delay.delay_estimate_smoothing,
|
||||
config.delay.delay_candidate_detection_threshold),
|
||||
"");
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -222,6 +222,19 @@ class Aec3ParametersParser {
|
|||
&cfg.delay.skew_hysteresis_blocks);
|
||||
ReadParam(section, "fixed_capture_delay_samples",
|
||||
&cfg.delay.fixed_capture_delay_samples);
|
||||
ReadParam(section, "delay_estimate_smoothing",
|
||||
&cfg.delay.delay_estimate_smoothing);
|
||||
ReadParam(section, "delay_candidate_detection_threshold",
|
||||
&cfg.delay.delay_candidate_detection_threshold);
|
||||
|
||||
Json::Value subsection;
|
||||
if (rtc::GetValueFromJsonObject(section, "delay_selection_thresholds",
|
||||
&subsection)) {
|
||||
ReadParam(subsection, "initial",
|
||||
&cfg.delay.delay_selection_thresholds.initial);
|
||||
ReadParam(subsection, "converged",
|
||||
&cfg.delay.delay_selection_thresholds.converged);
|
||||
}
|
||||
}
|
||||
|
||||
if (rtc::GetValueFromJsonObject(root, "filter", §ion)) {
|
||||
|
|
Loading…
Reference in a new issue