Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(260)

Unified Diff: webrtc/modules/audio_processing/aec3/block_processor.cc

Issue 2784023002: Major AEC3 render pipeline changes (Closed)
Patch Set: Disabled one more DEATH test that caused issues due to bug on bots Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: webrtc/modules/audio_processing/aec3/block_processor.cc
diff --git a/webrtc/modules/audio_processing/aec3/block_processor.cc b/webrtc/modules/audio_processing/aec3/block_processor.cc
index 5055b3f77deedcb7805989cf3f381f8f1a552ec3..79892345b10ff28d2d35bead2c538e76b9adc1aa 100644
--- a/webrtc/modules/audio_processing/aec3/block_processor.cc
+++ b/webrtc/modules/audio_processing/aec3/block_processor.cc
@@ -20,6 +20,8 @@
namespace webrtc {
namespace {
+enum class BlockProcessorApiCall { kCapture, kRender };
+
class BlockProcessorImpl final : public BlockProcessor {
public:
BlockProcessorImpl(int sample_rate_hz,
@@ -33,24 +35,25 @@ class BlockProcessorImpl final : public BlockProcessor {
bool capture_signal_saturation,
std::vector<std::vector<float>>* capture_block) override;
- bool BufferRender(std::vector<std::vector<float>>* block) override;
+ void BufferRender(const std::vector<std::vector<float>>& block) override;
void UpdateEchoLeakageStatus(bool leakage_detected) override;
private:
static int instance_count_;
+ bool no_capture_data_received_ = true;
+ bool no_render_data_received_ = true;
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_;
BlockProcessorMetrics metrics_;
+ bool render_buffer_overrun_occurred_ = false;
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,
@@ -75,40 +78,88 @@ void BlockProcessorImpl::ProcessCapture(
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);
+ data_dumper_->DumpRaw("aec3_processblock_call_order",
+ static_cast<int>(BlockProcessorApiCall::kCapture));
+ data_dumper_->DumpWav("aec3_processblock_capture_input", kBlockSize,
+ &(*capture_block)[0][0],
+ LowestBandRate(sample_rate_hz_), 1);
+
+ // Do not start processing until render data has been buffered as that will
+ // cause the buffers to be wrongly aligned.
+ no_capture_data_received_ = false;
+ if (no_render_data_received_) {
+ return;
}
- 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);
- metrics_.UpdateCapture(false);
+ data_dumper_->DumpWav("aec3_processblock_capture_input2", kBlockSize,
+ &(*capture_block)[0][0],
+ LowestBandRate(sample_rate_hz_), 1);
+
+ bool render_buffer_underrun = false;
+ if (render_buffer_overrun_occurred_) {
+ // Reset the render buffers and the alignment functionality when there has
+ // been a render buffer overrun as the buffer alignment may be noncausal.
+ delay_controller_->Reset();
+ render_buffer_->Reset();
} else {
- metrics_.UpdateCapture(true);
+ // Update the render buffers with new render data, filling the buffers with
+ // empty blocks when there is no render data available.
+ render_buffer_underrun = !render_buffer_->UpdateBuffers();
+
+ // Compute and and apply the render delay required to achieve proper signal
+ // alignment.
+ const size_t old_delay = render_buffer_->Delay();
+ const size_t new_delay = delay_controller_->GetDelay(
+ render_buffer_->GetDownsampledRenderBuffer(), (*capture_block)[0]);
+ render_buffer_->SetDelay(new_delay);
+ const size_t achieved_delay = render_buffer_->Delay();
+
+ // Inform the delay controller of the actually set delay to allow it to
+ // properly react to a non-feasible delay.
+ delay_controller_->SetDelay(achieved_delay);
+
+ // Remove the echo from the capture signal.
+ echo_remover_->ProcessCapture(
+ delay_controller_->AlignmentHeadroomSamples(),
+ EchoPathVariability(echo_path_gain_change,
+ old_delay != achieved_delay ||
+ old_delay != new_delay ||
+ render_buffer_overrun_occurred_),
+ capture_signal_saturation, render_buffer_->GetRenderBuffer(),
+ capture_block);
}
+
+ // Update the metrics.
+ metrics_.UpdateCapture(render_buffer_underrun);
+
+ render_buffer_overrun_occurred_ = false;
}
-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) {
- metrics_.UpdateRender(true);
- return false;
+void BlockProcessorImpl::BufferRender(
+ const std::vector<std::vector<float>>& block) {
+ RTC_DCHECK_EQ(NumBandsForRate(sample_rate_hz_), block.size());
+ RTC_DCHECK_EQ(kBlockSize, block[0].size());
+ data_dumper_->DumpRaw("aec3_processblock_call_order",
+ static_cast<int>(BlockProcessorApiCall::kRender));
+ data_dumper_->DumpWav("aec3_processblock_render_input", kBlockSize,
+ &block[0][0], LowestBandRate(sample_rate_hz_), 1);
+
+ no_render_data_received_ = false;
+
+ // Do not start buffer render data until capture data has been received as
+ // that data may give a false alignment.
+ if (no_capture_data_received_) {
+ return;
}
- metrics_.UpdateRender(false);
- return true;
+
+ data_dumper_->DumpWav("aec3_processblock_render_input2", kBlockSize,
+ &block[0][0], LowestBandRate(sample_rate_hz_), 1);
+
+ // Buffer the render data.
+ render_buffer_overrun_occurred_ = !render_buffer_->Insert(block);
+
+ // Update the metrics.
+ metrics_.UpdateRender(render_buffer_overrun_occurred_);
}
void BlockProcessorImpl::UpdateEchoLeakageStatus(bool leakage_detected) {
@@ -118,10 +169,10 @@ void BlockProcessorImpl::UpdateEchoLeakageStatus(bool 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<RenderDelayBuffer> render_buffer(
+ RenderDelayBuffer::Create(NumBandsForRate(sample_rate_hz)));
std::unique_ptr<RenderDelayController> delay_controller(
- RenderDelayController::Create(sample_rate_hz, *render_buffer));
+ RenderDelayController::Create(sample_rate_hz));
std::unique_ptr<EchoRemover> echo_remover(
EchoRemover::Create(sample_rate_hz));
return Create(sample_rate_hz, std::move(render_buffer),
@@ -132,7 +183,7 @@ 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));
+ RenderDelayController::Create(sample_rate_hz));
std::unique_ptr<EchoRemover> echo_remover(
EchoRemover::Create(sample_rate_hz));
return Create(sample_rate_hz, std::move(render_buffer),

Powered by Google App Engine
This is Rietveld 408576698