Corrected the behavior in AEC3 during buffer overruns and underruns
This CL corrects the behavior in AEC3 during buffer overruns and underruns in three ways. 1) When there is no render signal available (due to a buffering issues, a zero block is inserted instead of the previous render block. This avoids the same block being repeatedly inserted when there are many back-to-back calls. 2) The internal counters in the main adaptive filter gain are also reset when the filter is reset. 3) The internal counters in the shadow adaptive filter gain are reset when the filter is reset. BUG=chromium:717920,webrtc:7559 Review-Url: https://codereview.webrtc.org/2862533002 Cr-Commit-Position: refs/heads/master@{#17991}
This commit is contained in:
parent
5af6e25b10
commit
debaa442ed
@ -22,6 +22,7 @@ namespace webrtc {
|
||||
namespace {
|
||||
|
||||
constexpr float kHErrorInitial = 10000.f;
|
||||
constexpr int kPoorExcitationCounterInitial = 1000;
|
||||
|
||||
} // namespace
|
||||
|
||||
@ -30,7 +31,7 @@ int MainFilterUpdateGain::instance_count_ = 0;
|
||||
MainFilterUpdateGain::MainFilterUpdateGain()
|
||||
: data_dumper_(
|
||||
new ApmDataDumper(rtc::AtomicOps::Increment(&instance_count_))),
|
||||
poor_excitation_counter_(1000) {
|
||||
poor_excitation_counter_(kPoorExcitationCounterInitial) {
|
||||
H_error_.fill(kHErrorInitial);
|
||||
}
|
||||
|
||||
@ -38,6 +39,8 @@ MainFilterUpdateGain::~MainFilterUpdateGain() {}
|
||||
|
||||
void MainFilterUpdateGain::HandleEchoPathChange() {
|
||||
H_error_.fill(kHErrorInitial);
|
||||
poor_excitation_counter_ = kPoorExcitationCounterInitial;
|
||||
call_counter_ = 0;
|
||||
}
|
||||
|
||||
void MainFilterUpdateGain::Compute(
|
||||
|
||||
@ -97,6 +97,7 @@ class RenderDelayBufferImpl final : public RenderDelayBuffer {
|
||||
DownsampledRenderBuffer downsampled_render_buffer_;
|
||||
DecimatorBy4 render_decimator_;
|
||||
ApiCallJitterBuffer api_call_jitter_buffer_;
|
||||
const std::vector<std::vector<float>> zero_block_;
|
||||
RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(RenderDelayBufferImpl);
|
||||
};
|
||||
|
||||
@ -107,7 +108,8 @@ RenderDelayBufferImpl::RenderDelayBufferImpl(size_t num_bands)
|
||||
num_bands,
|
||||
std::max(kResidualEchoPowerRenderWindowSize, kAdaptiveFilterLength),
|
||||
std::vector<size_t>(1, kAdaptiveFilterLength)),
|
||||
api_call_jitter_buffer_(num_bands) {
|
||||
api_call_jitter_buffer_(num_bands),
|
||||
zero_block_(num_bands, std::vector<float>(kBlockSize, 0.f)) {
|
||||
buffer_.fill(std::vector<std::vector<float>>(
|
||||
num_bands, std::vector<float>(kBlockSize, 0.f)));
|
||||
|
||||
@ -147,12 +149,11 @@ bool RenderDelayBufferImpl::Insert(
|
||||
|
||||
bool RenderDelayBufferImpl::UpdateBuffers() {
|
||||
bool underrun = true;
|
||||
// Update the buffers with a new block if such is available, otherwise repeat
|
||||
// the previous block.
|
||||
// Update the buffers with a new block if such is available, otherwise insert
|
||||
// a block of silence.
|
||||
if (api_call_jitter_buffer_.Size() > 0) {
|
||||
last_insert_index_ = (last_insert_index_ + 1) % buffer_.size();
|
||||
api_call_jitter_buffer_.Remove(&buffer_[last_insert_index_]);
|
||||
|
||||
underrun = false;
|
||||
}
|
||||
|
||||
@ -162,14 +163,22 @@ bool RenderDelayBufferImpl::UpdateBuffers() {
|
||||
downsampled_render_buffer_.buffer.size();
|
||||
|
||||
std::array<float, kSubBlockSize> render_downsampled;
|
||||
render_decimator_.Decimate(buffer_[last_insert_index_][0],
|
||||
render_downsampled);
|
||||
if (underrun) {
|
||||
render_decimator_.Decimate(zero_block_[0], render_downsampled);
|
||||
} else {
|
||||
render_decimator_.Decimate(buffer_[last_insert_index_][0],
|
||||
render_downsampled);
|
||||
}
|
||||
std::copy(render_downsampled.rbegin(), render_downsampled.rend(),
|
||||
downsampled_render_buffer_.buffer.begin() +
|
||||
downsampled_render_buffer_.position);
|
||||
|
||||
fft_buffer_.Insert(
|
||||
buffer_[(last_insert_index_ - delay_ + buffer_.size()) % buffer_.size()]);
|
||||
if (underrun) {
|
||||
fft_buffer_.Insert(zero_block_);
|
||||
} else {
|
||||
fft_buffer_.Insert(buffer_[(last_insert_index_ - delay_ + buffer_.size()) %
|
||||
buffer_.size()]);
|
||||
}
|
||||
return !underrun;
|
||||
}
|
||||
|
||||
|
||||
@ -17,6 +17,13 @@
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
void ShadowFilterUpdateGain::HandleEchoPathChange() {
|
||||
// TODO(peah): Check whether this counter should instead be initialized to a
|
||||
// large value.
|
||||
poor_signal_excitation_counter_ = 0;
|
||||
call_counter_ = 0;
|
||||
}
|
||||
|
||||
void ShadowFilterUpdateGain::Compute(
|
||||
const RenderBuffer& render_buffer,
|
||||
const RenderSignalAnalyzer& render_signal_analyzer,
|
||||
|
||||
@ -21,6 +21,9 @@ namespace webrtc {
|
||||
// Provides functionality for computing the fixed gain for the shadow filter.
|
||||
class ShadowFilterUpdateGain {
|
||||
public:
|
||||
// Takes action in the case of a known echo path change.
|
||||
void HandleEchoPathChange();
|
||||
|
||||
// Computes the gain.
|
||||
void Compute(const RenderBuffer& render_buffer,
|
||||
const RenderSignalAnalyzer& render_signal_analyzer,
|
||||
@ -30,6 +33,8 @@ class ShadowFilterUpdateGain {
|
||||
FftData* G);
|
||||
|
||||
private:
|
||||
// TODO(peah): Check whether this counter should instead be initialized to a
|
||||
// large value.
|
||||
size_t poor_signal_excitation_counter_ = 0;
|
||||
size_t call_counter_ = 0;
|
||||
};
|
||||
|
||||
@ -55,6 +55,7 @@ void Subtractor::HandleEchoPathChange(
|
||||
main_filter_.HandleEchoPathChange();
|
||||
shadow_filter_.HandleEchoPathChange();
|
||||
G_main_.HandleEchoPathChange();
|
||||
G_shadow_.HandleEchoPathChange();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user