This CL adds code to the BlockProcessor, which basically constitutes the second layer in echo canceller 3. The CL includes two incomplete classes (EchoRemover and EchoPathDelayEstimator) which will be completed in upcoming CLs. Because of this, some of the unittests are disabled until those are added. BUG=webrtc:6018 Review-Url: https://codereview.webrtc.org/2611223003 Cr-Commit-Position: refs/heads/master@{#16319}
149 lines
5.5 KiB
C++
149 lines
5.5 KiB
C++
/*
|
|
* Copyright (c) 2016 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.
|
|
*/
|
|
#include "webrtc/modules/audio_processing/aec3/block_processor.h"
|
|
|
|
#include "webrtc/base/atomicops.h"
|
|
#include "webrtc/base/constructormagic.h"
|
|
#include "webrtc/base/optional.h"
|
|
#include "webrtc/modules/audio_processing/aec3/aec3_constants.h"
|
|
#include "webrtc/modules/audio_processing/aec3/echo_path_variability.h"
|
|
#include "webrtc/modules/audio_processing/logging/apm_data_dumper.h"
|
|
#include "webrtc/system_wrappers/include/logging.h"
|
|
|
|
namespace webrtc {
|
|
namespace {
|
|
|
|
class BlockProcessorImpl final : public BlockProcessor {
|
|
public:
|
|
BlockProcessorImpl(int sample_rate_hz,
|
|
std::unique_ptr<RenderDelayBuffer> render_buffer,
|
|
std::unique_ptr<RenderDelayController> delay_controller,
|
|
std::unique_ptr<EchoRemover> echo_remover);
|
|
|
|
~BlockProcessorImpl() override;
|
|
|
|
void ProcessCapture(bool echo_path_gain_change,
|
|
bool capture_signal_saturation,
|
|
std::vector<std::vector<float>>* capture_block) override;
|
|
|
|
bool BufferRender(std::vector<std::vector<float>>* block) override;
|
|
|
|
void UpdateEchoLeakageStatus(bool leakage_detected) override;
|
|
|
|
private:
|
|
static int instance_count_;
|
|
std::unique_ptr<ApmDataDumper> data_dumper_;
|
|
const size_t sample_rate_hz_;
|
|
std::unique_ptr<RenderDelayBuffer> render_buffer_;
|
|
std::unique_ptr<RenderDelayController> delay_controller_;
|
|
std::unique_ptr<EchoRemover> echo_remover_;
|
|
RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(BlockProcessorImpl);
|
|
};
|
|
|
|
constexpr size_t kRenderBufferSize = 250;
|
|
int BlockProcessorImpl::instance_count_ = 0;
|
|
constexpr size_t kMaxApiJitter = 30;
|
|
|
|
BlockProcessorImpl::BlockProcessorImpl(
|
|
int sample_rate_hz,
|
|
std::unique_ptr<RenderDelayBuffer> render_buffer,
|
|
std::unique_ptr<RenderDelayController> delay_controller,
|
|
std::unique_ptr<EchoRemover> echo_remover)
|
|
: data_dumper_(
|
|
new ApmDataDumper(rtc::AtomicOps::Increment(&instance_count_))),
|
|
sample_rate_hz_(sample_rate_hz),
|
|
render_buffer_(std::move(render_buffer)),
|
|
delay_controller_(std::move(delay_controller)),
|
|
echo_remover_(std::move(echo_remover)) {}
|
|
|
|
BlockProcessorImpl::~BlockProcessorImpl() = default;
|
|
|
|
void BlockProcessorImpl::ProcessCapture(
|
|
bool echo_path_gain_change,
|
|
bool capture_signal_saturation,
|
|
std::vector<std::vector<float>>* capture_block) {
|
|
RTC_DCHECK(capture_block);
|
|
RTC_DCHECK_EQ(NumBandsForRate(sample_rate_hz_), capture_block->size());
|
|
RTC_DCHECK_EQ(kBlockSize, (*capture_block)[0].size());
|
|
|
|
const size_t delay = delay_controller_->GetDelay((*capture_block)[0]);
|
|
const bool render_delay_change = delay != render_buffer_->Delay();
|
|
|
|
if (render_delay_change) {
|
|
render_buffer_->SetDelay(delay);
|
|
}
|
|
|
|
if (render_buffer_->IsBlockAvailable()) {
|
|
auto& render_block = render_buffer_->GetNext();
|
|
echo_remover_->ProcessBlock(
|
|
delay_controller_->AlignmentHeadroomSamples(),
|
|
EchoPathVariability(echo_path_gain_change, render_delay_change),
|
|
capture_signal_saturation, render_block, capture_block);
|
|
} else {
|
|
LOG(LS_INFO) << "AEC3 empty render buffer";
|
|
}
|
|
}
|
|
|
|
bool BlockProcessorImpl::BufferRender(std::vector<std::vector<float>>* block) {
|
|
RTC_DCHECK(block);
|
|
RTC_DCHECK_EQ(NumBandsForRate(sample_rate_hz_), block->size());
|
|
RTC_DCHECK_EQ(kBlockSize, (*block)[0].size());
|
|
|
|
const bool delay_controller_overrun =
|
|
!delay_controller_->AnalyzeRender((*block)[0]);
|
|
const bool render_buffer_overrun = !render_buffer_->Insert(block);
|
|
if (delay_controller_overrun || render_buffer_overrun) {
|
|
LOG(LS_INFO) << "AEC3 buffer overrrun";
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void BlockProcessorImpl::UpdateEchoLeakageStatus(bool leakage_detected) {
|
|
echo_remover_->UpdateEchoLeakageStatus(leakage_detected);
|
|
}
|
|
|
|
} // namespace
|
|
|
|
BlockProcessor* BlockProcessor::Create(int sample_rate_hz) {
|
|
std::unique_ptr<RenderDelayBuffer> render_buffer(RenderDelayBuffer::Create(
|
|
kRenderBufferSize, NumBandsForRate(sample_rate_hz), kMaxApiJitter));
|
|
std::unique_ptr<RenderDelayController> delay_controller(
|
|
RenderDelayController::Create(sample_rate_hz, *render_buffer));
|
|
std::unique_ptr<EchoRemover> echo_remover(
|
|
EchoRemover::Create(sample_rate_hz));
|
|
return Create(sample_rate_hz, std::move(render_buffer),
|
|
std::move(delay_controller), std::move(echo_remover));
|
|
}
|
|
|
|
BlockProcessor* BlockProcessor::Create(
|
|
int sample_rate_hz,
|
|
std::unique_ptr<RenderDelayBuffer> render_buffer) {
|
|
std::unique_ptr<RenderDelayController> delay_controller(
|
|
RenderDelayController::Create(sample_rate_hz, *render_buffer));
|
|
std::unique_ptr<EchoRemover> echo_remover(
|
|
EchoRemover::Create(sample_rate_hz));
|
|
return Create(sample_rate_hz, std::move(render_buffer),
|
|
std::move(delay_controller), std::move(echo_remover));
|
|
}
|
|
|
|
BlockProcessor* BlockProcessor::Create(
|
|
int sample_rate_hz,
|
|
std::unique_ptr<RenderDelayBuffer> render_buffer,
|
|
std::unique_ptr<RenderDelayController> delay_controller,
|
|
std::unique_ptr<EchoRemover> echo_remover) {
|
|
return new BlockProcessorImpl(sample_rate_hz, std::move(render_buffer),
|
|
std::move(delay_controller),
|
|
std::move(echo_remover));
|
|
}
|
|
|
|
} // namespace webrtc
|