blob: c2ad56b83dbd20c2067e77f72983cf88c6448c16 [file] [log] [blame]
peahe0eae3c2016-12-14 01:16:23 -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/echo_canceller3.h"
peahe0eae3c2016-12-14 01:16:23 -080011
Yves Gerey988cc082018-10-23 12:03:01 +020012#include <algorithm>
13#include <utility>
14
15#include "modules/audio_processing/aec3/aec3_common.h"
Per Åhgren0aefbf02019-08-23 21:29:17 +020016#include "modules/audio_processing/high_pass_filter.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020017#include "modules/audio_processing/logging/apm_data_dumper.h"
Steve Anton10542f22019-01-11 09:11:00 -080018#include "rtc_base/atomic_ops.h"
Gustaf Ullberg9249fbf2019-03-14 11:24:54 +010019#include "system_wrappers/include/field_trial.h"
peahe0eae3c2016-12-14 01:16:23 -080020
21namespace webrtc {
22
peahd0263542017-01-03 04:20:34 -080023namespace {
24
peahcf02cf12017-04-05 14:18:07 -070025enum class EchoCanceller3ApiCall { kCapture, kRender };
26
peahd0263542017-01-03 04:20:34 -080027bool DetectSaturation(rtc::ArrayView<const float> y) {
28 for (auto y_k : y) {
peah522d71b2017-02-23 05:16:26 -080029 if (y_k >= 32700.0f || y_k <= -32700.0f) {
peahd0263542017-01-03 04:20:34 -080030 return true;
31 }
32 }
33 return false;
34}
35
Per Åhgren251c7352018-03-28 16:31:57 +020036// Method for adjusting config parameter dependencies..
37EchoCanceller3Config AdjustConfig(const EchoCanceller3Config& config) {
38 EchoCanceller3Config adjusted_cfg = config;
Gustaf Ullberg9249fbf2019-03-14 11:24:54 +010039
40 if (field_trial::IsEnabled("WebRTC-Aec3ShortHeadroomKillSwitch")) {
41 // Two blocks headroom.
42 adjusted_cfg.delay.delay_headroom_samples = kBlockSize * 2;
43 }
44
Per Åhgren251c7352018-03-28 16:31:57 +020045 return adjusted_cfg;
46}
47
Per Åhgrend112c752019-09-02 13:56:56 +000048void FillSubFrameView(AudioBuffer* frame,
49 size_t sub_frame_index,
50 std::vector<rtc::ArrayView<float>>* sub_frame_view) {
peahd0263542017-01-03 04:20:34 -080051 RTC_DCHECK_GE(1, sub_frame_index);
52 RTC_DCHECK_LE(0, sub_frame_index);
53 RTC_DCHECK_EQ(frame->num_bands(), sub_frame_view->size());
Per Åhgrend112c752019-09-02 13:56:56 +000054 for (size_t k = 0; k < sub_frame_view->size(); ++k) {
55 (*sub_frame_view)[k] = rtc::ArrayView<float>(
56 &frame->split_bands(0)[k][sub_frame_index * kSubFrameLength],
57 kSubFrameLength);
peahd0263542017-01-03 04:20:34 -080058 }
59}
60
Per Åhgrend112c752019-09-02 13:56:56 +000061void FillSubFrameView(std::vector<std::vector<float>>* frame,
62 size_t sub_frame_index,
63 std::vector<rtc::ArrayView<float>>* sub_frame_view) {
peahd0263542017-01-03 04:20:34 -080064 RTC_DCHECK_GE(1, sub_frame_index);
65 RTC_DCHECK_EQ(frame->size(), sub_frame_view->size());
Per Åhgrend112c752019-09-02 13:56:56 +000066 for (size_t k = 0; k < frame->size(); ++k) {
67 (*sub_frame_view)[k] = rtc::ArrayView<float>(
68 &(*frame)[k][sub_frame_index * kSubFrameLength], kSubFrameLength);
peahd0263542017-01-03 04:20:34 -080069 }
70}
71
72void ProcessCaptureFrameContent(
73 AudioBuffer* capture,
peah69221db2017-01-27 03:28:19 -080074 bool level_change,
peahd0263542017-01-03 04:20:34 -080075 bool saturated_microphone_signal,
76 size_t sub_frame_index,
77 FrameBlocker* capture_blocker,
78 BlockFramer* output_framer,
79 BlockProcessor* block_processor,
Per Åhgrend112c752019-09-02 13:56:56 +000080 std::vector<std::vector<float>>* block,
81 std::vector<rtc::ArrayView<float>>* sub_frame_view) {
peahd0263542017-01-03 04:20:34 -080082 FillSubFrameView(capture, sub_frame_index, sub_frame_view);
83 capture_blocker->InsertSubFrameAndExtractBlock(*sub_frame_view, block);
peah69221db2017-01-27 03:28:19 -080084 block_processor->ProcessCapture(level_change, saturated_microphone_signal,
85 block);
peahd0263542017-01-03 04:20:34 -080086 output_framer->InsertBlockAndExtractSubFrame(*block, sub_frame_view);
87}
88
89void ProcessRemainingCaptureFrameContent(
peah69221db2017-01-27 03:28:19 -080090 bool level_change,
peahd0263542017-01-03 04:20:34 -080091 bool saturated_microphone_signal,
92 FrameBlocker* capture_blocker,
93 BlockFramer* output_framer,
94 BlockProcessor* block_processor,
Per Åhgrend112c752019-09-02 13:56:56 +000095 std::vector<std::vector<float>>* block) {
peahd0263542017-01-03 04:20:34 -080096 if (!capture_blocker->IsBlockAvailable()) {
97 return;
98 }
99
100 capture_blocker->ExtractBlock(block);
peah69221db2017-01-27 03:28:19 -0800101 block_processor->ProcessCapture(level_change, saturated_microphone_signal,
102 block);
peahd0263542017-01-03 04:20:34 -0800103 output_framer->InsertBlock(*block);
104}
105
peahcf02cf12017-04-05 14:18:07 -0700106void BufferRenderFrameContent(
Per Åhgrend112c752019-09-02 13:56:56 +0000107 std::vector<std::vector<float>>* render_frame,
peahd0263542017-01-03 04:20:34 -0800108 size_t sub_frame_index,
109 FrameBlocker* render_blocker,
110 BlockProcessor* block_processor,
Per Åhgrend112c752019-09-02 13:56:56 +0000111 std::vector<std::vector<float>>* block,
112 std::vector<rtc::ArrayView<float>>* sub_frame_view) {
peahd0263542017-01-03 04:20:34 -0800113 FillSubFrameView(render_frame, sub_frame_index, sub_frame_view);
114 render_blocker->InsertSubFrameAndExtractBlock(*sub_frame_view, block);
peahcf02cf12017-04-05 14:18:07 -0700115 block_processor->BufferRender(*block);
peahd0263542017-01-03 04:20:34 -0800116}
117
Per Åhgrend112c752019-09-02 13:56:56 +0000118void BufferRemainingRenderFrameContent(FrameBlocker* render_blocker,
119 BlockProcessor* block_processor,
120 std::vector<std::vector<float>>* block) {
peahd0263542017-01-03 04:20:34 -0800121 if (!render_blocker->IsBlockAvailable()) {
peahcf02cf12017-04-05 14:18:07 -0700122 return;
peahd0263542017-01-03 04:20:34 -0800123 }
124 render_blocker->ExtractBlock(block);
peahcf02cf12017-04-05 14:18:07 -0700125 block_processor->BufferRender(*block);
peahd0263542017-01-03 04:20:34 -0800126}
127
Per Åhgren0aefbf02019-08-23 21:29:17 +0200128void CopyBufferIntoFrame(const AudioBuffer& buffer,
peahcf02cf12017-04-05 14:18:07 -0700129 size_t num_bands,
Per Åhgrend112c752019-09-02 13:56:56 +0000130 size_t frame_length,
131 std::vector<std::vector<float>>* frame) {
peahd0263542017-01-03 04:20:34 -0800132 RTC_DCHECK_EQ(num_bands, frame->size());
Per Åhgrend112c752019-09-02 13:56:56 +0000133 RTC_DCHECK_EQ(frame_length, (*frame)[0].size());
134 for (size_t k = 0; k < num_bands; ++k) {
135 rtc::ArrayView<const float> buffer_view(&buffer.split_bands_const(0)[k][0],
136 frame_length);
137 std::copy(buffer_view.begin(), buffer_view.end(), (*frame)[k].begin());
peahcf02cf12017-04-05 14:18:07 -0700138 }
peahd0263542017-01-03 04:20:34 -0800139}
140
peahd0263542017-01-03 04:20:34 -0800141} // namespace
142
143class EchoCanceller3::RenderWriter {
144 public:
Mirko Bonadeif0d9cda2019-01-17 20:43:58 +0000145 RenderWriter(ApmDataDumper* data_dumper,
Per Åhgrend112c752019-09-02 13:56:56 +0000146 SwapQueue<std::vector<std::vector<float>>,
Mirko Bonadeif0d9cda2019-01-17 20:43:58 +0000147 Aec3RenderQueueItemVerifier>* render_transfer_queue,
Per Åhgrend112c752019-09-02 13:56:56 +0000148 int sample_rate_hz,
149 int frame_length,
150 int num_bands);
peahd0263542017-01-03 04:20:34 -0800151 ~RenderWriter();
Per Åhgren0aefbf02019-08-23 21:29:17 +0200152 void Insert(const AudioBuffer& input);
peahd0263542017-01-03 04:20:34 -0800153
154 private:
155 ApmDataDumper* data_dumper_;
Per Åhgrend112c752019-09-02 13:56:56 +0000156 const int sample_rate_hz_;
157 const size_t frame_length_;
158 const int num_bands_;
Per Åhgren0aefbf02019-08-23 21:29:17 +0200159 HighPassFilter high_pass_filter_;
Per Åhgrend112c752019-09-02 13:56:56 +0000160 std::vector<std::vector<float>> render_queue_input_frame_;
161 SwapQueue<std::vector<std::vector<float>>, Aec3RenderQueueItemVerifier>*
162 render_transfer_queue_;
peahd0263542017-01-03 04:20:34 -0800163 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(RenderWriter);
164};
165
166EchoCanceller3::RenderWriter::RenderWriter(
167 ApmDataDumper* data_dumper,
Per Åhgrend112c752019-09-02 13:56:56 +0000168 SwapQueue<std::vector<std::vector<float>>, Aec3RenderQueueItemVerifier>*
169 render_transfer_queue,
170 int sample_rate_hz,
171 int frame_length,
172 int num_bands)
peahd0263542017-01-03 04:20:34 -0800173 : data_dumper_(data_dumper),
Per Åhgrend112c752019-09-02 13:56:56 +0000174 sample_rate_hz_(sample_rate_hz),
175 frame_length_(frame_length),
peahd0263542017-01-03 04:20:34 -0800176 num_bands_(num_bands),
Per Åhgrend112c752019-09-02 13:56:56 +0000177 high_pass_filter_(1),
178 render_queue_input_frame_(num_bands_,
179 std::vector<float>(frame_length_, 0.f)),
peahd0263542017-01-03 04:20:34 -0800180 render_transfer_queue_(render_transfer_queue) {
181 RTC_DCHECK(data_dumper);
182}
183
184EchoCanceller3::RenderWriter::~RenderWriter() = default;
185
Per Åhgren0aefbf02019-08-23 21:29:17 +0200186void EchoCanceller3::RenderWriter::Insert(const AudioBuffer& input) {
187 RTC_DCHECK_EQ(1, input.num_channels());
Per Åhgrend112c752019-09-02 13:56:56 +0000188 RTC_DCHECK_EQ(frame_length_, input.num_frames_per_band());
Per Åhgren0aefbf02019-08-23 21:29:17 +0200189 RTC_DCHECK_EQ(num_bands_, input.num_bands());
Gustaf Ullberg7d042782018-01-16 13:39:27 +0100190
191 // TODO(bugs.webrtc.org/8759) Temporary work-around.
Per Åhgrend112c752019-09-02 13:56:56 +0000192 if (num_bands_ != static_cast<int>(input.num_bands()))
Gustaf Ullberg7d042782018-01-16 13:39:27 +0100193 return;
194
Per Åhgrend112c752019-09-02 13:56:56 +0000195 data_dumper_->DumpWav("aec3_render_input", frame_length_,
196 &input.split_bands_const(0)[0][0],
197 LowestBandRate(sample_rate_hz_), 1);
peahd0263542017-01-03 04:20:34 -0800198
Per Åhgrend112c752019-09-02 13:56:56 +0000199 CopyBufferIntoFrame(input, num_bands_, frame_length_,
peahcf02cf12017-04-05 14:18:07 -0700200 &render_queue_input_frame_);
Per Åhgrend112c752019-09-02 13:56:56 +0000201
202 high_pass_filter_.Process(render_queue_input_frame_[0]);
peahd0263542017-01-03 04:20:34 -0800203
peah925e9d72017-04-10 04:18:38 -0700204 static_cast<void>(render_transfer_queue_->Insert(&render_queue_input_frame_));
peahd0263542017-01-03 04:20:34 -0800205}
206
peahe0eae3c2016-12-14 01:16:23 -0800207int EchoCanceller3::instance_count_ = 0;
208
Gustaf Ullbergbd83b912017-10-18 12:32:42 +0200209EchoCanceller3::EchoCanceller3(const EchoCanceller3Config& config,
Per Åhgrend112c752019-09-02 13:56:56 +0000210 int sample_rate_hz)
211 : EchoCanceller3(
212 AdjustConfig(config),
213 sample_rate_hz,
214 std::unique_ptr<BlockProcessor>(
215 BlockProcessor::Create(AdjustConfig(config), sample_rate_hz))) {}
Per Åhgren8ba58612017-12-01 23:01:44 +0100216EchoCanceller3::EchoCanceller3(const EchoCanceller3Config& config,
217 int sample_rate_hz,
peahd0263542017-01-03 04:20:34 -0800218 std::unique_ptr<BlockProcessor> block_processor)
219 : data_dumper_(
220 new ApmDataDumper(rtc::AtomicOps::Increment(&instance_count_))),
Per Åhgren398689f2018-08-23 11:38:27 +0200221 config_(config),
peahd0263542017-01-03 04:20:34 -0800222 sample_rate_hz_(sample_rate_hz),
223 num_bands_(NumBandsForRate(sample_rate_hz_)),
Per Åhgrend112c752019-09-02 13:56:56 +0000224 frame_length_(rtc::CheckedDivExact(LowestBandRate(sample_rate_hz_), 100)),
225 output_framer_(num_bands_),
226 capture_blocker_(num_bands_),
227 render_blocker_(num_bands_),
Mirko Bonadeif0d9cda2019-01-17 20:43:58 +0000228 render_transfer_queue_(
229 kRenderTransferQueueSizeFrames,
Per Åhgrena66395e2019-08-30 08:54:09 +0200230 std::vector<std::vector<float>>(
Per Åhgrend112c752019-09-02 13:56:56 +0000231 num_bands_,
232 std::vector<float>(frame_length_, 0.f)),
233 Aec3RenderQueueItemVerifier(num_bands_, frame_length_)),
234 block_processor_(std::move(block_processor)),
235 render_queue_output_frame_(num_bands_,
236 std::vector<float>(frame_length_, 0.f)),
237 block_(num_bands_, std::vector<float>(kBlockSize, 0.f)),
238 sub_frame_view_(num_bands_),
Per Åhgren398689f2018-08-23 11:38:27 +0200239 block_delay_buffer_(num_bands_,
Per Åhgrend112c752019-09-02 13:56:56 +0000240 frame_length_,
Per Åhgren398689f2018-08-23 11:38:27 +0200241 config_.delay.fixed_capture_delay_samples) {
peah21920892017-02-08 05:08:56 -0800242 RTC_DCHECK(ValidFullBandRate(sample_rate_hz_));
243
Per Åhgrend112c752019-09-02 13:56:56 +0000244 render_writer_.reset(
245 new RenderWriter(data_dumper_.get(), &render_transfer_queue_,
246 sample_rate_hz_, frame_length_, num_bands_));
peahd0263542017-01-03 04:20:34 -0800247
248 RTC_DCHECK_EQ(num_bands_, std::max(sample_rate_hz_, 16000) / 16000);
249 RTC_DCHECK_GE(kMaxNumBands, num_bands_);
peahe0eae3c2016-12-14 01:16:23 -0800250}
251
252EchoCanceller3::~EchoCanceller3() = default;
253
Per Åhgren0aefbf02019-08-23 21:29:17 +0200254void EchoCanceller3::AnalyzeRender(const AudioBuffer& render) {
peahd0263542017-01-03 04:20:34 -0800255 RTC_DCHECK_RUNS_SERIALIZED(&render_race_checker_);
peahcf02cf12017-04-05 14:18:07 -0700256 data_dumper_->DumpRaw("aec3_call_order",
257 static_cast<int>(EchoCanceller3ApiCall::kRender));
258
peahd0263542017-01-03 04:20:34 -0800259 return render_writer_->Insert(render);
peahe0eae3c2016-12-14 01:16:23 -0800260}
261
Per Åhgren0aefbf02019-08-23 21:29:17 +0200262void EchoCanceller3::AnalyzeCapture(const AudioBuffer& capture) {
peahd0263542017-01-03 04:20:34 -0800263 RTC_DCHECK_RUNS_SERIALIZED(&capture_race_checker_);
Per Åhgren0aefbf02019-08-23 21:29:17 +0200264 data_dumper_->DumpWav("aec3_capture_analyze_input", capture.num_frames(),
265 capture.channels_const()[0], sample_rate_hz_, 1);
peahd0263542017-01-03 04:20:34 -0800266
267 saturated_microphone_signal_ = false;
Per Åhgrend112c752019-09-02 13:56:56 +0000268 for (size_t k = 0; k < capture.num_channels(); ++k) {
peahd0263542017-01-03 04:20:34 -0800269 saturated_microphone_signal_ |=
Per Åhgren0aefbf02019-08-23 21:29:17 +0200270 DetectSaturation(rtc::ArrayView<const float>(
Per Åhgrend112c752019-09-02 13:56:56 +0000271 capture.channels_const()[k], capture.num_frames()));
peahd0263542017-01-03 04:20:34 -0800272 if (saturated_microphone_signal_) {
273 break;
274 }
275 }
276}
peahe0eae3c2016-12-14 01:16:23 -0800277
peah69221db2017-01-27 03:28:19 -0800278void EchoCanceller3::ProcessCapture(AudioBuffer* capture, bool level_change) {
peahd0263542017-01-03 04:20:34 -0800279 RTC_DCHECK_RUNS_SERIALIZED(&capture_race_checker_);
280 RTC_DCHECK(capture);
peahe0eae3c2016-12-14 01:16:23 -0800281 RTC_DCHECK_EQ(1u, capture->num_channels());
peahd0263542017-01-03 04:20:34 -0800282 RTC_DCHECK_EQ(num_bands_, capture->num_bands());
Per Åhgrend112c752019-09-02 13:56:56 +0000283 RTC_DCHECK_EQ(frame_length_, capture->num_frames_per_band());
peahcf02cf12017-04-05 14:18:07 -0700284 data_dumper_->DumpRaw("aec3_call_order",
285 static_cast<int>(EchoCanceller3ApiCall::kCapture));
peahd0263542017-01-03 04:20:34 -0800286
Per Åhgren14f252a2018-11-27 18:02:56 +0100287 // Report capture call in the metrics and periodically update API call
288 // metrics.
289 api_call_metrics_.ReportCaptureCall();
290
Per Åhgren398689f2018-08-23 11:38:27 +0200291 // Optionally delay the capture signal.
292 if (config_.delay.fixed_capture_delay_samples > 0) {
293 block_delay_buffer_.DelaySignal(capture);
294 }
295
Per Åhgrend112c752019-09-02 13:56:56 +0000296 rtc::ArrayView<float> capture_lower_band =
297 rtc::ArrayView<float>(&capture->split_bands(0)[0][0], frame_length_);
peahd0263542017-01-03 04:20:34 -0800298
Per Åhgrend112c752019-09-02 13:56:56 +0000299 data_dumper_->DumpWav("aec3_capture_input", capture_lower_band,
300 LowestBandRate(sample_rate_hz_), 1);
peahd0263542017-01-03 04:20:34 -0800301
peahcf02cf12017-04-05 14:18:07 -0700302 EmptyRenderQueue();
peahd0263542017-01-03 04:20:34 -0800303
Per Åhgrend112c752019-09-02 13:56:56 +0000304 ProcessCaptureFrameContent(
305 capture, level_change, saturated_microphone_signal_, 0, &capture_blocker_,
306 &output_framer_, block_processor_.get(), &block_, &sub_frame_view_);
peahd0263542017-01-03 04:20:34 -0800307
Per Åhgrend112c752019-09-02 13:56:56 +0000308 if (sample_rate_hz_ != 8000) {
309 ProcessCaptureFrameContent(
310 capture, level_change, saturated_microphone_signal_, 1,
311 &capture_blocker_, &output_framer_, block_processor_.get(), &block_,
312 &sub_frame_view_);
313 }
peahd0263542017-01-03 04:20:34 -0800314
315 ProcessRemainingCaptureFrameContent(
peah69221db2017-01-27 03:28:19 -0800316 level_change, saturated_microphone_signal_, &capture_blocker_,
Per Åhgrend112c752019-09-02 13:56:56 +0000317 &output_framer_, block_processor_.get(), &block_);
peahd0263542017-01-03 04:20:34 -0800318
Per Åhgrend112c752019-09-02 13:56:56 +0000319 data_dumper_->DumpWav("aec3_capture_output", frame_length_,
320 &capture->split_bands(0)[0][0],
321 LowestBandRate(sample_rate_hz_), 1);
peahe0eae3c2016-12-14 01:16:23 -0800322}
323
Gustaf Ullberg332150d2017-11-22 14:17:39 +0100324EchoControl::Metrics EchoCanceller3::GetMetrics() const {
325 RTC_DCHECK_RUNS_SERIALIZED(&capture_race_checker_);
326 Metrics metrics;
327 block_processor_->GetMetrics(&metrics);
328 return metrics;
329}
330
Per Åhgrend0fa8202018-04-18 09:35:13 +0200331void EchoCanceller3::SetAudioBufferDelay(size_t delay_ms) {
332 RTC_DCHECK_RUNS_SERIALIZED(&capture_race_checker_);
333 block_processor_->SetAudioBufferDelay(delay_ms);
334}
335
peahcf02cf12017-04-05 14:18:07 -0700336void EchoCanceller3::EmptyRenderQueue() {
peahd0263542017-01-03 04:20:34 -0800337 RTC_DCHECK_RUNS_SERIALIZED(&capture_race_checker_);
peahd0263542017-01-03 04:20:34 -0800338 bool frame_to_buffer =
339 render_transfer_queue_.Remove(&render_queue_output_frame_);
340 while (frame_to_buffer) {
Per Åhgren14f252a2018-11-27 18:02:56 +0100341 // Report render call in the metrics.
342 api_call_metrics_.ReportRenderCall();
343
peahcf02cf12017-04-05 14:18:07 -0700344 BufferRenderFrameContent(&render_queue_output_frame_, 0, &render_blocker_,
Per Åhgrend112c752019-09-02 13:56:56 +0000345 block_processor_.get(), &block_, &sub_frame_view_);
peahd0263542017-01-03 04:20:34 -0800346
Per Åhgrend112c752019-09-02 13:56:56 +0000347 if (sample_rate_hz_ != 8000) {
348 BufferRenderFrameContent(&render_queue_output_frame_, 1, &render_blocker_,
349 block_processor_.get(), &block_,
350 &sub_frame_view_);
351 }
peahd0263542017-01-03 04:20:34 -0800352
peahcf02cf12017-04-05 14:18:07 -0700353 BufferRemainingRenderFrameContent(&render_blocker_, block_processor_.get(),
Per Åhgrend112c752019-09-02 13:56:56 +0000354 &block_);
peahd0263542017-01-03 04:20:34 -0800355
356 frame_to_buffer =
357 render_transfer_queue_.Remove(&render_queue_output_frame_);
358 }
peahd0263542017-01-03 04:20:34 -0800359}
peahe0eae3c2016-12-14 01:16:23 -0800360} // namespace webrtc