Corrected the delay agnostic AEC behavior during periods of silent farend signal.

Added conditional updating of the statistics and the delay estimate so that
updates are only done when the farend is non-stationary.

The reason for this is that all the values that go into the updating of the
statistics, and that in turn are also used to update the delay, are frozen
when the farend signal is non-stationary. Therefore, when the farend signal
is silent (stationary), the last estimates present before the silent (stationary)
period began are used to continue to update the statistics. This is a problem as
the updating is done in a manner that assumes that the estimates continue
to be updated.

This CL conditions the updating based on stationarity instead of silence
as both are treated in the same manner in the delay agnostic AEC.
This makes sense theoretically as the delay agnostic AEC operates on
analyzing power deviations (in bands) from a slowly updated average power and
therefore for a stationary signal will have no such deviations to base its analysis
on.

BUG=webrtc:5875, chromium:576624

NOTRY=True

Review-Url: https://codereview.webrtc.org/1967033002
Cr-Commit-Position: refs/heads/master@{#12700}
This commit is contained in:
peah 2016-05-12 05:08:45 -07:00 committed by Commit bot
parent 50b5c3be84
commit b1fc54d33e
3 changed files with 18 additions and 3 deletions

View file

@ -13,6 +13,7 @@
#include <assert.h> #include <assert.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <algorithm>
// Number of right shifts for scaling is linearly depending on number of bits in // Number of right shifts for scaling is linearly depending on number of bits in
// the far-end binary spectrum. // the far-end binary spectrum.
@ -618,15 +619,29 @@ int WebRtc_ProcessBinarySpectrum(BinaryDelayEstimator* self,
((value_best_candidate < self->minimum_probability) || ((value_best_candidate < self->minimum_probability) ||
(value_best_candidate < self->last_delay_probability))); (value_best_candidate < self->last_delay_probability)));
// Check for nonstationary farend signal.
const bool non_stationary_farend =
std::any_of(self->farend->far_bit_counts,
self->farend->far_bit_counts + self->history_size,
[](int a) { return a > 0; });
if (non_stationary_farend) {
// Only update the validation statistics when the farend is nonstationary
// as the underlying estimates are otherwise frozen.
UpdateRobustValidationStatistics(self, candidate_delay, valley_depth, UpdateRobustValidationStatistics(self, candidate_delay, valley_depth,
value_best_candidate); value_best_candidate);
}
if (self->robust_validation_enabled) { if (self->robust_validation_enabled) {
int is_histogram_valid = HistogramBasedValidation(self, candidate_delay); int is_histogram_valid = HistogramBasedValidation(self, candidate_delay);
valid_candidate = RobustValidation(self, candidate_delay, valid_candidate, valid_candidate = RobustValidation(self, candidate_delay, valid_candidate,
is_histogram_valid); is_histogram_valid);
} }
if (valid_candidate) {
// Only update the delay estimate when the farend is nonstationary and when
// a valid delay candidate is available.
if (non_stationary_farend && valid_candidate) {
if (candidate_delay != self->last_delay) { if (candidate_delay != self->last_delay) {
self->last_delay_histogram = self->last_delay_histogram =
(self->histogram[candidate_delay] > kLastHistogramMax ? (self->histogram[candidate_delay] > kLastHistogramMax ?