blob: d2ead63b02c1576b8a7be31e2e4681356b8fa397 [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"
17#include "modules/audio_processing/aec3/block_processor.h"
Per Åhgren38e2d952017-11-17 14:54:28 +010018#include "modules/audio_processing/aec3/decimator.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020019#include "modules/audio_processing/aec3/fft_data.h"
Per Åhgren38e2d952017-11-17 14:54:28 +010020#include "rtc_base/atomicops.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020021#include "rtc_base/checks.h"
22#include "rtc_base/constructormagic.h"
23#include "rtc_base/logging.h"
peah69221db2017-01-27 03:28:19 -080024
25namespace webrtc {
26namespace {
27
peahcf02cf12017-04-05 14:18:07 -070028class ApiCallJitterBuffer {
peah69221db2017-01-27 03:28:19 -080029 public:
peahcf02cf12017-04-05 14:18:07 -070030 explicit ApiCallJitterBuffer(size_t num_bands) {
31 buffer_.fill(std::vector<std::vector<float>>(
32 num_bands, std::vector<float>(kBlockSize, 0.f)));
peah69221db2017-01-27 03:28:19 -080033 }
peahcf02cf12017-04-05 14:18:07 -070034
35 ~ApiCallJitterBuffer() = default;
36
37 void Reset() {
38 size_ = 0;
39 last_insert_index_ = 0;
40 }
41
42 void Insert(const std::vector<std::vector<float>>& block) {
43 RTC_DCHECK_LT(size_, buffer_.size());
44 last_insert_index_ = (last_insert_index_ + 1) % buffer_.size();
45 RTC_DCHECK_EQ(buffer_[last_insert_index_].size(), block.size());
46 RTC_DCHECK_EQ(buffer_[last_insert_index_][0].size(), block[0].size());
47 for (size_t k = 0; k < block.size(); ++k) {
48 std::copy(block[k].begin(), block[k].end(),
49 buffer_[last_insert_index_][k].begin());
50 }
51 ++size_;
52 }
53
54 void Remove(std::vector<std::vector<float>>* block) {
55 RTC_DCHECK_LT(0, size_);
56 --size_;
57 const size_t extract_index =
58 (last_insert_index_ - size_ + buffer_.size()) % buffer_.size();
59 for (size_t k = 0; k < block->size(); ++k) {
60 std::copy(buffer_[extract_index][k].begin(),
61 buffer_[extract_index][k].end(), (*block)[k].begin());
62 }
63 }
64
65 size_t Size() const { return size_; }
66 bool Full() const { return size_ >= (buffer_.size()); }
67 bool Empty() const { return size_ == 0; }
peah69221db2017-01-27 03:28:19 -080068
69 private:
peahcf02cf12017-04-05 14:18:07 -070070 std::array<std::vector<std::vector<float>>, kMaxApiCallsJitterBlocks> buffer_;
71 size_t size_ = 0;
72 int last_insert_index_ = 0;
73};
peah69221db2017-01-27 03:28:19 -080074
peahcf02cf12017-04-05 14:18:07 -070075class RenderDelayBufferImpl final : public RenderDelayBuffer {
76 public:
Per Åhgren38e2d952017-11-17 14:54:28 +010077 RenderDelayBufferImpl(size_t num_bands,
78 size_t down_sampling_factor,
79 size_t downsampled_render_buffer_size,
80 size_t render_delay_buffer_size);
peahcf02cf12017-04-05 14:18:07 -070081 ~RenderDelayBufferImpl() override;
82
83 void Reset() override;
84 bool Insert(const std::vector<std::vector<float>>& block) override;
85 bool UpdateBuffers() override;
86 void SetDelay(size_t delay) override;
87 size_t Delay() const override { return delay_; }
88
89 const RenderBuffer& GetRenderBuffer() const override { return fft_buffer_; }
90
91 const DownsampledRenderBuffer& GetDownsampledRenderBuffer() const override {
92 return downsampled_render_buffer_;
93 }
94
95 private:
Per Åhgren38e2d952017-11-17 14:54:28 +010096 static int instance_count_;
97 std::unique_ptr<ApmDataDumper> data_dumper_;
peahcf02cf12017-04-05 14:18:07 -070098 const Aec3Optimization optimization_;
Per Åhgren38e2d952017-11-17 14:54:28 +010099 const size_t down_sampling_factor_;
100 const size_t sub_block_size_;
101 std::vector<std::vector<std::vector<float>>> buffer_;
peahcf02cf12017-04-05 14:18:07 -0700102 size_t delay_ = 0;
103 size_t last_insert_index_ = 0;
104 RenderBuffer fft_buffer_;
105 DownsampledRenderBuffer downsampled_render_buffer_;
Per Åhgren38e2d952017-11-17 14:54:28 +0100106 Decimator render_decimator_;
peahcf02cf12017-04-05 14:18:07 -0700107 ApiCallJitterBuffer api_call_jitter_buffer_;
peahdebaa442017-05-03 05:39:09 -0700108 const std::vector<std::vector<float>> zero_block_;
peah69221db2017-01-27 03:28:19 -0800109 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(RenderDelayBufferImpl);
110};
111
Per Åhgren38e2d952017-11-17 14:54:28 +0100112int RenderDelayBufferImpl::instance_count_ = 0;
113
114RenderDelayBufferImpl::RenderDelayBufferImpl(
115 size_t num_bands,
116 size_t down_sampling_factor,
117 size_t downsampled_render_buffer_size,
118 size_t render_delay_buffer_size)
119 : data_dumper_(
120 new ApmDataDumper(rtc::AtomicOps::Increment(&instance_count_))),
121 optimization_(DetectOptimization()),
122 down_sampling_factor_(down_sampling_factor),
123 sub_block_size_(down_sampling_factor_ > 0
124 ? kBlockSize / down_sampling_factor
125 : kBlockSize),
126 buffer_(
127 render_delay_buffer_size,
128 std::vector<std::vector<float>>(num_bands,
129 std::vector<float>(kBlockSize, 0.f))),
peah86afe9d2017-04-06 15:45:32 -0700130 fft_buffer_(
131 optimization_,
132 num_bands,
Per Åhgren1b4059e2017-10-15 20:19:21 +0200133 std::max(kUnknownDelayRenderWindowSize, kAdaptiveFilterLength),
peah86afe9d2017-04-06 15:45:32 -0700134 std::vector<size_t>(1, kAdaptiveFilterLength)),
Per Åhgren38e2d952017-11-17 14:54:28 +0100135 downsampled_render_buffer_(downsampled_render_buffer_size),
136 render_decimator_(down_sampling_factor_),
peahdebaa442017-05-03 05:39:09 -0700137 api_call_jitter_buffer_(num_bands),
138 zero_block_(num_bands, std::vector<float>(kBlockSize, 0.f)) {
peahcf02cf12017-04-05 14:18:07 -0700139 RTC_DCHECK_LT(buffer_.size(), downsampled_render_buffer_.buffer.size());
140}
peah69221db2017-01-27 03:28:19 -0800141
142RenderDelayBufferImpl::~RenderDelayBufferImpl() = default;
143
peahcf02cf12017-04-05 14:18:07 -0700144void RenderDelayBufferImpl::Reset() {
145 // Empty all data in the buffers.
146 delay_ = 0;
147 last_insert_index_ = 0;
148 downsampled_render_buffer_.position = 0;
Per Åhgren38e2d952017-11-17 14:54:28 +0100149 std::fill(downsampled_render_buffer_.buffer.begin(),
150 downsampled_render_buffer_.buffer.end(), 0.f);
peahcf02cf12017-04-05 14:18:07 -0700151 fft_buffer_.Clear();
152 api_call_jitter_buffer_.Reset();
peah4b572d02017-04-06 16:33:06 -0700153 for (auto& c : buffer_) {
154 for (auto& b : c) {
155 std::fill(b.begin(), b.end(), 0.f);
156 }
157 }
peahcf02cf12017-04-05 14:18:07 -0700158}
peah69221db2017-01-27 03:28:19 -0800159
peahcf02cf12017-04-05 14:18:07 -0700160bool RenderDelayBufferImpl::Insert(
161 const std::vector<std::vector<float>>& block) {
162 RTC_DCHECK_EQ(block.size(), buffer_[0].size());
163 RTC_DCHECK_EQ(block[0].size(), buffer_[0][0].size());
164
165 if (api_call_jitter_buffer_.Full()) {
166 // Report buffer overrun and let the caller handle the overrun.
peah69221db2017-01-27 03:28:19 -0800167 return false;
168 }
peahcf02cf12017-04-05 14:18:07 -0700169 api_call_jitter_buffer_.Insert(block);
peah69221db2017-01-27 03:28:19 -0800170
171 return true;
172}
173
peahcf02cf12017-04-05 14:18:07 -0700174bool RenderDelayBufferImpl::UpdateBuffers() {
175 bool underrun = true;
peahdebaa442017-05-03 05:39:09 -0700176 // Update the buffers with a new block if such is available, otherwise insert
177 // a block of silence.
peahcf02cf12017-04-05 14:18:07 -0700178 if (api_call_jitter_buffer_.Size() > 0) {
179 last_insert_index_ = (last_insert_index_ + 1) % buffer_.size();
180 api_call_jitter_buffer_.Remove(&buffer_[last_insert_index_]);
peahcf02cf12017-04-05 14:18:07 -0700181 underrun = false;
182 }
peah69221db2017-01-27 03:28:19 -0800183
peahcf02cf12017-04-05 14:18:07 -0700184 downsampled_render_buffer_.position =
Per Åhgren38e2d952017-11-17 14:54:28 +0100185 (downsampled_render_buffer_.position - sub_block_size_ +
peahcf02cf12017-04-05 14:18:07 -0700186 downsampled_render_buffer_.buffer.size()) %
187 downsampled_render_buffer_.buffer.size();
188
Per Åhgren38e2d952017-11-17 14:54:28 +0100189 rtc::ArrayView<const float> input(
190 underrun ? zero_block_[0].data() : buffer_[last_insert_index_][0].data(),
191 kBlockSize);
192 rtc::ArrayView<float> output(downsampled_render_buffer_.buffer.data() +
193 downsampled_render_buffer_.position,
194 sub_block_size_);
195 data_dumper_->DumpWav("aec3_render_decimator_input", input.size(),
196 input.data(), 16000, 1);
197 render_decimator_.Decimate(input, output);
198 data_dumper_->DumpWav("aec3_render_decimator_output", output.size(),
199 output.data(), 16000 / down_sampling_factor_, 1);
200 for (size_t k = 0; k < output.size() / 2; ++k) {
201 float tmp = output[k];
202 output[k] = output[output.size() - 1 - k];
203 output[output.size() - 1 - k] = tmp;
peahdebaa442017-05-03 05:39:09 -0700204 }
peahcf02cf12017-04-05 14:18:07 -0700205
peahdebaa442017-05-03 05:39:09 -0700206 if (underrun) {
207 fft_buffer_.Insert(zero_block_);
208 } else {
209 fft_buffer_.Insert(buffer_[(last_insert_index_ - delay_ + buffer_.size()) %
210 buffer_.size()]);
211 }
peahcf02cf12017-04-05 14:18:07 -0700212 return !underrun;
peah69221db2017-01-27 03:28:19 -0800213}
214
215void RenderDelayBufferImpl::SetDelay(size_t delay) {
peahcf02cf12017-04-05 14:18:07 -0700216 if (delay_ == delay) {
217 return;
218 }
219
220 // If there is a new delay set, clear the fft buffer.
221 fft_buffer_.Clear();
222
peah86afe9d2017-04-06 15:45:32 -0700223 if ((buffer_.size() - 1) < delay) {
peahcf02cf12017-04-05 14:18:07 -0700224 // If the desired delay is larger than the delay buffer, shorten the delay
225 // buffer size to achieve the desired alignment with the available buffer
226 // size.
peahcf02cf12017-04-05 14:18:07 -0700227 downsampled_render_buffer_.position =
peah86afe9d2017-04-06 15:45:32 -0700228 (downsampled_render_buffer_.position +
Per Åhgren38e2d952017-11-17 14:54:28 +0100229 sub_block_size_ * (delay - (buffer_.size() - 1))) %
peahcf02cf12017-04-05 14:18:07 -0700230 downsampled_render_buffer_.buffer.size();
231
232 last_insert_index_ =
peah86afe9d2017-04-06 15:45:32 -0700233 (last_insert_index_ - (delay - (buffer_.size() - 1)) + buffer_.size()) %
234 buffer_.size();
235 delay_ = buffer_.size() - 1;
peahcf02cf12017-04-05 14:18:07 -0700236 } else {
237 delay_ = delay;
238 }
peah69221db2017-01-27 03:28:19 -0800239}
240
241} // namespace
242
Per Åhgren38e2d952017-11-17 14:54:28 +0100243RenderDelayBuffer* RenderDelayBuffer::Create(
244 size_t num_bands,
245 size_t down_sampling_factor,
246 size_t downsampled_render_buffer_size,
247 size_t render_delay_buffer_size) {
248 return new RenderDelayBufferImpl(num_bands, down_sampling_factor,
249 downsampled_render_buffer_size,
250 render_delay_buffer_size);
peah69221db2017-01-27 03:28:19 -0800251}
252
253} // namespace webrtc