blob: 37a2378738cc5be3060d3c4560c5afd644a63213 [file] [log] [blame]
peah69221db2017-01-27 03:28:19 -08001/*
2 * Copyright (c) 2017 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 */
10
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#include "modules/audio_processing/aec3/render_delay_buffer.h"
peah69221db2017-01-27 03:28:19 -080012
13#include <string.h>
14#include <algorithm>
Per Åhgrenb6b00dc2018-02-20 22:18:27 +010015#include <numeric>
peah69221db2017-01-27 03:28:19 -080016
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020017#include "modules/audio_processing/aec3/aec3_common.h"
Per Åhgren8ba58612017-12-01 23:01:44 +010018#include "modules/audio_processing/aec3/aec3_fft.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020019#include "modules/audio_processing/aec3/block_processor.h"
Per Åhgren38e2d952017-11-17 14:54:28 +010020#include "modules/audio_processing/aec3/decimator.h"
Per Åhgren8ba58612017-12-01 23:01:44 +010021#include "modules/audio_processing/aec3/fft_buffer.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020022#include "modules/audio_processing/aec3/fft_data.h"
Per Åhgren8ba58612017-12-01 23:01:44 +010023#include "modules/audio_processing/aec3/matrix_buffer.h"
Per Åhgren38e2d952017-11-17 14:54:28 +010024#include "rtc_base/atomicops.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020025#include "rtc_base/checks.h"
26#include "rtc_base/constructormagic.h"
27#include "rtc_base/logging.h"
Per Åhgrene05c43c2018-05-09 12:26:51 +020028#include "system_wrappers/include/field_trial.h"
peah69221db2017-01-27 03:28:19 -080029
30namespace webrtc {
31namespace {
32
Per Åhgrene05c43c2018-05-09 12:26:51 +020033bool EnableZeroExternalDelayHeadroom() {
34 return !field_trial::IsEnabled(
35 "WebRTC-Aec3ZeroExternalDelayHeadroomKillSwitch");
36}
37
Gustaf Ullberg78b1c4a2018-05-25 10:12:58 +020038size_t GetDownSamplingFactor(const EchoCanceller3Config& config) {
39 // Do not use down sampling factor 8 if kill switch is triggered.
40 return (config.delay.down_sampling_factor == 8 &&
41 field_trial::IsEnabled("WebRTC-Aec3DownSamplingFactor8KillSwitch"))
42 ? 4
43 : config.delay.down_sampling_factor;
44}
45
peahcf02cf12017-04-05 14:18:07 -070046class RenderDelayBufferImpl final : public RenderDelayBuffer {
47 public:
Per Åhgren8ba58612017-12-01 23:01:44 +010048 RenderDelayBufferImpl(const EchoCanceller3Config& config, size_t num_bands);
peahcf02cf12017-04-05 14:18:07 -070049 ~RenderDelayBufferImpl() override;
50
51 void Reset() override;
Per Åhgren8ba58612017-12-01 23:01:44 +010052 BufferingEvent Insert(const std::vector<std::vector<float>>& block) override;
Per Åhgrenc59a5762017-12-11 21:34:19 +010053 BufferingEvent PrepareCaptureProcessing() override;
54 bool SetDelay(size_t delay) override;
Per Åhgren5c532d32018-03-22 00:29:25 +010055 size_t Delay() const override { return MapInternalDelayToExternalDelay(); }
Per Åhgren8ba58612017-12-01 23:01:44 +010056 size_t MaxDelay() const override {
Per Åhgren09a718a2017-12-11 22:28:45 +010057 return blocks_.buffer.size() - 1 - buffer_headroom_;
Per Åhgren8ba58612017-12-01 23:01:44 +010058 }
Per Åhgrenc59a5762017-12-11 21:34:19 +010059 RenderBuffer* GetRenderBuffer() override { return &echo_remover_buffer_; }
peahcf02cf12017-04-05 14:18:07 -070060
61 const DownsampledRenderBuffer& GetDownsampledRenderBuffer() const override {
Per Åhgren8ba58612017-12-01 23:01:44 +010062 return low_rate_;
peahcf02cf12017-04-05 14:18:07 -070063 }
64
Per Åhgrena76ef9d2018-01-25 07:01:34 +010065 bool CausalDelay(size_t delay) const override;
Per Åhgrenc59a5762017-12-11 21:34:19 +010066
Per Åhgrend0fa8202018-04-18 09:35:13 +020067 void SetAudioBufferDelay(size_t delay_ms) override;
68
peahcf02cf12017-04-05 14:18:07 -070069 private:
Per Åhgren38e2d952017-11-17 14:54:28 +010070 static int instance_count_;
71 std::unique_ptr<ApmDataDumper> data_dumper_;
peahcf02cf12017-04-05 14:18:07 -070072 const Aec3Optimization optimization_;
Per Åhgrenc59a5762017-12-11 21:34:19 +010073 const EchoCanceller3Config config_;
Gustaf Ullberg78b1c4a2018-05-25 10:12:58 +020074 size_t down_sampling_factor_;
Per Åhgrene05c43c2018-05-09 12:26:51 +020075 const bool use_zero_external_delay_headroom_;
Per Åhgren8ba58612017-12-01 23:01:44 +010076 const int sub_block_size_;
77 MatrixBuffer blocks_;
78 VectorBuffer spectra_;
79 FftBuffer ffts_;
Danil Chapovalovdb9f7ab2018-06-19 10:50:11 +020080 absl::optional<size_t> delay_;
81 absl::optional<int> internal_delay_;
Per Åhgren8ba58612017-12-01 23:01:44 +010082 RenderBuffer echo_remover_buffer_;
83 DownsampledRenderBuffer low_rate_;
Per Åhgren38e2d952017-11-17 14:54:28 +010084 Decimator render_decimator_;
peahdebaa442017-05-03 05:39:09 -070085 const std::vector<std::vector<float>> zero_block_;
Per Åhgren8ba58612017-12-01 23:01:44 +010086 const Aec3Fft fft_;
Per Åhgren8ba58612017-12-01 23:01:44 +010087 std::vector<float> render_ds_;
Per Åhgren09a718a2017-12-11 22:28:45 +010088 const int buffer_headroom_;
Per Åhgrenb4c188d2017-12-20 00:25:18 +010089 bool last_call_was_render_ = false;
90 int num_api_calls_in_a_row_ = 0;
91 int max_observed_jitter_ = 1;
92 size_t capture_call_counter_ = 0;
93 size_t render_call_counter_ = 0;
Per Åhgrenb6b00dc2018-02-20 22:18:27 +010094 bool render_activity_ = false;
95 size_t render_activity_counter_ = 0;
Danil Chapovalovdb9f7ab2018-06-19 10:50:11 +020096 absl::optional<size_t> external_audio_buffer_delay_;
Per Åhgrend0fa8202018-04-18 09:35:13 +020097 bool external_delay_verified_after_reset_ = false;
Per Åhgren8ba58612017-12-01 23:01:44 +010098
Per Åhgrenc59a5762017-12-11 21:34:19 +010099 int LowRateBufferOffset() const { return DelayEstimatorOffset(config_) >> 1; }
Per Åhgren5c532d32018-03-22 00:29:25 +0100100 int MapExternalDelayToInternalDelay(size_t external_delay_blocks) const;
101 int MapInternalDelayToExternalDelay() const;
Per Åhgrenc59a5762017-12-11 21:34:19 +0100102 void ApplyDelay(int delay);
103 void InsertBlock(const std::vector<std::vector<float>>& block,
104 int previous_write);
Per Åhgrenb6b00dc2018-02-20 22:18:27 +0100105 bool DetectActiveRender(rtc::ArrayView<const float> x) const;
Per Åhgren8ba58612017-12-01 23:01:44 +0100106
peah69221db2017-01-27 03:28:19 -0800107 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(RenderDelayBufferImpl);
108};
109
Per Åhgrenc59a5762017-12-11 21:34:19 +0100110// Increases the write indices for the render buffers.
111void IncreaseWriteIndices(int sub_block_size,
112 MatrixBuffer* blocks,
113 VectorBuffer* spectra,
114 FftBuffer* ffts,
115 DownsampledRenderBuffer* low_rate) {
116 low_rate->UpdateWriteIndex(-sub_block_size);
117 blocks->IncWriteIndex();
118 spectra->DecWriteIndex();
119 ffts->DecWriteIndex();
120}
121
122// Increases the read indices for the render buffers.
Danil Chapovalovdb9f7ab2018-06-19 10:50:11 +0200123void IncreaseReadIndices(const absl::optional<int>& delay,
Per Åhgrenc59a5762017-12-11 21:34:19 +0100124 int sub_block_size,
125 MatrixBuffer* blocks,
126 VectorBuffer* spectra,
127 FftBuffer* ffts,
128 DownsampledRenderBuffer* low_rate) {
129 RTC_DCHECK_NE(low_rate->read, low_rate->write);
130 low_rate->UpdateReadIndex(-sub_block_size);
131
132 if (blocks->read != blocks->write) {
133 blocks->IncReadIndex();
134 spectra->DecReadIndex();
135 ffts->DecReadIndex();
136 } else {
137 // Only allow underrun for blocks_ when the delay is not set.
138 RTC_DCHECK(!delay);
139 }
140}
141
142// Checks for a render buffer overrun.
143bool RenderOverrun(const MatrixBuffer& b, const DownsampledRenderBuffer& l) {
144 return l.read == l.write || b.read == b.write;
145}
146
147// Checks for a render buffer underrun. If the delay is not specified, only the
148// low rate buffer underrun is counted as the delay offset for the other buffers
149// is unknown.
Danil Chapovalovdb9f7ab2018-06-19 10:50:11 +0200150bool RenderUnderrun(const absl::optional<int>& delay,
Per Åhgrenc59a5762017-12-11 21:34:19 +0100151 const MatrixBuffer& b,
152 const DownsampledRenderBuffer& l) {
153 return l.read == l.write || (delay && b.read == b.write);
154}
155
156// Computes the latency in the buffer (the number of unread elements).
157int BufferLatency(const DownsampledRenderBuffer& l) {
158 return (l.buffer.size() + l.read - l.write) % l.buffer.size();
159}
160
161// Computes the mismatch between the number of render and capture calls based on
162// the known offset (achieved during reset) of the low rate buffer.
163bool ApiCallSkew(const DownsampledRenderBuffer& low_rate_buffer,
164 int sub_block_size,
165 int low_rate_buffer_offset_sub_blocks) {
166 int latency = BufferLatency(low_rate_buffer);
167 int skew = abs(low_rate_buffer_offset_sub_blocks * sub_block_size - latency);
168 int skew_limit = low_rate_buffer_offset_sub_blocks * sub_block_size;
169 return skew >= skew_limit;
170}
171
Per Åhgren38e2d952017-11-17 14:54:28 +0100172int RenderDelayBufferImpl::instance_count_ = 0;
173
Per Åhgren8ba58612017-12-01 23:01:44 +0100174RenderDelayBufferImpl::RenderDelayBufferImpl(const EchoCanceller3Config& config,
175 size_t num_bands)
Per Åhgren38e2d952017-11-17 14:54:28 +0100176 : data_dumper_(
177 new ApmDataDumper(rtc::AtomicOps::Increment(&instance_count_))),
178 optimization_(DetectOptimization()),
Per Åhgrenc59a5762017-12-11 21:34:19 +0100179 config_(config),
Gustaf Ullberg78b1c4a2018-05-25 10:12:58 +0200180 down_sampling_factor_(GetDownSamplingFactor(config)),
Per Åhgrene05c43c2018-05-09 12:26:51 +0200181 use_zero_external_delay_headroom_(EnableZeroExternalDelayHeadroom()),
Gustaf Ullberg78b1c4a2018-05-25 10:12:58 +0200182 sub_block_size_(static_cast<int>(down_sampling_factor_ > 0
183 ? kBlockSize / down_sampling_factor_
184 : kBlockSize)),
185 blocks_(GetRenderDelayBufferSize(down_sampling_factor_,
Per Åhgren09a718a2017-12-11 22:28:45 +0100186 config.delay.num_filters,
Per Åhgren08ea5892018-01-15 08:07:41 +0100187 config.filter.main.length_blocks),
Per Åhgren8ba58612017-12-01 23:01:44 +0100188 num_bands,
189 kBlockSize),
190 spectra_(blocks_.buffer.size(), kFftLengthBy2Plus1),
191 ffts_(blocks_.buffer.size()),
Per Åhgren5c532d32018-03-22 00:29:25 +0100192 delay_(config_.delay.default_delay),
Per Åhgrenec22e3f2017-12-20 15:20:37 +0100193 echo_remover_buffer_(&blocks_, &spectra_, &ffts_),
Gustaf Ullberg78b1c4a2018-05-25 10:12:58 +0200194 low_rate_(GetDownSampledBufferSize(down_sampling_factor_,
Per Åhgren8ba58612017-12-01 23:01:44 +0100195 config.delay.num_filters)),
Gustaf Ullberg78b1c4a2018-05-25 10:12:58 +0200196 render_decimator_(down_sampling_factor_),
Per Åhgren8ba58612017-12-01 23:01:44 +0100197 zero_block_(num_bands, std::vector<float>(kBlockSize, 0.f)),
198 fft_(),
Per Åhgren09a718a2017-12-11 22:28:45 +0100199 render_ds_(sub_block_size_, 0.f),
Per Åhgren08ea5892018-01-15 08:07:41 +0100200 buffer_headroom_(config.filter.main.length_blocks) {
Per Åhgren8ba58612017-12-01 23:01:44 +0100201 RTC_DCHECK_EQ(blocks_.buffer.size(), ffts_.buffer.size());
202 RTC_DCHECK_EQ(spectra_.buffer.size(), ffts_.buffer.size());
Per Åhgrenc59a5762017-12-11 21:34:19 +0100203
204 // Necessary condition to avoid unrecoverable echp due to noncausal alignment.
205 RTC_DCHECK_EQ(DelayEstimatorOffset(config_), LowRateBufferOffset() * 2);
Per Åhgren8ba58612017-12-01 23:01:44 +0100206 Reset();
peahcf02cf12017-04-05 14:18:07 -0700207}
peah69221db2017-01-27 03:28:19 -0800208
209RenderDelayBufferImpl::~RenderDelayBufferImpl() = default;
210
Per Åhgrenc59a5762017-12-11 21:34:19 +0100211// Resets the buffer delays and clears the reported delays.
peahcf02cf12017-04-05 14:18:07 -0700212void RenderDelayBufferImpl::Reset() {
Per Åhgrenb4c188d2017-12-20 00:25:18 +0100213 last_call_was_render_ = false;
214 num_api_calls_in_a_row_ = 1;
215
Per Åhgrenc59a5762017-12-11 21:34:19 +0100216 // Pre-fill the low rate buffer (which is used for delay estimation) to add
217 // headroom for the allowed api call jitter.
218 low_rate_.read = low_rate_.OffsetIndex(
219 low_rate_.write, LowRateBufferOffset() * sub_block_size_);
220
Per Åhgrend0fa8202018-04-18 09:35:13 +0200221 // Check for any external audio buffer delay and whether it is feasible.
Gustaf Ullberga49eacb2018-05-04 16:43:56 +0200222 if (external_audio_buffer_delay_) {
Per Åhgrene05c43c2018-05-09 12:26:51 +0200223 const size_t headroom = use_zero_external_delay_headroom_ ? 0 : 2;
Per Åhgrend0fa8202018-04-18 09:35:13 +0200224 size_t external_delay_to_set = 0;
Per Åhgrene05c43c2018-05-09 12:26:51 +0200225 if (*external_audio_buffer_delay_ < headroom) {
Per Åhgrend0fa8202018-04-18 09:35:13 +0200226 external_delay_to_set = 0;
227 } else {
Per Åhgrene05c43c2018-05-09 12:26:51 +0200228 external_delay_to_set = *external_audio_buffer_delay_ - headroom;
Per Åhgrend0fa8202018-04-18 09:35:13 +0200229 }
Per Åhgrenc59a5762017-12-11 21:34:19 +0100230
Gustaf Ullberg623d2812018-05-07 13:36:07 +0200231 external_delay_to_set = std::min(external_delay_to_set, MaxDelay());
Per Åhgrend0fa8202018-04-18 09:35:13 +0200232
233 // When an external delay estimate is available, use that delay as the
Gustaf Ullberg623d2812018-05-07 13:36:07 +0200234 // initial render buffer delay.
235 internal_delay_ = external_delay_to_set;
236 ApplyDelay(*internal_delay_);
237 delay_ = MapInternalDelayToExternalDelay();
238
Per Åhgrend0fa8202018-04-18 09:35:13 +0200239 external_delay_verified_after_reset_ = false;
240 } else {
241 // If an external delay estimate is not available, use that delay as the
242 // initial delay. Set the render buffer delays to the default delay.
243 ApplyDelay(config_.delay.default_delay);
244
245 // Unset the delays which are set by SetDelay.
Danil Chapovalovdb9f7ab2018-06-19 10:50:11 +0200246 delay_ = absl::nullopt;
247 internal_delay_ = absl::nullopt;
Per Åhgrend0fa8202018-04-18 09:35:13 +0200248 }
peahcf02cf12017-04-05 14:18:07 -0700249}
peah69221db2017-01-27 03:28:19 -0800250
Per Åhgrenc59a5762017-12-11 21:34:19 +0100251// Inserts a new block into the render buffers.
Per Åhgren8ba58612017-12-01 23:01:44 +0100252RenderDelayBuffer::BufferingEvent RenderDelayBufferImpl::Insert(
peahcf02cf12017-04-05 14:18:07 -0700253 const std::vector<std::vector<float>>& block) {
Per Åhgrenb4c188d2017-12-20 00:25:18 +0100254 ++render_call_counter_;
255 if (delay_) {
256 if (!last_call_was_render_) {
257 last_call_was_render_ = true;
258 num_api_calls_in_a_row_ = 1;
259 } else {
260 if (++num_api_calls_in_a_row_ > max_observed_jitter_) {
261 max_observed_jitter_ = num_api_calls_in_a_row_;
Per Åhgrenf7ac09f2018-03-22 07:45:43 +0100262 RTC_LOG(LS_WARNING)
Per Åhgrenb4c188d2017-12-20 00:25:18 +0100263 << "New max number api jitter observed at render block "
264 << render_call_counter_ << ": " << num_api_calls_in_a_row_
265 << " blocks";
266 }
267 }
268 }
269
Per Åhgrenc59a5762017-12-11 21:34:19 +0100270 // Increase the write indices to where the new blocks should be written.
271 const int previous_write = blocks_.write;
272 IncreaseWriteIndices(sub_block_size_, &blocks_, &spectra_, &ffts_,
273 &low_rate_);
peahcf02cf12017-04-05 14:18:07 -0700274
Per Åhgrenc59a5762017-12-11 21:34:19 +0100275 // Allow overrun and do a reset when render overrun occurrs due to more render
276 // data being inserted than capture data is received.
277 BufferingEvent event = RenderOverrun(blocks_, low_rate_)
Per Åhgren2e27d1c2017-12-12 09:33:23 +0100278 ? BufferingEvent::kRenderOverrun
Per Åhgrenc59a5762017-12-11 21:34:19 +0100279 : BufferingEvent::kNone;
280
Per Åhgrenb6b00dc2018-02-20 22:18:27 +0100281 // Detect and update render activity.
282 if (!render_activity_) {
283 render_activity_counter_ += DetectActiveRender(block[0]) ? 1 : 0;
284 render_activity_ = render_activity_counter_ >= 20;
285 }
286
Per Åhgrenc59a5762017-12-11 21:34:19 +0100287 // Insert the new render block into the specified position.
288 InsertBlock(block, previous_write);
289
290 if (event != BufferingEvent::kNone) {
291 Reset();
peah69221db2017-01-27 03:28:19 -0800292 }
peah69221db2017-01-27 03:28:19 -0800293
Per Åhgren8ba58612017-12-01 23:01:44 +0100294 return event;
peah69221db2017-01-27 03:28:19 -0800295}
296
Per Åhgrenc59a5762017-12-11 21:34:19 +0100297// Prepares the render buffers for processing another capture block.
298RenderDelayBuffer::BufferingEvent
299RenderDelayBufferImpl::PrepareCaptureProcessing() {
Per Åhgren8ba58612017-12-01 23:01:44 +0100300 BufferingEvent event = BufferingEvent::kNone;
Per Åhgrenb4c188d2017-12-20 00:25:18 +0100301 ++capture_call_counter_;
302
303 if (delay_) {
304 if (last_call_was_render_) {
305 last_call_was_render_ = false;
306 num_api_calls_in_a_row_ = 1;
307 } else {
308 if (++num_api_calls_in_a_row_ > max_observed_jitter_) {
309 max_observed_jitter_ = num_api_calls_in_a_row_;
Per Åhgrenf7ac09f2018-03-22 07:45:43 +0100310 RTC_LOG(LS_WARNING)
Per Åhgrenb4c188d2017-12-20 00:25:18 +0100311 << "New max number api jitter observed at capture block "
312 << capture_call_counter_ << ": " << num_api_calls_in_a_row_
313 << " blocks";
314 }
315 }
316 }
peah69221db2017-01-27 03:28:19 -0800317
Per Åhgrenc59a5762017-12-11 21:34:19 +0100318 if (RenderUnderrun(internal_delay_, blocks_, low_rate_)) {
319 // Don't increase the read indices if there is a render underrun.
Per Åhgren8ba58612017-12-01 23:01:44 +0100320 event = BufferingEvent::kRenderUnderrun;
peahdebaa442017-05-03 05:39:09 -0700321 } else {
Per Åhgrenc59a5762017-12-11 21:34:19 +0100322 // Increase the read indices in the render buffers to point to the most
323 // recent block to use in the capture processing.
324 IncreaseReadIndices(internal_delay_, sub_block_size_, &blocks_, &spectra_,
325 &ffts_, &low_rate_);
Per Åhgren8ba58612017-12-01 23:01:44 +0100326
Per Åhgrenc59a5762017-12-11 21:34:19 +0100327 // Check for skew in the API calls which, if too large, causes the delay
328 // estimation to be noncausal. Doing this check after the render indice
329 // increase saves one unit of allowed skew. Note that the skew check only
330 // should need to be one-sided as one of the skew directions results in an
331 // underrun.
332 bool skew = ApiCallSkew(low_rate_, sub_block_size_, LowRateBufferOffset());
333 event = skew ? BufferingEvent::kApiCallSkew : BufferingEvent::kNone;
Per Åhgren8ba58612017-12-01 23:01:44 +0100334 }
335
Per Åhgrenc59a5762017-12-11 21:34:19 +0100336 if (event != BufferingEvent::kNone) {
337 Reset();
338 }
339
Per Åhgrenb6b00dc2018-02-20 22:18:27 +0100340 echo_remover_buffer_.SetRenderActivity(render_activity_);
341 if (render_activity_) {
342 render_activity_counter_ = 0;
343 render_activity_ = false;
344 }
345
Per Åhgren8ba58612017-12-01 23:01:44 +0100346 return event;
peah69221db2017-01-27 03:28:19 -0800347}
348
Per Åhgrenc59a5762017-12-11 21:34:19 +0100349// Sets the delay and returns a bool indicating whether the delay was changed.
350bool RenderDelayBufferImpl::SetDelay(size_t delay) {
Gustaf Ullberg623d2812018-05-07 13:36:07 +0200351 if (!external_delay_verified_after_reset_ && external_audio_buffer_delay_ &&
352 delay_) {
353 int difference = static_cast<int>(delay) - static_cast<int>(*delay_);
354 RTC_LOG(LS_WARNING) << "Mismatch between first estimated delay after reset "
355 "and external delay: "
356 << difference << " blocks";
Per Åhgrend0fa8202018-04-18 09:35:13 +0200357 external_delay_verified_after_reset_ = true;
358 }
Per Åhgrenc59a5762017-12-11 21:34:19 +0100359 if (delay_ && *delay_ == delay) {
360 return false;
peahcf02cf12017-04-05 14:18:07 -0700361 }
Per Åhgren8ba58612017-12-01 23:01:44 +0100362 delay_ = delay;
Per Åhgren8ba58612017-12-01 23:01:44 +0100363
Per Åhgrenc59a5762017-12-11 21:34:19 +0100364 // Compute the internal delay and limit the delay to the allowed range.
Per Åhgren5c532d32018-03-22 00:29:25 +0100365 int internal_delay = MapExternalDelayToInternalDelay(*delay_);
Per Åhgrenc59a5762017-12-11 21:34:19 +0100366 internal_delay_ =
367 std::min(MaxDelay(), static_cast<size_t>(std::max(internal_delay, 0)));
368
369 // Apply the delay to the buffers.
370 ApplyDelay(*internal_delay_);
371 return true;
peah69221db2017-01-27 03:28:19 -0800372}
373
Per Åhgrenc59a5762017-12-11 21:34:19 +0100374// Returns whether the specified delay is causal.
Per Åhgrena76ef9d2018-01-25 07:01:34 +0100375bool RenderDelayBufferImpl::CausalDelay(size_t delay) const {
376 // Compute the internal delay and limit the delay to the allowed range.
Per Åhgren5c532d32018-03-22 00:29:25 +0100377 int internal_delay = MapExternalDelayToInternalDelay(delay);
Per Åhgrena76ef9d2018-01-25 07:01:34 +0100378 internal_delay =
379 std::min(MaxDelay(), static_cast<size_t>(std::max(internal_delay, 0)));
380
381 return internal_delay >=
382 static_cast<int>(config_.delay.min_echo_path_delay_blocks);
Per Åhgrenc59a5762017-12-11 21:34:19 +0100383}
Per Åhgren8ba58612017-12-01 23:01:44 +0100384
Per Åhgrend0fa8202018-04-18 09:35:13 +0200385void RenderDelayBufferImpl::SetAudioBufferDelay(size_t delay_ms) {
Gustaf Ullberga49eacb2018-05-04 16:43:56 +0200386 if (!external_audio_buffer_delay_) {
Per Åhgrend0fa8202018-04-18 09:35:13 +0200387 RTC_LOG(LS_WARNING)
388 << "Receiving a first reported externally buffer delay of " << delay_ms
389 << " ms.";
390 }
Gustaf Ullberg623d2812018-05-07 13:36:07 +0200391
392 // Convert delay from milliseconds to blocks (rounded down).
Gustaf Ullberga49eacb2018-05-04 16:43:56 +0200393 external_audio_buffer_delay_ = delay_ms / 4;
Per Åhgrend0fa8202018-04-18 09:35:13 +0200394}
395
Per Åhgrenc59a5762017-12-11 21:34:19 +0100396// Maps the externally computed delay to the delay used internally.
Per Åhgren5c532d32018-03-22 00:29:25 +0100397int RenderDelayBufferImpl::MapExternalDelayToInternalDelay(
Per Åhgrenc59a5762017-12-11 21:34:19 +0100398 size_t external_delay_blocks) const {
399 const int latency = BufferLatency(low_rate_);
400 RTC_DCHECK_LT(0, sub_block_size_);
401 RTC_DCHECK_EQ(0, latency % sub_block_size_);
402 int latency_blocks = latency / sub_block_size_;
403 return latency_blocks + static_cast<int>(external_delay_blocks) -
404 DelayEstimatorOffset(config_);
405}
Per Åhgren8ba58612017-12-01 23:01:44 +0100406
Per Åhgren5c532d32018-03-22 00:29:25 +0100407// Maps the internally used delay to the delay used externally.
408int RenderDelayBufferImpl::MapInternalDelayToExternalDelay() const {
409 const int latency = BufferLatency(low_rate_);
410 int latency_blocks = latency / sub_block_size_;
411 int internal_delay = spectra_.read >= spectra_.write
412 ? spectra_.read - spectra_.write
413 : spectra_.size + spectra_.read - spectra_.write;
414
415 return internal_delay - latency_blocks + DelayEstimatorOffset(config_);
416}
417
Per Åhgrenc59a5762017-12-11 21:34:19 +0100418// Set the read indices according to the delay.
419void RenderDelayBufferImpl::ApplyDelay(int delay) {
Per Åhgrenf7ac09f2018-03-22 07:45:43 +0100420 RTC_LOG(LS_WARNING) << "Applying internal delay of " << delay << " blocks.";
Per Åhgrenc59a5762017-12-11 21:34:19 +0100421 blocks_.read = blocks_.OffsetIndex(blocks_.write, -delay);
422 spectra_.read = spectra_.OffsetIndex(spectra_.write, delay);
423 ffts_.read = ffts_.OffsetIndex(ffts_.write, delay);
424}
Per Åhgren8ba58612017-12-01 23:01:44 +0100425
Per Åhgrenc59a5762017-12-11 21:34:19 +0100426// Inserts a block into the render buffers.
427void RenderDelayBufferImpl::InsertBlock(
428 const std::vector<std::vector<float>>& block,
429 int previous_write) {
430 auto& b = blocks_;
431 auto& lr = low_rate_;
432 auto& ds = render_ds_;
433 auto& f = ffts_;
434 auto& s = spectra_;
435 RTC_DCHECK_EQ(block.size(), b.buffer[b.write].size());
436 for (size_t k = 0; k < block.size(); ++k) {
437 RTC_DCHECK_EQ(block[k].size(), b.buffer[b.write][k].size());
438 std::copy(block[k].begin(), block[k].end(), b.buffer[b.write][k].begin());
439 }
Per Åhgren8ba58612017-12-01 23:01:44 +0100440
Gustaf Ullberg43c707a2018-05-22 15:27:23 +0200441 data_dumper_->DumpWav("aec3_render_decimator_input", block[0].size(),
442 block[0].data(), 16000, 1);
Per Åhgrenc59a5762017-12-11 21:34:19 +0100443 render_decimator_.Decimate(block[0], ds);
Gustaf Ullberg43c707a2018-05-22 15:27:23 +0200444 data_dumper_->DumpWav("aec3_render_decimator_output", ds.size(), ds.data(),
Gustaf Ullberg78b1c4a2018-05-25 10:12:58 +0200445 16000 / down_sampling_factor_, 1);
Per Åhgrenc59a5762017-12-11 21:34:19 +0100446 std::copy(ds.rbegin(), ds.rend(), lr.buffer.begin() + lr.write);
447 fft_.PaddedFft(block[0], b.buffer[previous_write][0], &f.buffer[f.write]);
448 f.buffer[f.write].Spectrum(optimization_, s.buffer[s.write]);
449}
Per Åhgren8ba58612017-12-01 23:01:44 +0100450
Per Åhgrenb6b00dc2018-02-20 22:18:27 +0100451bool RenderDelayBufferImpl::DetectActiveRender(
452 rtc::ArrayView<const float> x) const {
453 const float x_energy = std::inner_product(x.begin(), x.end(), x.begin(), 0.f);
454 return x_energy > (config_.render_levels.active_render_limit *
455 config_.render_levels.active_render_limit) *
456 kFftLengthBy2;
457}
458
peah69221db2017-01-27 03:28:19 -0800459} // namespace
460
Per Åhgrenc59a5762017-12-11 21:34:19 +0100461int RenderDelayBuffer::RenderDelayBuffer::DelayEstimatorOffset(
462 const EchoCanceller3Config& config) {
463 return config.delay.api_call_jitter_blocks * 2;
464}
465
Per Åhgren8ba58612017-12-01 23:01:44 +0100466RenderDelayBuffer* RenderDelayBuffer::Create(const EchoCanceller3Config& config,
467 size_t num_bands) {
468 return new RenderDelayBufferImpl(config, num_bands);
peah69221db2017-01-27 03:28:19 -0800469}
470
471} // namespace webrtc