blob: 9640131885401a5ae8342e201e8ae84268fec1fb [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>
15
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020016#include "modules/audio_processing/aec3/aec3_common.h"
Per Åhgren8ba58612017-12-01 23:01:44 +010017#include "modules/audio_processing/aec3/aec3_fft.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020018#include "modules/audio_processing/aec3/block_processor.h"
Per Åhgren38e2d952017-11-17 14:54:28 +010019#include "modules/audio_processing/aec3/decimator.h"
Per Åhgren8ba58612017-12-01 23:01:44 +010020#include "modules/audio_processing/aec3/fft_buffer.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020021#include "modules/audio_processing/aec3/fft_data.h"
Per Åhgren8ba58612017-12-01 23:01:44 +010022#include "modules/audio_processing/aec3/matrix_buffer.h"
Per Åhgren38e2d952017-11-17 14:54:28 +010023#include "rtc_base/atomicops.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020024#include "rtc_base/checks.h"
25#include "rtc_base/constructormagic.h"
26#include "rtc_base/logging.h"
peah69221db2017-01-27 03:28:19 -080027
28namespace webrtc {
29namespace {
30
Per Åhgren8ba58612017-12-01 23:01:44 +010031constexpr int kBufferHeadroom = kAdaptiveFilterLength;
peah69221db2017-01-27 03:28:19 -080032
peahcf02cf12017-04-05 14:18:07 -070033class RenderDelayBufferImpl final : public RenderDelayBuffer {
34 public:
Per Åhgren8ba58612017-12-01 23:01:44 +010035 RenderDelayBufferImpl(const EchoCanceller3Config& config, size_t num_bands);
peahcf02cf12017-04-05 14:18:07 -070036 ~RenderDelayBufferImpl() override;
37
38 void Reset() override;
Per Åhgren8ba58612017-12-01 23:01:44 +010039 BufferingEvent Insert(const std::vector<std::vector<float>>& block) override;
40 BufferingEvent PrepareCaptureCall() override;
peahcf02cf12017-04-05 14:18:07 -070041 void SetDelay(size_t delay) override;
42 size_t Delay() const override { return delay_; }
Per Åhgren8ba58612017-12-01 23:01:44 +010043 size_t MaxDelay() const override {
44 return blocks_.buffer.size() - 1 - kBufferHeadroom;
45 }
46 size_t MaxApiJitter() const override { return max_api_jitter_; }
47 const RenderBuffer& GetRenderBuffer() const override {
48 return echo_remover_buffer_;
49 }
peahcf02cf12017-04-05 14:18:07 -070050
51 const DownsampledRenderBuffer& GetDownsampledRenderBuffer() const override {
Per Åhgren8ba58612017-12-01 23:01:44 +010052 return low_rate_;
peahcf02cf12017-04-05 14:18:07 -070053 }
54
55 private:
Per Åhgren38e2d952017-11-17 14:54:28 +010056 static int instance_count_;
57 std::unique_ptr<ApmDataDumper> data_dumper_;
peahcf02cf12017-04-05 14:18:07 -070058 const Aec3Optimization optimization_;
Per Åhgren8ba58612017-12-01 23:01:44 +010059 const size_t api_call_jitter_blocks_;
60 const size_t min_echo_path_delay_blocks_;
61 const int sub_block_size_;
62 MatrixBuffer blocks_;
63 VectorBuffer spectra_;
64 FftBuffer ffts_;
65 size_t delay_;
66 int max_api_jitter_ = 0;
67 int render_surplus_ = 0;
68 bool first_reset_occurred_ = false;
69 RenderBuffer echo_remover_buffer_;
70 DownsampledRenderBuffer low_rate_;
Per Åhgren38e2d952017-11-17 14:54:28 +010071 Decimator render_decimator_;
peahdebaa442017-05-03 05:39:09 -070072 const std::vector<std::vector<float>> zero_block_;
Per Åhgren8ba58612017-12-01 23:01:44 +010073 const Aec3Fft fft_;
74 size_t capture_call_counter_ = 0;
75 std::vector<float> render_ds_;
76 int render_calls_in_a_row_ = 0;
77
78 void UpdateBuffersWithLatestBlock(size_t previous_write);
79 void IncreaseRead();
80 void IncreaseInsert();
81
peah69221db2017-01-27 03:28:19 -080082 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(RenderDelayBufferImpl);
83};
84
Per Åhgren38e2d952017-11-17 14:54:28 +010085int RenderDelayBufferImpl::instance_count_ = 0;
86
Per Åhgren8ba58612017-12-01 23:01:44 +010087RenderDelayBufferImpl::RenderDelayBufferImpl(const EchoCanceller3Config& config,
88 size_t num_bands)
Per Åhgren38e2d952017-11-17 14:54:28 +010089 : data_dumper_(
90 new ApmDataDumper(rtc::AtomicOps::Increment(&instance_count_))),
91 optimization_(DetectOptimization()),
Per Åhgren8ba58612017-12-01 23:01:44 +010092 api_call_jitter_blocks_(config.delay.api_call_jitter_blocks),
93 min_echo_path_delay_blocks_(config.delay.min_echo_path_delay_blocks),
94 sub_block_size_(
95 static_cast<int>(config.delay.down_sampling_factor > 0
96 ? kBlockSize / config.delay.down_sampling_factor
97 : kBlockSize)),
98 blocks_(GetRenderDelayBufferSize(config.delay.down_sampling_factor,
99 config.delay.num_filters),
100 num_bands,
101 kBlockSize),
102 spectra_(blocks_.buffer.size(), kFftLengthBy2Plus1),
103 ffts_(blocks_.buffer.size()),
104 delay_(min_echo_path_delay_blocks_),
105 echo_remover_buffer_(kAdaptiveFilterLength, &blocks_, &spectra_, &ffts_),
106 low_rate_(GetDownSampledBufferSize(config.delay.down_sampling_factor,
107 config.delay.num_filters)),
108 render_decimator_(config.delay.down_sampling_factor),
109 zero_block_(num_bands, std::vector<float>(kBlockSize, 0.f)),
110 fft_(),
111 render_ds_(sub_block_size_, 0.f) {
112 RTC_DCHECK_EQ(blocks_.buffer.size(), ffts_.buffer.size());
113 RTC_DCHECK_EQ(spectra_.buffer.size(), ffts_.buffer.size());
114 Reset();
115 first_reset_occurred_ = false;
peahcf02cf12017-04-05 14:18:07 -0700116}
peah69221db2017-01-27 03:28:19 -0800117
118RenderDelayBufferImpl::~RenderDelayBufferImpl() = default;
119
peahcf02cf12017-04-05 14:18:07 -0700120void RenderDelayBufferImpl::Reset() {
Per Åhgren8ba58612017-12-01 23:01:44 +0100121 delay_ = min_echo_path_delay_blocks_;
122 const int offset1 = std::max<int>(
123 std::min(api_call_jitter_blocks_, min_echo_path_delay_blocks_), 1);
124 const int offset2 = static_cast<int>(delay_ + offset1);
125 const int offset3 = offset1 * sub_block_size_;
126 low_rate_.read = low_rate_.OffsetIndex(low_rate_.write, offset3);
127 blocks_.read = blocks_.OffsetIndex(blocks_.write, -offset2);
128 spectra_.read = spectra_.OffsetIndex(spectra_.write, offset2);
129 ffts_.read = ffts_.OffsetIndex(ffts_.write, offset2);
130 render_surplus_ = 0;
131 first_reset_occurred_ = true;
peahcf02cf12017-04-05 14:18:07 -0700132}
peah69221db2017-01-27 03:28:19 -0800133
Per Åhgren8ba58612017-12-01 23:01:44 +0100134RenderDelayBuffer::BufferingEvent RenderDelayBufferImpl::Insert(
peahcf02cf12017-04-05 14:18:07 -0700135 const std::vector<std::vector<float>>& block) {
Per Åhgren8ba58612017-12-01 23:01:44 +0100136 RTC_DCHECK_EQ(block.size(), blocks_.buffer[0].size());
137 RTC_DCHECK_EQ(block[0].size(), blocks_.buffer[0][0].size());
138 BufferingEvent event = BufferingEvent::kNone;
peahcf02cf12017-04-05 14:18:07 -0700139
Per Åhgren8ba58612017-12-01 23:01:44 +0100140 ++render_surplus_;
141 if (first_reset_occurred_) {
142 ++render_calls_in_a_row_;
143 max_api_jitter_ = std::max(max_api_jitter_, render_calls_in_a_row_);
peah69221db2017-01-27 03:28:19 -0800144 }
peah69221db2017-01-27 03:28:19 -0800145
Per Åhgren8ba58612017-12-01 23:01:44 +0100146 const size_t previous_write = blocks_.write;
147 IncreaseInsert();
148
149 if (low_rate_.read == low_rate_.write || blocks_.read == blocks_.write) {
150 // Render overrun due to more render data being inserted than read. Discard
151 // the oldest render data.
152 event = BufferingEvent::kRenderOverrun;
153 IncreaseRead();
154 }
155
156 for (size_t k = 0; k < block.size(); ++k) {
157 std::copy(block[k].begin(), block[k].end(),
158 blocks_.buffer[blocks_.write][k].begin());
159 }
160
161 UpdateBuffersWithLatestBlock(previous_write);
162 return event;
peah69221db2017-01-27 03:28:19 -0800163}
164
Per Åhgren8ba58612017-12-01 23:01:44 +0100165RenderDelayBuffer::BufferingEvent RenderDelayBufferImpl::PrepareCaptureCall() {
166 BufferingEvent event = BufferingEvent::kNone;
167 render_calls_in_a_row_ = 0;
peah69221db2017-01-27 03:28:19 -0800168
Per Åhgren8ba58612017-12-01 23:01:44 +0100169 if (low_rate_.read == low_rate_.write || blocks_.read == blocks_.write) {
170 event = BufferingEvent::kRenderUnderrun;
peahdebaa442017-05-03 05:39:09 -0700171 } else {
Per Åhgren8ba58612017-12-01 23:01:44 +0100172 IncreaseRead();
peahdebaa442017-05-03 05:39:09 -0700173 }
Per Åhgren8ba58612017-12-01 23:01:44 +0100174 --render_surplus_;
175
176 echo_remover_buffer_.UpdateSpectralSum();
177
178 if (render_surplus_ >= static_cast<int>(api_call_jitter_blocks_)) {
179 event = BufferingEvent::kApiCallSkew;
180 RTC_LOG(LS_WARNING) << "Api call skew detected at " << capture_call_counter_
181 << ".";
182 }
183
184 ++capture_call_counter_;
185 return event;
peah69221db2017-01-27 03:28:19 -0800186}
187
188void RenderDelayBufferImpl::SetDelay(size_t delay) {
peahcf02cf12017-04-05 14:18:07 -0700189 if (delay_ == delay) {
190 return;
191 }
192
Per Åhgren8ba58612017-12-01 23:01:44 +0100193 const int delta_delay = static_cast<int>(delay_) - static_cast<int>(delay);
194 delay_ = delay;
195 if (delay_ > MaxDelay()) {
196 delay_ = std::min(MaxDelay(), delay);
197 RTC_NOTREACHED();
peahcf02cf12017-04-05 14:18:07 -0700198 }
Per Åhgren8ba58612017-12-01 23:01:44 +0100199
200 // Recompute the read indices according to the set delay.
201 blocks_.UpdateReadIndex(delta_delay);
202 spectra_.UpdateReadIndex(-delta_delay);
203 ffts_.UpdateReadIndex(-delta_delay);
peah69221db2017-01-27 03:28:19 -0800204}
205
Per Åhgren8ba58612017-12-01 23:01:44 +0100206void RenderDelayBufferImpl::UpdateBuffersWithLatestBlock(
207 size_t previous_write) {
208 render_decimator_.Decimate(blocks_.buffer[blocks_.write][0], render_ds_);
209 std::copy(render_ds_.rbegin(), render_ds_.rend(),
210 low_rate_.buffer.begin() + low_rate_.write);
211
212 fft_.PaddedFft(blocks_.buffer[blocks_.write][0],
213 blocks_.buffer[previous_write][0], &ffts_.buffer[ffts_.write]);
214
215 ffts_.buffer[ffts_.write].Spectrum(optimization_,
216 spectra_.buffer[spectra_.write]);
217};
218
219void RenderDelayBufferImpl::IncreaseRead() {
220 low_rate_.UpdateReadIndex(-sub_block_size_);
221 blocks_.IncReadIndex();
222 spectra_.DecReadIndex();
223 ffts_.DecReadIndex();
224};
225
226void RenderDelayBufferImpl::IncreaseInsert() {
227 low_rate_.UpdateWriteIndex(-sub_block_size_);
228 blocks_.IncWriteIndex();
229 spectra_.DecWriteIndex();
230 ffts_.DecWriteIndex();
231};
232
peah69221db2017-01-27 03:28:19 -0800233} // namespace
234
Per Åhgren8ba58612017-12-01 23:01:44 +0100235RenderDelayBuffer* RenderDelayBuffer::Create(const EchoCanceller3Config& config,
236 size_t num_bands) {
237 return new RenderDelayBufferImpl(config, num_bands);
peah69221db2017-01-27 03:28:19 -0800238}
239
240} // namespace webrtc