blob: 35332d8b5c5804d48662eeccf6da67ee8d371ae4 [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
peahcf02cf12017-04-05 14:18:07 -070038class RenderDelayBufferImpl final : public RenderDelayBuffer {
39 public:
Per Åhgren8ba58612017-12-01 23:01:44 +010040 RenderDelayBufferImpl(const EchoCanceller3Config& config, size_t num_bands);
peahcf02cf12017-04-05 14:18:07 -070041 ~RenderDelayBufferImpl() override;
42
43 void Reset() override;
Per Åhgren8ba58612017-12-01 23:01:44 +010044 BufferingEvent Insert(const std::vector<std::vector<float>>& block) override;
Per Åhgrenc59a5762017-12-11 21:34:19 +010045 BufferingEvent PrepareCaptureProcessing() override;
46 bool SetDelay(size_t delay) override;
Per Åhgren5c532d32018-03-22 00:29:25 +010047 size_t Delay() const override { return MapInternalDelayToExternalDelay(); }
Per Åhgren8ba58612017-12-01 23:01:44 +010048 size_t MaxDelay() const override {
Per Åhgren09a718a2017-12-11 22:28:45 +010049 return blocks_.buffer.size() - 1 - buffer_headroom_;
Per Åhgren8ba58612017-12-01 23:01:44 +010050 }
Per Åhgrenc59a5762017-12-11 21:34:19 +010051 RenderBuffer* GetRenderBuffer() override { return &echo_remover_buffer_; }
peahcf02cf12017-04-05 14:18:07 -070052
53 const DownsampledRenderBuffer& GetDownsampledRenderBuffer() const override {
Per Åhgren8ba58612017-12-01 23:01:44 +010054 return low_rate_;
peahcf02cf12017-04-05 14:18:07 -070055 }
56
Per Åhgrena76ef9d2018-01-25 07:01:34 +010057 bool CausalDelay(size_t delay) const override;
Per Åhgrenc59a5762017-12-11 21:34:19 +010058
Per Åhgrend0fa8202018-04-18 09:35:13 +020059 void SetAudioBufferDelay(size_t delay_ms) override;
60
peahcf02cf12017-04-05 14:18:07 -070061 private:
Per Åhgren38e2d952017-11-17 14:54:28 +010062 static int instance_count_;
63 std::unique_ptr<ApmDataDumper> data_dumper_;
peahcf02cf12017-04-05 14:18:07 -070064 const Aec3Optimization optimization_;
Per Åhgrenc59a5762017-12-11 21:34:19 +010065 const EchoCanceller3Config config_;
Per Åhgrene05c43c2018-05-09 12:26:51 +020066 const bool use_zero_external_delay_headroom_;
Per Åhgren8ba58612017-12-01 23:01:44 +010067 const int sub_block_size_;
68 MatrixBuffer blocks_;
69 VectorBuffer spectra_;
70 FftBuffer ffts_;
Per Åhgrenc59a5762017-12-11 21:34:19 +010071 rtc::Optional<size_t> delay_;
72 rtc::Optional<int> internal_delay_;
Per Åhgren8ba58612017-12-01 23:01:44 +010073 RenderBuffer echo_remover_buffer_;
74 DownsampledRenderBuffer low_rate_;
Per Åhgren38e2d952017-11-17 14:54:28 +010075 Decimator render_decimator_;
peahdebaa442017-05-03 05:39:09 -070076 const std::vector<std::vector<float>> zero_block_;
Per Åhgren8ba58612017-12-01 23:01:44 +010077 const Aec3Fft fft_;
Per Åhgren8ba58612017-12-01 23:01:44 +010078 std::vector<float> render_ds_;
Per Åhgren09a718a2017-12-11 22:28:45 +010079 const int buffer_headroom_;
Per Åhgrenb4c188d2017-12-20 00:25:18 +010080 bool last_call_was_render_ = false;
81 int num_api_calls_in_a_row_ = 0;
82 int max_observed_jitter_ = 1;
83 size_t capture_call_counter_ = 0;
84 size_t render_call_counter_ = 0;
Per Åhgrenb6b00dc2018-02-20 22:18:27 +010085 bool render_activity_ = false;
86 size_t render_activity_counter_ = 0;
Gustaf Ullberga49eacb2018-05-04 16:43:56 +020087 rtc::Optional<size_t> external_audio_buffer_delay_;
Per Åhgrend0fa8202018-04-18 09:35:13 +020088 bool external_delay_verified_after_reset_ = false;
Per Åhgren8ba58612017-12-01 23:01:44 +010089
Per Åhgrenc59a5762017-12-11 21:34:19 +010090 int LowRateBufferOffset() const { return DelayEstimatorOffset(config_) >> 1; }
Per Åhgren5c532d32018-03-22 00:29:25 +010091 int MapExternalDelayToInternalDelay(size_t external_delay_blocks) const;
92 int MapInternalDelayToExternalDelay() const;
Per Åhgrenc59a5762017-12-11 21:34:19 +010093 void ApplyDelay(int delay);
94 void InsertBlock(const std::vector<std::vector<float>>& block,
95 int previous_write);
Per Åhgrenb6b00dc2018-02-20 22:18:27 +010096 bool DetectActiveRender(rtc::ArrayView<const float> x) const;
Per Åhgren8ba58612017-12-01 23:01:44 +010097
peah69221db2017-01-27 03:28:19 -080098 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(RenderDelayBufferImpl);
99};
100
Per Åhgrenc59a5762017-12-11 21:34:19 +0100101// Increases the write indices for the render buffers.
102void IncreaseWriteIndices(int sub_block_size,
103 MatrixBuffer* blocks,
104 VectorBuffer* spectra,
105 FftBuffer* ffts,
106 DownsampledRenderBuffer* low_rate) {
107 low_rate->UpdateWriteIndex(-sub_block_size);
108 blocks->IncWriteIndex();
109 spectra->DecWriteIndex();
110 ffts->DecWriteIndex();
111}
112
113// Increases the read indices for the render buffers.
114void IncreaseReadIndices(const rtc::Optional<int>& delay,
115 int sub_block_size,
116 MatrixBuffer* blocks,
117 VectorBuffer* spectra,
118 FftBuffer* ffts,
119 DownsampledRenderBuffer* low_rate) {
120 RTC_DCHECK_NE(low_rate->read, low_rate->write);
121 low_rate->UpdateReadIndex(-sub_block_size);
122
123 if (blocks->read != blocks->write) {
124 blocks->IncReadIndex();
125 spectra->DecReadIndex();
126 ffts->DecReadIndex();
127 } else {
128 // Only allow underrun for blocks_ when the delay is not set.
129 RTC_DCHECK(!delay);
130 }
131}
132
133// Checks for a render buffer overrun.
134bool RenderOverrun(const MatrixBuffer& b, const DownsampledRenderBuffer& l) {
135 return l.read == l.write || b.read == b.write;
136}
137
138// Checks for a render buffer underrun. If the delay is not specified, only the
139// low rate buffer underrun is counted as the delay offset for the other buffers
140// is unknown.
141bool RenderUnderrun(const rtc::Optional<int>& delay,
142 const MatrixBuffer& b,
143 const DownsampledRenderBuffer& l) {
144 return l.read == l.write || (delay && b.read == b.write);
145}
146
147// Computes the latency in the buffer (the number of unread elements).
148int BufferLatency(const DownsampledRenderBuffer& l) {
149 return (l.buffer.size() + l.read - l.write) % l.buffer.size();
150}
151
152// Computes the mismatch between the number of render and capture calls based on
153// the known offset (achieved during reset) of the low rate buffer.
154bool ApiCallSkew(const DownsampledRenderBuffer& low_rate_buffer,
155 int sub_block_size,
156 int low_rate_buffer_offset_sub_blocks) {
157 int latency = BufferLatency(low_rate_buffer);
158 int skew = abs(low_rate_buffer_offset_sub_blocks * sub_block_size - latency);
159 int skew_limit = low_rate_buffer_offset_sub_blocks * sub_block_size;
160 return skew >= skew_limit;
161}
162
Per Åhgren38e2d952017-11-17 14:54:28 +0100163int RenderDelayBufferImpl::instance_count_ = 0;
164
Per Åhgren8ba58612017-12-01 23:01:44 +0100165RenderDelayBufferImpl::RenderDelayBufferImpl(const EchoCanceller3Config& config,
166 size_t num_bands)
Per Åhgren38e2d952017-11-17 14:54:28 +0100167 : data_dumper_(
168 new ApmDataDumper(rtc::AtomicOps::Increment(&instance_count_))),
169 optimization_(DetectOptimization()),
Per Åhgrenc59a5762017-12-11 21:34:19 +0100170 config_(config),
Per Åhgrene05c43c2018-05-09 12:26:51 +0200171 use_zero_external_delay_headroom_(EnableZeroExternalDelayHeadroom()),
Per Åhgren8ba58612017-12-01 23:01:44 +0100172 sub_block_size_(
173 static_cast<int>(config.delay.down_sampling_factor > 0
174 ? kBlockSize / config.delay.down_sampling_factor
175 : kBlockSize)),
176 blocks_(GetRenderDelayBufferSize(config.delay.down_sampling_factor,
Per Åhgren09a718a2017-12-11 22:28:45 +0100177 config.delay.num_filters,
Per Åhgren08ea5892018-01-15 08:07:41 +0100178 config.filter.main.length_blocks),
Per Åhgren8ba58612017-12-01 23:01:44 +0100179 num_bands,
180 kBlockSize),
181 spectra_(blocks_.buffer.size(), kFftLengthBy2Plus1),
182 ffts_(blocks_.buffer.size()),
Per Åhgren5c532d32018-03-22 00:29:25 +0100183 delay_(config_.delay.default_delay),
Per Åhgrenec22e3f2017-12-20 15:20:37 +0100184 echo_remover_buffer_(&blocks_, &spectra_, &ffts_),
Per Åhgren8ba58612017-12-01 23:01:44 +0100185 low_rate_(GetDownSampledBufferSize(config.delay.down_sampling_factor,
186 config.delay.num_filters)),
187 render_decimator_(config.delay.down_sampling_factor),
188 zero_block_(num_bands, std::vector<float>(kBlockSize, 0.f)),
189 fft_(),
Per Åhgren09a718a2017-12-11 22:28:45 +0100190 render_ds_(sub_block_size_, 0.f),
Per Åhgren08ea5892018-01-15 08:07:41 +0100191 buffer_headroom_(config.filter.main.length_blocks) {
Per Åhgren8ba58612017-12-01 23:01:44 +0100192 RTC_DCHECK_EQ(blocks_.buffer.size(), ffts_.buffer.size());
193 RTC_DCHECK_EQ(spectra_.buffer.size(), ffts_.buffer.size());
Per Åhgrenc59a5762017-12-11 21:34:19 +0100194
195 // Necessary condition to avoid unrecoverable echp due to noncausal alignment.
196 RTC_DCHECK_EQ(DelayEstimatorOffset(config_), LowRateBufferOffset() * 2);
Per Åhgren8ba58612017-12-01 23:01:44 +0100197 Reset();
peahcf02cf12017-04-05 14:18:07 -0700198}
peah69221db2017-01-27 03:28:19 -0800199
200RenderDelayBufferImpl::~RenderDelayBufferImpl() = default;
201
Per Åhgrenc59a5762017-12-11 21:34:19 +0100202// Resets the buffer delays and clears the reported delays.
peahcf02cf12017-04-05 14:18:07 -0700203void RenderDelayBufferImpl::Reset() {
Per Åhgrenb4c188d2017-12-20 00:25:18 +0100204 last_call_was_render_ = false;
205 num_api_calls_in_a_row_ = 1;
206
Per Åhgrenc59a5762017-12-11 21:34:19 +0100207 // Pre-fill the low rate buffer (which is used for delay estimation) to add
208 // headroom for the allowed api call jitter.
209 low_rate_.read = low_rate_.OffsetIndex(
210 low_rate_.write, LowRateBufferOffset() * sub_block_size_);
211
Per Åhgrend0fa8202018-04-18 09:35:13 +0200212 // Check for any external audio buffer delay and whether it is feasible.
Gustaf Ullberga49eacb2018-05-04 16:43:56 +0200213 if (external_audio_buffer_delay_) {
Per Åhgrene05c43c2018-05-09 12:26:51 +0200214 const size_t headroom = use_zero_external_delay_headroom_ ? 0 : 2;
Per Åhgrend0fa8202018-04-18 09:35:13 +0200215 size_t external_delay_to_set = 0;
Per Åhgrene05c43c2018-05-09 12:26:51 +0200216 if (*external_audio_buffer_delay_ < headroom) {
Per Åhgrend0fa8202018-04-18 09:35:13 +0200217 external_delay_to_set = 0;
218 } else {
Per Åhgrene05c43c2018-05-09 12:26:51 +0200219 external_delay_to_set = *external_audio_buffer_delay_ - headroom;
Per Åhgrend0fa8202018-04-18 09:35:13 +0200220 }
Per Åhgrenc59a5762017-12-11 21:34:19 +0100221
Gustaf Ullberg623d2812018-05-07 13:36:07 +0200222 external_delay_to_set = std::min(external_delay_to_set, MaxDelay());
Per Åhgrend0fa8202018-04-18 09:35:13 +0200223
224 // When an external delay estimate is available, use that delay as the
Gustaf Ullberg623d2812018-05-07 13:36:07 +0200225 // initial render buffer delay.
226 internal_delay_ = external_delay_to_set;
227 ApplyDelay(*internal_delay_);
228 delay_ = MapInternalDelayToExternalDelay();
229
Per Åhgrend0fa8202018-04-18 09:35:13 +0200230 external_delay_verified_after_reset_ = false;
231 } else {
232 // If an external delay estimate is not available, use that delay as the
233 // initial delay. Set the render buffer delays to the default delay.
234 ApplyDelay(config_.delay.default_delay);
235
236 // Unset the delays which are set by SetDelay.
237 delay_ = rtc::nullopt;
238 internal_delay_ = rtc::nullopt;
239 }
peahcf02cf12017-04-05 14:18:07 -0700240}
peah69221db2017-01-27 03:28:19 -0800241
Per Åhgrenc59a5762017-12-11 21:34:19 +0100242// Inserts a new block into the render buffers.
Per Åhgren8ba58612017-12-01 23:01:44 +0100243RenderDelayBuffer::BufferingEvent RenderDelayBufferImpl::Insert(
peahcf02cf12017-04-05 14:18:07 -0700244 const std::vector<std::vector<float>>& block) {
Per Åhgrenb4c188d2017-12-20 00:25:18 +0100245 ++render_call_counter_;
246 if (delay_) {
247 if (!last_call_was_render_) {
248 last_call_was_render_ = true;
249 num_api_calls_in_a_row_ = 1;
250 } else {
251 if (++num_api_calls_in_a_row_ > max_observed_jitter_) {
252 max_observed_jitter_ = num_api_calls_in_a_row_;
Per Åhgrenf7ac09f2018-03-22 07:45:43 +0100253 RTC_LOG(LS_WARNING)
Per Åhgrenb4c188d2017-12-20 00:25:18 +0100254 << "New max number api jitter observed at render block "
255 << render_call_counter_ << ": " << num_api_calls_in_a_row_
256 << " blocks";
257 }
258 }
259 }
260
Per Åhgrenc59a5762017-12-11 21:34:19 +0100261 // Increase the write indices to where the new blocks should be written.
262 const int previous_write = blocks_.write;
263 IncreaseWriteIndices(sub_block_size_, &blocks_, &spectra_, &ffts_,
264 &low_rate_);
peahcf02cf12017-04-05 14:18:07 -0700265
Per Åhgrenc59a5762017-12-11 21:34:19 +0100266 // Allow overrun and do a reset when render overrun occurrs due to more render
267 // data being inserted than capture data is received.
268 BufferingEvent event = RenderOverrun(blocks_, low_rate_)
Per Åhgren2e27d1c2017-12-12 09:33:23 +0100269 ? BufferingEvent::kRenderOverrun
Per Åhgrenc59a5762017-12-11 21:34:19 +0100270 : BufferingEvent::kNone;
271
Per Åhgrenb6b00dc2018-02-20 22:18:27 +0100272 // Detect and update render activity.
273 if (!render_activity_) {
274 render_activity_counter_ += DetectActiveRender(block[0]) ? 1 : 0;
275 render_activity_ = render_activity_counter_ >= 20;
276 }
277
Per Åhgrenc59a5762017-12-11 21:34:19 +0100278 // Insert the new render block into the specified position.
279 InsertBlock(block, previous_write);
280
281 if (event != BufferingEvent::kNone) {
282 Reset();
peah69221db2017-01-27 03:28:19 -0800283 }
peah69221db2017-01-27 03:28:19 -0800284
Per Åhgren8ba58612017-12-01 23:01:44 +0100285 return event;
peah69221db2017-01-27 03:28:19 -0800286}
287
Per Åhgrenc59a5762017-12-11 21:34:19 +0100288// Prepares the render buffers for processing another capture block.
289RenderDelayBuffer::BufferingEvent
290RenderDelayBufferImpl::PrepareCaptureProcessing() {
Per Åhgren8ba58612017-12-01 23:01:44 +0100291 BufferingEvent event = BufferingEvent::kNone;
Per Åhgrenb4c188d2017-12-20 00:25:18 +0100292 ++capture_call_counter_;
293
294 if (delay_) {
295 if (last_call_was_render_) {
296 last_call_was_render_ = false;
297 num_api_calls_in_a_row_ = 1;
298 } else {
299 if (++num_api_calls_in_a_row_ > max_observed_jitter_) {
300 max_observed_jitter_ = num_api_calls_in_a_row_;
Per Åhgrenf7ac09f2018-03-22 07:45:43 +0100301 RTC_LOG(LS_WARNING)
Per Åhgrenb4c188d2017-12-20 00:25:18 +0100302 << "New max number api jitter observed at capture block "
303 << capture_call_counter_ << ": " << num_api_calls_in_a_row_
304 << " blocks";
305 }
306 }
307 }
peah69221db2017-01-27 03:28:19 -0800308
Per Åhgrenc59a5762017-12-11 21:34:19 +0100309 if (RenderUnderrun(internal_delay_, blocks_, low_rate_)) {
310 // Don't increase the read indices if there is a render underrun.
Per Åhgren8ba58612017-12-01 23:01:44 +0100311 event = BufferingEvent::kRenderUnderrun;
peahdebaa442017-05-03 05:39:09 -0700312 } else {
Per Åhgrenc59a5762017-12-11 21:34:19 +0100313 // Increase the read indices in the render buffers to point to the most
314 // recent block to use in the capture processing.
315 IncreaseReadIndices(internal_delay_, sub_block_size_, &blocks_, &spectra_,
316 &ffts_, &low_rate_);
Per Åhgren8ba58612017-12-01 23:01:44 +0100317
Per Åhgrenc59a5762017-12-11 21:34:19 +0100318 // Check for skew in the API calls which, if too large, causes the delay
319 // estimation to be noncausal. Doing this check after the render indice
320 // increase saves one unit of allowed skew. Note that the skew check only
321 // should need to be one-sided as one of the skew directions results in an
322 // underrun.
323 bool skew = ApiCallSkew(low_rate_, sub_block_size_, LowRateBufferOffset());
324 event = skew ? BufferingEvent::kApiCallSkew : BufferingEvent::kNone;
Per Åhgren8ba58612017-12-01 23:01:44 +0100325 }
326
Per Åhgrenc59a5762017-12-11 21:34:19 +0100327 if (event != BufferingEvent::kNone) {
328 Reset();
329 }
330
Per Åhgrenb6b00dc2018-02-20 22:18:27 +0100331 echo_remover_buffer_.SetRenderActivity(render_activity_);
332 if (render_activity_) {
333 render_activity_counter_ = 0;
334 render_activity_ = false;
335 }
336
Per Åhgren8ba58612017-12-01 23:01:44 +0100337 return event;
peah69221db2017-01-27 03:28:19 -0800338}
339
Per Åhgrenc59a5762017-12-11 21:34:19 +0100340// Sets the delay and returns a bool indicating whether the delay was changed.
341bool RenderDelayBufferImpl::SetDelay(size_t delay) {
Gustaf Ullberg623d2812018-05-07 13:36:07 +0200342 if (!external_delay_verified_after_reset_ && external_audio_buffer_delay_ &&
343 delay_) {
344 int difference = static_cast<int>(delay) - static_cast<int>(*delay_);
345 RTC_LOG(LS_WARNING) << "Mismatch between first estimated delay after reset "
346 "and external delay: "
347 << difference << " blocks";
Per Åhgrend0fa8202018-04-18 09:35:13 +0200348 external_delay_verified_after_reset_ = true;
349 }
Per Åhgrenc59a5762017-12-11 21:34:19 +0100350 if (delay_ && *delay_ == delay) {
351 return false;
peahcf02cf12017-04-05 14:18:07 -0700352 }
Per Åhgren8ba58612017-12-01 23:01:44 +0100353 delay_ = delay;
Per Åhgren8ba58612017-12-01 23:01:44 +0100354
Per Åhgrenc59a5762017-12-11 21:34:19 +0100355 // Compute the internal delay and limit the delay to the allowed range.
Per Åhgren5c532d32018-03-22 00:29:25 +0100356 int internal_delay = MapExternalDelayToInternalDelay(*delay_);
Per Åhgrenc59a5762017-12-11 21:34:19 +0100357 internal_delay_ =
358 std::min(MaxDelay(), static_cast<size_t>(std::max(internal_delay, 0)));
359
360 // Apply the delay to the buffers.
361 ApplyDelay(*internal_delay_);
362 return true;
peah69221db2017-01-27 03:28:19 -0800363}
364
Per Åhgrenc59a5762017-12-11 21:34:19 +0100365// Returns whether the specified delay is causal.
Per Åhgrena76ef9d2018-01-25 07:01:34 +0100366bool RenderDelayBufferImpl::CausalDelay(size_t delay) const {
367 // Compute the internal delay and limit the delay to the allowed range.
Per Åhgren5c532d32018-03-22 00:29:25 +0100368 int internal_delay = MapExternalDelayToInternalDelay(delay);
Per Åhgrena76ef9d2018-01-25 07:01:34 +0100369 internal_delay =
370 std::min(MaxDelay(), static_cast<size_t>(std::max(internal_delay, 0)));
371
372 return internal_delay >=
373 static_cast<int>(config_.delay.min_echo_path_delay_blocks);
Per Åhgrenc59a5762017-12-11 21:34:19 +0100374}
Per Åhgren8ba58612017-12-01 23:01:44 +0100375
Per Åhgrend0fa8202018-04-18 09:35:13 +0200376void RenderDelayBufferImpl::SetAudioBufferDelay(size_t delay_ms) {
Gustaf Ullberga49eacb2018-05-04 16:43:56 +0200377 if (!external_audio_buffer_delay_) {
Per Åhgrend0fa8202018-04-18 09:35:13 +0200378 RTC_LOG(LS_WARNING)
379 << "Receiving a first reported externally buffer delay of " << delay_ms
380 << " ms.";
381 }
Gustaf Ullberg623d2812018-05-07 13:36:07 +0200382
383 // Convert delay from milliseconds to blocks (rounded down).
Gustaf Ullberga49eacb2018-05-04 16:43:56 +0200384 external_audio_buffer_delay_ = delay_ms / 4;
Per Åhgrend0fa8202018-04-18 09:35:13 +0200385}
386
Per Åhgrenc59a5762017-12-11 21:34:19 +0100387// Maps the externally computed delay to the delay used internally.
Per Åhgren5c532d32018-03-22 00:29:25 +0100388int RenderDelayBufferImpl::MapExternalDelayToInternalDelay(
Per Åhgrenc59a5762017-12-11 21:34:19 +0100389 size_t external_delay_blocks) const {
390 const int latency = BufferLatency(low_rate_);
391 RTC_DCHECK_LT(0, sub_block_size_);
392 RTC_DCHECK_EQ(0, latency % sub_block_size_);
393 int latency_blocks = latency / sub_block_size_;
394 return latency_blocks + static_cast<int>(external_delay_blocks) -
395 DelayEstimatorOffset(config_);
396}
Per Åhgren8ba58612017-12-01 23:01:44 +0100397
Per Åhgren5c532d32018-03-22 00:29:25 +0100398// Maps the internally used delay to the delay used externally.
399int RenderDelayBufferImpl::MapInternalDelayToExternalDelay() const {
400 const int latency = BufferLatency(low_rate_);
401 int latency_blocks = latency / sub_block_size_;
402 int internal_delay = spectra_.read >= spectra_.write
403 ? spectra_.read - spectra_.write
404 : spectra_.size + spectra_.read - spectra_.write;
405
406 return internal_delay - latency_blocks + DelayEstimatorOffset(config_);
407}
408
Per Åhgrenc59a5762017-12-11 21:34:19 +0100409// Set the read indices according to the delay.
410void RenderDelayBufferImpl::ApplyDelay(int delay) {
Per Åhgrenf7ac09f2018-03-22 07:45:43 +0100411 RTC_LOG(LS_WARNING) << "Applying internal delay of " << delay << " blocks.";
Per Åhgrenc59a5762017-12-11 21:34:19 +0100412 blocks_.read = blocks_.OffsetIndex(blocks_.write, -delay);
413 spectra_.read = spectra_.OffsetIndex(spectra_.write, delay);
414 ffts_.read = ffts_.OffsetIndex(ffts_.write, delay);
415}
Per Åhgren8ba58612017-12-01 23:01:44 +0100416
Per Åhgrenc59a5762017-12-11 21:34:19 +0100417// Inserts a block into the render buffers.
418void RenderDelayBufferImpl::InsertBlock(
419 const std::vector<std::vector<float>>& block,
420 int previous_write) {
421 auto& b = blocks_;
422 auto& lr = low_rate_;
423 auto& ds = render_ds_;
424 auto& f = ffts_;
425 auto& s = spectra_;
426 RTC_DCHECK_EQ(block.size(), b.buffer[b.write].size());
427 for (size_t k = 0; k < block.size(); ++k) {
428 RTC_DCHECK_EQ(block[k].size(), b.buffer[b.write][k].size());
429 std::copy(block[k].begin(), block[k].end(), b.buffer[b.write][k].begin());
430 }
Per Åhgren8ba58612017-12-01 23:01:44 +0100431
Per Åhgrenc59a5762017-12-11 21:34:19 +0100432 render_decimator_.Decimate(block[0], ds);
433 std::copy(ds.rbegin(), ds.rend(), lr.buffer.begin() + lr.write);
434 fft_.PaddedFft(block[0], b.buffer[previous_write][0], &f.buffer[f.write]);
435 f.buffer[f.write].Spectrum(optimization_, s.buffer[s.write]);
436}
Per Åhgren8ba58612017-12-01 23:01:44 +0100437
Per Åhgrenb6b00dc2018-02-20 22:18:27 +0100438bool RenderDelayBufferImpl::DetectActiveRender(
439 rtc::ArrayView<const float> x) const {
440 const float x_energy = std::inner_product(x.begin(), x.end(), x.begin(), 0.f);
441 return x_energy > (config_.render_levels.active_render_limit *
442 config_.render_levels.active_render_limit) *
443 kFftLengthBy2;
444}
445
peah69221db2017-01-27 03:28:19 -0800446} // namespace
447
Per Åhgrenc59a5762017-12-11 21:34:19 +0100448int RenderDelayBuffer::RenderDelayBuffer::DelayEstimatorOffset(
449 const EchoCanceller3Config& config) {
450 return config.delay.api_call_jitter_blocks * 2;
451}
452
Per Åhgren8ba58612017-12-01 23:01:44 +0100453RenderDelayBuffer* RenderDelayBuffer::Create(const EchoCanceller3Config& config,
454 size_t num_bands) {
455 return new RenderDelayBufferImpl(config, num_bands);
peah69221db2017-01-27 03:28:19 -0800456}
457
458} // namespace webrtc