blob: 4c83a554131eb2c0a082e5a63aeb18def074027c [file] [log] [blame]
peahd0263542017-01-03 04:20:34 -08001/*
2 * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020010#include "modules/audio_processing/aec3/block_processor.h"
peahd0263542017-01-03 04:20:34 -080011
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020012#include "api/optional.h"
13#include "modules/audio_processing/aec3/aec3_common.h"
14#include "modules/audio_processing/aec3/block_processor_metrics.h"
15#include "modules/audio_processing/aec3/echo_path_variability.h"
16#include "modules/audio_processing/logging/apm_data_dumper.h"
17#include "rtc_base/atomicops.h"
18#include "rtc_base/constructormagic.h"
Per Åhgrenfe9f2222017-09-26 23:33:26 +020019#include "rtc_base/logging.h"
peahd0263542017-01-03 04:20:34 -080020
21namespace webrtc {
22namespace {
23
peahcf02cf12017-04-05 14:18:07 -070024enum class BlockProcessorApiCall { kCapture, kRender };
25
peahd0263542017-01-03 04:20:34 -080026class BlockProcessorImpl final : public BlockProcessor {
27 public:
Per Åhgren8ba58612017-12-01 23:01:44 +010028 BlockProcessorImpl(const EchoCanceller3Config& config,
29 int sample_rate_hz,
peah69221db2017-01-27 03:28:19 -080030 std::unique_ptr<RenderDelayBuffer> render_buffer,
31 std::unique_ptr<RenderDelayController> delay_controller,
32 std::unique_ptr<EchoRemover> echo_remover);
33
peahd0263542017-01-03 04:20:34 -080034 ~BlockProcessorImpl() override;
35
peah69221db2017-01-27 03:28:19 -080036 void ProcessCapture(bool echo_path_gain_change,
37 bool capture_signal_saturation,
peahd0263542017-01-03 04:20:34 -080038 std::vector<std::vector<float>>* capture_block) override;
39
peahcf02cf12017-04-05 14:18:07 -070040 void BufferRender(const std::vector<std::vector<float>>& block) override;
peahd0263542017-01-03 04:20:34 -080041
peah69221db2017-01-27 03:28:19 -080042 void UpdateEchoLeakageStatus(bool leakage_detected) override;
peahd0263542017-01-03 04:20:34 -080043
Gustaf Ullberg332150d2017-11-22 14:17:39 +010044 void GetMetrics(EchoControl::Metrics* metrics) const override;
45
peahd0263542017-01-03 04:20:34 -080046 private:
peahd0263542017-01-03 04:20:34 -080047 static int instance_count_;
48 std::unique_ptr<ApmDataDumper> data_dumper_;
Per Åhgren8ba58612017-12-01 23:01:44 +010049 const EchoCanceller3Config config_;
50 bool capture_properly_started_ = false;
51 bool render_properly_started_ = false;
peah69221db2017-01-27 03:28:19 -080052 const size_t sample_rate_hz_;
53 std::unique_ptr<RenderDelayBuffer> render_buffer_;
54 std::unique_ptr<RenderDelayController> delay_controller_;
55 std::unique_ptr<EchoRemover> echo_remover_;
peahe985b3f2017-02-28 22:08:53 -080056 BlockProcessorMetrics metrics_;
Per Åhgren8ba58612017-12-01 23:01:44 +010057 RenderDelayBuffer::BufferingEvent render_event_;
Per Åhgrenc59a5762017-12-11 21:34:19 +010058 size_t capture_call_counter_ = 0;
peahd0263542017-01-03 04:20:34 -080059 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(BlockProcessorImpl);
60};
61
62int BlockProcessorImpl::instance_count_ = 0;
63
peah69221db2017-01-27 03:28:19 -080064BlockProcessorImpl::BlockProcessorImpl(
Per Åhgren8ba58612017-12-01 23:01:44 +010065 const EchoCanceller3Config& config,
peah69221db2017-01-27 03:28:19 -080066 int sample_rate_hz,
67 std::unique_ptr<RenderDelayBuffer> render_buffer,
68 std::unique_ptr<RenderDelayController> delay_controller,
69 std::unique_ptr<EchoRemover> echo_remover)
70 : data_dumper_(
71 new ApmDataDumper(rtc::AtomicOps::Increment(&instance_count_))),
Per Åhgren8ba58612017-12-01 23:01:44 +010072 config_(config),
peah69221db2017-01-27 03:28:19 -080073 sample_rate_hz_(sample_rate_hz),
74 render_buffer_(std::move(render_buffer)),
75 delay_controller_(std::move(delay_controller)),
Per Åhgren8ba58612017-12-01 23:01:44 +010076 echo_remover_(std::move(echo_remover)),
77 render_event_(RenderDelayBuffer::BufferingEvent::kNone) {
peah21920892017-02-08 05:08:56 -080078 RTC_DCHECK(ValidFullBandRate(sample_rate_hz_));
79}
peahd0263542017-01-03 04:20:34 -080080
81BlockProcessorImpl::~BlockProcessorImpl() = default;
82
83void BlockProcessorImpl::ProcessCapture(
peah69221db2017-01-27 03:28:19 -080084 bool echo_path_gain_change,
85 bool capture_signal_saturation,
peahd0263542017-01-03 04:20:34 -080086 std::vector<std::vector<float>>* capture_block) {
87 RTC_DCHECK(capture_block);
88 RTC_DCHECK_EQ(NumBandsForRate(sample_rate_hz_), capture_block->size());
89 RTC_DCHECK_EQ(kBlockSize, (*capture_block)[0].size());
Per Åhgrenc59a5762017-12-11 21:34:19 +010090
91 capture_call_counter_++;
92
peahcf02cf12017-04-05 14:18:07 -070093 data_dumper_->DumpRaw("aec3_processblock_call_order",
94 static_cast<int>(BlockProcessorApiCall::kCapture));
95 data_dumper_->DumpWav("aec3_processblock_capture_input", kBlockSize,
96 &(*capture_block)[0][0],
97 LowestBandRate(sample_rate_hz_), 1);
peah69221db2017-01-27 03:28:19 -080098
Per Åhgren8ba58612017-12-01 23:01:44 +010099 if (render_properly_started_) {
100 if (!capture_properly_started_) {
101 capture_properly_started_ = true;
102 render_buffer_->Reset();
103 }
104 } else {
105 // If no render data has yet arrived, do not process the capture signal.
peahcf02cf12017-04-05 14:18:07 -0700106 return;
peah69221db2017-01-27 03:28:19 -0800107 }
108
Per Åhgren8ba58612017-12-01 23:01:44 +0100109 EchoPathVariability echo_path_variability(
110 echo_path_gain_change, EchoPathVariability::DelayAdjustment::kNone,
111 false);
112
113 if (render_event_ == RenderDelayBuffer::BufferingEvent::kRenderOverrun &&
114 render_properly_started_) {
115 echo_path_variability.delay_change =
116 EchoPathVariability::DelayAdjustment::kBufferFlush;
117 delay_controller_->Reset();
Per Åhgrenc59a5762017-12-11 21:34:19 +0100118 RTC_LOG(LS_WARNING) << "Reset due to render buffer overrun at block "
119 << capture_call_counter_;
Per Åhgren8ba58612017-12-01 23:01:44 +0100120 }
121
122 // Update the render buffers with any newly arrived render blocks and prepare
123 // the render buffers for reading the render data corresponding to the current
124 // capture block.
Per Åhgrenc59a5762017-12-11 21:34:19 +0100125 render_event_ = render_buffer_->PrepareCaptureProcessing();
Per Åhgren8ba58612017-12-01 23:01:44 +0100126 RTC_DCHECK(RenderDelayBuffer::BufferingEvent::kRenderOverrun !=
127 render_event_);
128 if (render_event_ == RenderDelayBuffer::BufferingEvent::kRenderUnderrun) {
129 echo_path_variability.delay_change =
Per Åhgrenc59a5762017-12-11 21:34:19 +0100130 EchoPathVariability::DelayAdjustment::kDelayReset;
Per Åhgren8ba58612017-12-01 23:01:44 +0100131 delay_controller_->Reset();
Per Åhgrenc59a5762017-12-11 21:34:19 +0100132 capture_properly_started_ = false;
133 render_properly_started_ = false;
134
135 RTC_LOG(LS_WARNING) << "Reset due to render buffer underrrun at block "
136 << capture_call_counter_;
Per Åhgren8ba58612017-12-01 23:01:44 +0100137 } else if (render_event_ == RenderDelayBuffer::BufferingEvent::kApiCallSkew) {
138 // There have been too many render calls in a row. Reset to avoid noncausal
139 // echo.
140 echo_path_variability.delay_change =
141 EchoPathVariability::DelayAdjustment::kDelayReset;
142 delay_controller_->Reset();
Per Åhgren8ba58612017-12-01 23:01:44 +0100143 capture_properly_started_ = false;
144 render_properly_started_ = false;
Per Åhgrenc59a5762017-12-11 21:34:19 +0100145 RTC_LOG(LS_WARNING) << "Reset due to render buffer api skew at block "
146 << capture_call_counter_;
Per Åhgren8ba58612017-12-01 23:01:44 +0100147 }
148
peahcf02cf12017-04-05 14:18:07 -0700149 data_dumper_->DumpWav("aec3_processblock_capture_input2", kBlockSize,
150 &(*capture_block)[0][0],
151 LowestBandRate(sample_rate_hz_), 1);
152
peah4b572d02017-04-06 16:33:06 -0700153 // Compute and and apply the render delay required to achieve proper signal
154 // alignment.
Per Åhgrenc59a5762017-12-11 21:34:19 +0100155 rtc::Optional<size_t> estimated_delay = delay_controller_->GetDelay(
peah4b572d02017-04-06 16:33:06 -0700156 render_buffer_->GetDownsampledRenderBuffer(), (*capture_block)[0]);
peah4b572d02017-04-06 16:33:06 -0700157
Per Åhgrenc59a5762017-12-11 21:34:19 +0100158 if (estimated_delay) {
159 bool delay_change = render_buffer_->SetDelay(*estimated_delay);
160
161 if (delay_change) {
162 RTC_LOG(LS_WARNING) << "Delay changed to " << *estimated_delay
163 << " at block " << capture_call_counter_;
164 if (render_buffer_->CausalDelay()) {
165 echo_path_variability.delay_change =
166 EchoPathVariability::DelayAdjustment::kNewDetectedDelay;
167 } else {
168 // A noncausal delay has been detected. This can only happen if there is
169 // clockdrift, an audio pipeline issue has occurred or the specified
170 // minimum delay is too short. Perform a full reset.
171 echo_path_variability.delay_change =
172 EchoPathVariability::DelayAdjustment::kDelayReset;
173 delay_controller_->Reset();
174 render_buffer_->Reset();
175 capture_properly_started_ = false;
176 render_properly_started_ = false;
177 RTC_LOG(LS_WARNING) << "Reset due to noncausal delay at block "
178 << capture_call_counter_;
179 }
180 }
peah96b951c2017-08-22 10:26:07 -0700181 }
peah4b572d02017-04-06 16:33:06 -0700182
183 // Remove the echo from the capture signal.
184 echo_remover_->ProcessCapture(
Per Åhgrende22a172017-12-20 18:00:51 +0100185 echo_path_variability, capture_signal_saturation,
186 render_buffer_->GetRenderBuffer(), capture_block);
peah4b572d02017-04-06 16:33:06 -0700187
peahcf02cf12017-04-05 14:18:07 -0700188 // Update the metrics.
Per Åhgren8ba58612017-12-01 23:01:44 +0100189 metrics_.UpdateCapture(false);
peahcf02cf12017-04-05 14:18:07 -0700190
Per Åhgren8ba58612017-12-01 23:01:44 +0100191 render_event_ = RenderDelayBuffer::BufferingEvent::kNone;
peahd0263542017-01-03 04:20:34 -0800192}
193
peahcf02cf12017-04-05 14:18:07 -0700194void BlockProcessorImpl::BufferRender(
195 const std::vector<std::vector<float>>& block) {
196 RTC_DCHECK_EQ(NumBandsForRate(sample_rate_hz_), block.size());
197 RTC_DCHECK_EQ(kBlockSize, block[0].size());
198 data_dumper_->DumpRaw("aec3_processblock_call_order",
199 static_cast<int>(BlockProcessorApiCall::kRender));
200 data_dumper_->DumpWav("aec3_processblock_render_input", kBlockSize,
201 &block[0][0], LowestBandRate(sample_rate_hz_), 1);
peahcf02cf12017-04-05 14:18:07 -0700202 data_dumper_->DumpWav("aec3_processblock_render_input2", kBlockSize,
203 &block[0][0], LowestBandRate(sample_rate_hz_), 1);
204
Per Åhgren8ba58612017-12-01 23:01:44 +0100205 render_event_ = render_buffer_->Insert(block);
peahcf02cf12017-04-05 14:18:07 -0700206
Per Åhgren8ba58612017-12-01 23:01:44 +0100207 metrics_.UpdateRender(render_event_ !=
208 RenderDelayBuffer::BufferingEvent::kNone);
209
210 render_properly_started_ = true;
peahd0263542017-01-03 04:20:34 -0800211}
212
peah69221db2017-01-27 03:28:19 -0800213void BlockProcessorImpl::UpdateEchoLeakageStatus(bool leakage_detected) {
214 echo_remover_->UpdateEchoLeakageStatus(leakage_detected);
215}
peahd0263542017-01-03 04:20:34 -0800216
Gustaf Ullberg332150d2017-11-22 14:17:39 +0100217void BlockProcessorImpl::GetMetrics(EchoControl::Metrics* metrics) const {
218 echo_remover_->GetMetrics(metrics);
Per Åhgren83c4a022017-11-27 12:07:09 +0100219 const int block_size_ms = sample_rate_hz_ == 8000 ? 8 : 4;
Per Åhgrenc59a5762017-12-11 21:34:19 +0100220 rtc::Optional<size_t> delay = render_buffer_->Delay();
221 metrics->delay_ms = delay ? static_cast<int>(*delay) * block_size_ms : 0;
Gustaf Ullberg332150d2017-11-22 14:17:39 +0100222}
223
peahd0263542017-01-03 04:20:34 -0800224} // namespace
225
Gustaf Ullbergbd83b912017-10-18 12:32:42 +0200226BlockProcessor* BlockProcessor::Create(const EchoCanceller3Config& config,
227 int sample_rate_hz) {
Per Åhgren8ba58612017-12-01 23:01:44 +0100228 std::unique_ptr<RenderDelayBuffer> render_buffer(
229 RenderDelayBuffer::Create(config, NumBandsForRate(sample_rate_hz)));
peah69221db2017-01-27 03:28:19 -0800230 std::unique_ptr<RenderDelayController> delay_controller(
Per Åhgrenc59a5762017-12-11 21:34:19 +0100231 RenderDelayController::Create(
232 config, RenderDelayBuffer::DelayEstimatorOffset(config),
233 sample_rate_hz));
peah69221db2017-01-27 03:28:19 -0800234 std::unique_ptr<EchoRemover> echo_remover(
peah697a5902017-06-30 07:06:10 -0700235 EchoRemover::Create(config, sample_rate_hz));
236 return Create(config, sample_rate_hz, std::move(render_buffer),
peah69221db2017-01-27 03:28:19 -0800237 std::move(delay_controller), std::move(echo_remover));
238}
239
240BlockProcessor* BlockProcessor::Create(
Gustaf Ullbergbd83b912017-10-18 12:32:42 +0200241 const EchoCanceller3Config& config,
peah69221db2017-01-27 03:28:19 -0800242 int sample_rate_hz,
243 std::unique_ptr<RenderDelayBuffer> render_buffer) {
244 std::unique_ptr<RenderDelayController> delay_controller(
Per Åhgrenc59a5762017-12-11 21:34:19 +0100245 RenderDelayController::Create(
246 config, RenderDelayBuffer::DelayEstimatorOffset(config),
247 sample_rate_hz));
peah69221db2017-01-27 03:28:19 -0800248 std::unique_ptr<EchoRemover> echo_remover(
peah697a5902017-06-30 07:06:10 -0700249 EchoRemover::Create(config, sample_rate_hz));
250 return Create(config, sample_rate_hz, std::move(render_buffer),
peah69221db2017-01-27 03:28:19 -0800251 std::move(delay_controller), std::move(echo_remover));
252}
253
254BlockProcessor* BlockProcessor::Create(
Gustaf Ullbergbd83b912017-10-18 12:32:42 +0200255 const EchoCanceller3Config& config,
peah69221db2017-01-27 03:28:19 -0800256 int sample_rate_hz,
257 std::unique_ptr<RenderDelayBuffer> render_buffer,
258 std::unique_ptr<RenderDelayController> delay_controller,
259 std::unique_ptr<EchoRemover> echo_remover) {
Per Åhgren8ba58612017-12-01 23:01:44 +0100260 return new BlockProcessorImpl(
261 config, sample_rate_hz, std::move(render_buffer),
262 std::move(delay_controller), std::move(echo_remover));
peahd0263542017-01-03 04:20:34 -0800263}
264
265} // namespace webrtc